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-2017 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 <class_drawsegment.h>
36 #include <class_module.h>
37 #include <base_units.h>
40 
41 
54 static unsigned close_ness( const wxPoint& aLeft, const wxPoint& aRight )
55 {
56  // Don't need an accurate distance calculation, just something
57  // approximating it, for relative ordering.
58  return unsigned( std::abs( aLeft.x - aRight.x ) + abs( aLeft.y - aRight.y ) );
59 }
60 
70 inline bool close_enough( const wxPoint& aLeft, const wxPoint& aRight, unsigned aLimit )
71 {
72  // We don't use an accurate distance calculation, just something
73  // approximating it, since aLimit is non-exact anyway except when zero.
74  return close_ness( aLeft, aRight ) <= aLimit;
75 }
76 
86 inline bool close_st( const wxPoint& aReference, const wxPoint& aFirst, const wxPoint& aSecond )
87 {
88  // We don't use an accurate distance calculation, just something
89  // approximating to find the closest to the reference.
90  return close_ness( aReference, aFirst ) <= close_ness( aReference, aSecond );
91 }
92 
93 
103 static DRAWSEGMENT* findPoint( const wxPoint& aPoint, std::vector< DRAWSEGMENT* >& aList, unsigned aLimit )
104 {
105  unsigned min_d = INT_MAX;
106  int ndx_min = 0;
107 
108  // find the point closest to aPoint and perhaps exactly matching aPoint.
109  for( size_t i = 0; i < aList.size(); ++i )
110  {
111  DRAWSEGMENT* graphic = aList[i];
112  unsigned d;
113 
114  switch( graphic->GetShape() )
115  {
116  case S_ARC:
117  if( aPoint == graphic->GetArcStart() || aPoint == graphic->GetArcEnd() )
118  {
119  aList.erase( aList.begin() + i );
120  return graphic;
121  }
122 
123  d = close_ness( aPoint, graphic->GetArcStart() );
124  if( d < min_d )
125  {
126  min_d = d;
127  ndx_min = i;
128  }
129 
130  d = close_ness( aPoint, graphic->GetArcEnd() );
131  if( d < min_d )
132  {
133  min_d = d;
134  ndx_min = i;
135  }
136  break;
137 
138  default:
139  if( aPoint == graphic->GetStart() || aPoint == graphic->GetEnd() )
140  {
141  aList.erase( aList.begin() + i );
142  return graphic;
143  }
144 
145  d = close_ness( aPoint, graphic->GetStart() );
146  if( d < min_d )
147  {
148  min_d = d;
149  ndx_min = i;
150  }
151 
152  d = close_ness( aPoint, graphic->GetEnd() );
153  if( d < min_d )
154  {
155  min_d = d;
156  ndx_min = i;
157  }
158  }
159  }
160 
161  if( min_d <= aLimit )
162  {
163  DRAWSEGMENT* graphic = aList[ndx_min];
164  aList.erase( aList.begin() + ndx_min );
165  return graphic;
166  }
167 
168  return NULL;
169 }
170 
171 
183 bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SET& aPolygons,
184  wxString* aErrorText, unsigned int aTolerance, wxPoint* aErrorLocation )
185 {
186  if( aSegList.size() == 0 )
187  return true;
188 
189  wxString msg;
190 
191  // Make a working copy of aSegList, because the list is modified during calculations
192  std::vector< DRAWSEGMENT* > segList = aSegList;
193 
194  DRAWSEGMENT* graphic;
195  wxPoint prevPt;
196 
197  // Find edge point with minimum x, this should be in the outer polygon
198  // which will define the perimeter Edge.Cuts polygon.
199  wxPoint xmin = wxPoint( INT_MAX, 0 );
200  int xmini = 0;
201 
202  for( size_t i = 0; i < segList.size(); i++ )
203  {
204  graphic = (DRAWSEGMENT*) segList[i];
205 
206  switch( graphic->GetShape() )
207  {
208  case S_SEGMENT:
209  {
210  if( graphic->GetStart().x < xmin.x )
211  {
212  xmin = graphic->GetStart();
213  xmini = i;
214  }
215 
216  if( graphic->GetEnd().x < xmin.x )
217  {
218  xmin = graphic->GetEnd();
219  xmini = i;
220  }
221  }
222  break;
223 
224  case S_ARC:
225  // Freerouter does not yet understand arcs, so approximate
226  // an arc with a series of short lines and put those
227  // line segments into the !same! PATH.
228  {
229  wxPoint pstart = graphic->GetArcStart();
230  wxPoint center = graphic->GetCenter();
231  double angle = -graphic->GetAngle();
232  double radius = graphic->GetRadius();
233  int steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 );
234  wxPoint pt;
235 
236  for( int step = 1; step<=steps; ++step )
237  {
238  double rotation = ( angle * step ) / steps;
239 
240  pt = pstart;
241 
242  RotatePoint( &pt, center, rotation );
243 
244  if( pt.x < xmin.x )
245  {
246  xmin = pt;
247  xmini = i;
248  }
249  }
250  }
251  break;
252 
253  case S_CIRCLE:
254  {
255  wxPoint pt = graphic->GetCenter();
256 
257  // pt has minimum x point
258  pt.x -= graphic->GetRadius();
259 
260  // when the radius <= 0, this is a mal-formed circle. Skip it
261  if( graphic->GetRadius() > 0 && pt.x < xmin.x )
262  {
263  xmin = pt;
264  xmini = i;
265  }
266  }
267  break;
268 
269  case S_CURVE:
270  {
271  graphic->RebuildBezierToSegmentsPointsList( graphic->GetWidth() );
272 
273  for( unsigned int jj = 0; jj < graphic->GetBezierPoints().size(); jj++ )
274  {
275  wxPoint pt = graphic->GetBezierPoints()[jj];
276 
277  if( pt.x < xmin.x )
278  {
279  xmin = pt;
280  xmini = i;
281  }
282  }
283  }
284  break;
285 
286  case S_POLYGON:
287  {
288  const auto poly = graphic->GetPolyShape();
289  MODULE* module = aSegList[0]->GetParentModule();
290  double orientation = module ? module->GetOrientation() : 0.0;
291  VECTOR2I offset = module ? module->GetPosition() : VECTOR2I( 0, 0 );
292 
293  for( auto iter = poly.CIterate(); iter; iter++ )
294  {
295  auto pt = *iter;
296  RotatePoint( pt, orientation );
297  pt += offset;
298 
299  if( pt.x < xmin.x )
300  {
301  xmin.x = pt.x;
302  xmin.y = pt.y;
303  xmini = i;
304  }
305  }
306  }
307  break;
308  default:
309  break;
310  }
311  }
312 
313  // Grab the left most point, assume its on the board's perimeter, and see if we
314  // can put enough graphics together by matching endpoints to formulate a cohesive
315  // polygon.
316 
317  graphic = (DRAWSEGMENT*) segList[xmini];
318 
319  // The first DRAWSEGMENT is in 'graphic', ok to remove it from 'items'
320  segList.erase( segList.begin() + xmini );
321 
322  // Output the Edge.Cuts perimeter as circle or polygon.
323  if( graphic->GetShape() == S_CIRCLE )
324  {
325  int steps = GetArcToSegmentCount( graphic->GetRadius(), ARC_LOW_DEF, 360.0 );
326  TransformCircleToPolygon( aPolygons, graphic->GetCenter(), graphic->GetRadius(), steps );
327  }
328  else if( graphic->GetShape() == S_POLYGON )
329  {
330  MODULE* module = graphic->GetParentModule(); // NULL for items not in footprints
331  double orientation = module ? module->GetOrientation() : 0.0;
332  VECTOR2I offset = module ? module->GetPosition() : VECTOR2I( 0, 0 );
333 
334  aPolygons.NewOutline();
335 
336  for( auto it = graphic->GetPolyShape().CIterate( 0 ); it; it++ )
337  {
338  auto pt = *it;
339  RotatePoint( pt, orientation );
340  pt += offset;
341  aPolygons.Append( pt );
342  }
343  }
344  else
345  {
346  // Polygon start point. Arbitrarily chosen end of the
347  // segment and build the poly from here.
348 
349  wxPoint startPt = wxPoint( graphic->GetEnd() );
350  prevPt = graphic->GetEnd();
351  aPolygons.NewOutline();
352  aPolygons.Append( prevPt );
353 
354  // Do not append the other end point yet of this 'graphic', this first
355  // 'graphic' might be an arc or a curve.
356 
357  for(;;)
358  {
359  switch( graphic->GetShape() )
360  {
361  case S_SEGMENT:
362  {
363  wxPoint nextPt;
364 
365  // Use the line segment end point furthest away from
366  // prevPt as we assume the other end to be ON prevPt or
367  // very close to it.
368 
369  if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
370  nextPt = graphic->GetEnd();
371  else
372  nextPt = graphic->GetStart();
373 
374  aPolygons.Append( nextPt );
375  prevPt = nextPt;
376  }
377  break;
378 
379  case S_ARC:
380  // We do not support arcs in polygons, so approximate
381  // an arc with a series of short lines and put those
382  // line segments into the !same! PATH.
383  {
384  wxPoint pstart = graphic->GetArcStart();
385  wxPoint pend = graphic->GetArcEnd();
386  wxPoint pcenter = graphic->GetCenter();
387  double angle = -graphic->GetAngle();
388  double radius = graphic->GetRadius();
389  int steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 );
390 
391  if( !close_enough( prevPt, pstart, aTolerance ) )
392  {
393  wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), aTolerance ) );
394 
395  angle = -angle;
396  std::swap( pstart, pend );
397  }
398 
399  wxPoint nextPt;
400 
401  for( int step = 1; step<=steps; ++step )
402  {
403  double rotation = ( angle * step ) / steps;
404  nextPt = pstart;
405  RotatePoint( &nextPt, pcenter, rotation );
406 
407  aPolygons.Append( nextPt );
408  }
409 
410  prevPt = nextPt;
411  }
412  break;
413 
414  case S_CURVE:
415  // We do not support Bezier curves in polygons, so approximate
416  // with a series of short lines and put those
417  // line segments into the !same! PATH.
418  {
419  wxPoint nextPt;
420  bool reverse = false;
421 
422  // Use the end point furthest away from
423  // prevPt as we assume the other end to be ON prevPt or
424  // very close to it.
425 
426  if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
427  nextPt = graphic->GetEnd();
428  else
429  {
430  nextPt = graphic->GetStart();
431  reverse = true;
432  }
433 
434  if( reverse )
435  {
436  for( int jj = graphic->GetBezierPoints().size()-1; jj >= 0; jj-- )
437  aPolygons.Append( graphic->GetBezierPoints()[jj] );
438  }
439  else
440  {
441  for( size_t jj = 0; jj < graphic->GetBezierPoints().size(); jj++ )
442  aPolygons.Append( graphic->GetBezierPoints()[jj] );
443  }
444 
445  prevPt = nextPt;
446  }
447  break;
448 
449  default:
450  if( aErrorText )
451  {
452  msg.Printf( "Unsupported DRAWSEGMENT type %s.",
453  BOARD_ITEM::ShowShape( graphic->GetShape() ) );
454 
455  *aErrorText << msg << "\n";
456  }
457 
458  if( aErrorLocation )
459  *aErrorLocation = graphic->GetPosition();
460 
461  return false;
462  }
463 
464  // Get next closest segment.
465 
466  graphic = findPoint( prevPt, segList, aTolerance );
467 
468  // If there are no more close segments, check if the board
469  // outline polygon can be closed.
470 
471  if( !graphic )
472  {
473  if( close_enough( startPt, prevPt, aTolerance ) )
474  {
475  // Close the polygon back to start point
476  // aPolygons.Append( startPt ); // not needed
477  }
478  else
479  {
480  if( aErrorText )
481  {
482  msg.Printf( _( "Unable to find segment with an endpoint of (%s, %s)." ),
483  StringFromValue( MILLIMETRES, prevPt.x, true ),
484  StringFromValue( MILLIMETRES, prevPt.y, true ) );
485 
486  *aErrorText << msg << "\n";
487  }
488 
489  if( aErrorLocation )
490  *aErrorLocation = prevPt;
491 
492  return false;
493  }
494  break;
495  }
496  }
497  }
498 
499  while( segList.size() )
500  {
501  // emit a signal layers keepout for every interior polygon left...
502  int hole = aPolygons.NewHole();
503 
504  graphic = (DRAWSEGMENT*) segList[0];
505  segList.erase( segList.begin() );
506 
507  // Both circles and polygons on the edge cuts layer are closed items that
508  // do not connect to other elements, so we process them independently
509  if( graphic->GetShape() == S_POLYGON )
510  {
511  MODULE* module = graphic->GetParentModule(); // NULL for items not in footprints
512  double orientation = module ? module->GetOrientation() : 0.0;
513  VECTOR2I offset = module ? module->GetPosition() : VECTOR2I( 0, 0 );
514 
515  for( auto it = graphic->GetPolyShape().CIterate(); it; it++ )
516  {
517  auto val = *it;
518  RotatePoint( val, orientation );
519  val += offset;
520 
521  aPolygons.Append( val, -1, hole );
522  }
523  }
524  else if( graphic->GetShape() == S_CIRCLE )
525  {
526  // make a circle by segments;
527  wxPoint center = graphic->GetCenter();
528  double angle = 3600.0;
529  wxPoint start = center;
530  int radius = graphic->GetRadius();
531  int steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, 360.0 );
532  wxPoint nextPt;
533 
534  start.x += radius;
535 
536  for( int step = 0; step < steps; ++step )
537  {
538  double rotation = ( angle * step ) / steps;
539  nextPt = start;
540  RotatePoint( &nextPt.x, &nextPt.y, center.x, center.y, rotation );
541  aPolygons.Append( nextPt, -1, hole );
542  }
543  }
544  else
545  {
546  // Polygon start point. Arbitrarily chosen end of the
547  // segment and build the poly from here.
548 
549  wxPoint startPt( graphic->GetEnd() );
550  prevPt = graphic->GetEnd();
551  aPolygons.Append( prevPt, -1, hole );
552 
553  // do not append the other end point yet, this first 'graphic' might be an arc
554  for(;;)
555  {
556  switch( graphic->GetShape() )
557  {
558  case S_SEGMENT:
559  {
560  wxPoint nextPt;
561 
562  // Use the line segment end point furthest away from
563  // prevPt as we assume the other end to be ON prevPt or
564  // very close to it.
565 
566  if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
567  {
568  nextPt = graphic->GetEnd();
569  }
570  else
571  {
572  nextPt = graphic->GetStart();
573  }
574 
575  prevPt = nextPt;
576  aPolygons.Append( prevPt, -1, hole );
577  }
578  break;
579 
580  case S_ARC:
581  // Freerouter does not yet understand arcs, so approximate
582  // an arc with a series of short lines and put those
583  // line segments into the !same! PATH.
584  {
585  wxPoint pstart = graphic->GetArcStart();
586  wxPoint pend = graphic->GetArcEnd();
587  wxPoint pcenter = graphic->GetCenter();
588  double angle = -graphic->GetAngle();
589  int radius = graphic->GetRadius();
590  int steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 );
591 
592  if( !close_enough( prevPt, pstart, aTolerance ) )
593  {
594  wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), aTolerance ) );
595 
596  angle = -angle;
597  std::swap( pstart, pend );
598  }
599 
600  wxPoint nextPt;
601 
602  for( int step = 1; step <= steps; ++step )
603  {
604  double rotation = ( angle * step ) / steps;
605 
606  nextPt = pstart;
607  RotatePoint( &nextPt, pcenter, rotation );
608 
609  aPolygons.Append( nextPt, -1, hole );
610  }
611 
612  prevPt = nextPt;
613  }
614  break;
615 
616  case S_CURVE:
617  // We do not support Bezier curves in polygons, so approximate
618  // with a series of short lines and put those
619  // line segments into the !same! PATH.
620  {
621  wxPoint nextPt;
622  bool reverse = false;
623 
624  // Use the end point furthest away from
625  // prevPt as we assume the other end to be ON prevPt or
626  // very close to it.
627 
628  if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
629  nextPt = graphic->GetEnd();
630  else
631  {
632  nextPt = graphic->GetStart();
633  reverse = true;
634  }
635 
636  if( reverse )
637  {
638  for( int jj = graphic->GetBezierPoints().size()-1; jj >= 0; jj-- )
639  aPolygons.Append( graphic->GetBezierPoints()[jj], -1, hole );
640  }
641  else
642  {
643  for( size_t jj = 0; jj < graphic->GetBezierPoints().size(); jj++ )
644  aPolygons.Append( graphic->GetBezierPoints()[jj], -1, hole );
645  }
646 
647  prevPt = nextPt;
648  }
649  break;
650 
651  default:
652  if( aErrorText )
653  {
654  msg.Printf( "Unsupported DRAWSEGMENT type %s.",
655  BOARD_ITEM::ShowShape( graphic->GetShape() ) );
656 
657  *aErrorText << msg << "\n";
658  }
659 
660  if( aErrorLocation )
661  *aErrorLocation = graphic->GetPosition();
662 
663  return false;
664  }
665 
666  // Get next closest segment.
667 
668  graphic = findPoint( prevPt, segList, aTolerance );
669 
670  // If there are no more close segments, check if polygon
671  // can be closed.
672 
673  if( !graphic )
674  {
675  if( close_enough( startPt, prevPt, aTolerance ) )
676  {
677  // Close the polygon back to start point
678  // aPolygons.Append( startPt, -1, hole ); // not needed
679  }
680  else
681  {
682  if( aErrorText )
683  {
684  msg.Printf( _( "Unable to find segment with an endpoint of (%s, %s)." ),
685  StringFromValue( MILLIMETRES, prevPt.x, true ),
686  StringFromValue( MILLIMETRES, prevPt.y, true ) );
687 
688  *aErrorText << msg << "\n";
689  }
690 
691  if( aErrorLocation )
692  *aErrorLocation = prevPt;
693 
694  return false;
695  }
696  break;
697  }
698  }
699  }
700  }
701 
702  return true;
703 }
704 
705 #include <class_board.h>
706 #include <collectors.h>
707 
708 /* This function is used to extract a board outlines (3D view, automatic zones build ...)
709  * Any closed outline inside the main outline is a hole
710  * All contours should be closed, i.e. valid closed polygon vertices
711  */
713  wxString* aErrorText, unsigned int aTolerance, wxPoint* aErrorLocation )
714 {
715  PCB_TYPE_COLLECTOR items;
716 
717  // Get all the DRAWSEGMENTS and module graphics into 'items',
718  // then keep only those on layer == Edge_Cuts.
719  static const KICAD_T scan_graphics[] = { PCB_LINE_T, PCB_MODULE_EDGE_T, EOT };
720  items.Collect( aBoard, scan_graphics );
721 
722  // Make a working copy of aSegList, because the list is modified during calculations
723  std::vector< DRAWSEGMENT* > segList;
724 
725  for( int ii = 0; ii < items.GetCount(); ii++ )
726  {
727  if( items[ii]->GetLayer() == Edge_Cuts )
728  segList.push_back( static_cast< DRAWSEGMENT* >( items[ii] ) );
729  }
730 
731  bool success = ConvertOutlineToPolygon( segList, aOutlines, aErrorText, aTolerance, aErrorLocation );
732 
733  if( !success || !aOutlines.OutlineCount() )
734  {
735  // Creates a valid polygon outline is not possible.
736  // So uses the board edge cuts bounding box to create a
737  // rectangular outline
738  // When no edge cuts items, build a contour
739  // from global bounding box
740 
741  EDA_RECT bbbox = aBoard->GetBoardEdgesBoundingBox();
742 
743  // If null area, uses the global bounding box.
744  if( ( bbbox.GetWidth() ) == 0 || ( bbbox.GetHeight() == 0 ) )
745  bbbox = aBoard->ComputeBoundingBox();
746 
747  // Ensure non null area. If happen, gives a minimal size.
748  if( ( bbbox.GetWidth() ) == 0 || ( bbbox.GetHeight() == 0 ) )
749  bbbox.Inflate( Millimeter2iu( 1.0 ) );
750 
751  aOutlines.RemoveAllContours();
752  aOutlines.NewOutline();
753 
754  wxPoint corner;
755  aOutlines.Append( bbbox.GetOrigin() );
756 
757  corner.x = bbbox.GetOrigin().x;
758  corner.y = bbbox.GetEnd().y;
759  aOutlines.Append( corner );
760 
761  aOutlines.Append( bbbox.GetEnd() );
762 
763  corner.x = bbbox.GetEnd().x;
764  corner.y = bbbox.GetOrigin().y;
765  aOutlines.Append( corner );
766  }
767 
768  return success;
769 }
int GetCount() const
Function GetCount returns the number of objects in the list.
Definition: collector.h:114
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.
const wxPoint GetOrigin() const
Definition: eda_rect.h:112
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
Implementation of conversion functions that require both schematic and board internal units...
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...
EDA_RECT ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Function ComputeBoundingBox calculates the bounding box containing all board items (or board edge seg...
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...
CONST_ITERATOR CIterate(int aFirst, int aLast, bool aIterateHoles=false) const
int GetHeight() const
Definition: eda_rect.h:118
const wxPoint GetPosition() const override
usual segment : line with rounded ends
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:216
int OutlineCount() const
Returns the number of outlines in the set
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, which is expected to be a outline, therefore a closed main outline with perhaps closed inner outlines.
VECTOR2< int > VECTOR2I
Definition: vector2d.h:587
#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.
const wxPoint & GetArcStart() const
const EDA_RECT GetBoardEdgesBoundingBox() const
Function GetBoardEdgesBoundingBox Returns the board bounding box calculated using exclusively the boa...
Definition: class_board.h:810
bool BuildBoardPolygonOutlines(BOARD *aBoard, SHAPE_POLY_SET &aOutlines, wxString *aErrorText, unsigned int aTolerance, wxPoint *aErrorLocation)
STROKE_T GetShape() const
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
double GetOrientation() const
Definition: class_module.h:188
Class SHAPE_POLY_SET.
Arcs (with rounded ends)
a few functions useful in geometry calculations.
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
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:522
const wxPoint GetEnd() const
Definition: eda_rect.h:114
const std::vector< wxPoint > & GetBezierPoints() 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:171
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.
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...
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
static void reverse(privcurve_t *curve)
Definition: trace.cpp:1025
int GetWidth() const
Definition: eda_rect.h:117
int GetWidth() const
static bool GetLayer(MODEL_VRML &aModel, LAYER_NUM layer, VRML_LAYER **vlayer)
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
MODULE * GetParentModule() const
Function GetParentModule returns a pointer to the parent module, or NULL if DRAWSEGMENT does not belo...
Module description (excepted pads)
Collect all BOARD_ITEM objects of a given set of KICAD_T type(s).
Definition: collectors.h:627
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:91
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.
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) ...