KiCad PCB EDA Suite
convert_drawsegment_list_to_polygon.cpp File Reference

functions to convert a shape built with DRAWSEGMENTS to a polygon. More...

#include <trigo.h>
#include <macros.h>
#include <class_drawsegment.h>
#include <base_units.h>
#include <convert_basic_shapes_to_polygon.h>
#include <geometry/geometry_utils.h>
#include <class_board.h>
#include <collectors.h>

Go to the source code of this file.

Functions

static unsigned close_ness (const wxPoint &aLeft, const wxPoint &aRight)
 Function close_ness is a non-exact distance (also called Manhattan distance) used to approximate the distance between two points. More...
 
bool close_enough (const wxPoint &aLeft, const wxPoint &aRight, unsigned aLimit)
 Function close_enough is a local and tunable method of qualifying the proximity of two points. More...
 
bool close_st (const wxPoint &aReference, const wxPoint &aFirst, const wxPoint &aSecond)
 Function close_st is a local method of qualifying if either the start of end point of a segment is closest to a point. More...
 
static DRAWSEGMENTfindPoint (const wxPoint &aPoint, std::vector< DRAWSEGMENT * > &aList, unsigned aLimit)
 Searches for a DRAWSEGMENT matching a given end point or start point in a list, and if found, removes it from the TYPE_COLLECTOR and returns it, else returns NULL. More...
 
bool ConvertOutlineToPolygon (std::vector< DRAWSEGMENT * > &aSegList, SHAPE_POLY_SET &aPolygons, wxString *aErrorText, unsigned int aTolerance)
 Function ConvertOutlineToPolygon build a polygon (with holes) from a DRAWSEGMENT list, which is expected to be a outline, therefore a closed main outline with perhaps closed inner outlines. More...
 
bool BuildBoardPolygonOutlines (BOARD *aBoard, SHAPE_POLY_SET &aOutlines, wxString *aErrorText, unsigned int aTolerance)
 

Detailed Description

functions to convert a shape built with DRAWSEGMENTS to a polygon.

expecting the shape describes shape similar to a polygon

Definition in file convert_drawsegment_list_to_polygon.cpp.

Function Documentation

bool BuildBoardPolygonOutlines ( BOARD aBoard,
SHAPE_POLY_SET aOutlines,
wxString *  aErrorText,
unsigned int  aTolerance 
)

Definition at line 653 of file convert_drawsegment_list_to_polygon.cpp.

References SHAPE_POLY_SET::Append(), PCB_TYPE_COLLECTOR::Collect(), BOARD::ComputeBoundingBox(), ConvertOutlineToPolygon(), Edge_Cuts, EOT, BOARD::GetBoardEdgesBoundingBox(), COLLECTOR::GetCount(), EDA_RECT::GetEnd(), EDA_RECT::GetHeight(), GetLayer(), EDA_RECT::GetOrigin(), EDA_RECT::GetWidth(), EDA_RECT::Inflate(), SHAPE_POLY_SET::NewOutline(), SHAPE_POLY_SET::OutlineCount(), PCB_LINE_T, PCB_MODULE_EDGE_T, SHAPE_POLY_SET::RemoveAllContours(), wxPoint::x, and wxPoint::y.

Referenced by BOARD::Duplicate(), BOARD::GetBoardPolygonOutlines(), DIALOG_EXPORT_STEP::onExportButton(), and DIALOG_EXPORT_STEP::onUpdateYPos().

