KiCad PCB EDA Suite
convert_basic_shapes_to_polygon.h File Reference
#include <geometry/shape_poly_set.h>
#include <geometry/geometry_utils.h>
#include <wx/gdicmn.h>

Go to the source code of this file.

Enumerations

enum  RECT_CHAMFER_POSITIONS : int {
  RECT_NO_CHAMFER = 0, RECT_CHAMFER_TOP_LEFT = 1, RECT_CHAMFER_TOP_RIGHT = 2, RECT_CHAMFER_BOTTOM_LEFT = 4,
  RECT_CHAMFER_BOTTOM_RIGHT = 8, RECT_CHAMFER_ALL
}
 

Functions

void TransformCircleToPolygon (SHAPE_POLY_SET &aCornerBuffer, wxPoint aCenter, int aRadius, int aError, ERROR_LOC aErrorLoc)
 Function TransformCircleToPolygon convert a circle to a polygon, using multiple straight lines. More...
 
void TransformOvalToPolygon (SHAPE_POLY_SET &aCornerBuffer, wxPoint aStart, wxPoint aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc)
 convert a oblong shape to a polygon, using multiple segments It is similar to TransformRoundedEndsSegmentToPolygon, but the polygon is outside the actual oblong shape (a segment with rounded ends) It is suitable to create oblong clearance areas. More...
 
void TransformRoundChamferedRectToPolygon (SHAPE_POLY_SET &aCornerBuffer, const wxPoint &aPosition, const wxSize &aSize, double aRotation, int aCornerRadius, double aChamferRatio, int aChamferCorners, int aError, ERROR_LOC aErrorLoc)
 convert a rectangle with rounded corners and/or chamfered corners to a polygon Convert rounded corners arcs to multiple straight lines. More...
 
void TransformArcToPolygon (SHAPE_POLY_SET &aCornerBuffer, wxPoint aStart, wxPoint aMid, wxPoint aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc)
 Function TransformArcToPolygon Creates a polygon from an Arc Convert arcs to multiple straight segments. More...
 
void TransformRingToPolygon (SHAPE_POLY_SET &aCornerBuffer, wxPoint aCentre, int aRadius, int aWidth, int aError, ERROR_LOC aErrorLoc)
 Function TransformRingToPolygon Creates a polygon from a ring Convert arcs to multiple straight segments. More...
 

Enumeration Type Documentation

◆ RECT_CHAMFER_POSITIONS

Function Documentation

◆ TransformArcToPolygon()

void TransformArcToPolygon ( SHAPE_POLY_SET aCornerBuffer,
wxPoint  aStart,
wxPoint  aMid,
wxPoint  aEnd,
int  aWidth,
int  aError,
ERROR_LOC  aErrorLoc 
)

Function TransformArcToPolygon Creates a polygon from an Arc Convert arcs to multiple straight segments.

Parameters
aCornerBuffer= a buffer to store the polygon
aCentre= centre of the arc or circle
aStart= start point of the arc, or a point on the circle
aArcAngle= arc angle in 0.1 degrees. For a circle, aArcAngle = 3600
aWidth= width (thickness) of the line
aError= the IU allowed for error in approximation
aErrorLoc= should the approximation error be placed outside or inside the polygon?

Definition at line 352 of file convert_basic_shapes_to_polygon.cpp.

354 {
355  SHAPE_ARC arc( aStart, aMid, aEnd, aWidth );
356  SHAPE_LINE_CHAIN arcSpine = arc.ConvertToPolyline( aError );
357 
358  if( aErrorLoc == ERROR_OUTSIDE )
359  aWidth += 2 * aError;
360  else
361  aWidth -= 2 * aError;
362 
363  for( int ii = 0; ii < arcSpine.GetSegmentCount(); ++ii )
364  {
365  SEG seg = arcSpine.GetSegment( ii );
366 
367  // Note that the error here is only for the rounded ends; we still need to shrink or
368  // expand the width above for the segments themselves.
369  TransformOvalToPolygon( aCornerBuffer, (wxPoint) seg.A, (wxPoint) seg.B, aWidth, aError,
370  aErrorLoc );
371  }
372 }
virtual size_t GetSegmentCount() const override
virtual const SEG GetSegment(int aIndex) const override
Definition: seg.h:39
SHAPE_LINE_CHAIN.
VECTOR2I A
Definition: seg.h:47
void TransformOvalToPolygon(SHAPE_POLY_SET &aCornerBuffer, wxPoint aStart, wxPoint aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc)
convert a oblong shape to a polygon, using multiple segments It is similar to TransformRoundedEndsSeg...
VECTOR2I B
Definition: seg.h:48

