KiCad PCB EDA Suite
convert_drawsegment_list_to_polygon.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2015 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6  * Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
32 #include <trigo.h>
33 #include <macros.h>
34 
35 #include <math/vector2d.h>
36 #include <class_drawsegment.h>
37 #include <class_module.h>
38 #include <base_units.h>
42 
43 
56 static unsigned close_ness( const wxPoint& aLeft, const wxPoint& aRight )
57 {
58  // Don't need an accurate distance calculation, just something
59  // approximating it, for relative ordering.
60  return unsigned( std::abs( aLeft.x - aRight.x ) + abs( aLeft.y - aRight.y ) );
61 }
62 
72 inline bool close_enough( const wxPoint& aLeft, const wxPoint& aRight, unsigned aLimit )
73 {
74  // We don't use an accurate distance calculation, just something
75  // approximating it, since aLimit is non-exact anyway except when zero.
76  return close_ness( aLeft, aRight ) <= aLimit;
77 }
78 
88 inline bool close_st( const wxPoint& aReference, const wxPoint& aFirst, const wxPoint& aSecond )
89 {
90  // We don't use an accurate distance calculation, just something
91  // approximating to find the closest to the reference.
92  return close_ness( aReference, aFirst ) <= close_ness( aReference, aSecond );
93 }
94 
95 
105 static DRAWSEGMENT* findPoint( const wxPoint& aPoint, std::vector< DRAWSEGMENT* >& aList, unsigned aLimit )
106 {
107  unsigned min_d = INT_MAX;
108  int ndx_min = 0;
109 
110  // find the point closest to aPoint and perhaps exactly matching aPoint.
111  for( size_t i = 0; i < aList.size(); ++i )
112  {
113  DRAWSEGMENT* graphic = aList[i];
114  unsigned d;
115 
116  switch( graphic->GetShape() )
117  {
118  case S_ARC:
119  if( aPoint == graphic->GetArcStart() || aPoint == graphic->GetArcEnd() )
120  {
121  aList.erase( aList.begin() + i );
122  return graphic;
123  }
124 
125  d = close_ness( aPoint, graphic->GetArcStart() );
126  if( d < min_d )
127  {
128  min_d = d;
129  ndx_min = i;
130  }
131 
132  d = close_ness( aPoint, graphic->GetArcEnd() );
133  if( d < min_d )
134  {
135  min_d = d;
136  ndx_min = i;
137  }
138  break;
139 
140  default:
141  if( aPoint == graphic->GetStart() || aPoint == graphic->GetEnd() )
142  {
143  aList.erase( aList.begin() + i );
144  return graphic;
145  }
146 
147  d = close_ness( aPoint, graphic->GetStart() );
148  if( d < min_d )
149  {
150  min_d = d;
151  ndx_min = i;
152  }
153 
154  d = close_ness( aPoint, graphic->GetEnd() );
155  if( d < min_d )
156  {
157  min_d = d;
158  ndx_min = i;
159  }
160  }
161  }
162 
163  if( min_d <= aLimit )
164  {
165  DRAWSEGMENT* graphic = aList[ndx_min];
166  aList.erase( aList.begin() + ndx_min );
167  return graphic;
168  }
169 
170  return NULL;
171 }
172 
173 
185 bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SET& aPolygons,
186  wxString* aErrorText, unsigned int aTolerance, wxPoint* aErrorLocation )
187 {
188  if( aSegList.size() == 0 )
189  return true;
190 
191  wxString msg;
192 
193  // Make a working copy of aSegList, because the list is modified during calculations
194  std::vector< DRAWSEGMENT* > segList = aSegList;
195 
196  DRAWSEGMENT* graphic;
197  wxPoint prevPt;
198 
199  // Find edge point with minimum x, this should be in the outer polygon
200  // which will define the perimeter polygon polygon.
201  wxPoint xmin = wxPoint( INT_MAX, 0 );
202  int xmini = 0;
203 
204  for( size_t i = 0; i < segList.size(); i++ )
205  {
206  graphic = (DRAWSEGMENT*) segList[i];
207 
208  switch( graphic->GetShape() )
209  {
210  case S_RECT:
211  case S_SEGMENT:
212  {
213  if( graphic->GetStart().x < xmin.x )
214  {
215  xmin = graphic->GetStart();
216  xmini = i;
217  }
218 
219  if( graphic->GetEnd().x < xmin.x )
220  {
221  xmin = graphic->GetEnd();
222  xmini = i;
223  }
224  }
225  break;
226 
227  case S_ARC:
228  // Freerouter does not yet understand arcs, so approximate
229  // an arc with a series of short lines and put those
230  // line segments into the !same! PATH.
231  {
232  wxPoint pstart = graphic->GetArcStart();
233  wxPoint center = graphic->GetCenter();
234  double angle = -graphic->GetAngle();
235  double radius = graphic->GetRadius();
236  int steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 );
237  wxPoint pt;
238 
239  for( int step = 1; step<=steps; ++step )
240  {
241  double rotation = ( angle * step ) / steps;
242 
243  pt = pstart;
244 
245  RotatePoint( &pt, center, rotation );
246 
247  if( pt.x < xmin.x )
248  {
249  xmin = pt;
250  xmini = i;
251  }
252  }
253  }
254  break;
255 
256  case S_CIRCLE:
257  {
258  wxPoint pt = graphic->GetCenter();
259 
260  // pt has minimum x point
261  pt.x -= graphic->GetRadius();
262 
263  // when the radius <= 0, this is a mal-formed circle. Skip it
264  if( graphic->GetRadius() > 0 && pt.x < xmin.x )
265  {
266  xmin = pt;
267  xmini = i;
268  }
269  }
270  break;
271 
272  case S_CURVE:
273  {
274  graphic->RebuildBezierToSegmentsPointsList( graphic->GetWidth() );
275 
276  for( unsigned int jj = 0; jj < graphic->GetBezierPoints().size(); jj++ )
277  {
278  wxPoint pt = graphic->GetBezierPoints()[jj];
279 
280  if( pt.x < xmin.x )
281  {
282  xmin = pt;
283  xmini = i;
284  }
285  }
286  }
287  break;
288 
289  case S_POLYGON:
290  {
291  const auto poly = graphic->GetPolyShape();
292  MODULE* module = aSegList[0]->GetParentModule();
293  double orientation = module ? module->GetOrientation() : 0.0;
294  VECTOR2I offset = module ? module->GetPosition() : VECTOR2I( 0, 0 );
295 
296  for( auto iter = poly.CIterate(); iter; iter++ )
297  {
298  auto pt = *iter;
299  RotatePoint( pt, orientation );
300  pt += offset;
301 
302  if( pt.x < xmin.x )
303  {
304  xmin.x = pt.x;
305  xmin.y = pt.y;
306  xmini = i;
307  }
308  }
309  }
310  break;
311  default:
312  break;
313  }
314  }
315 
316  // Grab the left most point, assume its on the board's perimeter, and see if we
317  // can put enough graphics together by matching endpoints to formulate a cohesive
318  // polygon.
319 
320  graphic = (DRAWSEGMENT*) segList[xmini];
321 
322  // The first DRAWSEGMENT is in 'graphic', ok to remove it from 'items'
323  segList.erase( segList.begin() + xmini );
324 
325  // Output the outline perimeter as polygon.
326  if( graphic->GetShape() == S_CIRCLE )
327  {
328  TransformCircleToPolygon( aPolygons, graphic->GetCenter(), graphic->GetRadius(), aTolerance );
329  }
330  else if( graphic->GetShape() == S_RECT )
331  {
332  std::vector<wxPoint> pts;
333  graphic->GetRectCorners( &pts );
334 
335  aPolygons.NewOutline();
336 
337  for( const wxPoint& pt : pts )
338  aPolygons.Append( pt );
339  }
340  else if( graphic->GetShape() == S_POLYGON )
341  {
342  MODULE* module = graphic->GetParentModule(); // NULL for items not in footprints
343  double orientation = module ? module->GetOrientation() : 0.0;
344  VECTOR2I offset = module ? module->GetPosition() : VECTOR2I( 0, 0 );
345 
346  aPolygons.NewOutline();
347 
348  for( auto it = graphic->GetPolyShape().CIterate( 0 ); it; it++ )
349  {
350  auto pt = *it;
351  RotatePoint( pt, orientation );
352  pt += offset;
353  aPolygons.Append( pt );
354  }
355  }
356  else
357  {
358  // Polygon start point. Arbitrarily chosen end of the
359  // segment and build the poly from here.
360 
361  wxPoint startPt = wxPoint( graphic->GetEnd() );
362  prevPt = graphic->GetEnd();
363  aPolygons.NewOutline();
364  aPolygons.Append( prevPt );
365 
366  // Do not append the other end point yet of this 'graphic', this first
367  // 'graphic' might be an arc or a curve.
368 
369  for(;;)
370  {
371  switch( graphic->GetShape() )
372  {
373  case S_SEGMENT:
374  {
375  wxPoint nextPt;
376 
377  // Use the line segment end point furthest away from
378  // prevPt as we assume the other end to be ON prevPt or
379  // very close to it.
380 
381  if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
382  nextPt = graphic->GetEnd();
383  else
384  nextPt = graphic->GetStart();
385 
386  aPolygons.Append( nextPt );
387  prevPt = nextPt;
388  }
389  break;
390 
391  case S_ARC:
392  // We do not support arcs in polygons, so approximate
393  // an arc with a series of short lines and put those
394  // line segments into the !same! PATH.
395  {
396  wxPoint pstart = graphic->GetArcStart();
397  wxPoint pend = graphic->GetArcEnd();
398  wxPoint pcenter = graphic->GetCenter();
399  double angle = -graphic->GetAngle();
400  double radius = graphic->GetRadius();
401  int steps = GetArcToSegmentCount( radius, aTolerance, angle / 10.0 );
402 
403  if( !close_enough( prevPt, pstart, aTolerance ) )
404  {
405  wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), aTolerance ) );
406 
407  angle = -angle;
408  std::swap( pstart, pend );
409  }
410 
411  wxPoint nextPt;
412 
413  for( int step = 1; step<=steps; ++step )
414  {
415  double rotation = ( angle * step ) / steps;
416  nextPt = pstart;
417  RotatePoint( &nextPt, pcenter, rotation );
418 
419  aPolygons.Append( nextPt );
420  }
421 
422  prevPt = nextPt;
423  }
424  break;
425 
426  case S_CURVE:
427  // We do not support Bezier curves in polygons, so approximate
428  // with a series of short lines and put those
429  // line segments into the !same! PATH.
430  {
431  wxPoint nextPt;
432  bool reverse = false;
433 
434  // Use the end point furthest away from
435  // prevPt as we assume the other end to be ON prevPt or
436  // very close to it.
437 
438  if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
439  nextPt = graphic->GetEnd();
440  else
441  {
442  nextPt = graphic->GetStart();
443  reverse = true;
444  }
445 
446  if( reverse )
447  {
448  for( int jj = graphic->GetBezierPoints().size()-1; jj >= 0; jj-- )
449  aPolygons.Append( graphic->GetBezierPoints()[jj] );
450  }
451  else
452  {
453  for( size_t jj = 0; jj < graphic->GetBezierPoints().size(); jj++ )
454  aPolygons.Append( graphic->GetBezierPoints()[jj] );
455  }
456 
457  prevPt = nextPt;
458  }
459  break;
460 
461  default:
462  if( aErrorText )
463  {
464  msg.Printf( "Unsupported DRAWSEGMENT type %s.",
465  BOARD_ITEM::ShowShape( graphic->GetShape() ) );
466 
467  *aErrorText << msg << "\n";
468  }
469 
470  if( aErrorLocation )
471  *aErrorLocation = graphic->GetPosition();
472 
473  return false;
474  }
475 
476  // Get next closest segment.
477 
478  graphic = findPoint( prevPt, segList, aTolerance );
479 
480  // If there are no more close segments, check if the board
481  // outline polygon can be closed.
482 
483  if( !graphic )
484  {
485  if( close_enough( startPt, prevPt, aTolerance ) )
486  {
487  // Close the polygon back to start point
488  // aPolygons.Append( startPt ); // not needed
489  }
490  else
491  {
492  if( aErrorText )
493  {
494  msg.Printf( _( "Unable to find segment with an endpoint of (%s, %s)." ),
495  StringFromValue( EDA_UNITS::MILLIMETRES, prevPt.x, true ),
496  StringFromValue( EDA_UNITS::MILLIMETRES, prevPt.y, true ) );
497 
498  *aErrorText << msg << "\n";
499  }
500 
501  if( aErrorLocation )
502  *aErrorLocation = prevPt;
503 
504  return false;
505  }
506  break;
507  }
508  }
509  }
510 
511  while( segList.size() )
512  {
513  // emit a signal layers keepout for every interior polygon left...
514  int hole = aPolygons.NewHole();
515 
516  graphic = (DRAWSEGMENT*) segList[0];
517  segList.erase( segList.begin() );
518 
519  // Both circles and polygons on the edge cuts layer are closed items that
520  // do not connect to other elements, so we process them independently
521  if( graphic->GetShape() == S_POLYGON )
522  {
523  MODULE* module = graphic->GetParentModule(); // NULL for items not in footprints
524  double orientation = module ? module->GetOrientation() : 0.0;
525  VECTOR2I offset = module ? module->GetPosition() : VECTOR2I( 0, 0 );
526 
527  for( auto it = graphic->GetPolyShape().CIterate(); it; it++ )
528  {
529  auto val = *it;
530  RotatePoint( val, orientation );
531  val += offset;
532 
533  aPolygons.Append( val, -1, hole );
534  }
535  }
536  else if( graphic->GetShape() == S_CIRCLE )
537  {
538  // make a circle by segments;
539  wxPoint center = graphic->GetCenter();
540  double angle = 3600.0;
541  wxPoint start = center;
542  int radius = graphic->GetRadius();
543  int steps = std::max<int>( 4, GetArcToSegmentCount( radius, aTolerance, 360.0 ) );
544  wxPoint nextPt;
545 
546  start.x += radius;
547 
548  for( int step = 0; step < steps; ++step )
549  {
550  double rotation = ( angle * step ) / steps;
551  nextPt = start;
552  RotatePoint( &nextPt.x, &nextPt.y, center.x, center.y, rotation );
553  aPolygons.Append( nextPt, -1, hole );
554  }
555  }
556  else if( graphic->GetShape() == S_RECT )
557  {
558  std::vector<wxPoint> pts;
559  graphic->GetRectCorners( &pts );
560 
561  for( const wxPoint& pt : pts )
562  aPolygons.Append( pt, -1, hole );
563  }
564  else
565  {
566  // Polygon start point. Arbitrarily chosen end of the
567  // segment and build the poly from here.
568 
569  wxPoint startPt( graphic->GetEnd() );
570  prevPt = graphic->GetEnd();
571  aPolygons.Append( prevPt, -1, hole );
572 
573  // do not append the other end point yet, this first 'graphic' might be an arc
574  for(;;)
575  {
576  switch( graphic->GetShape() )
577  {
578  case S_SEGMENT:
579  {
580  wxPoint nextPt;
581 
582  // Use the line segment end point furthest away from
583  // prevPt as we assume the other end to be ON prevPt or
584  // very close to it.
585 
586  if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
587  {
588  nextPt = graphic->GetEnd();
589  }
590  else
591  {
592  nextPt = graphic->GetStart();
593  }
594 
595  prevPt = nextPt;
596  aPolygons.Append( prevPt, -1, hole );
597  }
598  break;
599 
600  case S_ARC:
601  // Freerouter does not yet understand arcs, so approximate
602  // an arc with a series of short lines and put those
603  // line segments into the !same! PATH.
604  {
605  wxPoint pstart = graphic->GetArcStart();
606  wxPoint pend = graphic->GetArcEnd();
607  wxPoint pcenter = graphic->GetCenter();
608  double angle = -graphic->GetAngle();
609  int radius = graphic->GetRadius();
610  int steps = GetArcToSegmentCount( radius, aTolerance, angle / 10.0 );
611 
612  if( !close_enough( prevPt, pstart, aTolerance ) )
613  {
614  wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), aTolerance ) );
615 
616  angle = -angle;
617  std::swap( pstart, pend );
618  }
619 
620  wxPoint nextPt;
621 
622  for( int step = 1; step <= steps; ++step )
623  {
624  double rotation = ( angle * step ) / steps;
625 
626  nextPt = pstart;
627  RotatePoint( &nextPt, pcenter, rotation );
628 
629  aPolygons.Append( nextPt, -1, hole );
630  }
631 
632  prevPt = nextPt;
633  }
634  break;
635 
636  case S_CURVE:
637  // We do not support Bezier curves in polygons, so approximate
638  // with a series of short lines and put those
639  // line segments into the !same! PATH.
640  {
641  wxPoint nextPt;
642  bool reverse = false;
643 
644  // Use the end point furthest away from
645  // prevPt as we assume the other end to be ON prevPt or
646  // very close to it.
647 
648  if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
649  nextPt = graphic->GetEnd();
650  else
651  {
652  nextPt = graphic->GetStart();
653  reverse = true;
654  }
655 
656  if( reverse )
657  {
658  for( int jj = graphic->GetBezierPoints().size()-1; jj >= 0; jj-- )
659  aPolygons.Append( graphic->GetBezierPoints()[jj], -1, hole );
660  }
661  else
662  {
663  for( size_t jj = 0; jj < graphic->GetBezierPoints().size(); jj++ )
664  aPolygons.Append( graphic->GetBezierPoints()[jj], -1, hole );
665  }
666 
667  prevPt = nextPt;
668  }
669  break;
670 
671  default:
672  if( aErrorText )
673  {
674  msg.Printf( "Unsupported DRAWSEGMENT type %s.",
675  BOARD_ITEM::ShowShape( graphic->GetShape() ) );
676 
677  *aErrorText << msg << "\n";
678  }
679 
680  if( aErrorLocation )
681  *aErrorLocation = graphic->GetPosition();
682 
683  return false;
684  }
685 
686  // Get next closest segment.
687 
688  graphic = findPoint( prevPt, segList, aTolerance );
689 
690  // If there are no more close segments, check if polygon
691  // can be closed.
692 
693  if( !graphic )
694  {
695  if( close_enough( startPt, prevPt, aTolerance ) )
696  {
697  // Close the polygon back to start point
698  // aPolygons.Append( startPt, -1, hole ); // not needed
699  }
700  else
701  {
702  if( aErrorText )
703  {
704  msg.Printf( _( "Unable to find segment with an endpoint of (%s, %s)." ),
705  StringFromValue( EDA_UNITS::MILLIMETRES, prevPt.x, true ),
706  StringFromValue( EDA_UNITS::MILLIMETRES, prevPt.y, true ) );
707 
708  *aErrorText << msg << "\n";
709  }
710 
711  if( aErrorLocation )
712  *aErrorLocation = prevPt;
713 
714  return false;
715  }
716  break;
717  }
718  }
719  }
720  }
721 
722  // All of the silliness that follows is to work around the segment iterator
723  // while checking for collisions.
724  // TODO: Implement proper segment and point iterators that follow std
725  for( auto seg1 = aPolygons.IterateSegmentsWithHoles(); seg1; seg1++ )
726  {
727  auto seg2 = seg1;
728 
729  for( ++seg2; seg2; seg2++ )
730  {
731  // Check for exact overlapping segments. This is not viewed
732  // as an intersection below
733  if( *seg1 == *seg2 ||
734  ( ( *seg1 ).A == ( *seg2 ).B && ( *seg1 ).B == ( *seg2 ).A ) )
735  {
736  if( aErrorLocation )
737  {
738  aErrorLocation->x = ( *seg1 ).A.x;
739  aErrorLocation->y = ( *seg1 ).A.y;
740  }
741 
742  return false;
743  }
744 
745  if( auto pt = seg1.Get().Intersect( seg2.Get(), true ) )
746  {
747  if( aErrorLocation )
748  {
749  aErrorLocation->x = pt->x;
750  aErrorLocation->y = pt->y;
751  }
752 
753  return false;
754  }
755  }
756  }
757 
758  return true;
759 }
760 
761 #include <class_board.h>
762 #include <collectors.h>
763 
764 /* This function is used to extract a board outlines (3D view, automatic zones build ...)
765  * Any closed outline inside the main outline is a hole
766  * All contours should be closed, i.e. valid closed polygon vertices
767  */
769  wxString* aErrorText, unsigned int aTolerance, wxPoint* aErrorLocation )
770 {
771  PCB_TYPE_COLLECTOR items;
772  bool success = false;
773 
774  // Get all the DRAWSEGMENTS and module graphics into 'items',
775  // then keep only those on layer == Edge_Cuts.
776  static const KICAD_T scan_graphics[] = { PCB_LINE_T, PCB_MODULE_EDGE_T, EOT };
777  items.Collect( aBoard, scan_graphics );
778 
779  // Make a working copy of aSegList, because the list is modified during calculations
780  std::vector< DRAWSEGMENT* > segList;
781 
782  for( int ii = 0; ii < items.GetCount(); ii++ )
783  {
784  if( items[ii]->GetLayer() == Edge_Cuts )
785  segList.push_back( static_cast< DRAWSEGMENT* >( items[ii] ) );
786  }
787 
788  if( segList.size() )
789  {
790  success = ConvertOutlineToPolygon( segList, aOutlines, aErrorText, aTolerance,
791  aErrorLocation );
792  }
793 
794  if( !success || !aOutlines.OutlineCount() )
795  {
796  // Couldn't create a valid polygon outline. Use the board edge cuts bounding box to
797  // create a rectangular outline, or, failing that, the bounding box of the items on
798  // the board.
799 
800  EDA_RECT bbbox = aBoard->GetBoardEdgesBoundingBox();
801 
802  // If null area, uses the global bounding box.
803  if( ( bbbox.GetWidth() ) == 0 || ( bbbox.GetHeight() == 0 ) )
804  bbbox = aBoard->ComputeBoundingBox();
805 
806  // Ensure non null area. If happen, gives a minimal size.
807  if( ( bbbox.GetWidth() ) == 0 || ( bbbox.GetHeight() == 0 ) )
808  bbbox.Inflate( Millimeter2iu( 1.0 ) );
809 
810  aOutlines.RemoveAllContours();
811  aOutlines.NewOutline();
812 
813  wxPoint corner;
814  aOutlines.Append( bbbox.GetOrigin() );
815 
816  corner.x = bbbox.GetOrigin().x;
817  corner.y = bbbox.GetEnd().y;
818  aOutlines.Append( corner );
819 
820  aOutlines.Append( bbbox.GetEnd() );
821 
822  corner.x = bbbox.GetEnd().x;
823  corner.y = bbbox.GetOrigin().y;
824  aOutlines.Append( corner );
825  }
826 
827  return success;
828 }
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.
double GetOrientation() const
Definition: class_module.h:221
wxPoint GetArcStart() const
int OutlineCount() const
Returns the number of outlines in the set
wxPoint GetArcEnd() const
SEGMENT_ITERATOR IterateSegmentsWithHoles()
Returns an iterator object, for all outlines in the set (with holes)
Implementation of conversion functions that require both schematic and board internal units.
const EDA_RECT GetBoardEdgesBoundingBox() const
Function GetBoardEdgesBoundingBox Returns the board bounding box calculated using exclusively the boa...
Definition: class_board.h:824
STROKE_T GetShape() const
polygon (not yet used for tracks, but could be in microwave apps)
void RebuildBezierToSegmentsPointsList(int aMinSegLen)
Rebuild the m_BezierPoints vertex list that approximate the Bezier curve by a list of segments Has me...
int GetWidth() const
Definition: eda_rect.h:119
usual segment : line with rounded ends
const std::vector< wxPoint > & GetBezierPoints() const
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
bool ConvertOutlineToPolygon(std::vector< DRAWSEGMENT * > &aSegList, SHAPE_POLY_SET &aPolygons, wxString *aErrorText, unsigned int aTolerance, wxPoint *aErrorLocation)
Function ConvertOutlineToPolygon build a polygon (with holes) from a DRAWSEGMENT list,...
VECTOR2< int > VECTOR2I
Definition: vector2d.h:594
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
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 ...
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
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...
This file contains miscellaneous commonly used macros and functions.
bool BuildBoardPolygonOutlines(BOARD *aBoard, SHAPE_POLY_SET &aOutlines, wxString *aErrorText, unsigned int aTolerance, wxPoint *aErrorLocation)
wxPoint GetPosition() const override
int GetCount() const
Function GetCount returns the number of objects in the list.
Definition: collector.h:101
const wxPoint GetEnd() const
Definition: eda_rect.h:116
segment with non rounded ends
#define NULL
SHAPE_POLY_SET.
const wxPoint GetOrigin() const
Definition: eda_rect.h:114
Arcs (with rounded ends)
MODULE * GetParentModule() const
Function GetParentModule returns a pointer to the parent module, or NULL if DRAWSEGMENT does not belo...
a few functions useful in geometry calculations.
int GetRadius() const
Function GetRadius returns the radius of this item Has meaning only for arc and circle.
SHAPE_POLY_SET & GetPolyShape()
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_ITERATOR CIterate(int aFirst, int aLast, bool aIterateHoles=false) const
void Collect(BOARD_ITEM *aBoard, const KICAD_T aScanList[])
Collect BOARD_ITEM objects using this class's Inspector method, which does the collection.
Definition: collectors.cpp:596
int GetHeight() const
Definition: eda_rect.h:120
int GetWidth() const
double GetAngle() const
Class to handle a graphic segment.
BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:184
#define _(s)
Definition: 3d_actions.cpp:33
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
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,...
void TransformCircleToPolygon(SHAPE_POLY_SET &aCornerBuffer, wxPoint aCenter, int aRadius, int aError)
Function TransformCircleToPolygon convert a circle to a polygon, using multiple straight lines.
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
static bool GetLayer(MODEL_VRML &aModel, LAYER_NUM layer, VRML_LAYER **vlayer)
EDA_RECT ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Function ComputeBoundingBox calculates the bounding box containing all board items (or board edge seg...
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
wxPoint GetPosition() const override
Definition: class_module.h:216
Collect all BOARD_ITEM objects of a given set of KICAD_T type(s).
Definition: collectors.h:621
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:91
void GetRectCorners(std::vector< wxPoint > *pts) const
static constexpr int Millimeter2iu(double mm)
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
wxString StringFromValue(EDA_UNITS aUnits, double aValue, bool aAddUnitSymbol, bool aUseMils, EDA_DATA_TYPE aType)
Function StringFromValue returns the string from aValue according to units (inch, mm ....
Definition: base_units.cpp:233
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
wxPoint GetCenter() const override
Function GetCenter()
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)