655 {
656  PCB_TYPE_COLLECTOR items;
657 
658  // Get all the DRAWSEGMENTS and module graphics into 'items',
659  // then keep only those on layer == Edge_Cuts.
660  static const KICAD_T scan_graphics[] = { PCB_LINE_T, PCB_MODULE_EDGE_T, EOT };
661  items.Collect( aBoard, scan_graphics );
662 
663  // Make a working copy of aSegList, because the list is modified during calculations
664  std::vector< DRAWSEGMENT* > segList;
665 
666  for( int ii = 0; ii < items.GetCount(); ii++ )
667  {
668  if( items[ii]->GetLayer() == Edge_Cuts )
669  segList.push_back( static_cast< DRAWSEGMENT* >( items[ii] ) );
670  }
671 
672  bool success = ConvertOutlineToPolygon( segList, aOutlines, aErrorText, aTolerance );
673 
674  if( !success || !aOutlines.OutlineCount() )
675  {
676  // Creates a valid polygon outline is not possible.
677  // So uses the board edge cuts bounding box to create a
678  // rectangular outline
679  // When no edge cuts items, build a contour
680  // from global bounding box
681 
682  EDA_RECT bbbox = aBoard->GetBoardEdgesBoundingBox();
683 
684  // If null area, uses the global bounding box.
685  if( ( bbbox.GetWidth() ) == 0 || ( bbbox.GetHeight() == 0 ) )
686  bbbox = aBoard->ComputeBoundingBox();
687 
688  // Ensure non null area. If happen, gives a minimal size.
689  if( ( bbbox.GetWidth() ) == 0 || ( bbbox.GetHeight() == 0 ) )
690  bbbox.Inflate( Millimeter2iu( 1.0 ) );
691 
692  aOutlines.RemoveAllContours();
693  aOutlines.NewOutline();
694 
695  wxPoint corner;
696  aOutlines.Append( bbbox.GetOrigin() );
697 
698  corner.x = bbbox.GetOrigin().x;
699  corner.y = bbbox.GetEnd().y;
700  aOutlines.Append( corner );
701 
702  aOutlines.Append( bbbox.GetEnd() );
703 
704  corner.x = bbbox.GetEnd().x;
705  corner.y = bbbox.GetOrigin().y;
706  aOutlines.Append( corner );
707  }
708 
709  return success;
710 }
int GetCount() const
Function GetCount returns the number of objects in the list.
Definition: collector.h:106
bool ConvertOutlineToPolygon(std::vector< DRAWSEGMENT * > &aSegList, SHAPE_POLY_SET &aPolygons, wxString *aErrorText, unsigned int aTolerance)
Function ConvertOutlineToPolygon build a polygon (with holes) from a DRAWSEGMENT list, which is expected to be a outline, therefore a closed main outline with perhaps closed inner outlines.
const wxPoint GetOrigin() const
Definition: eda_rect.h:112
EDA_RECT ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Function ComputeBoundingBox calculates the bounding box containing all board items (or board edge seg...
int GetHeight() const
Definition: eda_rect.h:118
int OutlineCount() const
Returns the number of outlines in the set
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
search types array terminator (End Of Types)
Definition: typeinfo.h:82
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:78
const EDA_RECT GetBoardEdgesBoundingBox() const
Function GetBoardEdgesBoundingBox Returns the board bounding box calculated using exclusively the boa...
Definition: class_board.h:804
int NewOutline()
Creates a new empty polygon in the set and returns its index
void Collect(BOARD_ITEM *aBoard, const KICAD_T aScanList[])
Collect BOARD_ITEM objects using this class&#39;s Inspector method, which does the collection.
Definition: collectors.cpp:498
const wxPoint GetEnd() const
Definition: eda_rect.h:114
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
int GetWidth() const
Definition: eda_rect.h:117
static bool GetLayer(MODEL_VRML &aModel, LAYER_NUM layer, VRML_LAYER **vlayer)
Collect all BOARD_ITEM objects of a given set of KICAD_T type(s).
Definition: collectors.h:590
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:91
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline) ...
bool close_enough ( const wxPoint aLeft,
const wxPoint aRight,
unsigned  aLimit 
)
inline

Function close_enough is a local and tunable method of qualifying the proximity of two points.

Parameters
aLeftis the first point
aRightis the second point
aLimitis a measure of proximity that the caller knows about.
Returns
bool - true if the two points are close enough, else false.