References SEG::A, SEG::B, SHAPE_ARC::ConvertToPolyline(), ERROR_OUTSIDE, SHAPE_LINE_CHAIN::GetSegment(), SHAPE_LINE_CHAIN::GetSegmentCount(), and TransformOvalToPolygon().

Referenced by TRACK::TransformShapeWithClearanceToPolygon(), and PCB_SHAPE::TransformShapeWithClearanceToPolygon().

◆ TransformCircleToPolygon()

void TransformCircleToPolygon ( SHAPE_POLY_SET aCornerBuffer,
wxPoint  aCenter,
int  aRadius,
int  aError,
ERROR_LOC  aErrorLoc 
)

Function TransformCircleToPolygon convert a circle to a polygon, using multiple straight lines.

Parameters
aCornerBuffer= a buffer to store the polygon
aCenter= the center of the circle
aRadius= the radius of the circle
aError= the IU allowed for error in approximation
aErrorLoc= should the approximation error be placed outside or inside the polygon?

Definition at line 65 of file convert_basic_shapes_to_polygon.cpp.

67 {
68  wxPoint corner_position;
69  int numSegs = GetArcToSegmentCount( aRadius, aError, 360.0 );
70  int delta = 3600 / numSegs; // rotate angle in 0.1 degree
71  int radius = aRadius;
72 
73  if( aErrorLoc == ERROR_OUTSIDE )
74  radius += GetCircleToPolyCorrection( aError );
75 
76  aCornerBuffer.NewOutline();
77 
78  for( int angle = 0; angle < 3600; angle += delta )
79  {
80  corner_position.x = radius;
81  corner_position.y = 0;
82  RotatePoint( &corner_position, angle );
83  corner_position += aCenter;
84  aCornerBuffer.Append( corner_position.x, corner_position.y );
85  }
86 
87  // Finish circle
88  corner_position.x = radius;
89  corner_position.y = 0;
90  corner_position += aCenter;
91  aCornerBuffer.Append( corner_position.x, corner_position.y );
92 }
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
int GetCircleToPolyCorrection(int aMaxError)
int NewOutline()
Creates a new empty polygon in the set and returns its index
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
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)

References PNS::angle(), SHAPE_POLY_SET::Append(), ERROR_OUTSIDE, GetArcToSegmentCount(), GetCircleToPolyCorrection(), SHAPE_POLY_SET::NewOutline(), and RotatePoint().

Referenced by ZONE_FILLER::addHatchFillTypeOnZone(), addHoleToPolygon(), ZONE_FILLER::buildCopperItemClearances(), ConvertOutlineToPolygon(), D_CODE::ConvertShapeToPolygon(), BOARD_ADAPTER::createLayers(), AM_PRIMITIVE::DrawBasicShape(), PAD::MergePrimitivesAsPolygon(), TRACK::TransformShapeWithClearanceToPolygon(), PCB_SHAPE::TransformShapeWithClearanceToPolygon(), and PAD::TransformShapeWithClearanceToPolygon().

◆ TransformOvalToPolygon()

void TransformOvalToPolygon ( SHAPE_POLY_SET aCornerBuffer,
wxPoint  aStart,
wxPoint  aEnd,
int  aWidth,
int  aError,
ERROR_LOC  aErrorLoc 
)

convert a oblong shape to a polygon, using multiple segments It is similar to TransformRoundedEndsSegmentToPolygon, but the polygon is outside the actual oblong shape (a segment with rounded ends) It is suitable to create oblong clearance areas.

because multiple segments create a smaller area than the circle, the radius of the circle to approximate must be bigger ( radius*aCorrectionFactor) to create segments outside the circle.

Parameters
aCornerBuffer= a buffer to store the polygon
aStart= the first point of the segment
aEnd= the second point of the segment
aWidth= the width of the segment
aError= the IU allowed for error in approximation
aErrorLoc= should the approximation error be placed outside or inside the polygon?

Definition at line 95 of file convert_basic_shapes_to_polygon.cpp.

