KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_pads_arc_structures.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) 2025 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 <boost/test/unit_test.hpp>
21#include <sstream>
23
24using namespace PADS_IO;
25
26
27BOOST_AUTO_TEST_SUITE( PadsArcStructures )
28
29
30BOOST_AUTO_TEST_CASE( Arc_DefaultConstruction )
31{
32 ARC arc{};
33 BOOST_CHECK_EQUAL( arc.cx, 0.0 );
34 BOOST_CHECK_EQUAL( arc.cy, 0.0 );
35 BOOST_CHECK_EQUAL( arc.radius, 0.0 );
36 BOOST_CHECK_EQUAL( arc.start_angle, 0.0 );
37 BOOST_CHECK_EQUAL( arc.delta_angle, 0.0 );
38}
39
40
41BOOST_AUTO_TEST_CASE( Arc_AggregateInitialization )
42{
43 ARC arc{ 100.0, 200.0, 50.0, 45.0, 90.0 };
44 BOOST_CHECK_EQUAL( arc.cx, 100.0 );
45 BOOST_CHECK_EQUAL( arc.cy, 200.0 );
46 BOOST_CHECK_EQUAL( arc.radius, 50.0 );
47 BOOST_CHECK_EQUAL( arc.start_angle, 45.0 );
48 BOOST_CHECK_EQUAL( arc.delta_angle, 90.0 );
49}
50
51
52BOOST_AUTO_TEST_CASE( ArcPoint_DefaultConstruction )
53{
54 ARC_POINT pt;
55 BOOST_CHECK_EQUAL( pt.x, 0.0 );
56 BOOST_CHECK_EQUAL( pt.y, 0.0 );
57 BOOST_CHECK_EQUAL( pt.is_arc, false );
58 BOOST_CHECK_EQUAL( pt.arc.cx, 0.0 );
59 BOOST_CHECK_EQUAL( pt.arc.cy, 0.0 );
60}
61
62
63BOOST_AUTO_TEST_CASE( ArcPoint_LineConstruction )
64{
65 ARC_POINT pt( 100.0, 200.0 );
66 BOOST_CHECK_EQUAL( pt.x, 100.0 );
67 BOOST_CHECK_EQUAL( pt.y, 200.0 );
68 BOOST_CHECK_EQUAL( pt.is_arc, false );
69}
70
71
72BOOST_AUTO_TEST_CASE( ArcPoint_ArcConstruction )
73{
74 ARC arc{ 50.0, 50.0, 25.0, 0.0, 180.0 };
75 ARC_POINT pt( 75.0, 50.0, arc );
76
77 BOOST_CHECK_EQUAL( pt.x, 75.0 );
78 BOOST_CHECK_EQUAL( pt.y, 50.0 );
79 BOOST_CHECK_EQUAL( pt.is_arc, true );
80 BOOST_CHECK_EQUAL( pt.arc.cx, 50.0 );
81 BOOST_CHECK_EQUAL( pt.arc.cy, 50.0 );
82 BOOST_CHECK_EQUAL( pt.arc.radius, 25.0 );
85}
86
87
88BOOST_AUTO_TEST_CASE( ArcPoint_EmplaceBack_Line )
89{
90 std::vector<ARC_POINT> points;
91 points.emplace_back( 10.0, 20.0 );
92 points.emplace_back( 30.0, 40.0 );
93
94 BOOST_REQUIRE_EQUAL( points.size(), 2 );
95 BOOST_CHECK_EQUAL( points[0].x, 10.0 );
96 BOOST_CHECK_EQUAL( points[0].y, 20.0 );
97 BOOST_CHECK_EQUAL( points[0].is_arc, false );
98 BOOST_CHECK_EQUAL( points[1].x, 30.0 );
99 BOOST_CHECK_EQUAL( points[1].y, 40.0 );
100 BOOST_CHECK_EQUAL( points[1].is_arc, false );
101}
102
103
104BOOST_AUTO_TEST_CASE( ArcPoint_EmplaceBack_Arc )
105{
106 std::vector<ARC_POINT> points;
107 points.emplace_back( 0.0, 0.0 );
108 points.emplace_back( 100.0, 0.0, ARC{ 50.0, 0.0, 50.0, 180.0, -180.0 } );
109
110 BOOST_REQUIRE_EQUAL( points.size(), 2 );
111 BOOST_CHECK_EQUAL( points[1].is_arc, true );
112 BOOST_CHECK_EQUAL( points[1].arc.cx, 50.0 );
113 BOOST_CHECK_EQUAL( points[1].arc.delta_angle, -180.0 );
114}
115
116
117BOOST_AUTO_TEST_CASE( Arc_FullCircle )
118{
119 // A 360-degree arc represents a full circle
120 ARC arc{ 0.0, 0.0, 100.0, 0.0, 360.0 };
121 BOOST_CHECK_EQUAL( arc.delta_angle, 360.0 );
122}
123
124
125BOOST_AUTO_TEST_CASE( Arc_NegativeDelta )
126{
127 // Negative delta angle means clockwise direction
128 ARC arc{ 0.0, 0.0, 50.0, 90.0, -90.0 };
129 BOOST_CHECK_EQUAL( arc.start_angle, 90.0 );
130 BOOST_CHECK_EQUAL( arc.delta_angle, -90.0 );
131}
132
133
134BOOST_AUTO_TEST_CASE( Polyline_DefaultConstruction )
135{
136 POLYLINE polyline;
137 polyline.layer = 0;
138 polyline.width = 10.0;
139 polyline.closed = true;
140
141 BOOST_CHECK( polyline.points.empty() );
142 BOOST_CHECK_EQUAL( polyline.closed, true );
143}
144
145
146BOOST_AUTO_TEST_CASE( Polyline_WithPoints )
147{
148 POLYLINE polyline;
149 polyline.layer = 1;
150 polyline.width = 5.0;
151 polyline.closed = false;
152 polyline.points.emplace_back( 0.0, 0.0 );
153 polyline.points.emplace_back( 100.0, 0.0 );
154 polyline.points.emplace_back( 100.0, 100.0 );
155
156 BOOST_REQUIRE_EQUAL( polyline.points.size(), 3 );
157 BOOST_CHECK_EQUAL( polyline.closed, false );
158 BOOST_CHECK_EQUAL( polyline.points[2].x, 100.0 );
159 BOOST_CHECK_EQUAL( polyline.points[2].y, 100.0 );
160}
161
162
163BOOST_AUTO_TEST_CASE( Track_UsesArcPoint )
164{
165 TRACK track;
166 track.layer = 1;
167 track.width = 10.0;
168 track.points.emplace_back( 0.0, 0.0 );
169 track.points.emplace_back( 50.0, 50.0 );
170 track.points.emplace_back( 100.0, 50.0, ARC{ 75.0, 50.0, 25.0, 180.0, -180.0 } );
171
172 BOOST_REQUIRE_EQUAL( track.points.size(), 3 );
173 BOOST_CHECK_EQUAL( track.points[0].is_arc, false );
174 BOOST_CHECK_EQUAL( track.points[1].is_arc, false );
175 BOOST_CHECK_EQUAL( track.points[2].is_arc, true );
176 BOOST_CHECK_EQUAL( track.points[2].arc.radius, 25.0 );
177}
178
179
180BOOST_AUTO_TEST_CASE( Pour_UsesArcPoint )
181{
182 POUR pour;
183 pour.net_name = "GND";
184 pour.layer = 1;
185 pour.priority = 0;
186 pour.width = 10.0;
187 pour.points.emplace_back( 0.0, 0.0 );
188 pour.points.emplace_back( 100.0, 0.0 );
189 pour.points.emplace_back( 100.0, 100.0 );
190 pour.points.emplace_back( 0.0, 100.0 );
191
192 BOOST_REQUIRE_EQUAL( pour.points.size(), 4 );
193 BOOST_CHECK_EQUAL( pour.net_name, "GND" );
194}
195
196
197BOOST_AUTO_TEST_CASE( DecalItem_UsesArcPoint )
198{
199 DECAL_ITEM item;
200 item.type = "CLOSED";
201 item.layer = 26; // Silkscreen Top
202 item.width = 8.0;
203 item.points.emplace_back( 0.0, 0.0 );
204 item.points.emplace_back( 50.0, 0.0 );
205 item.points.emplace_back( 50.0, 50.0 );
206 item.points.emplace_back( 0.0, 50.0 );
207
208 BOOST_REQUIRE_EQUAL( item.points.size(), 4 );
209 BOOST_CHECK_EQUAL( item.type, "CLOSED" );
210}
211
212
213BOOST_AUTO_TEST_CASE( Arc_FromBoundingBox )
214{
215 // PADS arc format: XLOC YLOC ISA IDA CX-R CY-R CX+R CY+R
216 // Example: 0 0 900 -900 -50 -50 50 50
217 // This represents arc from (0,0), center at (0,0), radius 50, 90deg start, -90deg delta
218 double bboxMinX = -50.0, bboxMinY = -50.0;
219 double bboxMaxX = 50.0, bboxMaxY = 50.0;
220 int startAngleTenths = 900; // 90.0 degrees
221 int deltaAngleTenths = -900; // -90.0 degrees (clockwise)
222
223 double cx = ( bboxMinX + bboxMaxX ) / 2.0;
224 double cy = ( bboxMinY + bboxMaxY ) / 2.0;
225 double radius = ( bboxMaxX - bboxMinX ) / 2.0;
226 double startAngle = startAngleTenths / 10.0;
227 double deltaAngle = deltaAngleTenths / 10.0;
228
229 BOOST_CHECK_CLOSE( cx, 0.0, 0.001 );
230 BOOST_CHECK_CLOSE( cy, 0.0, 0.001 );
231 BOOST_CHECK_CLOSE( radius, 50.0, 0.001 );
232 BOOST_CHECK_CLOSE( startAngle, 90.0, 0.001 );
233 BOOST_CHECK_CLOSE( deltaAngle, -90.0, 0.001 );
234}
235
236
237BOOST_AUTO_TEST_CASE( Arc_FromBoundingBox_OffCenter )
238{
239 // Arc with center at (100, 200), radius 25
240 // Bounding box: (75, 175) to (125, 225)
241 double bboxMinX = 75.0, bboxMinY = 175.0;
242 double bboxMaxX = 125.0, bboxMaxY = 225.0;
243
244 double cx = ( bboxMinX + bboxMaxX ) / 2.0;
245 double cy = ( bboxMinY + bboxMaxY ) / 2.0;
246 double radius = ( bboxMaxX - bboxMinX ) / 2.0;
247
248 BOOST_CHECK_CLOSE( cx, 100.0, 0.001 );
249 BOOST_CHECK_CLOSE( cy, 200.0, 0.001 );
250 BOOST_CHECK_CLOSE( radius, 25.0, 0.001 );
251}
252
253
254BOOST_AUTO_TEST_CASE( ArcPoint_ParseFromStream )
255{
256 // Simulate parsing a PADS arc line: "0 0 900 -900 -50 -50 50 50"
257 std::string line = "0 0 900 -900 -50 -50 50 50";
258 std::istringstream iss( line );
259
260 double dx, dy;
261 int startAngleTenths, deltaAngleTenths;
262 double bboxMinX, bboxMinY, bboxMaxX, bboxMaxY;
263
264 iss >> dx >> dy;
265 bool hasArc = static_cast<bool>( iss >> startAngleTenths >> deltaAngleTenths
266 >> bboxMinX >> bboxMinY >> bboxMaxX >> bboxMaxY );
267
268 BOOST_CHECK( hasArc );
269 BOOST_CHECK_EQUAL( startAngleTenths, 900 );
270 BOOST_CHECK_EQUAL( deltaAngleTenths, -900 );
271}
272
273
274BOOST_AUTO_TEST_CASE( ArcPoint_ParseFromStream_NoArc )
275{
276 // Simulate parsing a simple PADS line point: "100 200"
277 std::string line = "100 200";
278 std::istringstream iss( line );
279
280 double dx, dy;
281 int startAngleTenths, deltaAngleTenths;
282 double bboxMinX, bboxMinY, bboxMaxX, bboxMaxY;
283
284 iss >> dx >> dy;
285 bool hasArc = static_cast<bool>( iss >> startAngleTenths >> deltaAngleTenths
286 >> bboxMinX >> bboxMinY >> bboxMaxX >> bboxMaxY );
287
288 BOOST_CHECK( !hasArc );
289 BOOST_CHECK_CLOSE( dx, 100.0, 0.001 );
290 BOOST_CHECK_CLOSE( dy, 200.0, 0.001 );
291}
292
293
A point that may be either a line endpoint or an arc segment.
Definition pads_parser.h:68
ARC arc
Arc parameters (only valid when is_arc is true)
Definition pads_parser.h:72
bool is_arc
True if this segment is an arc, false for line.
Definition pads_parser.h:71
double y
Endpoint Y coordinate.
Definition pads_parser.h:70
double x
Endpoint X coordinate.
Definition pads_parser.h:69
Arc definition using center point, radius, and angles.
Definition pads_parser.h:53
double radius
Arc radius.
Definition pads_parser.h:56
double cx
Center X coordinate.
Definition pads_parser.h:54
double delta_angle
Arc sweep angle in degrees (positive = CCW)
Definition pads_parser.h:58
double start_angle
Start angle in degrees (0 = +X, CCW positive)
Definition pads_parser.h:57
double cy
Center Y coordinate.
Definition pads_parser.h:55
std::vector< ARC_POINT > points
Shape points, may include arc segments.
std::string type
CLOSED, OPEN, CIRCLE, COPCLS, TAG, etc.
A polyline that may contain arc segments.
bool closed
True if polyline forms a closed shape.
std::vector< ARC_POINT > points
Polyline vertices, may include arcs.
std::string net_name
std::vector< ARC_POINT > points
Pour outline, may include arc segments.
std::vector< ARC_POINT > points
Track points, may include arc segments.
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(Arc_DefaultConstruction)
int radius
BOOST_CHECK_EQUAL(result, "25.4")