Definition at line 69 of file convert_drawsegment_list_to_polygon.cpp.

References close_ness().

Referenced by ConvertOutlineToPolygon().

70 {
71  // We don't use an accurate distance calculation, just something
72  // approximating it, since aLimit is non-exact anyway except when zero.
73  return close_ness( aLeft, aRight ) <= aLimit;
74 }
static unsigned close_ness(const wxPoint &aLeft, const wxPoint &aRight)
Function close_ness is a non-exact distance (also called Manhattan distance) used to approximate the ...
static unsigned close_ness ( const wxPoint aLeft,
const wxPoint aRight 
)
static

Function close_ness is a non-exact distance (also called Manhattan distance) used to approximate the distance between two points.

The distance is very in-exact, but can be helpful when used to pick between alternative neighboring points.

Parameters
aLeftis the first point
aRightis the second point
Returns
unsigned - a measure of proximity that the caller knows about, in BIU, but remember it is only an approximation.

Definition at line 53 of file convert_drawsegment_list_to_polygon.cpp.

References abs, wxPoint::x, and wxPoint::y.

Referenced by close_enough(), close_st(), and findPoint().

54 {
55  // Don't need an accurate distance calculation, just something
56  // approximating it, for relative ordering.
57  return unsigned( std::abs( aLeft.x - aRight.x ) + abs( aLeft.y - aRight.y ) );
58 }
#define abs(a)
Definition: auxiliary.h:84
bool close_st ( const wxPoint aReference,
const wxPoint aFirst,
const wxPoint aSecond 
)
inline

Function close_st is a local method of qualifying if either the start of end point of a segment is closest to a point.

Parameters
aReferenceis the reference point
aFirstis the first point
aSecondis the second point
Returns
bool - true if the the first point is closest to the reference, otherwise false.

Definition at line 85 of file convert_drawsegment_list_to_polygon.cpp.

References close_ness().

Referenced by ConvertOutlineToPolygon().

86 {
87  // We don't use an accurate distance calculation, just something
88  // approximating to find the closest to the reference.
89  return close_ness( aReference, aFirst ) <= close_ness( aReference, aSecond );
90 }
static unsigned close_ness(const wxPoint &aLeft, const wxPoint &aRight)
Function close_ness is a non-exact distance (also called Manhattan distance) used to approximate the ...
bool ConvertOutlineToPolygon ( std::vector< DRAWSEGMENT * > &  aSegList,
SHAPE_POLY_SET aPolygons,
wxString *  aErrorText,
unsigned int  aTolerance 
)

Function ConvertOutlineToPolygon build a polygon (with holes) from a DRAWSEGMENT list, which is expected to be a outline, therefore a closed main outline with perhaps closed inner outlines.

These closed inner outlines are considered as holes in the main outline

Parameters
aSegListthe initial list of drawsegments (only lines, circles and arcs).
aPolygonswill contain the complex polygon.
aToleranceis the max distance between points that is still accepted as connected (internal units)
aErrorTextis a wxString to return error message.

Definition at line 181 of file convert_drawsegment_list_to_polygon.cpp.

References PNS::angle(), SHAPE_POLY_SET::Append(), close_enough(), close_st(), findPoint(), BOARD_ITEM::FormatInternalUnits(), FROM_UTF8(), DRAWSEGMENT::GetAngle(), DRAWSEGMENT::GetArcEnd(), DRAWSEGMENT::GetArcStart(), GetArcToSegmentCount(), DRAWSEGMENT::GetBezierPoints(), DRAWSEGMENT::GetCenter(), GetChars(), DRAWSEGMENT::GetEnd(), DRAWSEGMENT::GetRadius(), DRAWSEGMENT::GetShape(), DRAWSEGMENT::GetStart(), DRAWSEGMENT::GetWidth(), i, SHAPE_POLY_SET::NewHole(), SHAPE_POLY_SET::NewOutline(), DRAWSEGMENT::RebuildBezierToSegmentsPointsList(), reverse(), RotatePoint(), S_ARC, S_CIRCLE, S_CURVE, S_SEGMENT, BOARD_ITEM::ShowShape(), TransformCircleToPolygon(), wxPoint::x, and wxPoint::y.