97 {
98  // To build the polygonal shape outside the actual shape, we use a bigger
99  // radius to build rounded ends.
100  // However, the width of the segment is too big.
101  // so, later, we will clamp the polygonal shape with the bounding box
102  // of the segment.
103  int radius = aWidth / 2;
104  int numSegs = GetArcToSegmentCount( radius, aError, 360.0 );
105  int delta = 3600 / numSegs; // rotate angle in 0.1 degree
106  int correction = GetCircleToPolyCorrection( aError );
107 
108  if( aErrorLoc == ERROR_OUTSIDE )
109  radius += correction;
110 
111  // end point is the coordinate relative to aStart
112  wxPoint endp = aEnd - aStart;
113  wxPoint startp = aStart;
114  wxPoint corner;
115  SHAPE_POLY_SET polyshape;
116 
117  polyshape.NewOutline();
118 
119  // normalize the position in order to have endp.x >= 0
120  // it makes calculations more easy to understand
121  if( endp.x < 0 )
122  {
123  endp = aStart - aEnd;
124  startp = aEnd;
125  }
126 
127  // delta_angle is in radian
128  double delta_angle = atan2( (double)endp.y, (double)endp.x );
129  int seg_len = KiROUND( EuclideanNorm( endp ) );
130 
131  // Compute the outlines of the segment, and creates a polygon
132  // Note: the polygonal shape is built from the equivalent horizontal
133  // segment starting at {0,0}, and ending at {seg_len,0}
134 
135  // add right rounded end:
136 
137  for( int angle = 0; angle < 1800; angle += delta )
138  {
139  corner = wxPoint( 0, radius );
140  RotatePoint( &corner, angle );
141  corner.x += seg_len;
142  polyshape.Append( corner.x, corner.y );
143  }
144 
145  // Finish arc:
146  corner = wxPoint( seg_len, -radius );
147  polyshape.Append( corner.x, corner.y );
148 
149  // add left rounded end:
150  for( int angle = 0; angle < 1800; angle += delta )
151  {
152  corner = wxPoint( 0, -radius );
153  RotatePoint( &corner, angle );
154  polyshape.Append( corner.x, corner.y );
155  }
156 
157  // Finish arc:
158  corner = wxPoint( 0, radius );
159  polyshape.Append( corner.x, corner.y );
160 
161  // Now trim the edges of the polygonal shape which will be slightly outside the
162  // track width.
163  SHAPE_POLY_SET bbox;
164  bbox.NewOutline();
165  // Build the bbox (a horizontal rectangle).
166  int halfwidth = aWidth / 2; // Use the exact segment width for the bbox height
167  corner.x = -radius - 2; // use a bbox width slightly bigger to avoid
168  // creating useless corner at segment ends
169  corner.y = halfwidth;
170  bbox.Append( corner.x, corner.y );
171  corner.y = -halfwidth;
172  bbox.Append( corner.x, corner.y );
173  corner.x = radius + seg_len + 2;
174  bbox.Append( corner.x, corner.y );
175  corner.y = halfwidth;
176  bbox.Append( corner.x, corner.y );
177 
178  // Now, clamp the shape
180  // Note the final polygon is a simple, convex polygon with no hole
181  // due to the shape of initial polygons
182 
183  // Rotate and move the polygon to its right location
184  polyshape.Rotate( delta_angle, VECTOR2I( 0, 0 ) );
185  polyshape.Move( startp );
186 
187  aCornerBuffer.Append( polyshape);
188 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:134
void Rotate(double aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Function Rotate rotates all vertices by a given angle.
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
VECTOR2< int > VECTOR2I
Definition: vector2d.h:594
void Move(const VECTOR2I &aVector) override
SHAPE_POLY_SET.
int GetCircleToPolyCorrection(int aMaxError)
void BooleanIntersection(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset intersection For aFastMode meaning, see function booleanOp
int NewOutline()
Creates a new empty polygon in the set and returns its index
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
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)

References PNS::angle(), SHAPE_POLY_SET::Append(), SHAPE_POLY_SET::BooleanIntersection(), ERROR_OUTSIDE, EuclideanNorm(), GetArcToSegmentCount(), GetCircleToPolyCorrection(), KiROUND(), SHAPE_POLY_SET::Move(), SHAPE_POLY_SET::NewOutline(), SHAPE_POLY_SET::PM_STRICTLY_SIMPLE, SHAPE_POLY_SET::Rotate(), and RotatePoint().

Referenced by addTextSegmToPoly(), BOARD_ADAPTER::buildPadShapeThickOutlineAsPolygon(), DIALOG_PAD_PROPERTIES::padValuesOK(), DXF_PLOTTER::PlotPoly(), DXF_PLOTTER::ThickSegment(), TransformArcToPolygon(), PAD::TransformHoleWithClearanceToPolygon(), TRACK::TransformShapeWithClearanceToPolygon(), PCB_SHAPE::TransformShapeWithClearanceToPolygon(), and PAD::TransformShapeWithClearanceToPolygon().

◆ TransformRingToPolygon()

void TransformRingToPolygon ( SHAPE_POLY_SET aCornerBuffer,
wxPoint  aCentre,
int  aRadius,
int  aWidth,
int  aError,
ERROR_LOC  aErrorLoc 
)

Function TransformRingToPolygon Creates a polygon from a ring Convert arcs to multiple straight segments.

Parameters
aCornerBuffer= a buffer to store the polygon
aCentre= centre of the arc or circle
aRadius= radius of the circle
aWidth= width (thickness) of the ring
aError= the IU allowed for error in approximation
aErrorLoc= should the approximation error be placed outside or inside the polygon?

Definition at line 375 of file convert_basic_shapes_to_polygon.cpp.

377 {
378  int inner_radius = aRadius - ( aWidth / 2 );
379  int outer_radius = inner_radius + aWidth;
380 
381  if( inner_radius <= 0 )
382  { //In this case, the ring is just a circle (no hole inside)
383  TransformCircleToPolygon( aCornerBuffer, aCentre, aRadius + ( aWidth / 2 ), aError,
384  aErrorLoc );
385  return;
386  }
387 
388  SHAPE_POLY_SET buffer;
389 
390  TransformCircleToPolygon( buffer, aCentre, outer_radius, aError, aErrorLoc );
391 
392  // Build the hole:
393  buffer.NewHole();
394  TransformCircleToPolygon( buffer.Hole( 0, 0 ), aCentre, inner_radius, aError, aErrorLoc );
395 
397  aCornerBuffer.Append( buffer );
398 }
int NewHole(int aOutline=-1)
Creates a new hole in a given outline
void TransformCircleToPolygon(SHAPE_LINE_CHAIN &aCornerBuffer, wxPoint aCenter, int aRadius, int aError, ERROR_LOC aErrorLoc)
SHAPE_LINE_CHAIN & Hole(int aOutline, int aHole)
Returns the reference to aHole-th hole in the aIndex-th outline
SHAPE_POLY_SET.
void Fracture(POLYGON_MODE aFastMode)
Converts a set of polygons with holes to a singe outline with "slits"/"fractures" connecting the oute...
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)

References SHAPE_POLY_SET::Append(), SHAPE_POLY_SET::Fracture(), SHAPE_POLY_SET::Hole(), SHAPE_POLY_SET::NewHole(), SHAPE_POLY_SET::PM_FAST, and TransformCircleToPolygon().

Referenced by BOARD_ADAPTER::buildPadShapeThickOutlineAsPolygon(), AM_PRIMITIVE::DrawBasicShape(), and PCB_SHAPE::TransformShapeWithClearanceToPolygon().

◆ TransformRoundChamferedRectToPolygon()

void TransformRoundChamferedRectToPolygon ( SHAPE_POLY_SET aCornerBuffer,
const wxPoint &  aPosition,
const wxSize &  aSize,
double  aRotation,
int  aCornerRadius,
double  aChamferRatio,
int  aChamferCorners,
int  aError,
ERROR_LOC  aErrorLoc 
)

convert a rectangle with rounded corners and/or chamfered corners to a polygon Convert rounded corners arcs to multiple straight lines.

This will generate at least 16 segments per circle

Parameters
aCornerBuffer= a buffer to store the polygon
aPosition= the coordinate of the center of the rectangle
aSize= the size of the rectangle
aCornerRadius= radius of rounded corners (can be 0)
aRotation= rotation in 0.1 degrees of the rectangle
aChamferRatio= ratio between smaller rect size and chamfer value
aChamferCorners= identifier of the corners to chamfer: 0 = no chamfer 1 = TOP_LEFT 2 = TOP_RIGHT 4 = BOTTOM_LEFT 8 = BOTTOM_RIGHT One can have more than one chamfered corner by ORing the corner identifers
aError= the IU allowed for error in approximation
aErrorLoc= should the approximation error be placed outside or inside the polygon?

Definition at line 281 of file convert_basic_shapes_to_polygon.cpp.

285 {
286  SHAPE_POLY_SET outline;
287  TransformRoundRectToPolygon( outline, aSize, aCornerRadius, aError, aErrorLoc );
288 
289  if( aChamferCorners )
290  {
291  // Now we have the round rect outline, in position 0,0 orientation 0.0.
292  // Chamfer the corner(s).
293  int chamfer_value = aChamferRatio * std::min( aSize.x, aSize.y );
294 
295  SHAPE_POLY_SET chamfered_corner; // corner shape for the current corner to chamfer
296 
297  int corner_id[4] =
298  {
301  };
302  // Depending on the corner position, signX[] and signY[] give the sign of chamfer
303  // coordinates relative to the corner position
304  // The first corner is the top left corner, then top right, bottom left and bottom right
305  int signX[4] = {1, -1, 1,-1 };
306  int signY[4] = {1, 1, -1,-1 };
307 
308  for( int ii = 0; ii < 4; ii++ )
309  {
310  if( (corner_id[ii] & aChamferCorners) == 0 )
311  continue;
312 
313  VECTOR2I corner_pos( -signX[ii]*aSize.x/2, -signY[ii]*aSize.y/2 );
314 
315  if( aCornerRadius )
316  {
317  // We recreate a rectangular area covering the full rounded corner
318  // (max size = aSize/2) to rebuild the corner before chamfering, to be sure
319  // the rounded corner shape does not overlap the chamfered corner shape:
320  chamfered_corner.RemoveAllContours();
321  chamfered_corner.NewOutline();
322  chamfered_corner.Append( 0, 0 );
323  chamfered_corner.Append( 0, signY[ii] * aSize.y / 2 );
324  chamfered_corner.Append( signX[ii] * aSize.x / 2, signY[ii] * aSize.y / 2 );
325  chamfered_corner.Append( signX[ii] * aSize.x / 2, 0 );
326  chamfered_corner.Move( corner_pos );
327  outline.BooleanAdd( chamfered_corner, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
328  }
329 
330  // Now chamfer this corner
331  chamfered_corner.RemoveAllContours();
332  chamfered_corner.NewOutline();
333  chamfered_corner.Append( 0, 0 );
334  chamfered_corner.Append( 0, signY[ii] * chamfer_value );
335  chamfered_corner.Append( signX[ii] * chamfer_value, 0 );
336  chamfered_corner.Move( corner_pos );
337  outline.BooleanSubtract( chamfered_corner, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
338  }
339  }
340 
341  // Rotate and move the outline:
342  if( aRotation != 0.0 )
343  outline.Rotate( DECIDEG2RAD( -aRotation ), VECTOR2I( 0, 0 ) );
344 
345  outline.Move( VECTOR2I( aPosition ) );
346 
347  // Add the outline:
348  aCornerBuffer.Append( outline );
349 }
void BooleanAdd(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset union For aFastMode meaning, see function booleanOp
VECTOR2 defines a general 2D-vector/point.
Definition: vector2d.h:61
void Rotate(double aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Function Rotate rotates all vertices by a given angle.
void TransformRoundRectToPolygon(SHAPE_POLY_SET &aCornerBuffer, const wxSize &aSize, int aCornerRadius, int aError, ERROR_LOC aErrorLoc)
VECTOR2< int > VECTOR2I
Definition: vector2d.h:594
void Move(const VECTOR2I &aVector) override
SHAPE_POLY_SET.
int NewOutline()
Creates a new empty polygon in the set and returns its index
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
double DECIDEG2RAD(double deg)
Definition: trigo.h:221
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset difference For aFastMode meaning, see function booleanOp
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)

References SHAPE_POLY_SET::Append(), SHAPE_POLY_SET::BooleanAdd(), SHAPE_POLY_SET::BooleanSubtract(), DECIDEG2RAD(), SHAPE_POLY_SET::Move(), SHAPE_POLY_SET::NewOutline(), SHAPE_POLY_SET::PM_STRICTLY_SIMPLE, RECT_CHAMFER_BOTTOM_LEFT, RECT_CHAMFER_BOTTOM_RIGHT, RECT_CHAMFER_TOP_LEFT, RECT_CHAMFER_TOP_RIGHT, SHAPE_POLY_SET::RemoveAllContours(), SHAPE_POLY_SET::Rotate(), and TransformRoundRectToPolygon().

Referenced by PAD::BuildEffectiveShapes(), export_vrml_padshape(), GERBER_PLOTTER::FlashPadChamferRoundRect(), PSLIKE_PLOTTER::FlashPadRoundRect(), HPGL_PLOTTER::FlashPadRoundRect(), DXF_PLOTTER::FlashPadRoundRect(), GERBER_PLOTTER::FlashPadRoundRect(), DSN::SPECCTRA_DB::makePADSTACK(), and PAD::TransformShapeWithClearanceToPolygon().