KiCad PCB EDA Suite
playground.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) 2020 KiCad Developers.
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, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24
25// WARNING - this Tom's crappy PNS hack tool code. Please don't complain about its quality
26// (unless you want to improve it).
27
28#include <pgm_base.h>
30
32#include "label_manager.h"
33
34#include <geometry/shape_arc.h>
35
36std::shared_ptr<PNS_LOG_VIEWER_OVERLAY> overlay;
37
38
39bool collideArc2Arc( const SHAPE_ARC& a1, const SHAPE_ARC& a2, int clearance, SEG& minDistSeg )
40{
41 SEG mediatrix( a1.GetCenter(), a2.GetCenter() );
42
43 std::vector<VECTOR2I> ips;
44
45 // Basic case - arcs intersect
46 if( a1.Intersect( a2, &ips ) > 0 )
47 {
48 minDistSeg.A = minDistSeg.B = ips[0];
49 return true;
50 }
51
52 // Arcs don't intersect, build a list of points to check
53 std::vector<VECTOR2I> ptsA;
54 std::vector<VECTOR2I> ptsB;
55
56 bool cocentered = ( mediatrix.A == mediatrix.B );
57
58 // 1: Interior points of both arcs, which are on the line segment between the two centres
59 if( !cocentered )
60 {
61 a1.IntersectLine( mediatrix, &ptsA );
62 a2.IntersectLine( mediatrix, &ptsB );
63 }
64
65 // 2: Check arc end points
66 ptsA.push_back( a1.GetP0() );
67 ptsA.push_back( a1.GetP1() );
68 ptsB.push_back( a2.GetP0() );
69 ptsB.push_back( a2.GetP1() );
70
71 // 3: Endpoint of one and "projected" point on the other, which is on the
72 // line segment through that endpoint and the centre of the other arc
73 a1.IntersectLine( SEG( a2.GetP0(), a1.GetCenter() ), &ptsA );
74 a1.IntersectLine( SEG( a2.GetP1(), a1.GetCenter() ), &ptsA );
75
76 a2.IntersectLine( SEG( a1.GetP0(), a2.GetCenter() ), &ptsB );
77 a2.IntersectLine( SEG( a1.GetP1(), a2.GetCenter() ), &ptsB );
78
79 double minDist = std::numeric_limits<double>::max();
80 bool minDistFound = false;
81
82 // @todo performance might be improved by only checking certain points (e.g only check end
83 // points against other end points or their corresponding "projected" points)
84 for( const VECTOR2I& ptA : ptsA )
85 {
86 for( const VECTOR2I& ptB : ptsB )
87 {
88 double dist = ( ptA - ptB ).EuclideanNorm() - a1.GetWidth() / 2.0 - a2.GetWidth() / 2.0;
89
90 if( dist < clearance )
91 {
92 if( !minDistFound || dist < minDist )
93 {
94 minDist = dist;
95 minDistSeg = SEG( ptA, ptB );
96 }
97
98 minDistFound = true;
99 }
100 }
101 }
102
103 return minDistFound;
104}
105
106
107int playground_main_func( int argc, char* argv[] )
108{
109 auto frame = new PNS_LOG_VIEWER_FRAME( nullptr );
110 Pgm().App().SetTopWindow( frame ); // wxApp gets a face.
111 frame->Show();
112
113 struct ARC_DATA
114 {
115 double cx, cy, sx, sy, ca, w;
116 };
117
118 const ARC_DATA test_data [] =
119 {
120 {73.843527, 74.355869, 71.713528, 72.965869, -76.36664803, 0.2},
121 {71.236473, 74.704131, 73.366472, 76.094131, -76.36664803, 0.2},
122 {82.542335, 74.825975, 80.413528, 73.435869, -76.4, 0.2},
123 {76.491192, 73.839894, 78.619999, 75.23, -76.4, 0.2},
124 {89.318807, 74.810106, 87.19, 73.42, -76.4, 0.2},
125 {87.045667, 74.632941, 88.826472, 75.794131, -267.9, 0.2},
126 {94.665667, 73.772941, 96.446472, 74.934131, -267.9, 0.2},
127 {94.750009, 73.74012, 93.6551, 73.025482, -255.5, 0.2},
128 {72.915251, 80.493054, 73.570159, 81.257692, -260.5, 0.2}, // end points clearance false positive
129 {73.063537, 82.295989, 71.968628, 81.581351, -255.5, 0.2},
130 {79.279991, 80.67988, 80.3749, 81.394518, -255.5, 0.2},
131 {79.279991, 80.67988, 80.3749, 81.694518, -255.5, 0.2 },
132 {88.495265, 81.766089, 90.090174, 82.867869, -255.5, 0.2},
133 {86.995265, 81.387966, 89.090174, 82.876887, -255.5, 0.2},
134 {96.149734, 81.792126, 94.99, 83.37, -347.2, 0.2},
135 {94.857156, 81.240589, 95.91, 83.9, -288.5, 0.2},
136 {72.915251, 86.493054, 73.970159, 87.257692, -260.5, 0.2}, // end points clearance #1
137 {73.063537, 88.295989, 71.968628, 87.581351, -255.5, 0.2},
138 {78.915251, 86.393054, 79.970159, 87.157692, 99.5, 0.2}, // end points clearance #2 - false positive
139 {79.063537, 88.295989, 77.968628, 87.581351, -255.5, 0.2},
140 {85.915251, 86.993054, 86.970159, 87.757692, 99.5, 0.2}, // intersection - false negative
141 {86.063537, 88.295989, 84.968628, 87.581351, -255.5, 0.2},
142 {94.6551, 88.295989, 95.6551, 88.295989, 90.0, 0.2 }, // simulating diff pair
143 {94.6551, 88.295989, 95.8551, 88.295989, 90.0, 0.2 },
144 {73.77532, 93.413654, 75.70532, 93.883054, 60.0, 0.1 }, // one arc fully enclosed in other
145 {73.86532, 93.393054, 75.86532, 93.393054, 90.0, 0.3 },
146 {79.87532, 93.413654, 81.64532, 94.113054, 60.0, 0.1 }, // concentric
147 {79.87532, 93.413654, 81.86532, 93.393054, 90.0, 0.3 }
148 };
149
150
151 overlay = frame->GetOverlay();
152
153
154 overlay->SetIsFill( false );
155 overlay->SetLineWidth( 10000 );
156
157 std::vector<SHAPE_ARC> arcs;
158 int n_arcs = sizeof( test_data ) / sizeof( ARC_DATA );
159
160 BOX2I vp;
161
162 for( int i = 0; i < n_arcs; i++ )
163 {
164 const ARC_DATA& d = test_data[i];
165
166 SHAPE_ARC arc( VECTOR2D( pcbIUScale.mmToIU( d.cx ), pcbIUScale.mmToIU( d.cy ) ),
167 VECTOR2D( pcbIUScale.mmToIU( d.sx ), pcbIUScale.mmToIU( d.sy ) ),
168 EDA_ANGLE( d.ca, DEGREES_T ), pcbIUScale.mmToIU( d.w ) );
169
170 arcs.push_back( arc );
171
172 if( i == 0 )
173 vp = arc.BBox();
174 else
175 vp.Merge( arc.BBox() );
176 }
177
178 printf("Read %zu arcs\n", arcs.size() );
179
180 LABEL_MANAGER labelMgr( frame->GetPanel()->GetGAL() );
181 frame->GetPanel()->GetView()->SetViewport( BOX2D( vp.GetOrigin(), vp.GetSize() ) );
182
183 for(int i = 0; i < arcs.size(); i+= 2)
184 {
185 SEG closestDist;
186 std::vector<VECTOR2I> ips;
187 bool collides = collideArc2Arc( arcs[i], arcs[i+1], 0, closestDist );
188 int ni = arcs[i].Intersect( arcs[i+1], &ips );
189
190 overlay->SetLineWidth( 10000.0 );
191 overlay->SetStrokeColor( GREEN );
192
193 for( int j = 0; j < ni; j++ )
194 overlay->AnnotatedPoint( ips[j], arcs[i].GetWidth() );
195
196 if( collides )
197 {
198 overlay->SetStrokeColor( YELLOW );
199 overlay->Line( closestDist.A, closestDist.B );
200 overlay->SetLineWidth( 10000 );
201 overlay->SetGlyphSize( { 100000, 100000 } );
202 overlay->BitmapText( wxString::Format( "dist=%d, l=%d", closestDist.Length() ),
203 closestDist.A + VECTOR2I( 0, -arcs[i].GetWidth() ),
205 }
206
207 overlay->SetLineWidth( 10000 );
208 overlay->SetStrokeColor( CYAN );
209 overlay->AnnotatedPoint( arcs[i].GetP0(), arcs[i].GetWidth() / 2 );
210 overlay->AnnotatedPoint( arcs[i + 1].GetP0(), arcs[i + 1].GetWidth() / 2 );
211 overlay->AnnotatedPoint( arcs[i].GetArcMid(), arcs[i].GetWidth() / 2 );
212 overlay->AnnotatedPoint( arcs[i + 1].GetArcMid(), arcs[i + 1].GetWidth() / 2 );
213 overlay->AnnotatedPoint( arcs[i].GetP1(), arcs[i].GetWidth() / 2 );
214 overlay->AnnotatedPoint( arcs[i + 1].GetP1(), arcs[i + 1].GetWidth() / 2 );
215
216
217 overlay->SetStrokeColor( RED );
218 overlay->Arc( arcs[i] );
219 overlay->SetStrokeColor( MAGENTA );
220 overlay->Arc( arcs[i + 1] );
221 }
222
223
224 overlay = nullptr;
225
226 return 0;
227}
228
229
230
231int drawShapes( int argc, char* argv[] )
232{
233 SHAPE_ARC arc( VECTOR2I( 206000000, 140110000 ), VECTOR2I( 201574617, 139229737 ),
234 VECTOR2I( 197822958, 136722959 ), 250000 );
235
236 SHAPE_LINE_CHAIN lc( { /* VECTOR2I( 159600000, 142500000 ), VECTOR2I( 159600000, 142600000 ),
237 VECTOR2I( 166400000, 135800000 ), VECTOR2I( 166400000, 111600000 ),
238 VECTOR2I( 190576804, 111600000 ), VECTOR2I( 192242284, 113265480 ),
239 VECTOR2I( 192255720, 113265480 ),*/
240 VECTOR2I( 203682188, 124691948 ), VECTOR2I( 203682188, 140332188 ),
241 /* VECTOR2I( 206000000, 142650000 ) */ },
242 false );
243
244 auto frame = new PNS_LOG_VIEWER_FRAME( nullptr );
245 Pgm().App().SetTopWindow( frame ); // wxApp gets a face.
246 frame->Show();
247
248 overlay = frame->GetOverlay();
249
250
251 overlay->SetIsFill( false );
252 overlay->SetLineWidth( arc.GetWidth() );
253 overlay->SetStrokeColor( RED );
254 overlay->Arc( arc );
255 overlay->SetLineWidth( arc.GetWidth() / 20 );
256 overlay->SetStrokeColor( GREEN );
257 overlay->Polyline( lc );
258
259 overlay->SetLineWidth( 80000.0 );
260 overlay->SetStrokeColor( CYAN );
261
262 for( int i = 0; i < lc.PointCount(); ++i )
263 {
264 int mult = ( i % 2 ) ? 1 : -1;
265 overlay->AnnotatedPoint( lc.GetPoint( i ), arc.GetWidth() * 2 );
266 overlay->SetGlyphSize( { 800000, 800000 } );
267 overlay->BitmapText( wxString::Format( "x=%d, y=%d",
268 lc.GetPoint( i ).x,
269 lc.GetPoint( i ).y ),
270 lc.GetPoint( i ) + VECTOR2I( 0, mult*arc.GetWidth() * 4 ),
272 }
273
274 arc.Collide( &lc, 100000 );
275
276 BOX2I vp = arc.BBox();
277 vp.Merge( lc.BBox() );
278 vp.Inflate( (800000 + arc.GetWidth() * 4 )*2);
279 frame->GetPanel()->GetView()->SetViewport( BOX2D( vp.GetOrigin(), vp.GetSize() ) );
280
281 overlay = nullptr;
282
283 return 0;
284}
285
286
288 "playground",
289 "Geometry/drawing playground",
291} );
292
293
295 "drawShapes",
296 "drawing shapes",
298} );
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
BOX2< VECTOR2D > BOX2D
Definition: box2.h:848
const Vec & GetOrigin() const
Definition: box2.h:183
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:506
const Vec & GetSize() const
Definition: box2.h:179
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:588
Definition: seg.h:42
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
int Length() const
Return the length (this).
Definition: seg.h:326
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
Definition: shape_arc.cpp:355
int GetWidth() const
Definition: shape_arc.h:157
const VECTOR2I & GetP1() const
Definition: shape_arc.h:113
int IntersectLine(const SEG &aSeg, std::vector< VECTOR2I > *aIpsBuffer) const
Find intersection points between this arc and aSeg, treating aSeg as an infinite line.
Definition: shape_arc.cpp:273
bool Collide(const SEG &aSeg, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if the boundary of shape (this) lies closer to the segment aSeg than aClearance,...
Definition: shape_arc.cpp:241
int Intersect(const SHAPE_ARC &aArc, std::vector< VECTOR2I > *aIpsBuffer) const
Find intersection points between this arc and aArc.
Definition: shape_arc.cpp:294
VECTOR2I GetCenter() const
Definition: shape_arc.cpp:433
const VECTOR2I & GetP0() const
Definition: shape_arc.h:112
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
static bool Register(const KI_TEST::UTILITY_PROGRAM &aProgInfo)
Register a utility program factory function against an ID string.
@ MAGENTA
Definition: color4d.h:60
@ GREEN
Definition: color4d.h:57
@ CYAN
Definition: color4d.h:58
@ YELLOW
Definition: color4d.h:67
@ RED
Definition: color4d.h:59
static constexpr EDA_ANGLE & ANGLE_HORIZONTAL
Definition: eda_angle.h:408
@ DEGREES_T
Definition: eda_angle.h:31
see class PGM_BASE
static bool registered
Definition: playground.cpp:287
int playground_main_func(int argc, char *argv[])
Definition: playground.cpp:107
static bool registered1
Definition: playground.cpp:294
int drawShapes(int argc, char *argv[])
Definition: playground.cpp:231
bool collideArc2Arc(const SHAPE_ARC &a1, const SHAPE_ARC &a2, int clearance, SEG &minDistSeg)
Definition: playground.cpp:39
std::shared_ptr< PNS_LOG_VIEWER_OVERLAY > overlay
Definition: playground.cpp:36
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:111
constexpr int mmToIU(double mm) const
Definition: base_units.h:89
double EuclideanNorm(const VECTOR2I &vector)
Definition: trigo.h:129
VECTOR2< double > VECTOR2D
Definition: vector2d.h:617
VECTOR2< int > VECTOR2I
Definition: vector2d.h:618