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 
31 #include "pns_log_viewer_frame.h"
32 #include "label_manager.h"
33 
34 #include <geometry/shape_arc.h>
35 
36 std::shared_ptr<PNS_LOG_VIEWER_OVERLAY> overlay;
37 
38 
39 bool 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 
107 int 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( Millimeter2iu( d.cx ), Millimeter2iu( d.cy ) ),
167  VECTOR2D( Millimeter2iu( d.sx ), Millimeter2iu( d.sy ) ), d.ca,
168  Millimeter2iu( 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 %lu 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.0 );
201  overlay->SetGlyphSize( { 100000.0, 100000.0 } );
202  overlay->BitmapText( wxString::Format( "dist=%d, l=%d", closestDist.Length() ),
203  closestDist.A + VECTOR2I( 0, -arcs[i].GetWidth() ), 0 );
204  }
205 
206  overlay->SetLineWidth( 10000.0 );
207  overlay->SetStrokeColor( CYAN );
208  overlay->AnnotatedPoint( arcs[i].GetP0(), arcs[i].GetWidth() / 2 );
209  overlay->AnnotatedPoint( arcs[i + 1].GetP0(), arcs[i + 1].GetWidth() / 2 );
210  overlay->AnnotatedPoint( arcs[i].GetArcMid(), arcs[i].GetWidth() / 2 );
211  overlay->AnnotatedPoint( arcs[i + 1].GetArcMid(), arcs[i + 1].GetWidth() / 2 );
212  overlay->AnnotatedPoint( arcs[i].GetP1(), arcs[i].GetWidth() / 2 );
213  overlay->AnnotatedPoint( arcs[i + 1].GetP1(), arcs[i + 1].GetWidth() / 2 );
214 
215 
216  overlay->SetStrokeColor( RED );
217  overlay->Arc( arcs[i] );
218  overlay->SetStrokeColor( MAGENTA );
219  overlay->Arc( arcs[i + 1] );
220  }
221 
222 
223  overlay = nullptr;
224 
225  return 0;
226 }
227 
229  "playground",
230  "Geometry/drawing playground",
232 } );
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:146
int Length() const
Return the length (this).
Definition: seg.h:350
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
static bool registered
Definition: playground.cpp:228
BOX2< VECTOR2D > BOX2D
Definition: box2.h:507
int Intersect(const SHAPE_ARC &aArc, std::vector< VECTOR2I > *aIpsBuffer) const
Find intersection points between this arc and aArc.
Definition: shape_arc.cpp:319
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:106
Definition: color4d.h:67
VECTOR2< double > VECTOR2D
Definition: vector2d.h:622
static bool Register(const KI_TEST::UTILITY_PROGRAM &aProgInfo)
Register a utility program factory function against an ID string.
Definition: color4d.h:57
const VECTOR2I & GetP0() const
Definition: shape_arc.h:111
Definition: color4d.h:58
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:363
Definition: color4d.h:59
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:301
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
Definition: seg.h:40
int GetWidth() const
Definition: shape_arc.h:156
int playground_main_func(int argc, char *argv[])
Definition: playground.cpp:107
see class PGM_BASE
VECTOR2I A
Definition: seg.h:48
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:380
const Vec & GetSize() const
Definition: box2.h:172
const Vec & GetOrigin() const
Definition: box2.h:176
static constexpr int Millimeter2iu(double mm)
const VECTOR2I & GetP1() const
Definition: shape_arc.h:112
VECTOR2I GetCenter() const
Definition: shape_arc.cpp:464
VECTOR2I B
Definition: seg.h:49