KiCad PCB EDA Suite
convert_basic_shapes_to_polygon.h File Reference

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

int ConvertArcToPolyline (SHAPE_LINE_CHAIN &aPolyline, VECTOR2I aCenter, int aRadius, const EDA_ANGLE &aStartAngleDeg, const EDA_ANGLE &aArcAngleDeg, double aAccuracy, ERROR_LOC aErrorLoc)
 Generate a polyline to approximate a arc. More...
 
void TransformCircleToPolygon (SHAPE_LINE_CHAIN &aBuffer, const VECTOR2I &aCenter, int aRadius, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
 Convert a circle to a polygon, using multiple straight lines. More...
 
void TransformCircleToPolygon (SHAPE_POLY_SET &aBuffer, const VECTOR2I &aCenter, int aRadius, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
 Convert a circle to a polygon, using multiple straight lines. More...
 
void TransformOvalToPolygon (SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
 Convert a oblong shape to a polygon, using multiple segments. More...
 
void TransformTrapezoidToPolygon (SHAPE_POLY_SET &aBuffer, const VECTOR2I &aPosition, const VECTOR2I &aSize, const EDA_ANGLE &aRotation, int aDeltaX, int aDeltaY, int aInflate, int aError, ERROR_LOC aErrorLoc)
 Convert a rectangle or trapezoid to a polygon. More...
 
void TransformRoundChamferedRectToPolygon (SHAPE_POLY_SET &aBuffer, const VECTOR2I &aPosition, const VECTOR2I &aSize, const EDA_ANGLE &aRotation, int aCornerRadius, double aChamferRatio, int aChamferCorners, int aInflate, int aError, ERROR_LOC aErrorLoc)
 Convert a rectangle with rounded corners and/or chamfered corners to a polygon. More...
 
void TransformArcToPolygon (SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc)
 Convert arc to multiple straight segments. More...
 
void TransformRingToPolygon (SHAPE_POLY_SET &aBuffer, const VECTOR2I &aCentre, int aRadius, int aWidth, int aError, ERROR_LOC aErrorLoc)
 Convert arcs to multiple straight segments. More...
 

Enumeration Type Documentation

◆ RECT_CHAMFER_POSITIONS

Enumerator
RECT_NO_CHAMFER 
RECT_CHAMFER_TOP_LEFT 
RECT_CHAMFER_TOP_RIGHT 
RECT_CHAMFER_BOTTOM_LEFT 
RECT_CHAMFER_BOTTOM_RIGHT 
RECT_CHAMFER_ALL 

Definition at line 36 of file convert_basic_shapes_to_polygon.h.

Function Documentation

◆ ConvertArcToPolyline()

int ConvertArcToPolyline ( SHAPE_LINE_CHAIN aPolyline,
VECTOR2I  aCenter,
int  aRadius,
const EDA_ANGLE aStartAngleDeg,
const EDA_ANGLE aArcAngleDeg,
double  aAccuracy,
ERROR_LOC  aErrorLoc 
)

Generate a polyline to approximate a arc.

Parameters
aPolylineis a buffer to store the polyline.
aCenteris the center of the arc.
aRadiusis the radius of the arc.
aStartAngleDegis the starting point of the arc.
aArcAngleDegis the angle of the arc.
aErroris the internal units allowed for error approximation.
aErrorLocdetermines if the approximation error be placed outside or inside the polygon.

Definition at line 515 of file convert_basic_shapes_to_polygon.cpp.

518{
519 int n = 2;
520
521 if( aRadius >= aAccuracy )
522 n = GetArcToSegmentCount( aRadius, aAccuracy, aArcAngle ) + 1;
523
524 EDA_ANGLE delta = aArcAngle / n;
525
526 if( aErrorLoc == ERROR_INSIDE )
527 {
528 // This is the easy case: with the error on the inside the endpoints of each segment
529 // are error-free.
530
531 EDA_ANGLE rot = aStartAngle;
532
533 for( int i = 0; i <= n; i++, rot += delta )
534 {
535 double x = aCenter.x + aRadius * rot.Cos();
536 double y = aCenter.y + aRadius * rot.Sin();
537
538 aPolyline.Append( KiROUND( x ), KiROUND( y ) );
539 }
540 }
541 else
542 {
543 // This is the hard case: with the error on the outside it's the segment midpoints
544 // that are error-free. So we need to add a half-segment at each end of the arc to get
545 // them correct.
546
547 int seg360 = std::abs( KiROUND( n * 360.0 / aArcAngle.AsDegrees() ) );
548 int actual_delta_radius = CircleToEndSegmentDeltaRadius( aRadius, seg360 );
549 int errorRadius = aRadius + actual_delta_radius;
550
551 double x = aCenter.x + aRadius * aStartAngle.Cos();
552 double y = aCenter.y + aRadius * aStartAngle.Sin();
553
554 aPolyline.Append( KiROUND( x ), KiROUND( y ) );
555
556 EDA_ANGLE rot = aStartAngle + delta / 2;
557
558 for( int i = 0; i < n; i++, rot += delta )
559 {
560 x = aCenter.x + errorRadius * rot.Cos();
561 y = aCenter.y + errorRadius * rot.Sin();
562
563 aPolyline.Append( KiROUND( x ), KiROUND( y ) );
564 }
565
566 x = aCenter.x + aRadius * ( aStartAngle + aArcAngle ).Cos();
567 y = aCenter.y + aRadius * ( aStartAngle + aArcAngle ).Sin();
568
569 aPolyline.Append( KiROUND( x ), KiROUND( y ) );
570 }
571
572 return n;
573}
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
int CircleToEndSegmentDeltaRadius(int aInnerCircleRadius, int aSegCount)
@ ERROR_INSIDE
int GetArcToSegmentCount(int aRadius, int aErrorMax, const EDA_ANGLE &aArcAngle)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:418
constexpr int delta
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:85

References std::abs(), SHAPE_LINE_CHAIN::Append(), EDA_ANGLE::AsDegrees(), CircleToEndSegmentDeltaRadius(), EDA_ANGLE::Cos(), delta, ERROR_INSIDE, GetArcToSegmentCount(), KiROUND(), EDA_ANGLE::Sin(), VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by DSN::SPECCTRA_DB::makeIMAGE(), and TransformArcToPolygon().

◆ TransformArcToPolygon()

void TransformArcToPolygon ( SHAPE_POLY_SET aBuffer,
const VECTOR2I aStart,
const VECTOR2I aMid,
const VECTOR2I aEnd,
int  aWidth,
int  aError,
ERROR_LOC  aErrorLoc 
)

Convert arc to multiple straight segments.

Parameters
aBufferis a buffer to store the polygon.
aCentreis the center of the arc or circle.
aStartis the start point of the arc or a point on the circle.
aArcAngleis the arc angle in 0.1 degrees. For a circle, aArcAngle = 3600.
aWidthis the width (thickness) of the line.
aErroris the internal units allowed for error in approximation.
aErrorLocdetermines if the approximation error be placed outside or inside the polygon.

Definition at line 576 of file convert_basic_shapes_to_polygon.cpp.

578{
579 SEG startToEnd( aStart, aEnd );
580 int distanceToMid = startToEnd.Distance( aMid );
581
582 if( distanceToMid <= 1 )
583 {
584 // Not an arc but essentially a straight line with a small error
585 TransformOvalToPolygon( aBuffer, aStart, aEnd, aWidth + distanceToMid, aError, aErrorLoc );
586 return;
587 }
588
589 // This appproximation builds a single polygon by starting with a 180 degree arc at one
590 // end, then the outer edge of the arc, then a 180 degree arc at the other end, and finally
591 // the inner edge of the arc.
592 SHAPE_ARC arc( aStart, aMid, aEnd, aWidth );
593 EDA_ANGLE arc_angle_start = arc.GetStartAngle();
594 EDA_ANGLE arc_angle = arc.GetCentralAngle();
595 EDA_ANGLE arc_angle_end = arc_angle_start + arc_angle;
596 EDA_ANGLE sweep = arc_angle < ANGLE_0 ? -ANGLE_180 : ANGLE_180;
597
598 if( arc_angle < ANGLE_0 )
599 {
600 std::swap( arc_angle_start, arc_angle_end );
601 arc = SHAPE_ARC( aEnd, aMid, aStart, aWidth );
602 arc_angle = -arc_angle;
603 }
604
605 int radial_offset = arc.GetWidth() / 2;
606 int arc_outer_radius = arc.GetRadius() + radial_offset;
607 int arc_inner_radius = arc.GetRadius() - radial_offset;
608 ERROR_LOC errorLocInner = ( aErrorLoc == ERROR_INSIDE ) ? ERROR_OUTSIDE : ERROR_INSIDE;
609 ERROR_LOC errorLocOuter = ( aErrorLoc == ERROR_INSIDE ) ? ERROR_INSIDE : ERROR_OUTSIDE;
610
611 SHAPE_POLY_SET polyshape;
612 polyshape.NewOutline();
613
614 SHAPE_LINE_CHAIN& outline = polyshape.Outline( 0 );
615
616 // Starting end
617 ConvertArcToPolyline( outline, arc.GetP0(), radial_offset, arc_angle_start - ANGLE_180,
618 ANGLE_180, aError, aErrorLoc );
619
620 // Outside edge
621 ConvertArcToPolyline( outline, arc.GetCenter(), arc_outer_radius, arc_angle_start, arc_angle,
622 aError, errorLocOuter );
623
624 // Other end
625 ConvertArcToPolyline( outline, arc.GetP1(), radial_offset, arc_angle_end, ANGLE_180, aError,
626 aErrorLoc );
627
628 // Inside edge
629 if( arc_inner_radius > 0 )
630 {
631 ConvertArcToPolyline( outline, arc.GetCenter(), arc_inner_radius, arc_angle_end,
632 -arc_angle, aError, errorLocInner );
633 }
634
635 aBuffer.Append( polyshape );
636}
Definition: seg.h:42
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
Represent a set of closed polygons.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Add a new vertex to the contour indexed by aOutline and aHole (defaults to the outline of the last po...
SHAPE_LINE_CHAIN & Outline(int aIndex)
int NewOutline()
Creates a new hole in a given outline.
int ConvertArcToPolyline(SHAPE_LINE_CHAIN &aPolyline, VECTOR2I aCenter, int aRadius, const EDA_ANGLE &aStartAngle, const EDA_ANGLE &aArcAngle, double aAccuracy, ERROR_LOC aErrorLoc)
Generate a polyline to approximate a arc.
void TransformOvalToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount)
Convert a oblong shape to a polygon, using multiple segments.
static constexpr EDA_ANGLE & ANGLE_180
Definition: eda_angle.h:433
static constexpr EDA_ANGLE & ANGLE_0
Definition: eda_angle.h:429
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
@ ERROR_OUTSIDE

References ANGLE_0, ANGLE_180, SHAPE_POLY_SET::Append(), ConvertArcToPolyline(), SEG::Distance(), ERROR_INSIDE, ERROR_OUTSIDE, SHAPE_ARC::GetCenter(), SHAPE_ARC::GetCentralAngle(), SHAPE_ARC::GetP0(), SHAPE_ARC::GetP1(), SHAPE_ARC::GetRadius(), SHAPE_ARC::GetStartAngle(), SHAPE_ARC::GetWidth(), SHAPE_POLY_SET::NewOutline(), SHAPE_POLY_SET::Outline(), and TransformOvalToPolygon().

Referenced by BOOST_AUTO_TEST_CASE(), KIGFX::PCB_PAINTER::draw(), CADSTAR_PCB_ARCHIVE_LOADER::loadCoppers(), EDA_SHAPE::TransformShapeToPolygon(), and PCB_TRACK::TransformShapeToPolygon().

◆ TransformCircleToPolygon() [1/2]

void TransformCircleToPolygon ( SHAPE_LINE_CHAIN aBuffer,
const VECTOR2I aCenter,
int  aRadius,
int  aError,
ERROR_LOC  aErrorLoc,
int  aMinSegCount = 0 
)

Convert a circle to a polygon, using multiple straight lines.

Parameters
aBufferis a buffer to store the polygon.
aCenteris the center of the circle.
aRadiusis the radius of the circle.
aErroris the internal units allowed for error approximation.
aErrorLocdetermines if the approximation error be placed outside or inside the polygon.
aMinSegCountis the min count of segments to approximate. Default = 0 to do not force a min count.

Definition at line 38 of file convert_basic_shapes_to_polygon.cpp.

40{
41 VECTOR2I corner_position;
42 int numSegs = GetArcToSegmentCount( aRadius, aError, FULL_CIRCLE );
43 numSegs = std::max( aMinSegCount, numSegs );
44
45 // The shape will be built with a even number of segs. Reason: the horizontal
46 // diameter begins and ends to points on the actual circle, or circle
47 // expanded by aError if aErrorLoc == ERROR_OUTSIDE.
48 // This is used by Arc to Polygon shape convert.
49 if( numSegs & 1 )
50 numSegs++;
51
52 EDA_ANGLE delta = ANGLE_360 / numSegs;
53 int radius = aRadius;
54
55 if( aErrorLoc == ERROR_OUTSIDE )
56 {
57 // The outer radius should be radius+aError
58 // Recalculate the actual approx error, as it can be smaller than aError
59 // because numSegs is clamped to a minimal value
60 int actual_delta_radius = CircleToEndSegmentDeltaRadius( radius, numSegs );
61 radius += GetCircleToPolyCorrection( actual_delta_radius );
62 }
63
65 {
66 corner_position.x = radius;
67 corner_position.y = 0;
68 RotatePoint( corner_position, angle );
69 corner_position += aCenter;
70 aBuffer.Append( corner_position.x, corner_position.y );
71 }
72
73 aBuffer.SetClosed( true );
74}
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
static constexpr EDA_ANGLE & ANGLE_360
Definition: eda_angle.h:435
static constexpr EDA_ANGLE & FULL_CIRCLE
Definition: eda_angle.h:427
int GetCircleToPolyCorrection(int aMaxError)
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Definition: trigo.cpp:183

References PNS::angle(), ANGLE_0, ANGLE_360, SHAPE_LINE_CHAIN::Append(), CircleToEndSegmentDeltaRadius(), delta, ERROR_OUTSIDE, FULL_CIRCLE, GetArcToSegmentCount(), GetCircleToPolyCorrection(), RotatePoint(), SHAPE_LINE_CHAIN::SetClosed(), VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by ZONE_FILLER::addHatchFillTypeOnZone(), addHoleToPolygon(), ZONE_FILLER::buildCopperItemClearances(), TEARDROP_MANAGER::ComputePointsOnPadVia(), AM_PRIMITIVE::ConvertBasicShapeToPolygon(), D_CODE::ConvertShapeToPolygon(), BOARD_ADAPTER::createLayers(), TEARDROP_MANAGER::findAnchorPointsOnTrack(), DSN::SPECCTRA_DB::makeIMAGE(), PAD::MergePrimitivesAsPolygon(), TransformRingToPolygon(), EDA_SHAPE::TransformShapeToPolygon(), PCB_DIMENSION_BASE::TransformShapeToPolygon(), PCB_TRACK::TransformShapeToPolygon(), and PAD::TransformShapeToPolygon().

◆ TransformCircleToPolygon() [2/2]

void TransformCircleToPolygon ( SHAPE_POLY_SET aBuffer,
const VECTOR2I aCenter,
int  aRadius,
int  aError,
ERROR_LOC  aErrorLoc,
int  aMinSegCount = 0 
)

Convert a circle to a polygon, using multiple straight lines.

Parameters
aBufferis a buffer to store the polygon.
aCenteris the center of the circle.
aRadiusis the radius of the circle.
aErroris the internal units allowed for error in approximation.
aErrorLocdetermines if the approximation error be placed outside or inside the polygon.
aMinSegCountis the min count of segments to approximate. Default = 0 to do not force a min count.

Definition at line 77 of file convert_basic_shapes_to_polygon.cpp.

79{
80 VECTOR2I corner_position;
81 int numSegs = GetArcToSegmentCount( aRadius, aError, FULL_CIRCLE );
82 numSegs = std::max( aMinSegCount, numSegs );
83
84 // The shape will be built with a even number of segs. Reason: the horizontal
85 // diameter begins and ends to points on the actual circle, or circle
86 // expanded by aError if aErrorLoc == ERROR_OUTSIDE.
87 // This is used by Arc to Polygon shape convert.
88 if( numSegs & 1 )
89 numSegs++;
90
91 EDA_ANGLE delta = ANGLE_360 / numSegs;
92 int radius = aRadius;
93
94 if( aErrorLoc == ERROR_OUTSIDE )
95 {
96 // The outer radius should be radius+aError
97 // Recalculate the actual approx error, as it can be smaller than aError
98 // because numSegs is clamped to a minimal value
99 int actual_delta_radius = CircleToEndSegmentDeltaRadius( radius, numSegs );
100 radius += GetCircleToPolyCorrection( actual_delta_radius );
101 }
102
103 aBuffer.NewOutline();
104
106 {
107 corner_position.x = radius;
108 corner_position.y = 0;
109 RotatePoint( corner_position, angle );
110 corner_position += aCenter;
111 aBuffer.Append( corner_position.x, corner_position.y );
112 }
113
114 // Finish circle
115 corner_position.x = radius;
116 corner_position.y = 0;
117 corner_position += aCenter;
118 aBuffer.Append( corner_position.x, corner_position.y );
119}

References PNS::angle(), ANGLE_0, ANGLE_360, SHAPE_POLY_SET::Append(), CircleToEndSegmentDeltaRadius(), delta, ERROR_OUTSIDE, FULL_CIRCLE, GetArcToSegmentCount(), GetCircleToPolyCorrection(), SHAPE_POLY_SET::NewOutline(), RotatePoint(), VECTOR2< T >::x, and VECTOR2< T >::y.

◆ TransformOvalToPolygon()

void TransformOvalToPolygon ( SHAPE_POLY_SET aBuffer,
const VECTOR2I aStart,
const VECTOR2I aEnd,
int  aWidth,
int  aError,
ERROR_LOC  aErrorLoc,
int  aMinSegCount = 0 
)

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
aBufferis a buffer to store the polygon.
aStartis the first point of the segment.
aEndis the second point of the segment.
aWidthis the width of the segment.
aErroris the internal units allowed for error in approximation.
aErrorLocdetermines if the approximation error be placed outside or inside the polygon.
aMinSegCountis the min count of segments to approximate. Default = 0 to do not force a min count.

Definition at line 122 of file convert_basic_shapes_to_polygon.cpp.

124{
125 // To build the polygonal shape outside the actual shape, we use a bigger
126 // radius to build rounded ends.
127 // However, the width of the segment is too big.
128 // so, later, we will clamp the polygonal shape with the bounding box
129 // of the segment.
130 int radius = aWidth / 2;
131 int numSegs = GetArcToSegmentCount( radius, aError, FULL_CIRCLE );
132 numSegs = std::max( aMinSegCount, numSegs );
133
134 EDA_ANGLE delta = ANGLE_360 / numSegs;
135
136 if( aErrorLoc == ERROR_OUTSIDE )
137 {
138 // The outer radius should be radius+aError
139 // Recalculate the actual approx error, as it can be smaller than aError
140 // because numSegs is clamped to a minimal value
141 int actual_delta_radius = CircleToEndSegmentDeltaRadius( radius, numSegs );
142 int correction = GetCircleToPolyCorrection( actual_delta_radius );
143 radius += correction;
144 }
145
146 // end point is the coordinate relative to aStart
147 VECTOR2I endp = aEnd - aStart;
148 VECTOR2I startp = aStart;
149 VECTOR2I corner;
150 SHAPE_POLY_SET polyshape;
151
152 polyshape.NewOutline();
153
154 // normalize the position in order to have endp.x >= 0
155 // it makes calculations more easy to understand
156 if( endp.x < 0 )
157 {
158 endp = aStart - aEnd;
159 startp = aEnd;
160 }
161
162 EDA_ANGLE delta_angle( endp );
163 int seg_len = KiROUND( EuclideanNorm( endp ) );
164
165 // Compute the outlines of the segment, and creates a polygon
166 // Note: the polygonal shape is built from the equivalent horizontal
167 // segment starting at {0,0}, and ending at {seg_len,0}
168
169 // add right rounded end:
170
172 {
173 corner = VECTOR2I( 0, radius );
174 RotatePoint( corner, angle );
175 corner.x += seg_len;
176 polyshape.Append( corner.x, corner.y );
177 }
178
179 // Finish arc:
180 corner = VECTOR2I( seg_len, -radius );
181 polyshape.Append( corner.x, corner.y );
182
183 // add left rounded end:
185 {
186 corner = VECTOR2I( 0, -radius );
187 RotatePoint( corner, angle );
188 polyshape.Append( corner.x, corner.y );
189 }
190
191 // Finish arc:
192 corner = VECTOR2I( 0, radius );
193 polyshape.Append( corner.x, corner.y );
194
195 // Now trim the edges of the polygonal shape which will be slightly outside the
196 // track width.
197 SHAPE_POLY_SET bbox;
198 bbox.NewOutline();
199 // Build the bbox (a horizontal rectangle).
200 int halfwidth = aWidth / 2; // Use the exact segment width for the bbox height
201 corner.x = -radius - 2; // use a bbox width slightly bigger to avoid
202 // creating useless corner at segment ends
203 corner.y = halfwidth;
204 bbox.Append( corner.x, corner.y );
205 corner.y = -halfwidth;
206 bbox.Append( corner.x, corner.y );
207 corner.x = radius + seg_len + 2;
208 bbox.Append( corner.x, corner.y );
209 corner.y = halfwidth;
210 bbox.Append( corner.x, corner.y );
211
212 // Now, clamp the shape
214 // Note the final polygon is a simple, convex polygon with no hole
215 // due to the shape of initial polygons
216
217 // Rotate and move the polygon to its right location
218 polyshape.Rotate( -delta_angle );
219 polyshape.Move( startp );
220
221 aBuffer.Append( polyshape);
222}
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
void BooleanIntersection(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset union between a and b, store the result in it self For aFastMode meaning,...
void Move(const VECTOR2I &aVector) override
constexpr double correction
double EuclideanNorm(const VECTOR2I &vector)
Definition: trigo.h:129
VECTOR2< int > VECTOR2I
Definition: vector2d.h:590

References PNS::angle(), ANGLE_0, ANGLE_180, ANGLE_360, SHAPE_POLY_SET::Append(), SHAPE_POLY_SET::BooleanIntersection(), CircleToEndSegmentDeltaRadius(), correction, delta, ERROR_OUTSIDE, EuclideanNorm(), FULL_CIRCLE, GetArcToSegmentCount(), GetCircleToPolyCorrection(), KiROUND(), SHAPE_POLY_SET::Move(), SHAPE_POLY_SET::NewOutline(), SHAPE_POLY_SET::PM_STRICTLY_SIMPLE, SHAPE_POLY_SET::Rotate(), RotatePoint(), VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by BOARD_ADAPTER::buildPadOutlineAsPolygon(), FOOTPRINT::CheckPads(), CALLBACK_GAL::DrawGlyph(), KIFONT::OUTLINE_FONT::getTextAsGlyphsUnlocked(), CADSTAR_PCB_ARCHIVE_LOADER::loadCoppers(), DIALOG_PAD_PROPERTIES::padValuesOK(), DXF_PLOTTER::PlotPoly(), DXF_PLOTTER::ThickSegment(), TransformArcToPolygon(), PAD::TransformHoleToPolygon(), EDA_SHAPE::TransformShapeToPolygon(), FP_TEXTBOX::TransformShapeToPolygon(), PCB_DIMENSION_BASE::TransformShapeToPolygon(), PCB_TEXTBOX::TransformShapeToPolygon(), PCB_TRACK::TransformShapeToPolygon(), PAD::TransformShapeToPolygon(), FP_TEXT::TransformTextToPolySet(), FP_TEXTBOX::TransformTextToPolySet(), PCB_TEXT::TransformTextToPolySet(), and PCB_TEXTBOX::TransformTextToPolySet().

◆ TransformRingToPolygon()

void TransformRingToPolygon ( SHAPE_POLY_SET aBuffer,
const VECTOR2I aCentre,
int  aRadius,
int  aWidth,
int  aError,
ERROR_LOC  aErrorLoc 
)

Convert arcs to multiple straight segments.

Parameters
aBufferis a buffer to store the polygon.
aCentreis the center of the arc or circle.
aRadiusis the radius of the circle.
aWidthis the width (thickness) of the ring.
aErroris the internal units allowed for error in approximation.
aErrorLocdetermines if the approximation error be placed outside or inside the polygon.

Definition at line 639 of file convert_basic_shapes_to_polygon.cpp.

641{
642 int inner_radius = aRadius - ( aWidth / 2 );
643 int outer_radius = inner_radius + aWidth;
644
645 if( inner_radius <= 0 )
646 {
647 //In this case, the ring is just a circle (no hole inside)
648 TransformCircleToPolygon( aBuffer, aCentre, aRadius + ( aWidth / 2 ), aError, aErrorLoc );
649 return;
650 }
651
652 SHAPE_POLY_SET buffer;
653
654 TransformCircleToPolygon( buffer, aCentre, outer_radius, aError, aErrorLoc );
655
656 // Build the hole:
657 buffer.NewHole();
658 // The circle is the hole, so the approximation error location is the opposite of aErrorLoc
659 ERROR_LOC inner_err_loc = aErrorLoc == ERROR_OUTSIDE ? ERROR_INSIDE : ERROR_OUTSIDE;
660 TransformCircleToPolygon( buffer.Hole( 0, 0 ), aCentre, inner_radius,
661 aError, inner_err_loc );
662
664 aBuffer.Append( buffer );
665}
void Fracture(POLYGON_MODE aFastMode)
Convert a single outline slitted ("fractured") polygon into a set ouf outlines with holes.
SHAPE_LINE_CHAIN & Hole(int aOutline, int aHole)
Return the aIndex-th subpolygon in the set.
int NewHole(int aOutline=-1)
Adds a new outline to the set and returns its index.
void TransformCircleToPolygon(SHAPE_LINE_CHAIN &aBuffer, const VECTOR2I &aCenter, int aRadius, int aError, ERROR_LOC aErrorLoc, int aMinSegCount)
Convert a circle to a polygon, using multiple straight lines.

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

Referenced by BOARD_ADAPTER::buildPadOutlineAsPolygon(), AM_PRIMITIVE::ConvertBasicShapeToPolygon(), and EDA_SHAPE::TransformShapeToPolygon().

◆ TransformRoundChamferedRectToPolygon()

void TransformRoundChamferedRectToPolygon ( SHAPE_POLY_SET aBuffer,
const VECTOR2I aPosition,
const VECTOR2I aSize,
const EDA_ANGLE aRotation,
int  aCornerRadius,
double  aChamferRatio,
int  aChamferCorners,
int  aInflate,
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
aBufferis a buffer to store the polygon.
aPositionis the coordinate of the center of the rectangle.
aSizeis the size of the rectangle.
aCornerRadiusis the radius of rounded corners (can be 0).
aRotationis the rotationof the rectangle.
aChamferRatiois the ratio between smaller rect side and chamfer value.
aChamferCornersis the 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 identifiers.
aInflateis the (positive) shape inflation or 0
aErroris the IU allowed for error in approximation.
aErrorLocdetermines if the approximation error be placed outside or inside the polygon.

Definition at line 448 of file convert_basic_shapes_to_polygon.cpp.

453{
454 SHAPE_POLY_SET outline;
455 VECTOR2I size( aSize / 2 );
456 int chamferCnt = std::bitset<8>( aChamferCorners ).count();
457 double chamferDeduct = 0;
458
459 if( aInflate < 0 )
460 {
461 size.x = std::max( 1, size.x + aInflate );
462 size.y = std::max( 1, size.y + aInflate );
463 chamferDeduct = aInflate * ( 2.0 - M_SQRT2 );
464 aCornerRadius = std::max( 0, aCornerRadius + aInflate );
465 aInflate = 0;
466 }
467
468 std::vector<ROUNDED_CORNER> corners;
469 corners.reserve( 4 + chamferCnt );
470 corners.emplace_back( -size.x, -size.y, aCornerRadius );
471 corners.emplace_back( size.x, -size.y, aCornerRadius );
472 corners.emplace_back( size.x, size.y, aCornerRadius );
473 corners.emplace_back( -size.x, size.y, aCornerRadius );
474
475 if( aChamferCorners )
476 {
477 int shorterSide = std::min( aSize.x, aSize.y );
478 int chamfer = std::max( 0, KiROUND( aChamferRatio * shorterSide + chamferDeduct ) );
481 int sign[8] = { 0, 1, -1, 0, 0, -1, 1, 0 };
482
483 for( int cc = 0, pos = 0; cc < 4; cc++, pos++ )
484 {
485 if( !( aChamferCorners & chamId[cc] ) )
486 continue;
487
488 corners[pos].m_radius = 0;
489
490 if( chamfer == 0 )
491 continue;
492
493 corners.insert( corners.begin() + pos + 1, corners[pos] );
494 corners[pos].m_position.x += sign[( 2 * cc ) & 7] * chamfer;
495 corners[pos].m_position.y += sign[( 2 * cc - 2 ) & 7] * chamfer;
496 corners[pos + 1].m_position.x += sign[( 2 * cc + 1 ) & 7] * chamfer;
497 corners[pos + 1].m_position.y += sign[( 2 * cc - 1 ) & 7] * chamfer;
498 pos++;
499 }
500
501 if( chamferCnt > 1 && 2 * chamfer >= shorterSide )
503 }
504
505 CornerListToPolygon( outline, corners, aInflate, aError, aErrorLoc );
506
507 if( !aRotation.IsZero() )
508 outline.Rotate( aRotation );
509
510 outline.Move( aPosition );
511 aBuffer.Append( outline );
512}
bool IsZero() const
Definition: eda_angle.h:169
void CornerListToPolygon(SHAPE_POLY_SET &outline, std::vector< ROUNDED_CORNER > &aCorners, int aInflate, int aError, ERROR_LOC aErrorLoc)
void CornerListRemoveDuplicates(std::vector< ROUNDED_CORNER > &aCorners)
int sign(T val)
Definition: util.h:124

References SHAPE_POLY_SET::Append(), CornerListRemoveDuplicates(), CornerListToPolygon(), EDA_ANGLE::IsZero(), KiROUND(), SHAPE_POLY_SET::Move(), RECT_CHAMFER_BOTTOM_LEFT, RECT_CHAMFER_BOTTOM_RIGHT, RECT_CHAMFER_TOP_LEFT, RECT_CHAMFER_TOP_RIGHT, SHAPE_POLY_SET::Rotate(), sign(), VECTOR2< T >::x, and VECTOR2< T >::y.

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

◆ TransformTrapezoidToPolygon()

void TransformTrapezoidToPolygon ( SHAPE_POLY_SET aBuffer,
const VECTOR2I aPosition,
const VECTOR2I aSize,
const EDA_ANGLE aRotation,
int  aDeltaX,
int  aDeltaY,
int  aInflate,
int  aError,
ERROR_LOC  aErrorLoc 
)

Convert a rectangle or trapezoid to a polygon.

This will generate at least 16 segments per circle (when using inflate).

Parameters
aBufferis a buffer to store the polygon.
aPositionis the coordinate of the center of the rectangle.
aSizeis the size of the rectangle.
aDeltaXis the delta for trapezoids in X direction
aDeltaYis the delta for trapezoids in Y direction
aInflateis the (positive) shape inflation or 0
aErroris the IU allowed for error in approximation.
aErrorLocdetermines if the approximation error be placed outside or inside the polygon.

Definition at line 375 of file convert_basic_shapes_to_polygon.cpp.

378{
379 SHAPE_POLY_SET outline;
380 VECTOR2I size( aSize / 2 );
381 std::vector<ROUNDED_CORNER> corners;
382
383 if( aInflate < 0 )
384 {
385 if( !aDeltaX && !aDeltaY ) // rectangle
386 {
387 size.x = std::max( 1, size.x + aInflate );
388 size.y = std::max( 1, size.y + aInflate );
389 }
390 else if( aDeltaX ) // horizontal trapezoid
391 {
392 double slope = (double) aDeltaX / size.x;
393 int yShrink = KiROUND( ( std::hypot( size.x, aDeltaX ) * aInflate ) / size.x );
394 size.y = std::max( 1, size.y + yShrink );
395 size.x = std::max( 1, size.x + aInflate );
396 aDeltaX = KiROUND( size.x * slope );
397
398 if( aDeltaX > size.y ) // shrinking turned the trapezoid into a triangle
399 {
400 corners.reserve( 3 );
401 corners.emplace_back( -size.x, -size.y - aDeltaX );
402 corners.emplace_back( KiROUND( size.y / slope ), 0 );
403 corners.emplace_back( -size.x, size.y + aDeltaX );
404 }
405 }
406 else // vertical trapezoid
407 {
408 double slope = (double) aDeltaY / size.y;
409 int xShrink = KiROUND( ( std::hypot( size.y, aDeltaY ) * aInflate ) / size.y );
410 size.x = std::max( 1, size.x + xShrink );
411 size.y = std::max( 1, size.y + aInflate );
412 aDeltaY = KiROUND( size.y * slope );
413
414 if( aDeltaY > size.x )
415 {
416 corners.reserve( 3 );
417 corners.emplace_back( 0, -KiROUND( size.x / slope ) );
418 corners.emplace_back( size.x + aDeltaY, size.y );
419 corners.emplace_back( -size.x - aDeltaY, size.y );
420 }
421 }
422
423 aInflate = 0;
424 }
425
426 if( corners.empty() )
427 {
428 corners.reserve( 4 );
429 corners.emplace_back( -size.x + aDeltaY, -size.y - aDeltaX );
430 corners.emplace_back( size.x - aDeltaY, -size.y + aDeltaX );
431 corners.emplace_back( size.x + aDeltaY, size.y - aDeltaX );
432 corners.emplace_back( -size.x - aDeltaY, size.y + aDeltaX );
433
434 if( std::abs( aDeltaY ) == std::abs( size.x ) || std::abs( aDeltaX ) == std::abs( size.y ) )
436 }
437
438 CornerListToPolygon( outline, corners, aInflate, aError, aErrorLoc );
439
440 if( !aRotation.IsZero() )
441 outline.Rotate( aRotation );
442
443 outline.Move( VECTOR2I( aPosition ) );
444 aBuffer.Append( outline );
445}

References std::abs(), SHAPE_POLY_SET::Append(), CornerListRemoveDuplicates(), CornerListToPolygon(), EDA_ANGLE::IsZero(), KiROUND(), SHAPE_POLY_SET::Move(), SHAPE_POLY_SET::Rotate(), VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by PAD::TransformShapeToPolygon().