KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_connect_board_shapes.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 (C) 2026 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
21#include <boost/test/unit_test.hpp>
22
23#include <pcb_shape.h>
24#include <fix_board_shape.h>
25
26// Coordinates are in nanometres. The weld cap is 0.01 mm (10000 nm).
27// The chaining value is large so the ends always get paired and only the gap size decides.
28static const int CHAINING = 3000000; // 3 mm, the Heal Shapes default
29
30BOOST_AUTO_TEST_SUITE( ConnectBoardShapesTests )
31
32
33// A hairline gap between two near-straight facets should weld the closest ends together.
34BOOST_AUTO_TEST_CASE( HairlineCollinearGapWelds )
35{
36 PCB_SHAPE a( nullptr, SHAPE_T::SEGMENT );
37 a.SetStart( VECTOR2I( 0, 0 ) );
38 a.SetEnd( VECTOR2I( 1000000, 10000 ) );
39
40 PCB_SHAPE b( nullptr, SHAPE_T::SEGMENT );
41 b.SetStart( VECTOR2I( 1000100, 10100 ) ); // 141 nm diagonal gap from a.end
42 b.SetEnd( VECTOR2I( 2000100, 20100 ) ); // same direction as a -> angle ~0
43
44 std::vector<PCB_SHAPE*> shapes{ &a, &b };
46
47 BOOST_CHECK( a.GetEnd() == b.GetStart() );
48 BOOST_CHECK_EQUAL( a.GetEnd().x, 1000050 );
49 BOOST_CHECK_EQUAL( a.GetEnd().y, 10050 );
50}
51
52
53// A big gap is a real feature (a slot or neck), not rounding noise, so leave it alone.
54BOOST_AUTO_TEST_CASE( LargeCollinearGapSurvives )
55{
56 PCB_SHAPE a( nullptr, SHAPE_T::SEGMENT );
57 a.SetStart( VECTOR2I( 0, 0 ) );
58 a.SetEnd( VECTOR2I( 1000000, 10000 ) );
59
60 PCB_SHAPE b( nullptr, SHAPE_T::SEGMENT );
61 b.SetStart( VECTOR2I( 2000000, 20000 ) ); // ~1 mm gap, well over the 0.01 mm cap
62 b.SetEnd( VECTOR2I( 3000000, 30000 ) );
63
64 std::vector<PCB_SHAPE*> shapes{ &a, &b };
66
67 BOOST_CHECK_EQUAL( a.GetEnd().x, 1000000 );
68 BOOST_CHECK_EQUAL( a.GetEnd().y, 10000 );
69 BOOST_CHECK_EQUAL( b.GetStart().x, 2000000 );
70 BOOST_CHECK_EQUAL( b.GetStart().y, 20000 );
71}
72
73
74// A real corner should still extend the segments to their sharp crossing, not the midpoint.
75BOOST_AUTO_TEST_CASE( RealCornerExtendsToIntersection )
76{
77 PCB_SHAPE a( nullptr, SHAPE_T::SEGMENT );
78 a.SetStart( VECTOR2I( 0, 0 ) );
79 a.SetEnd( VECTOR2I( 999000, 0 ) ); // horizontal, short of the corner
80
81 PCB_SHAPE b( nullptr, SHAPE_T::SEGMENT );
82 b.SetStart( VECTOR2I( 1000000, 1000 ) ); // vertical, short of the corner
83 b.SetEnd( VECTOR2I( 1000000, 1000000 ) );
84
85 std::vector<PCB_SHAPE*> shapes{ &a, &b };
87
88 // The two lines cross at (1000000, 0), not at the midpoint.
89 BOOST_CHECK( a.GetEnd() == b.GetStart() );
90 BOOST_CHECK_EQUAL( a.GetEnd().x, 1000000 );
91 BOOST_CHECK_EQUAL( a.GetEnd().y, 0 );
92}
93
94
95// Right at the cap: just under 0.01 mm welds, just over is left alone.
96BOOST_AUTO_TEST_CASE( WeldCapBoundary )
97{
98 {
99 PCB_SHAPE a( nullptr, SHAPE_T::SEGMENT );
100 a.SetStart( VECTOR2I( 0, 0 ) );
101 a.SetEnd( VECTOR2I( 1000000, 0 ) );
102
103 PCB_SHAPE b( nullptr, SHAPE_T::SEGMENT );
104 b.SetStart( VECTOR2I( 1009000, 0 ) ); // 9 um gap, under the 10 um cap
105 b.SetEnd( VECTOR2I( 2009000, 0 ) );
106
107 std::vector<PCB_SHAPE*> shapes{ &a, &b };
108 ConnectBoardShapes( shapes, CHAINING );
109
110 BOOST_CHECK( a.GetEnd() == b.GetStart() );
111 }
112
113 {
114 PCB_SHAPE a( nullptr, SHAPE_T::SEGMENT );
115 a.SetStart( VECTOR2I( 0, 0 ) );
116 a.SetEnd( VECTOR2I( 1000000, 0 ) );
117
118 PCB_SHAPE b( nullptr, SHAPE_T::SEGMENT );
119 b.SetStart( VECTOR2I( 1011000, 0 ) ); // 11 um gap, over the 10 um cap
120 b.SetEnd( VECTOR2I( 2011000, 0 ) );
121
122 std::vector<PCB_SHAPE*> shapes{ &a, &b };
123 ConnectBoardShapes( shapes, CHAINING );
124
125 BOOST_CHECK_EQUAL( a.GetEnd().x, 1000000 );
126 BOOST_CHECK_EQUAL( b.GetStart().x, 1011000 );
127 }
128}
129
130
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:240
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:190
void SetEnd(const VECTOR2I &aEnd) override
void SetStart(const VECTOR2I &aStart) override
@ SEGMENT
Definition eda_shape.h:46
void ConnectBoardShapes(std::vector< PCB_SHAPE * > &aShapeList, int aChainingEpsilon)
Connects shapes to each other, making continious contours (adjacent shapes will have a common vertex)...
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_AUTO_TEST_CASE(HairlineCollinearGapWelds)
static const int CHAINING
BOOST_AUTO_TEST_SUITE_END()
BOOST_CHECK_EQUAL(result, "25.4")
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683