KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_pcb_constraint.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
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU 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 <memory>
21
23
24#include <geometry/shape.h>
25
27#include <core/typeinfo.h>
28
29
30BOOST_AUTO_TEST_SUITE( ConstraintSolverItem )
31
32
33BOOST_AUTO_TEST_CASE( BasicProperties )
34{
36
39
40 // A constraint carries no geometry and is on no layer.
41 BOOST_CHECK( c.GetLayerSet() == LSET() );
42 BOOST_CHECK( !c.HitTest( VECTOR2I( 0, 0 ), 1000000 ) );
43 BOOST_CHECK( c.ViewGetLayers().empty() );
44
45 // Driving by default.
46 BOOST_CHECK( c.IsDriving() );
47 BOOST_CHECK( !c.HasValue() );
48}
49
50
51BOOST_AUTO_TEST_CASE( GeometrySurfaceIsSafe )
52{
54
55 // The base BOARD_ITEM transforms wxFAIL_MSG and GetEffectiveShape is unimplemented;
56 // a constraint overrides them so any generic item walk stays safe.
57 BOOST_CHECK_NO_THROW( c.Move( VECTOR2I( 1000, 1000 ) ) );
58 BOOST_CHECK_NO_THROW( c.Rotate( VECTOR2I( 0, 0 ), ANGLE_90 ) );
59
60 std::shared_ptr<SHAPE> shape = c.GetEffectiveShape();
61 BOOST_REQUIRE( shape );
62 BOOST_CHECK_EQUAL( shape->Type(), SH_COMPOUND );
63}
64
65
66BOOST_AUTO_TEST_CASE( MembersAndValue )
67{
69
70 KIID a, b;
73 c.SetValue( 5.0 );
74 c.SetDriving( false );
75
76 BOOST_CHECK_EQUAL( c.GetMembers().size(), 2 );
77 BOOST_CHECK( c.GetMembers()[0].m_item == a );
78 BOOST_CHECK( c.GetMembers()[0].m_anchor == CONSTRAINT_ANCHOR::START );
79 BOOST_CHECK( c.GetMembers()[1].m_anchor == CONSTRAINT_ANCHOR::END );
80 BOOST_CHECK( c.HasValue() );
81 BOOST_CHECK_CLOSE( *c.GetValue(), 5.0, 1e-9 );
82 BOOST_CHECK( !c.IsDriving() );
83}
84
85
86BOOST_AUTO_TEST_CASE( CloneIsAFaithfulCopy )
87{
91 c.SetValue( 2.5 );
92
93 std::unique_ptr<BOARD_ITEM> clone( static_cast<BOARD_ITEM*>( c.Clone() ) );
94
95 // Clone preserves the uuid and compares equal to its source.
96 BOOST_CHECK( clone->m_Uuid == c.m_Uuid );
97 BOOST_CHECK( *static_cast<PCB_CONSTRAINT*>( clone.get() ) == c );
98 BOOST_CHECK( c == *clone );
99}
100
101
102BOOST_AUTO_TEST_CASE( EqualityAndSimilarity )
103{
104 KIID a, b;
105
109
113
114 BOOST_CHECK( c1 == c2 );
115 BOOST_CHECK_CLOSE( c1.Similarity( c2 ), 1.0, 1e-9 );
116
117 // A different type is wholly dissimilar.
121 BOOST_CHECK( !( c1 == cPerp ) );
122 BOOST_CHECK_EQUAL( c1.Similarity( cPerp ), 0.0 );
123
124 // Same type, different members compares unequal but partially similar.
127 BOOST_CHECK( !( c1 == c3 ) );
128 BOOST_CHECK_LT( c1.Similarity( c3 ), 1.0 );
129 BOOST_CHECK_GT( c1.Similarity( c3 ), 0.0 );
130}
131
132
133BOOST_AUTO_TEST_CASE( DuplicateDetection )
134{
135 KIID a, b, c;
136
137 auto make = [&]( PCB_CONSTRAINT_TYPE aType, const KIID& aFirst, const KIID& aSecond )
138 {
139 PCB_CONSTRAINT constraint( nullptr, aType );
140 constraint.AddMember( aFirst, CONSTRAINT_ANCHOR::WHOLE );
141 constraint.AddMember( aSecond, CONSTRAINT_ANCHOR::WHOLE );
142 return constraint;
143 };
144
145 PCB_CONSTRAINT parallelAB = make( PCB_CONSTRAINT_TYPE::PARALLEL, a, b );
146
147 // Same type and members is a duplicate, and member order does not matter (A-B == B-A).
148 BOOST_CHECK( ConstraintsAreDuplicate( parallelAB, make( PCB_CONSTRAINT_TYPE::PARALLEL, a, b ) ) );
149 BOOST_CHECK( ConstraintsAreDuplicate( parallelAB, make( PCB_CONSTRAINT_TYPE::PARALLEL, b, a ) ) );
150
151 // A different type or a different member is not a duplicate.
152 BOOST_CHECK( !ConstraintsAreDuplicate( parallelAB, make( PCB_CONSTRAINT_TYPE::PERPENDICULAR, a, b ) ) );
153 BOOST_CHECK( !ConstraintsAreDuplicate( parallelAB, make( PCB_CONSTRAINT_TYPE::PARALLEL, a, c ) ) );
154
155 // Value and driving are ignored: a second fixed-length on the same segment is still a duplicate
156 // (it could only conflict).
159 len1.SetValue( 5.0 );
160
163 len2.SetValue( 9.0 );
164 len2.SetDriving( false );
165
166 BOOST_CHECK( ConstraintsAreDuplicate( len1, len2 ) );
167
168 // An empty-member constraint is never a duplicate (it is an error state, not a relation).
171 BOOST_CHECK( !ConstraintsAreDuplicate( empty1, empty2 ) );
172}
173
174
175BOOST_AUTO_TEST_CASE( VertexMemberIdentity )
176{
177 KIID id;
181
182 BOOST_CHECK( a == b );
183 BOOST_CHECK( !( a == c ) );
184 BOOST_CHECK( ConstraintAnchorFromToken( wxS( "vertex" ) ) == CONSTRAINT_ANCHOR::VERTEX );
185}
186
187
188BOOST_AUTO_TEST_CASE( VertexIndexInDuplicateDetection )
189{
190 KIID item, other;
191
192 auto make = [&]( int aFirstIndex, int aSecondIndex )
193 {
194 PCB_CONSTRAINT constraint( nullptr, PCB_CONSTRAINT_TYPE::COINCIDENT );
195 constraint.AddMember( item, CONSTRAINT_ANCHOR::VERTEX, aFirstIndex );
196 constraint.AddMember( other, CONSTRAINT_ANCHOR::VERTEX, aSecondIndex );
197 return constraint;
198 };
199
200 PCB_CONSTRAINT vertex02 = make( 0, 2 );
201
202 // Index is part of a member identity so the same anchor on a different vertex of the same
203 // item is a different relation even with order insensitive comparison
204 BOOST_CHECK( ConstraintsAreDuplicate( vertex02, make( 0, 2 ) ) );
205 BOOST_CHECK( !ConstraintsAreDuplicate( vertex02, make( 2, 2 ) ) );
206 BOOST_CHECK( !ConstraintsAreDuplicate( vertex02, make( 0, 3 ) ) );
207}
208
209
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:83
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition board_item.h:296
const KIID m_Uuid
Definition eda_item.h:531
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:108
Definition kiid.h:44
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
A geometric constraint between board items (issue #2329).
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
const std::vector< CONSTRAINT_MEMBER > & GetMembers() const
std::vector< int > ViewGetLayers() const override
Return the all the layers within the VIEW the object is painted on.
std::optional< double > GetValue() const
bool IsDriving() const
A driving constraint forces its value; a reference (non-driving) one only measures it.
PCB_CONSTRAINT_TYPE GetConstraintType() const
void AddMember(const KIID &aItem, CONSTRAINT_ANCHOR aAnchor=CONSTRAINT_ANCHOR::WHOLE, int aIndex=-1)
double Similarity(const BOARD_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
bool HasValue() const
void SetValue(std::optional< double > aValue)
void SetDriving(bool aDriving)
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
void Move(const VECTOR2I &aMoveVector) override
Move this object.
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const override
Empty shape so any generic GetItemSet()/RunOnChildren consumer stays safe.
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:413
bool ConstraintsAreDuplicate(const PCB_CONSTRAINT &aA, const PCB_CONSTRAINT &aB)
True if two constraints express the same relation, meaning the same type and the same members compare...
CONSTRAINT_ANCHOR ConstraintAnchorFromToken(const wxString &aToken)
Parse an anchor token; returns WHOLE for an unknown token.
@ VERTEX
An indexed rectangle corner or polygon outline vertex; pairs with CONSTRAINT_MEMBER::m_index.
@ RADIUS
The radius (scalar feature) of an arc or circle.
@ WHOLE
The item as a whole (a segment as a line, a circle).
@ START
First endpoint of a segment or arc.
@ END
Second endpoint of a segment or arc.
PCB_CONSTRAINT_TYPE
The geometric relationship a PCB_CONSTRAINT enforces between its members.
@ COINCIDENT
Two points are made to coincide.
@ PERPENDICULAR
Two segments are perpendicular.
@ EQUAL_RADIUS
Two arcs/circles have equal radius.
@ FIXED_LENGTH
A segment has a driving length value.
@ PARALLEL
Two segments are parallel.
@ SH_COMPOUND
compound shape, consisting of multiple simple shapes
Definition shape.h:49
One participant in a constraint: a referenced board item plus the feature of that item that participa...
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(BasicProperties)
BOOST_CHECK_EQUAL(result, "25.4")
@ PCB_CONSTRAINT_T
class PCB_CONSTRAINT, a geometric constraint between board items
Definition typeinfo.h:238
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683