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_SEGMENT:
211  {
212  if( graphic->GetStart().x < xmin.x )
213  {
214  xmin = graphic->GetStart();
215  xmini = i;
216  }
217 
218  if( graphic->GetEnd().x < xmin.x )
219  {
220  xmin = graphic->GetEnd();
221  xmini = i;
222  }
223  }
224  break;
225 
226  case S_ARC:
227  // Freerouter does not yet understand arcs, so approximate
228  // an arc with a series of short lines and put those
229  // line segments into the !same! PATH.
230  {
231  wxPoint pstart = graphic->GetArcStart();
232  wxPoint center = graphic->GetCenter();
233  double angle = -graphic->GetAngle();
234  double radius = graphic->GetRadius();
235  int steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 );
236  wxPoint pt;
237 
238  for( int step = 1; step<=steps; ++step )
239  {
240  double rotation = ( angle * step ) / steps;
241 
242  pt = pstart;
243 
244  RotatePoint( &pt, center, rotation );
245 
246  if( pt.x < xmin.x )
247  {
248  xmin = pt;
249  xmini = i;
250  }
251  }
252  }
253  break;
254 
255  case S_CIRCLE:
256  {
257  wxPoint pt = graphic->GetCenter();
258 
259  // pt has minimum x point
260  pt.x -= graphic->GetRadius();
261 
262  // when the radius <= 0, this is a mal-formed circle. Skip it
263  if( graphic->GetRadius() > 0 && pt.x < xmin.x )
264  {
265  xmin = pt;
266  xmini = i;
267  }
268  }
269  break;
270 
271  case S_CURVE:
272  {
273  graphic->RebuildBezierToSegmentsPointsList( graphic->GetWidth() );
274 
275  for( unsigned int jj = 0; jj < graphic->GetBezierPoints().size(); jj++ )
276  {
277  wxPoint pt = graphic->GetBezierPoints()[jj];
278 
279  if( pt.x < xmin.x )
280  {
281  xmin = pt;
282  xmini = i;
283  }
284  }
285  }
286  break;
287 
288  case S_POLYGON:
289  {
290  const auto poly = graphic->GetPolyShape();
291  MODULE* module = aSegList[0]->GetParentModule();
292  double orientation = module ? module->GetOrientation() : 0.0;
293  VECTOR2I offset = module ? module->GetPosition() : VECTOR2I( 0, 0 );
294 
295  for( auto iter = poly.CIterate(); iter; iter++ )
296  {
297  auto pt = *iter;
298  RotatePoint( pt, orientation );
299  pt += offset;
300 
301  if( pt.x < xmin.x )
302  {
303  xmin.x = pt.x;
304  xmin.y = pt.y;
305  xmini = i;
306  }
307  }
308  }
309  break;
310  default:
311  break;
312  }
313  }
314 
315  // Grab the left most point, assume its on the board's perimeter, and see if we
316  // can put enough graphics together by matching endpoints to formulate a cohesive
317  // polygon.
318 
319  graphic = (DRAWSEGMENT*) segList[xmini];
320 
321  // The first DRAWSEGMENT is in 'graphic', ok to remove it from 'items'
322  segList.erase( segList.begin() + xmini );
323 
324  // Output the outline perimeter as polygon.
325  if( graphic->GetShape() == S_CIRCLE )
326  {
327  int steps = std::max<int>( 4, GetArcToSegmentCount( graphic->GetRadius(), aTolerance, 360.0 ) );
328  TransformCircleToPolygon( aPolygons, graphic->GetCenter(), graphic->GetRadius(), steps );
329  }
330  else if( graphic->GetShape() == S_POLYGON )
331  {
332  MODULE* module = graphic->GetParentModule(); // NULL for items not in footprints
333  double orientation = module ? module->GetOrientation() : 0.0;
334  VECTOR2I offset = module ? module->GetPosition() : VECTOR2I( 0, 0 );
335 
336  aPolygons.NewOutline();
337 
338  for( auto it = graphic->GetPolyShape().CIterate( 0 ); it; it++ )
339  {
340  auto pt = *it;
341  RotatePoint( pt, orientation );
342  pt += offset;
343  aPolygons.Append( pt );
344  }
345  }
346  else
347  {
348  // Polygon start point. Arbitrarily chosen end of the
349  // segment and build the poly from here.
350 
351  wxPoint startPt = wxPoint( graphic->GetEnd() );
352  prevPt = graphic->GetEnd();
353  aPolygons.NewOutline();
354  aPolygons.Append( prevPt );
355 
356  // Do not append the other end point yet of this 'graphic', this first
357  // 'graphic' might be an arc or a curve.
358 
359  for(;;)
360  {
361  switch( graphic->GetShape() )
362  {
363  case S_SEGMENT:
364  {
365  wxPoint nextPt;
366 
367  // Use the line segment end point furthest away from
368  // prevPt as we assume the other end to be ON prevPt or
369  // very close to it.
370 
371  if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
372  nextPt = graphic->GetEnd();
373  else
374  nextPt = graphic->GetStart();
375 
376  aPolygons.Append( nextPt );
377  prevPt = nextPt;
378  }
379  break;
380 
381  case S_ARC:
382  // We do not support arcs in polygons, so approximate
383  // an arc with a series of short lines and put those
384  // line segments into the !same! PATH.
385  {
386  wxPoint pstart = graphic->GetArcStart();
387  wxPoint pend = graphic->GetArcEnd();
388  wxPoint pcenter = graphic->GetCenter();
389  double angle = -graphic->GetAngle();
390  double radius = graphic->GetRadius();
391  int steps = GetArcToSegmentCount( radius, aTolerance, angle / 10.0 );
392 
393  if( !close_enough( prevPt, pstart, aTolerance ) )
394  {
395  wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), aTolerance ) );
396 
397  angle = -angle;
398  std::swap( pstart, pend );
399  }
400 
401  wxPoint nextPt;
402 
403  for( int step = 1; step<=steps; ++step )
404  {
405  double rotation = ( angle * step ) / steps;
406  nextPt = pstart;
407  RotatePoint( &nextPt, pcenter, rotation );
408 
409  aPolygons.Append( nextPt );
410  }
411 
412  prevPt = nextPt;
413  }
414  break;
415 
416  case S_CURVE:
417  // We do not support Bezier curves in polygons, so approximate
418  // with a series of short lines and put those
419  // line segments into the !same! PATH.
420  {
421  wxPoint nextPt;
422  bool reverse = false;
423 
424  // Use the end point furthest away from
425  // prevPt as we assume the other end to be ON prevPt or
426  // very close to it.
427 
428  if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
429  nextPt = graphic->GetEnd();
430  else
431  {
432  nextPt = graphic->GetStart();
433  reverse = true;
434  }
435 
436  if( reverse )
437  {
438  for( int jj = graphic->GetBezierPoints().size()-1; jj >= 0; jj-- )
439  aPolygons.Append( graphic->GetBezierPoints()[jj] );
440  }
441  else
442  {
443  for( size_t jj = 0; jj < graphic->GetBezierPoints().size(); jj++ )
444  aPolygons.Append( graphic->GetBezierPoints()[jj] );
445  }
446 
447  prevPt = nextPt;
448  }
449  break;
450 
451  default:
452  if( aErrorText )
453  {
454  msg.Printf( "Unsupported DRAWSEGMENT type %s.",
455  BOARD_ITEM::ShowShape( graphic->GetShape() ) );
456 
457  *aErrorText << msg << "\n";
458  }
459 
460  if( aErrorLocation )
461  *aErrorLocation = graphic->GetPosition();
462 
463  return false;
464  }
465 
466  // Get next closest segment.
467 
468  graphic = findPoint( prevPt, segList, aTolerance );
469 
470  // If there are no more close segments, check if the board
471  // outline polygon can be closed.
472 
473  if( !graphic )
474  {
475  if( close_enough( startPt, prevPt, aTolerance ) )
476  {
477  // Close the polygon back to start point
478  // aPolygons.Append( startPt ); // not needed
479  }
480  else
481  {
482  if( aErrorText )
483  {
484  msg.Printf( _( "Unable to find segment with an endpoint of (%s, %s)." ),
485  StringFromValue( MILLIMETRES, prevPt.x, true ),
486  StringFromValue( MILLIMETRES, prevPt.y, true ) );
487 
488  *aErrorText << msg << "\n";
489  }
490 
491  if( aErrorLocation )
492  *aErrorLocation = prevPt;
493 
494  return false;
495  }
496  break;
497  }
498  }
499  }
500 
501  while( segList.size() )
502  {
503  // emit a signal layers keepout for every interior polygon left...
504  int hole = aPolygons.NewHole();
505 
506  graphic = (DRAWSEGMENT*) segList[0];
507  segList.erase( segList.begin() );
508 
509  // Both circles and polygons on the edge cuts layer are closed items that
510  // do not connect to other elements, so we process them independently
511  if( graphic->GetShape() == S_POLYGON )
512  {
513  MODULE* module = graphic->GetParentModule(); // NULL for items not in footprints
514  double orientation = module ? module->GetOrientation() : 0.0;
515  VECTOR2I offset = module ? module->GetPosition() : VECTOR2I( 0, 0 );
516 
517  for( auto it = graphic->GetPolyShape().CIterate(); it; it++ )
518  {
519  auto val = *it;
520  RotatePoint( val, orientation );
521  val += offset;
522 
523  aPolygons.Append( val, -1, hole );
524  }
525  }
526  else if( graphic->GetShape() == S_CIRCLE )
527  {
528  // make a circle by segments;
529  wxPoint center = graphic->GetCenter();
530  double angle = 3600.0;
531  wxPoint start = center;
532  int radius = graphic->GetRadius();
533  int steps = std::max<int>( 4, GetArcToSegmentCount( radius, aTolerance, 360.0 ) );
534  wxPoint nextPt;
535 
536  start.x += radius;
537 
538  for( int step = 0; step < steps; ++step )
539  {
540  double rotation = ( angle * step ) / steps;
541  nextPt = start;
542  RotatePoint( &nextPt.x, &nextPt.y, center.x, center.y, rotation );
543  aPolygons.Append( nextPt, -1, hole );
544  }
545  }
546  else
547  {
548  // Polygon start point. Arbitrarily chosen end of the
549  // segment and build the poly from here.
550 
551  wxPoint startPt( graphic->GetEnd() );
552  prevPt = graphic->GetEnd();
553  aPolygons.Append( prevPt, -1, hole );
554 
555  // do not append the other end point yet, this first 'graphic' might be an arc
556  for(;;)
557  {
558  switch( graphic->GetShape() )
559  {
560  case S_SEGMENT:
561  {
562  wxPoint nextPt;
563 
564  // Use the line segment end point furthest away from
565  // prevPt as we assume the other end to be ON prevPt or
566  // very close to it.
567 
568  if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
569  {
570  nextPt = graphic->GetEnd();
571  }
572  else
573  {
574  nextPt = graphic->GetStart();
575  }
576 
577  prevPt = nextPt;
578  aPolygons.Append( prevPt, -1, hole );
579  }
580  break;
581 
582  case S_ARC:
583  // Freerouter does not yet understand arcs, so approximate
584  // an arc with a series of short lines and put those
585  // line segments into the !same! PATH.
586  {
587  wxPoint pstart = graphic->GetArcStart();
588  wxPoint pend = graphic->GetArcEnd();
589  wxPoint pcenter = graphic->GetCenter();
590  double angle = -graphic->GetAngle();
591  int radius = graphic->GetRadius();
592  int steps = GetArcToSegmentCount( radius, aTolerance, angle / 10.0 );
593 
594  if( !close_enough( prevPt, pstart, aTolerance ) )
595  {
596  wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), aTolerance ) );
597 
598  angle = -angle;
599  std::swap( pstart, pend );
600  }
601 
602  wxPoint nextPt;
603 
604  for( int step = 1; step <= steps; ++step )
605  {
606  double rotation = ( angle * step ) / steps;
607 
608  nextPt = pstart;
609  RotatePoint( &nextPt, pcenter, rotation );
610 
611  aPolygons.Append( nextPt, -1, hole );
612  }
613 
614  prevPt = nextPt;
615  }
616  break;
617 
618  case S_CURVE:
619  // We do not support Bezier curves in polygons, so approximate
620  // with a series of short lines and put those
621  // line segments into the !same! PATH.
622  {
623  wxPoint nextPt;
624  bool reverse = false;
625 
626  // Use the end point furthest away from
627  // prevPt as we assume the other end to be ON prevPt or
628  // very close to it.
629 
630  if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
631  nextPt = graphic->GetEnd();
632  else
633  {
634  nextPt = graphic->GetStart();
635  reverse = true;
636  }
637 
638  if( reverse )
639  {
640  for( int jj = graphic->GetBezierPoints().size()-1; jj >= 0; jj-- )
641  aPolygons.Append( graphic->GetBezierPoints()[jj], -1, hole );
642  }
643  else
644  {
645  for( size_t jj = 0; jj < graphic->GetBezierPoints().size(); jj++ )
646  aPolygons.Append( graphic->GetBezierPoints()[jj], -1, hole );
647  }
648 
649  prevPt = nextPt;
650  }
651  break;
652 
653  default:
654  if( aErrorText )
655  {
656  msg.Printf( "Unsupported DRAWSEGMENT type %s.",
657  BOARD_ITEM::ShowShape( graphic->GetShape() ) );
658 
659  *aErrorText << msg << "\n";
660  }
661 
662  if( aErrorLocation )
663  *aErrorLocation = graphic->GetPosition();
664 
665  return false;
666  }
667 
668  // Get next closest segment.
669 
670  graphic = findPoint( prevPt, segList, aTolerance );
671 
672  // If there are no more close segments, check if polygon
673  // can be closed.
674 
675  if( !graphic )
676  {
677  if( close_enough( startPt, prevPt, aTolerance ) )
678  {
679  // Close the polygon back to start point
680  // aPolygons.Append( startPt, -1, hole ); // not needed
681  }
682  else
683  {
684  if( aErrorText )
685  {
686  msg.Printf( _( "Unable to find segment with an endpoint of (%s, %s)." ),
687  StringFromValue( MILLIMETRES, prevPt.x, true ),
688  StringFromValue( MILLIMETRES, prevPt.y, true ) );
689 
690  *aErrorText << msg << "\n";
691  }
692 
693  if( aErrorLocation )
694  *aErrorLocation = prevPt;
695 
696  return false;
697  }
698  break;
699  }
700  }
701  }
702  }
703 
704  // All of the silliness that follows is to work around the segment iterator
705  // while checking for collisions.
706  // TODO: Implement proper segment and point iterators that follow std
707  for( auto seg1 = aPolygons.IterateSegmentsWithHoles(); seg1; seg1++ )
708  {
709  auto seg2 = seg1;
710 
711  for( ++seg2; seg2; seg2++ )
712  {
713  // Check for exact overlapping segments. This is not viewed
714  // as an intersection below
715  if( *seg1 == *seg2 ||
716  ( ( *seg1 ).A == ( *seg2 ).B && ( *seg1 ).B == ( *seg2 ).A ) )
717  {
718  if( aErrorLocation )
719  {
720  aErrorLocation->x = ( *seg1 ).A.x;
721  aErrorLocation->y = ( *seg1 ).A.y;
722  }
723 
724  return false;
725  }
726 
727  if( auto pt = seg1.Get().Intersect( seg2.Get(), true ) )
728  {
729  if( aErrorLocation )
730  {
731  aErrorLocation->x = pt->x;
732  aErrorLocation->y = pt->y;
733  }
734 
735  return false;
736  }
737  }
738  }
739 
740  return true;
741 }
742 
743 #include <class_board.h>
744 #include <collectors.h>
745 
746 /* This function is used to extract a board outlines (3D view, automatic zones build ...)
747  * Any closed outline inside the main outline is a hole
748  * All contours should be closed, i.e. valid closed polygon vertices
749  */
751  wxString* aErrorText, unsigned int aTolerance, wxPoint* aErrorLocation )
752 {
753  PCB_TYPE_COLLECTOR items;
754 
755  // Get all the DRAWSEGMENTS and module graphics into 'items',
756  // then keep only those on layer == Edge_Cuts.
757  static const KICAD_T scan_graphics[] = { PCB_LINE_T, PCB_MODULE_EDGE_T, EOT };
758  items.Collect( aBoard, scan_graphics );
759 
760  // Make a working copy of aSegList, because the list is modified during calculations
761  std::vector< DRAWSEGMENT* > segList;
762 
763  for( int ii = 0; ii < items.GetCount(); ii++ )
764  {
765  if( items[ii]->GetLayer() == Edge_Cuts )
766  segList.push_back( static_cast< DRAWSEGMENT* >( items[ii] ) );
767  }
768 
769  bool success = ConvertOutlineToPolygon( segList, aOutlines, aErrorText, aTolerance, aErrorLocation );
770 
771  if( !success || !aOutlines.OutlineCount() )
772  {
773  // Creates a valid polygon outline is not possible.
774  // So uses the board edge cuts bounding box to create a
775  // rectangular outline
776  // When no edge cuts items, build a contour
777  // from global bounding box
778 
779  EDA_RECT bbbox = aBoard->GetBoardEdgesBoundingBox();
780 
781  // If null area, uses the global bounding box.
782  if( ( bbbox.GetWidth() ) == 0 || ( bbbox.GetHeight() == 0 ) )
783  bbbox = aBoard->ComputeBoundingBox();
784 
785  // Ensure non null area. If happen, gives a minimal size.
786  if( ( bbbox.GetWidth() ) == 0 || ( bbbox.GetHeight() == 0 ) )
787  bbbox.Inflate( Millimeter2iu( 1.0 ) );
788 
789  aOutlines.RemoveAllContours();
790  aOutlines.NewOutline();
791 
792  wxPoint corner;
793  aOutlines.Append( bbbox.GetOrigin() );
794 
795  corner.x = bbbox.GetOrigin().x;
796  corner.y = bbbox.GetEnd().y;
797  aOutlines.Append( corner );
798 
799  aOutlines.Append( bbbox.GetEnd() );
800 
801  corner.x = bbbox.GetEnd().x;
802  corner.y = bbbox.GetOrigin().y;
803  aOutlines.Append( corner );
804  }
805 
806  return success;
807 }
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:188
int OutlineCount() const
Returns the number of outlines in the set
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
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 wxPoint GetCenter() const override
Function GetCenter()
const EDA_RECT GetBoardEdgesBoundingBox() const
Function GetBoardEdgesBoundingBox Returns the board bounding box calculated using exclusively the boa...
Definition: class_board.h:802
STROKE_T GetShape() const
const wxPoint GetArcEnd() const
Class BOARD to handle a board.
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:117
const wxPoint GetPosition() const override
usual segment : line with rounded ends
const std::vector< wxPoint > & GetBezierPoints() const
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:216
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:587
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
#define abs(a)
Definition: auxiliary.h:84
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)
int GetCount() const
Function GetCount returns the number of objects in the list.
Definition: collector.h:114
const wxPoint GetEnd() const
Definition: eda_rect.h:114
Class SHAPE_POLY_SET.
const wxPoint GetOrigin() const
Definition: eda_rect.h:112
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.
const wxPoint & GetArcStart() const
int GetRadius() const
Function GetRadius returns the radius of this item Has meaning only for arc and circle.
SHAPE_POLY_SET & GetPolyShape()
void TransformCircleToPolygon(SHAPE_LINE_CHAIN &aBuffer, wxPoint aCenter, int aRadius, int aCircleToSegmentsCount)
Function TransformCircleToPolygon convert a circle to a polygon, using multiple straight lines.
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:513
int GetHeight() const
Definition: eda_rect.h:118
int GetWidth() const
double GetAngle() const
Class to handle a graphic segment.
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:170
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
size_t i
Definition: json11.cpp:597
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,...
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
static void reverse(privcurve_t *curve)
Definition: trace.cpp:1025
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...
wxString StringFromValue(EDA_UNITS_T aUnits, int aValue, bool aAddUnitSymbol, bool aUseMils)
Function StringFromValue returns the string from aValue according to units (inch, mm ....
Definition: base_units.cpp:210
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
Module description (excepted pads)
Collect all BOARD_ITEM objects of a given set of KICAD_T type(s).
Definition: collectors.h:622
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:91
const wxPoint GetPosition() const override
Definition: class_module.h:183
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)