Referenced by BuildBoardPolygonOutlines(), MODULE::BuildPolyCourtyard(), and MODULE::CoverageRatio().

183 {
184  if( aSegList.size() == 0 )
185  return true;
186 
187  wxString msg;
188 
189  // Make a working copy of aSegList, because the list is modified during calculations
190  std::vector< DRAWSEGMENT* > segList = aSegList;
191 
192  DRAWSEGMENT* graphic;
193  wxPoint prevPt;
194 
195  // Find edge point with minimum x, this should be in the outer polygon
196  // which will define the perimeter Edge.Cuts polygon.
197  wxPoint xmin = wxPoint( INT_MAX, 0 );
198  int xmini = 0;
199 
200  for( size_t i = 0; i < segList.size(); i++ )
201  {
202  graphic = (DRAWSEGMENT*) segList[i];
203 
204  switch( graphic->GetShape() )
205  {
206  case S_SEGMENT:
207  {
208  if( graphic->GetStart().x < xmin.x )
209  {
210  xmin = graphic->GetStart();
211  xmini = i;
212  }
213 
214  if( graphic->GetEnd().x < xmin.x )
215  {
216  xmin = graphic->GetEnd();
217  xmini = i;
218  }
219  }
220  break;
221 
222  case S_ARC:
223  // Freerouter does not yet understand arcs, so approximate
224  // an arc with a series of short lines and put those
225  // line segments into the !same! PATH.
226  {
227  wxPoint pstart = graphic->GetArcStart();
228  wxPoint center = graphic->GetCenter();
229  double angle = -graphic->GetAngle();
230  double radius = graphic->GetRadius();
231  int steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 );
232  wxPoint pt;
233 
234  for( int step = 1; step<=steps; ++step )
235  {
236  double rotation = ( angle * step ) / steps;
237 
238  pt = pstart;
239 
240  RotatePoint( &pt, center, rotation );
241 
242  if( pt.x < xmin.x )
243  {
244  xmin = pt;
245  xmini = i;
246  }
247  }
248  }
249  break;
250 
251  case S_CIRCLE:
252  {
253  wxPoint pt = graphic->GetCenter();
254 
255  // pt has minimum x point
256  pt.x -= graphic->GetRadius();
257 
258  // when the radius <= 0, this is a mal-formed circle. Skip it
259  if( graphic->GetRadius() > 0 && pt.x < xmin.x )
260  {
261  xmin = pt;
262  xmini = i;
263  }
264  }
265  break;
266 
267  case S_CURVE:
268  {
269  graphic->RebuildBezierToSegmentsPointsList( graphic->GetWidth() );
270 
271  for( unsigned int jj = 0; jj < graphic->GetBezierPoints().size(); jj++ )
272  {
273  wxPoint pt = graphic->GetBezierPoints()[jj];
274 
275  if( pt.x < xmin.x )
276  {
277  xmin = pt;
278  xmini = i;
279  }
280  }
281  }
282  break;
283 
284  default:
285  break;
286  }
287  }
288 
289  // Grab the left most point, assume its on the board's perimeter, and see if we
290  // can put enough graphics together by matching endpoints to formulate a cohesive
291  // polygon.
292 
293  graphic = (DRAWSEGMENT*) segList[xmini];
294 
295  // The first DRAWSEGMENT is in 'graphic', ok to remove it from 'items'
296  segList.erase( segList.begin() + xmini );
297 
298  // Output the Edge.Cuts perimeter as circle or polygon.
299  if( graphic->GetShape() == S_CIRCLE )
300  {
301  int steps = GetArcToSegmentCount( graphic->GetRadius(), ARC_LOW_DEF, 360.0 );
302  TransformCircleToPolygon( aPolygons, graphic->GetCenter(), graphic->GetRadius(), steps );
303  }
304  else
305  {
306  // Polygon start point. Arbitrarily chosen end of the
307  // segment and build the poly from here.
308 
309  wxPoint startPt = wxPoint( graphic->GetEnd() );
310  prevPt = graphic->GetEnd();
311  aPolygons.NewOutline();
312  aPolygons.Append( prevPt );
313 
314  // Do not append the other end point yet of this 'graphic', this first
315  // 'graphic' might be an arc or a curve.
316 
317  for(;;)
318  {
319  switch( graphic->GetShape() )
320  {
321  case S_SEGMENT:
322  {
323  wxPoint nextPt;
324 
325  // Use the line segment end point furthest away from
326  // prevPt as we assume the other end to be ON prevPt or
327  // very close to it.
328 
329  if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
330  nextPt = graphic->GetEnd();
331  else
332  nextPt = graphic->GetStart();
333 
334  aPolygons.Append( nextPt );
335  prevPt = nextPt;
336  }
337  break;
338 
339  case S_ARC:
340  // We do not support arcs in polygons, so approximate
341  // an arc with a series of short lines and put those
342  // line segments into the !same! PATH.
343  {
344  wxPoint pstart = graphic->GetArcStart();
345  wxPoint pend = graphic->GetArcEnd();
346  wxPoint pcenter = graphic->GetCenter();
347  double angle = -graphic->GetAngle();
348  double radius = graphic->GetRadius();
349  int steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 );
350 
351  if( !close_enough( prevPt, pstart, aTolerance ) )
352  {
353  wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), aTolerance ) );
354 
355  angle = -angle;
356  std::swap( pstart, pend );
357  }
358 
359  wxPoint nextPt;
360 
361  for( int step = 1; step<=steps; ++step )
362  {
363  double rotation = ( angle * step ) / steps;
364  nextPt = pstart;
365  RotatePoint( &nextPt, pcenter, rotation );
366 
367  aPolygons.Append( nextPt );
368  }
369 
370  prevPt = nextPt;
371  }
372  break;
373 
374  case S_CURVE:
375  // We do not support Bezier curves in polygons, so approximate
376  // with a series of short lines and put those
377  // line segments into the !same! PATH.
378  {
379  wxPoint nextPt;
380  bool reverse = false;
381 
382  // Use the end point furthest away from
383  // prevPt as we assume the other end to be ON prevPt or
384  // very close to it.
385 
386  if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
387  nextPt = graphic->GetEnd();
388  else
389  {
390  nextPt = graphic->GetStart();
391  reverse = true;
392  }
393 
394  if( reverse )
395  {
396  for( int jj = graphic->GetBezierPoints().size()-1;
397  jj >= 0; jj-- )
398  aPolygons.Append( graphic->GetBezierPoints()[jj] );
399  }
400  else
401  {
402  for( unsigned int jj = 0;
403  jj < graphic->GetBezierPoints().size(); jj++ )
404  aPolygons.Append( graphic->GetBezierPoints()[jj] );
405  }
406 
407  prevPt = nextPt;
408  }
409  break;
410 
411  default:
412  if( aErrorText )
413  {
414  msg.Printf( _( "Unsupported DRAWSEGMENT type %s" ),
415  GetChars( BOARD_ITEM::ShowShape( graphic->GetShape() ) ) );
416 
417  *aErrorText << msg << "\n";
418  }
419 
420  return false;
421  }
422 
423  // Get next closest segment.
424 
425  graphic = findPoint( prevPt, segList, aTolerance );
426 
427  // If there are no more close segments, check if the board
428  // outline polygon can be closed.
429 
430  if( !graphic )
431  {
432  if( close_enough( startPt, prevPt, aTolerance ) )
433  {
434  // Close the polygon back to start point
435  // aPolygons.Append( startPt ); // not needed
436  }
437  else
438  {
439  if( aErrorText )
440  {
441  msg.Printf(
442  _( "Unable to find the next boundary segment with an endpoint of (%s mm, %s mm). "
443  "graphic outline must form a contiguous, closed polygon." ),
444  GetChars( FROM_UTF8( BOARD_ITEM::FormatInternalUnits( prevPt.x ).c_str() ) ),
445  GetChars( FROM_UTF8( BOARD_ITEM::FormatInternalUnits( prevPt.y ).c_str() ) )
446  );
447 
448  *aErrorText << msg << "\n";
449  }
450 
451  return false;
452  }
453  break;
454  }
455  }
456  }
457 
458  while( segList.size() )
459  {
460  // emit a signal layers keepout for every interior polygon left...
461  int hole = aPolygons.NewHole();
462 
463  graphic = (DRAWSEGMENT*) segList[0];
464  segList.erase( segList.begin() );
465 
466  if( graphic->GetShape() == S_CIRCLE )
467  {
468  // make a circle by segments;
469  wxPoint center = graphic->GetCenter();
470  double angle = 3600.0;
471  wxPoint start = center;
472  int radius = graphic->GetRadius();
473  int steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, 360.0 );
474  wxPoint nextPt;
475 
476  start.x += radius;
477 
478  for( int step = 0; step < steps; ++step )
479  {
480  double rotation = ( angle * step ) / steps;
481  nextPt = start;
482  RotatePoint( &nextPt.x, &nextPt.y, center.x, center.y, rotation );
483  aPolygons.Append( nextPt, -1, hole );
484  }
485  }
486  else
487  {
488  // Polygon start point. Arbitrarily chosen end of the
489  // segment and build the poly from here.
490 
491  wxPoint startPt( graphic->GetEnd() );
492  prevPt = graphic->GetEnd();
493  aPolygons.Append( prevPt, -1, hole );
494 
495  // do not append the other end point yet, this first 'graphic' might be an arc
496  for(;;)
497  {
498  switch( graphic->GetShape() )
499  {
500  case S_SEGMENT:
501  {
502  wxPoint nextPt;
503 
504  // Use the line segment end point furthest away from
505  // prevPt as we assume the other end to be ON prevPt or
506  // very close to it.
507 
508  if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
509  {
510  nextPt = graphic->GetEnd();
511  }
512  else
513  {
514  nextPt = graphic->GetStart();
515  }
516 
517  prevPt = nextPt;
518  aPolygons.Append( prevPt, -1, hole );
519  }
520  break;
521 
522  case S_ARC:
523  // Freerouter does not yet understand arcs, so approximate
524  // an arc with a series of short lines and put those
525  // line segments into the !same! PATH.
526  {
527  wxPoint pstart = graphic->GetArcStart();
528  wxPoint pend = graphic->GetArcEnd();
529  wxPoint pcenter = graphic->GetCenter();
530  double angle = -graphic->GetAngle();
531  int radius = graphic->GetRadius();
532  int steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 );
533 
534  if( !close_enough( prevPt, pstart, aTolerance ) )
535  {
536  wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), aTolerance ) );
537 
538  angle = -angle;
539  std::swap( pstart, pend );
540  }
541 
542  wxPoint nextPt;
543 
544  for( int step = 1; step <= steps; ++step )
545  {
546  double rotation = ( angle * step ) / steps;
547 
548  nextPt = pstart;
549  RotatePoint( &nextPt, pcenter, rotation );
550 
551  aPolygons.Append( nextPt, -1, hole );
552  }
553 
554  prevPt = nextPt;
555  }
556  break;
557 
558  case S_CURVE:
559  // We do not support Bezier curves in polygons, so approximate
560  // with a series of short lines and put those
561  // line segments into the !same! PATH.
562  {
563  wxPoint nextPt;
564  bool reverse = false;
565 
566  // Use the end point furthest away from
567  // prevPt as we assume the other end to be ON prevPt or
568  // very close to it.
569 
570  if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
571  nextPt = graphic->GetEnd();
572  else
573  {
574  nextPt = graphic->GetStart();
575  reverse = true;
576  }
577 
578  if( reverse )
579  {
580  for( int jj = graphic->GetBezierPoints().size()-1;
581  jj >= 0; jj-- )
582  aPolygons.Append( graphic->GetBezierPoints()[jj], -1, hole );
583  }
584  else
585  {
586  for( unsigned int jj = 0;
587  jj < graphic->GetBezierPoints().size(); jj++ )
588  aPolygons.Append( graphic->GetBezierPoints()[jj], -1, hole );
589  }
590 
591  prevPt = nextPt;
592  }
593  break;
594 
595  default:
596  if( aErrorText )
597  {
598  msg.Printf( _( "Unsupported DRAWSEGMENT type %s" ),
599  GetChars( BOARD_ITEM::ShowShape( graphic->GetShape() ) ) );
600 
601  *aErrorText << msg << "\n";
602  }
603 
604  return false;
605  }
606 
607  // Get next closest segment.
608 
609  graphic = findPoint( prevPt, segList, aTolerance );
610 
611  // If there are no more close segments, check if polygon
612  // can be closed.
613 
614  if( !graphic )
615  {
616  if( close_enough( startPt, prevPt, aTolerance ) )
617  {
618  // Close the polygon back to start point
619  // aPolygons.Append( startPt, -1, hole ); // not needed
620  }
621  else
622  {
623  if( aErrorText )
624  {
625  msg.Printf(
626  _( "Unable to find the next graphic segment with an endpoint of (%s mm, %s mm).\n"
627  "Edit graphics, making them contiguous polygons each." ),
628  GetChars( FROM_UTF8( BOARD_ITEM::FormatInternalUnits( prevPt.x ).c_str() ) ),
629  GetChars( FROM_UTF8( BOARD_ITEM::FormatInternalUnits( prevPt.y ).c_str() ) )
630  );
631 
632  *aErrorText << msg << "\n";
633  }
634 
635  return false;
636  }
637  break;
638  }
639  }
640  }
641  }
642 
643  return true;
644 }
int NewHole(int aOutline=-1)
Creates a new hole in a given outline
static wxString ShowShape(STROKE_T aShape)
Function ShowShape converts the enum STROKE_T integer value to a wxString.
static wxString FROM_UTF8(const char *cstring)
function FROM_UTF8 converts a UTF8 encoded C string to a wxString for all wxWidgets build modes...
Definition: macros.h:53
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
const wxPoint GetCenter() const override
Function GetCenter()
void TransformCircleToPolygon(SHAPE_POLY_SET &aCornerBuffer, wxPoint aCenter, int aRadius, int aCircleToSegmentsCount)
Function TransformCircleToPolygon convert a circle to a polygon, using multiple straight lines...
void RebuildBezierToSegmentsPointsList(int aMinSegLen)
Rebuild the m_BezierPoints vertex list that approximate the Bezier curve by a list of segments Has me...
usual segment : line with rounded ends
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:216
static std::string FormatInternalUnits(int aValue)
Function FormatInternalUnits converts aValue from board internal units to a string appropriate for wr...
bool close_st(const wxPoint &aReference, const wxPoint &aFirst, const wxPoint &aSecond)
Function close_st is a local method of qualifying if either the start of end point of a segment is cl...
const wxPoint & GetArcStart() const
STROKE_T GetShape() const
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
Arcs (with rounded ends)
Bezier Curve.
bool close_enough(const wxPoint &aLeft, const wxPoint &aRight, unsigned aLimit)
Function close_enough is a local and tunable method of qualifying the proximity of two points...
int NewOutline()
Creates a new empty polygon in the set and returns its index
const std::vector< wxPoint > & GetBezierPoints() const
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
double GetAngle() const
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
size_t i
Definition: json11.cpp:597
const wxPoint GetArcEnd() const
static DRAWSEGMENT * findPoint(const wxPoint &aPoint, std::vector< DRAWSEGMENT * > &aList, unsigned aLimit)
Searches for a DRAWSEGMENT matching a given end point or start point in a list, and if found...
static void reverse(privcurve_t *curve)
Definition: trace.cpp:1025
int GetWidth() const
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
int GetRadius() const
Function GetRadius returns the radius of this item Has meaning only for arc and circle.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline) ...
static DRAWSEGMENT* findPoint ( const wxPoint aPoint,
std::vector< DRAWSEGMENT * > &  aList,
unsigned  aLimit 
)
static

