KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_intersection.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#include <boost/test/unit_test.hpp>
21
23
24
25BOOST_AUTO_TEST_SUITE( Intersection )
26
27
29{
30 std::vector<VECTOR2I> intersections;
32
33 std::visit( INTERSECTION_VISITOR( aB, intersections, contact ), aA );
34 return contact;
35}
36
37
38BOOST_AUTO_TEST_CASE( CrossingGeometryReportsNoSpecialContact )
39{
40 INTERSECTION_CONTACT contact = contactOf( SEG( { 0, 0 }, { 100, 0 } ), SEG( { 50, -50 }, { 50, 50 } ) );
41
42 BOOST_CHECK( !contact.m_Tangent );
43 BOOST_CHECK( !contact.m_Overlapping );
44}
45
46
47BOOST_AUTO_TEST_CASE( CollinearSegmentsSharingAnExtentOverlap )
48{
49 INTERSECTION_CONTACT contact = contactOf( SEG( { 0, 0 }, { 100, 0 } ), SEG( { 20, 0 }, { 80, 0 } ) );
50
51 // The point list gives one point here, same as a crossing. Hence the flag.
52 BOOST_CHECK( contact.m_Overlapping );
53 BOOST_CHECK( !contact.m_Tangent );
54}
55
56
57// A shared carrier is not enough. Only a shared extent counts.
58BOOST_AUTO_TEST_CASE( SegmentsWithoutASharedExtentDoNotOverlap )
59{
60 const SEG source( { 0, 0 }, { 100, 0 } );
61
62 BOOST_CHECK( !contactOf( source, SEG( { 100, 0 }, { 200, 0 } ) ).m_Overlapping ); // meeting at one end
63 BOOST_CHECK( !contactOf( source, SEG( { 200, 0 }, { 300, 0 } ) ).m_Overlapping ); // elsewhere on the line
64 BOOST_CHECK( !contactOf( source, SEG( { 0, 10 }, { 100, 10 } ) ).m_Overlapping ); // parallel, off the line
65}
66
67
68BOOST_AUTO_TEST_CASE( SegmentGrazingACircleIsTangent )
69{
70 const SEG source( { 0, 0 }, { 100, 0 } );
71
72 BOOST_CHECK( contactOf( source, CIRCLE( { 50, 50 }, 50 ) ).m_Tangent );
73 BOOST_CHECK( !contactOf( SEG( { 0, 25 }, { 100, 25 } ), CIRCLE( { 50, 50 }, 50 ) ).m_Tangent );
74
75 // Carrier line grazes it. Touch point is off the segment.
76 BOOST_CHECK( !contactOf( source, CIRCLE( { 500, 50 }, 50 ) ).m_Tangent );
77}
78
79
80BOOST_AUTO_TEST_CASE( SegmentGrazingAnArcIsTangentOnlyWhereTheArcRuns )
81{
82 // Upper half of a circle above the segment. Arc dips down to touch.
83 const SHAPE_ARC touching( { 0, 100 }, { 50, 50 }, { 100, 100 }, 0 );
84 const SHAPE_ARC awayFromTouch( { 100, 100 }, { 50, 150 }, { 0, 100 }, 0 );
85
86 BOOST_CHECK( contactOf( SEG( { 0, 50 }, { 100, 50 } ), touching ).m_Tangent );
87 BOOST_CHECK( !contactOf( SEG( { 0, 50 }, { 100, 50 } ), awayFromTouch ).m_Tangent );
88}
89
90
91BOOST_AUTO_TEST_CASE( TangentCirclesReportTangency )
92{
93 BOOST_CHECK( contactOf( CIRCLE( { 0, 0 }, 50 ), CIRCLE( { 100, 0 }, 50 ) ).m_Tangent );
94 BOOST_CHECK( !contactOf( CIRCLE( { 0, 0 }, 50 ), CIRCLE( { 80, 0 }, 50 ) ).m_Tangent );
95 BOOST_CHECK( !contactOf( CIRCLE( { 0, 0 }, 50 ), CIRCLE( { 500, 0 }, 50 ) ).m_Tangent );
96}
97
98
99BOOST_AUTO_TEST_CASE( ArcsOnACommonCircleOverlapOnlyWhenTheirSweepsDo )
100{
101 // All points sit on r=100 about the origin. Rebuilt carriers match exactly.
102 const SHAPE_ARC first( { 100, 0 }, { 80, 60 }, { 60, 80 }, 0 );
103 const SHAPE_ARC overlapping( { 80, 60 }, { 60, 80 }, { 0, 100 }, 0 );
104 const SHAPE_ARC touchingAtOneEnd( { 60, 80 }, { 0, 100 }, { -60, 80 }, 0 );
105
106 BOOST_CHECK( contactOf( first, overlapping ).m_Overlapping );
107 BOOST_CHECK( !contactOf( first, touchingAtOneEnd ).m_Overlapping );
108}
109
110
111BOOST_AUTO_TEST_CASE( ContactAccumulatesAcrossVisits )
112{
113 std::vector<VECTOR2I> intersections;
114 INTERSECTION_CONTACT contact;
115 const SEG source( { 0, 0 }, { 100, 0 } );
116
117 std::visit( INTERSECTION_VISITOR( INTERSECTABLE_GEOM( SEG( { 50, -50 }, { 50, 50 } ) ), intersections, contact ),
118 INTERSECTABLE_GEOM( source ) );
119 BOOST_CHECK( !contact.m_Overlapping );
120
121 std::visit( INTERSECTION_VISITOR( INTERSECTABLE_GEOM( SEG( { 20, 0 }, { 80, 0 } ) ), intersections, contact ),
122 INTERSECTABLE_GEOM( source ) );
123 BOOST_CHECK( contact.m_Overlapping );
124}
125
126
Definition seg.h:38
std::variant< LINE, HALF_LINE, SEG, CIRCLE, SHAPE_ARC, SHAPE_ELLIPSE, BOX2I > INTERSECTABLE_GEOM
A variant type that can hold any of the supported geometry types for intersection calculations.
How two geometries meet, beyond where they cross.
bool m_Tangent
Touch at one point, no crossing.
bool m_Overlapping
Collinear or concentric, more than one point shared.
A visitor that visits INTERSECTABLE_GEOM variant objects with another (which is held as state: m_othe...
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(CrossingGeometryReportsNoSpecialContact)
static INTERSECTION_CONTACT contactOf(const INTERSECTABLE_GEOM &aA, const INTERSECTABLE_GEOM &aB)