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 <base_units.h>
39 
40 
53 static unsigned close_ness( const wxPoint& aLeft, const wxPoint& aRight )
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 }
59 
69 inline bool close_enough( const wxPoint& aLeft, const wxPoint& aRight, unsigned aLimit )
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 }
75 
85 inline bool close_st( const wxPoint& aReference, const wxPoint& aFirst, const wxPoint& aSecond )
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 }
91 
92 
102 static DRAWSEGMENT* findPoint( const wxPoint& aPoint, std::vector< DRAWSEGMENT* >& aList, unsigned aLimit )
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 }
169 
170 
181 bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SET& aPolygons,
182  wxString* aErrorText, unsigned int aTolerance )
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 }
645 
646 #include <class_board.h>
647 #include <collectors.h>
648 
649 /* This function is used to extract a board outlines (3D view, automatic zones build ...)
650  * Any closed outline inside the main outline is a hole
651  * All contours should be closed, i.e. valid closed polygon vertices
652  */
654  wxString* aErrorText, unsigned int aTolerance )
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
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.
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
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)
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.
void RebuildBezierToSegmentsPointsList(int aMinSegLen)
Rebuild the m_BezierPoints vertex list that approximate the Bezier curve by a list of segments Has me...
int GetHeight() const
Definition: eda_rect.h:118
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
#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
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...
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:803
STROKE_T GetShape() const
bool BuildBoardPolygonOutlines(BOARD *aBoard, SHAPE_POLY_SET &aOutlines, wxString *aErrorText, unsigned int aTolerance)
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
Class SHAPE_POLY_SET.
Arcs (with rounded ends)
a few functions useful in geometry calculations.
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:498
const wxPoint GetEnd() const
Definition: eda_rect.h:114
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
Class to handle a graphic segment.
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:169
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)
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
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.
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) ...