Searches for a DRAWSEGMENT matching a given end point or start point in a list, and if found, removes it from the TYPE_COLLECTOR and returns it, else returns NULL.

Parameters
aPointThe starting or ending point to search for.
aListThe list to remove from.
aLimitis the distance from aPoint that still constitutes a valid find.
Returns
DRAWSEGMENT* - The first DRAWSEGMENT that has a start or end point matching aPoint, otherwise NULL if none.

Definition at line 102 of file convert_drawsegment_list_to_polygon.cpp.

References close_ness(), DRAWSEGMENT::GetArcEnd(), DRAWSEGMENT::GetArcStart(), DRAWSEGMENT::GetEnd(), DRAWSEGMENT::GetShape(), DRAWSEGMENT::GetStart(), i, and S_ARC.

Referenced by ConvertOutlineToPolygon().

103 {
104  unsigned min_d = INT_MAX;
105  int ndx_min = 0;
106 
107  // find the point closest to aPoint and perhaps exactly matching aPoint.
108  for( size_t i = 0; i < aList.size(); ++i )
109  {
110  DRAWSEGMENT* graphic = aList[i];
111  unsigned d;
112 
113  switch( graphic->GetShape() )
114  {
115  case S_ARC:
116  if( aPoint == graphic->GetArcStart() || aPoint == graphic->GetArcEnd() )
117  {
118  aList.erase( aList.begin() + i );
119  return graphic;
120  }
121 
122  d = close_ness( aPoint, graphic->GetArcStart() );
123  if( d < min_d )
124  {
125  min_d = d;
126  ndx_min = i;
127  }
128 
129  d = close_ness( aPoint, graphic->GetArcEnd() );
130  if( d < min_d )
131  {
132  min_d = d;
133  ndx_min = i;
134  }
135  break;
136 
137  default:
138  if( aPoint == graphic->GetStart() || aPoint == graphic->GetEnd() )
139  {
140  aList.erase( aList.begin() + i );
141  return graphic;
142  }
143 
144  d = close_ness( aPoint, graphic->GetStart() );
145  if( d < min_d )
146  {
147  min_d = d;
148  ndx_min = i;
149  }
150 
151  d = close_ness( aPoint, graphic->GetEnd() );
152  if( d < min_d )
153  {
154  min_d = d;
155  ndx_min = i;
156  }
157  }
158  }
159 
160  if( min_d <= aLimit )
161  {
162  DRAWSEGMENT* graphic = aList[ndx_min];
163  aList.erase( aList.begin() + ndx_min );
164  return graphic;
165  }
166 
167  return NULL;
168 }
static unsigned close_ness(const wxPoint &aLeft, const wxPoint &aRight)
Function close_ness is a non-exact distance (also called Manhattan distance) used to approximate the ...
const wxPoint & GetArcStart() const
STROKE_T GetShape() const
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
Arcs (with rounded ends)
size_t i
Definition: json11.cpp:597
const wxPoint GetArcEnd() const
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.