46 BOOST_CHECK_SMALL( aActual.
x - aExpected.
x, aTolerance );
47 BOOST_CHECK_SMALL( aActual.
y - aExpected.
y, aTolerance );
60 BOOST_CHECK_SMALL( aActual.
AsDegrees() - aExpectedDegrees, aTolerance );
66 BOOST_CHECK_MESSAGE( aActual.
AsDegrees() > aMinDegrees && aActual.
AsDegrees() < aMaxDegrees,
67 "Expected angle " << aActual.
AsDegrees() <<
" to be between " << aMinDegrees <<
" and "
74 for(
SHAPE* shape : aShapes )
95 "Issue 13626: clockwise semicircle",
96 {-428880000, 117229160 },
97 {-430060565, 113472820 },
99 {-431241130, 109716480 },
103 "Issue 13626: anticlockwise arc",
104 { -431241130, 109716480 },
105 { -434923630, 112954230 },
107 { -439827050, 112936200 },
117 BOOST_TEST_INFO_SCOPE( c.m_CaseName );
154 "Issue 15694: clockwise arc",
165 "Issue 15694: anticlockwise arc",
179 const double angle_tol = 0.1;
183 BOOST_TEST_INFO_SCOPE( c.m_CaseName );
213 ( angle.
AsDegrees() )( c.m_ExpectedAngleAfterSwapDeg )( 360.0 )( angle_tol ) );
251 arc2.SetArcGeometry( start, mid,
end );
272 poly.
Append( { 1000000, 0 } );
273 poly.
Append( { 1000000, 1000000 } );
301 poly.
Append( { 1000000, 0 } );
302 poly.
Append( { 1000000, 1000000 } );
303 poly.
Append( { 0, 1000000 } );
313 shape.
SetEnd( { 1000000, 1000000 } );
330 poly.
Append( { 1000, 0 } );
331 poly.
Append( { 1000, 1000 } );
334 poly.
Append( { 5000, 5000 } );
335 poly.
Append( { 6000, 5000 } );
337 const std::vector<VECTOR2I>
expected = {
338 { 0, 0 }, { 1000, 0 }, { 1000, 1000 }, { 5000, 5000 }, { 6000, 5000 }
343 BOOST_REQUIRE_EQUAL( points.size(),
expected.size() );
345 for(
size_t ii = 0; ii <
expected.size(); ++ii )
422 BOOST_CHECK( !shapes.empty() );
424 for(
SHAPE* s : shapes )
478 shape.
SetEnd( { 1000, 0 } );
495 shape.
SetEnd( { 1000, 1000 } );
519 segment.
SetEnd( { 100, 20 } );
526 arc.SetStart( { 10, 0 } );
527 arc.SetEnd( { 20, 30 } );
529 BOOST_CHECK( arc.GetLineEndingEndpoints( start,
end ) );
534 bezier.SetStart( { 0, 0 } );
535 bezier.SetBezierC1( { 20, 0 } );
536 bezier.SetBezierC2( { 80, 100 } );
537 bezier.SetEnd( { 100, 100 } );
538 bezier.RebuildBezierToSegmentsPointsList( 1 );
540 BOOST_CHECK( bezier.GetLineEndingEndpoints( start,
end ) );
549 poly.
Append( { 50, 10 } );
550 poly.
Append( { 100, 20 } );
551 polyShape.SetPolyShape( poly );
553 BOOST_CHECK( polyShape.GetLineEndingEndpoints( start,
end ) );
581 shape.
SetEnd( { 1000, 0 } );
588 BOOST_REQUIRE_EQUAL( shapes.size(), 1 );
590 BOX2I bbox = shapes[0]->BBox();
591 BOOST_CHECK( bbox.
GetLeft() <= 800 );
592 BOOST_CHECK( bbox.
GetRight() >= 1200 );
593 BOOST_CHECK( bbox.
GetTop() <= -200 );
604 shape.
SetEnd( { 1000, 0 } );
612 BOOST_REQUIRE_EQUAL( shapes.size(), 2 );
614 for(
SHAPE* shapePtr : shapes )
629 shape.
SetEnd( { 1000, 0 } );
637 BOOST_CHECK( bbox.
GetLeft() <= 800 );
638 BOOST_CHECK( bbox.
GetRight() >= 1200 );
639 BOOST_CHECK( bbox.
GetTop() <= -200 );
648 shape.
SetEnd( { 1000, 1000 } );
656 BOOST_CHECK( bbox.
GetLeft() <= 718 );
657 BOOST_CHECK( bbox.
GetRight() >= 1282 );
658 BOOST_CHECK( bbox.
GetTop() <= 718 );
667 shape.
SetEnd( { 1000, 0 } );
693 shape.
SetEnd( { 1000, 0 } );
702 for(
SHAPE* shapePtr : shapes )
723 shape.
SetEnd( { 1000, 0 } );
731 BOOST_REQUIRE_EQUAL( shapes.size(), 1 );
746 shape.
SetEnd( { 1000, 0 } );
757 BOOST_CHECK( shapes.empty() );
767 shape.
SetEnd( { 1000, 0 } );
775 bool collides =
false;
777 for(
SHAPE* shapePtr : shapes )
779 if( shapePtr->Collide( probe.
GetSeg(), 0 ) )
786 BOOST_CHECK( collides );
796 shape.
SetEnd( { 1000, 0 } );
809 BOOST_CHECK_GT( unshortenedBodyPlusEnding.
BBox().
GetRight(), 1000 );
810 BOOST_CHECK_LE( shortenedBodyPlusEnding.
BBox().
GetRight(), 1001 );
826 constexpr double radius = 1000.0;
827 constexpr double radToDeg = 180.0 /
M_PI;
832 BOOST_CHECK( arcAngle >
ANGLE_0 );
848 constexpr double radius = 1000.0;
849 constexpr double radToDeg = 180.0 /
M_PI;
854 BOOST_CHECK( arcAngle <
ANGLE_0 );
883 shape.
SetEnd( { 1000, 0 } );
901 shape.
SetEnd( { 1000, 0 } );
923 shape.
SetEnd( { 1000, 0 } );
941 shape.
SetEnd( { 1000, 0 } );
951 BOOST_REQUIRE_GE( points.size(), 2 );
963 shape.
SetEnd( { 1000, 0 } );
1002 shape.
SetEnd( { 100000, 0 } );
1014 BOOST_REQUIRE_EQUAL( shapes.size(), 1 );
1018 BOOST_REQUIRE_GE(
chain->SegmentCount(), 2 );
1020 double chainLength = 0.0;
1022 for(
int ii = 0; ii <
chain->SegmentCount(); ++ii )
1028 std::vector<SEG> pieces;
1033 pieces.emplace_back( a, b );
1036 std::vector<double> runs;
1039 for(
size_t ii = 0; ii < pieces.size(); )
1045 while( jj < pieces.size() && pieces[jj].A ==
end )
1052 runs.push_back( length );
1057 BOOST_REQUIRE_MESSAGE( runs.size() > 5,
"expected many dashes, got " << runs.size() <<
" run(s)" );
1063 double expected = chainLength * dash / ( dash + gap );
1066 "dashes should cover " <<
expected <<
" IU of the " << chainLength
1067 <<
" IU shortened body, they cover " << drawn );
1085 VECTOR2D penultimate( 1000, 1000 );
1104 VECTOR2D penultimate( 1000, 1000 );
1145 std::vector<VECTOR2I> pts;
1148 BOOST_REQUIRE_EQUAL( pts.size(), 3 );
1153 BOOST_REQUIRE_EQUAL( pts.size(), 3 );
1160 BOOST_REQUIRE_EQUAL( pts.size(), 3 );
constexpr EDA_IU_SCALE schIUScale
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
constexpr coord_type GetLeft() const
constexpr coord_type GetRight() const
constexpr coord_type GetTop() const
constexpr coord_type GetBottom() const
"Standard" polygon editing behavior for EDA_SHAPE polygons.
void MakePoints(EDIT_POINTS &aPoints) override
Construct the initial set of edit points for the item and append to the given list.
bool UpdatePoints(EDIT_POINTS &aPoints) override
Update the list of the edit points for the item.
EDA_SHAPE_MOCK(SHAPE_T aShapeType)
static bool ShortenSegmentForEndings(VECTOR2I &aStart, VECTOR2I &aEnd, const LINE_ENDING &aStartEnding, const LINE_ENDING &aEndEnding, int aLineWidth)
Shorten a segment body for line endings.
EDA_ANGLE GetArcAngle() const
virtual void SetEnd(const VECTOR2I &aEnd)
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false, bool includeFill=false) const
Convert the shape to a closed polygon.
int GetEllipseMinorRadius() const
const VECTOR2I & GetEllipseCenter() const
bool GetLineEndingsBoundingBox(BOX2I &aBBox, int aLineWidth) const
void SetCenter(const VECTOR2I &aCenter)
VECTOR2I getCenter() const
std::vector< SHAPE * > MakeEffectiveShapesWithLineEndings(int aLineWidth) const
Make effective geometry for the shape body shortened for line endings plus the line-ending geometry i...
void SetEndEndingLength(int aLength)
void SetStartEndingStyle(LINE_ENDING_STYLE aStyle)
EDA_ANGLE GetEllipseEndAngle() const
void SetEndEndingWidth(int aWidth)
int GetEllipseMajorRadius() const
std::vector< VECTOR2I > GetPolyPoints() const
Duplicate the polygon outlines into a flat list of VECTOR2I points.
void TransformWithLineEndingsToPolygon(SHAPE_POLY_SET &aBuffer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const
Convert the shape body shortened for line endings plus line-ending geometry to polygons.
void TransformLineEndingsToPolygon(SHAPE_POLY_SET &aBuffer, int aClearance, int aError, ERROR_LOC aErrorLoc, int aLineWidth) const
Append only the line-ending geometry associated with this shape to a polygon set.
virtual std::vector< SHAPE * > MakeEffectiveShapes(bool aEdgeOnly=false) const
Make a set of SHAPE objects representing the EDA_SHAPE.
bool ShortenPolyForEndings(VECTOR2D &aFirst, VECTOR2D &aLast, const VECTOR2D &aSecond, const VECTOR2D &aPenultimate, int aLineWidth) const
SHAPE_POLY_SET & GetPolyShape()
void GetEndingTangents(EDA_ANGLE &aStartTangent, EDA_ANGLE &aEndTangent, int aLineWidth=0) const
Compute outward-facing tangent angles at the start and end of the shape.
EDA_ANGLE GetEllipseRotation() const
void SetEndEndingStyle(LINE_ENDING_STYLE aStyle)
virtual void SetEllipseEndAngle(const EDA_ANGLE &aA)
std::vector< SHAPE * > MakeEffectiveShapesForStroking(int aLineWidth=-1) const
Make a set of SHAPE objects to hand to STROKE_PARAMS::Stroke().
virtual void SetBezierC2(const VECTOR2I &aPt)
bool GetShortenedBodyPolyPoints(const SHAPE_LINE_CHAIN &aOutline, int aOutlineIdx, std::vector< VECTOR2I > &aPoints, int aLineWidth) const
Copy an outline and apply line-ending body shortening when applicable.
virtual void SetBezierC1(const VECTOR2I &aPt)
bool GetLineEndingEndpoints(VECTOR2I &aStartPoint, VECTOR2I &aEndPoint) const
Return the source endpoints used to place line endings.
virtual void SetEllipseRotation(const EDA_ANGLE &aA)
EDA_SHAPE(SHAPE_T aType, int aLineWidth, FILL_T aFill)
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
virtual void SetEllipseCenter(const VECTOR2I &aPt)
void SetStartEndingLength(int aLength)
void SetEndEndingStrokeWidth(int aWidth)
virtual void SetEllipseMinorRadius(int aR)
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
virtual void SetEllipseMajorRadius(int aR)
virtual void SetShape(SHAPE_T aShape)
std::vector< SHAPE * > MakeLineEndingEffectiveShapes(int aLineWidth) const
Make the line-ending geometry associated with this shape.
void SetStartEndingWidth(int aWidth)
EDA_ANGLE GetEllipseStartAngle() const
bool EndsSwapped() const
Have the start and end points been swapped since they were set?
virtual void SetEllipseStartAngle(const EDA_ANGLE &aA)
void SetArcGeometry(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Set the three controlling points for an arc.
std::optional< BEZIER< double > > ShortenedBezierCurve(int aLineWidth) const
Return the cubic Bezier curve shortened for line endings.
void SetArcAngleAndEnd(const EDA_ANGLE &aAngle, bool aCheckNegativeAngle=false)
Set the end point from the angle center and start.
virtual int GetWidth() const
bool ShortenArcForEndings(EDA_ANGLE &aStartAngle, EDA_ANGLE &aArcAngle, double aRadius, int aLineWidth) const
Shorten an arc body for line endings.
std::vector< VECTOR2D > ShortenedBezierPolyline(int aLineWidth) const
Return the flattened Bezier polyline after line-ending shortening.
virtual void SetWidth(int aWidth)
virtual void SetPolyShape(const SHAPE_POLY_SET &aShape)
virtual void SetStart(const VECTOR2I &aStart)
EDIT_POINTS is a VIEW_ITEM that manages EDIT_POINTs and EDIT_LINEs and draws them.
unsigned int PointsSize() const
Return number of stored EDIT_POINTs.
A color representation with 4 components: red, green, blue, alpha.
static const COLOR4D BLACK
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
double GetGapLength(int aLineWidth) const
double GetDashLength(int aLineWidth) const
An abstract base class for deriving all objects that can be added to a VIEW.
Decorative shape (arrowhead, circle, square) at the start or end of a graphic line,...
static int DefaultAccuracyForPCB()
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
Represent a set of closed polygons.
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)
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
const SEG & GetSeg() const
VECTOR2I GetEnd() const override
VECTOR2I GetStart() const override
int GetWidth() const override
An abstract shape on 2D plane.
static void Stroke(const SHAPE *aShape, LINE_STYLE aLineStyle, int aWidth, const KIGFX::RENDER_SETTINGS *aRenderSettings, const std::function< void(const VECTOR2I &a, const VECTOR2I &b)> &aStroker)
const KIGFX::COLOR4D & GetGridColor() override
Return current grid color settings.
KIGFX::COLOR4D GetColor(const KIGFX::VIEW_ITEM *aItem, int aLayer) const override
Returns the color that should be used to draw the specific VIEW_ITEM on the specific layer using curr...
void SetBackgroundColor(const KIGFX::COLOR4D &aColor) override
Set the background color.
const KIGFX::COLOR4D & GetBackgroundColor() const override
Return current background color settings.
const KIGFX::COLOR4D & GetCursorColor() override
Return current cursor color settings.
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
static constexpr EDA_ANGLE ANGLE_0
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
void EditArcEndpointKeepCenter(EDA_SHAPE &aArc, const VECTOR2I &aCenter, const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd, const VECTOR2I &aCursor, const EDA_IU_SCALE &aIuScale)
Move an arc endpoint around the existing center, pulling the opposite endpoint along to keep the radi...
void EditArcMidKeepCenter(EDA_SHAPE &aArc, const VECTOR2I &aCenter, const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd, const VECTOR2I &aCursor, const EDA_IU_SCALE &aIuScale)
Move the mid point of an arc while keeping the center, rotating the endpoints onto the new radius.
bool IsWithinWrapped(T aValue, T aNominal, T aWrap, T aError)
Check if a value is within a tolerance of a nominal value, wrapping to a given val.
bool IsWithin(T aValue, T aNominal, T aError)
Check if a value is within a tolerance of a nominal value.
bool IsVecWithinTol(const VEC &aVec, const VEC &aExp, typename VEC::coord_type aTol)
Check that both x and y of a vector are within expected error.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
bool m_ExpectedStartEndSwapped
VECTOR2I m_ExpectedEndBeforeSwap
bool m_ExpectedStartEndSwapped
VECTOR2I m_ExpectedCenter
double m_ExpectedAngleAfterSwapDeg
VECTOR2I m_ExpectedEndAfterSwap
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
static void deleteShapes(std::vector< SHAPE * > &aShapes)
static void checkAngleClose(const EDA_ANGLE &aActual, double aExpectedDegrees, double aTolerance=1e-6)
static void checkAngleInRange(const EDA_ANGLE &aActual, double aMinDegrees, double aMaxDegrees)
static void checkVectorClose(const VECTOR2D &aActual, const VECTOR2D &aExpected, double aTolerance=1e-6)
static const std::vector< SET_ARC_GEOMETRY_CASE > set_arc_geometry_cases
BOOST_AUTO_TEST_CASE(SetAngleAndEnd)
static void checkVectorEqual(const VECTOR2I &aActual, const VECTOR2I &aExpected)
static const std::vector< SET_ANGLE_END_CASE > set_angle_end_cases
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
VECTOR3I expected(15, 30, 45)
SHAPE_ARC arc2(c.m_arc2.GenerateArc())
const SHAPE_LINE_CHAIN chain
BOOST_CHECK_PREDICATE(ArePolylineEndPointsNearCircle,(chain)(c.m_geom.m_center_point)(radius)(accuracy+epsilon))
BOOST_CHECK_EQUAL(result, "25.4")
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D