KiCad PCB EDA Suite
drc_clearance_test_functions.cpp
Go to the documentation of this file.
1 
5 /*
6  * This program source code file is part of KiCad, a free EDA CAD application.
7  *
8  * Copyright (C) 2004-2016 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.fr
9  * Copyright (C) 2007 Dick Hollenbeck, dick@softplc.com
10  * Copyright (C) 2016 KiCad Developers, see change_log.txt for contributors.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, you may find one here:
24  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
25  * or you may search the http://www.gnu.org website for the version 2 license,
26  * or you may write to the Free Software Foundation, Inc.,
27  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
28  */
29 
34 #include <fctsys.h>
35 #include <wxPcbStruct.h>
36 #include <trigo.h>
37 
38 #include <pcbnew.h>
39 #include <drc_stuff.h>
40 
41 #include <class_board.h>
42 #include <class_module.h>
43 #include <class_track.h>
44 #include <class_zone.h>
45 #include <class_marker_pcb.h>
46 #include <math_for_graphics.h>
49 
50 
51 /* compare 2 convex polygons and return true if distance > aDist
52  * i.e if for each edge of the first polygon distance from each edge of the other polygon
53  * is >= aDist
54  */
55 bool poly2polyDRC( wxPoint* aTref, int aTrefCount,
56  wxPoint* aTcompare, int aTcompareCount, int aDist )
57 {
58  /* Test if one polygon is contained in the other and thus the polygon overlap.
59  * This case is not covered by the following check if one polygone is
60  * completely contained in the other (because edges don't intersect)!
61  */
62  if( TestPointInsidePolygon( aTref, aTrefCount, aTcompare[0] ) )
63  return false;
64 
65  if( TestPointInsidePolygon( aTcompare, aTcompareCount, aTref[0] ) )
66  return false;
67 
68  for( int ii = 0, jj = aTrefCount - 1; ii < aTrefCount; jj = ii, ii++ )
69  { // for all edges in aTref
70  for( int kk = 0, ll = aTcompareCount - 1; kk < aTcompareCount; ll = kk, kk++ )
71  { // for all edges in aTcompare
72  double d;
74  aTref[ii].x, aTref[ii].y, aTref[jj].x, aTref[jj].y,
75  aTcompare[kk].x, aTcompare[kk].y, aTcompare[ll].x, aTcompare[ll].y,
76  NULL, NULL, &d );
77 
78  if( intersect || ( d< aDist ) )
79  return false;
80  }
81  }
82 
83  return true;
84 }
85 
86 /* compare a trapezoids (can be rectangle) and a segment and return true if distance > aDist
87  */
88 bool poly2segmentDRC( wxPoint* aTref, int aTrefCount, wxPoint aSegStart, wxPoint aSegEnd, int aDist )
89 {
90  /* Test if the segment is contained in the polygon.
91  * This case is not covered by the following check if the segment is
92  * completely contained in the polygon (because edges don't intersect)!
93  */
94  if( TestPointInsidePolygon( aTref, aTrefCount, aSegStart ) )
95  return false;
96 
97  for( int ii = 0, jj = aTrefCount-1; ii < aTrefCount; jj = ii, ii++ )
98  { // for all edges in polygon
99  double d;
101  aTref[ii].x, aTref[ii].y, aTref[jj].x, aTref[jj].y,
102  aSegStart.x, aSegStart.y, aSegEnd.x, aSegEnd.y,
103  NULL, NULL, &d );
104 
105  if( intersect || ( d < aDist) )
106  return false;
107  }
108 
109  return true;
110 }
111 
112 /* compare a polygon to a point and return true if distance > aDist
113  * do not use this function for horizontal or vertical rectangles
114  * because there is a faster an easier way to compare the distance
115  */
116 bool convex2pointDRC( wxPoint* aTref, int aTrefCount, wxPoint aPcompare, int aDist )
117 {
118  /* Test if aPcompare point is contained in the polygon.
119  * This case is not covered by the following check if this point is inside the polygon
120  */
121  if( TestPointInsidePolygon( aTref, aTrefCount, aPcompare ) )
122  {
123  return false;
124  }
125 
126  // Test distance between aPcompare and each segment of the polygon:
127  for( int ii = 0, jj = aTrefCount - 1; ii < aTrefCount; jj = ii, ii++ ) // for all edge in polygon
128  {
129  if( TestSegmentHit( aPcompare, aTref[ii], aTref[jj], aDist ) )
130  return false;
131  }
132 
133  return true;
134 }
135 
136 
137 bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
138 {
139  TRACK* track;
140  wxPoint delta; // length on X and Y axis of segments
141  LSET layerMask;
142  int net_code_ref;
143  wxPoint shape_pos;
144 
145  NETCLASSPTR netclass = aRefSeg->GetNetClass();
147 
148  /* In order to make some calculations more easier or faster,
149  * pads and tracks coordinates will be made relative to the reference segment origin
150  */
151  wxPoint origin = aRefSeg->GetStart(); // origin will be the origin of other coordinates
152 
153  m_segmEnd = delta = aRefSeg->GetEnd() - origin;
154  m_segmAngle = 0;
155 
156  layerMask = aRefSeg->GetLayerSet();
157  net_code_ref = aRefSeg->GetNetCode();
158 
159  // Phase 0 : Test vias
160  if( aRefSeg->Type() == PCB_VIA_T )
161  {
162  const VIA *refvia = static_cast<const VIA*>( aRefSeg );
163  // test if the via size is smaller than minimum
164  if( refvia->GetViaType() == VIA_MICROVIA )
165  {
166  if( refvia->GetWidth() < dsnSettings.m_MicroViasMinSize )
167  {
168  m_currentMarker = fillMarker( refvia, NULL,
170  return false;
171  }
172  if( refvia->GetDrillValue() < dsnSettings.m_MicroViasMinDrill )
173  {
174  m_currentMarker = fillMarker( refvia, NULL,
176  return false;
177  }
178  }
179  else
180  {
181  if( refvia->GetWidth() < dsnSettings.m_ViasMinSize )
182  {
183  m_currentMarker = fillMarker( refvia, NULL,
185  return false;
186  }
187  if( refvia->GetDrillValue() < dsnSettings.m_ViasMinDrill )
188  {
189  m_currentMarker = fillMarker( refvia, NULL,
191  return false;
192  }
193  }
194 
195  // test if via's hole is bigger than its diameter
196  // This test is necessary since the via hole size and width can be modified
197  // and a default via hole can be bigger than some vias sizes
198  if( refvia->GetDrillValue() > refvia->GetWidth() )
199  {
200  m_currentMarker = fillMarker( refvia, NULL,
202  return false;
203  }
204 
205  // For microvias: test if they are blind vias and only between 2 layers
206  // because they are used for very small drill size and are drill by laser
207  // and **only one layer** can be drilled
208  if( refvia->GetViaType() == VIA_MICROVIA )
209  {
210  LAYER_ID layer1, layer2;
211  bool err = true;
212 
213  refvia->LayerPair( &layer1, &layer2 );
214 
215  if( layer1 > layer2 )
216  std::swap( layer1, layer2 );
217 
218  if( layer2 == B_Cu && layer1 == m_pcb->GetDesignSettings().GetCopperLayerCount() - 2 )
219  err = false;
220  else if( layer1 == F_Cu && layer2 == In1_Cu )
221  err = false;
222 
223  if( err )
224  {
225  m_currentMarker = fillMarker( refvia, NULL,
227  return false;
228  }
229  }
230  }
231  else // This is a track segment
232  {
233  if( aRefSeg->GetWidth() < dsnSettings.m_TrackMinWidth )
234  {
235  m_currentMarker = fillMarker( aRefSeg, NULL,
237  return false;
238  }
239  }
240 
241  // for a non horizontal or vertical segment Compute the segment angle
242  // in tenths of degrees and its length
243  if( delta.x || delta.y )
244  {
245  // Compute the segment angle in 0,1 degrees
246  m_segmAngle = ArcTangente( delta.y, delta.x );
247 
248  // Compute the segment length: we build an equivalent rotated segment,
249  // this segment is horizontal, therefore dx = length
250  RotatePoint( &delta, m_segmAngle ); // delta.x = length, delta.y = 0
251  }
252 
253  m_segmLength = delta.x;
254 
255  /******************************************/
256  /* Phase 1 : test DRC track to pads : */
257  /******************************************/
258 
259  /* Use a dummy pad to test DRC tracks versus holes, for pads not on all copper layers
260  * but having a hole
261  * This dummy pad has the size and shape of the hole
262  * to test tracks to pad hole DRC, using checkClearanceSegmToPad test function.
263  * Therefore, this dummy pad is a circle or an oval.
264  * A pad must have a parent because some functions expect a non null parent
265  * to find the parent board, and some other data
266  */
267  MODULE dummymodule( m_pcb ); // Creates a dummy parent
268  D_PAD dummypad( &dummymodule );
269 
270  dummypad.SetLayerSet( LSET::AllCuMask() ); // Ensure the hole is on all layers
271 
272  // Compute the min distance to pads
273  if( testPads )
274  {
275  unsigned pad_count = m_pcb->GetPadCount();
276 
277  for( unsigned ii = 0; ii<pad_count; ++ii )
278  {
279  D_PAD* pad = m_pcb->GetPad( ii );
280 
281  /* No problem if pads are on an other layer,
282  * But if a drill hole exists (a pad on a single layer can have a hole!)
283  * we must test the hole
284  */
285  if( !( pad->GetLayerSet() & layerMask ).any() )
286  {
287  /* We must test the pad hole. In order to use the function
288  * checkClearanceSegmToPad(),a pseudo pad is used, with a shape and a
289  * size like the hole
290  */
291  if( pad->GetDrillSize().x == 0 )
292  continue;
293 
294  dummypad.SetSize( pad->GetDrillSize() );
295  dummypad.SetPosition( pad->GetPosition() );
296  dummypad.SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
298  dummypad.SetOrientation( pad->GetOrientation() );
299 
300  m_padToTestPos = dummypad.GetPosition() - origin;
301 
302  if( !checkClearanceSegmToPad( &dummypad, aRefSeg->GetWidth(),
303  netclass->GetClearance() ) )
304  {
305  m_currentMarker = fillMarker( aRefSeg, pad,
307  return false;
308  }
309 
310  continue;
311  }
312 
313  // The pad must be in a net (i.e pt_pad->GetNet() != 0 )
314  // but no problem if the pad netcode is the current netcode (same net)
315  if( pad->GetNetCode() // the pad must be connected
316  && net_code_ref == pad->GetNetCode() ) // the pad net is the same as current net -> Ok
317  continue;
318 
319  // DRC for the pad
320  shape_pos = pad->ShapePos();
321  m_padToTestPos = shape_pos - origin;
322 
323  if( !checkClearanceSegmToPad( pad, aRefSeg->GetWidth(), aRefSeg->GetClearance( pad ) ) )
324  {
325  m_currentMarker = fillMarker( aRefSeg, pad,
327  return false;
328  }
329  }
330  }
331 
332  /***********************************************/
333  /* Phase 2: test DRC with other track segments */
334  /***********************************************/
335 
336  // At this point the reference segment is the X axis
337 
338  // Test the reference segment with other track segments
339  wxPoint segStartPoint;
340  wxPoint segEndPoint;
341  for( track = aStart; track; track = track->Next() )
342  {
343  // No problem if segments have the same net code:
344  if( net_code_ref == track->GetNetCode() )
345  continue;
346 
347  // No problem if segment are on different layers :
348  if( !( layerMask & track->GetLayerSet() ).any() )
349  continue;
350 
351  // the minimum distance = clearance plus half the reference track
352  // width plus half the other track's width
353  int w_dist = aRefSeg->GetClearance( track );
354  w_dist += (aRefSeg->GetWidth() + track->GetWidth()) / 2;
355 
356  // Due to many double to int conversions during calculations, which
357  // create rounding issues,
358  // the exact clearance margin cannot be really known.
359  // To avoid false bad DRC detection due to these rounding issues,
360  // slightly decrease the w_dist (remove one nanometer is enough !)
361  w_dist -= 1;
362 
363  // If the reference segment is a via, we test it here
364  if( aRefSeg->Type() == PCB_VIA_T )
365  {
366  delta = track->GetEnd() - track->GetStart();
367  segStartPoint = aRefSeg->GetStart() - track->GetStart();
368 
369  if( track->Type() == PCB_VIA_T )
370  {
371  // Test distance between two vias, i.e. two circles, trivial case
372  if( EuclideanNorm( segStartPoint ) < w_dist )
373  {
374  m_currentMarker = fillMarker( aRefSeg, track,
376  return false;
377  }
378  }
379  else // test via to segment
380  {
381  // Compute l'angle du segment a tester;
382  double angle = ArcTangente( delta.y, delta.x );
383 
384  // Compute new coordinates ( the segment become horizontal)
385  RotatePoint( &delta, angle );
386  RotatePoint( &segStartPoint, angle );
387 
388  if( !checkMarginToCircle( segStartPoint, w_dist, delta.x ) )
389  {
390  m_currentMarker = fillMarker( track, aRefSeg,
392  return false;
393  }
394  }
395 
396  continue;
397  }
398 
399  /* We compute segStartPoint, segEndPoint = starting and ending point coordinates for
400  * the segment to test in the new axis : the new X axis is the
401  * reference segment. We must translate and rotate the segment to test
402  */
403  segStartPoint = track->GetStart() - origin;
404  segEndPoint = track->GetEnd() - origin;
405  RotatePoint( &segStartPoint, m_segmAngle );
406  RotatePoint( &segEndPoint, m_segmAngle );
407  if( track->Type() == PCB_VIA_T )
408  {
409  if( checkMarginToCircle( segStartPoint, w_dist, m_segmLength ) )
410  continue;
411 
412  m_currentMarker = fillMarker( aRefSeg, track,
414  return false;
415  }
416 
417  /* We have changed axis:
418  * the reference segment is Horizontal.
419  * 3 cases : the segment to test can be parallel, perpendicular or have an other direction
420  */
421  if( segStartPoint.y == segEndPoint.y ) // parallel segments
422  {
423  if( abs( segStartPoint.y ) >= w_dist )
424  continue;
425 
426  // Ensure segStartPoint.x <= segEndPoint.x
427  if( segStartPoint.x > segEndPoint.x )
428  std::swap( segStartPoint.x, segEndPoint.x );
429 
430  if( segStartPoint.x > (-w_dist) && segStartPoint.x < (m_segmLength + w_dist) ) /* possible error drc */
431  {
432  // the start point is inside the reference range
433  // X........
434  // O--REF--+
435 
436  // Fine test : we consider the rounded shape of each end of the track segment:
437  if( segStartPoint.x >= 0 && segStartPoint.x <= m_segmLength )
438  {
439  m_currentMarker = fillMarker( aRefSeg, track,
441  return false;
442  }
443 
444  if( !checkMarginToCircle( segStartPoint, w_dist, m_segmLength ) )
445  {
446  m_currentMarker = fillMarker( aRefSeg, track,
448  return false;
449  }
450  }
451 
452  if( segEndPoint.x > (-w_dist) && segEndPoint.x < (m_segmLength + w_dist) )
453  {
454  // the end point is inside the reference range
455  // .....X
456  // O--REF--+
457  // Fine test : we consider the rounded shape of the ends
458  if( segEndPoint.x >= 0 && segEndPoint.x <= m_segmLength )
459  {
460  m_currentMarker = fillMarker( aRefSeg, track,
462  return false;
463  }
464 
465  if( !checkMarginToCircle( segEndPoint, w_dist, m_segmLength ) )
466  {
467  m_currentMarker = fillMarker( aRefSeg, track,
469  return false;
470  }
471  }
472 
473  if( segStartPoint.x <=0 && segEndPoint.x >= 0 )
474  {
475  // the segment straddles the reference range (this actually only
476  // checks if it straddles the origin, because the other cases where already
477  // handled)
478  // X.............X
479  // O--REF--+
480  m_currentMarker = fillMarker( aRefSeg, track,
482  return false;
483  }
484  }
485  else if( segStartPoint.x == segEndPoint.x ) // perpendicular segments
486  {
487  if( ( segStartPoint.x <= (-w_dist) ) || ( segStartPoint.x >= (m_segmLength + w_dist) ) )
488  continue;
489 
490  // Test if segments are crossing
491  if( segStartPoint.y > segEndPoint.y )
492  std::swap( segStartPoint.y, segEndPoint.y );
493 
494  if( (segStartPoint.y < 0) && (segEndPoint.y > 0) )
495  {
496  m_currentMarker = fillMarker( aRefSeg, track,
498  return false;
499  }
500 
501  // At this point the drc error is due to an end near a reference segm end
502  if( !checkMarginToCircle( segStartPoint, w_dist, m_segmLength ) )
503  {
504  m_currentMarker = fillMarker( aRefSeg, track,
506  return false;
507  }
508  if( !checkMarginToCircle( segEndPoint, w_dist, m_segmLength ) )
509  {
510  m_currentMarker = fillMarker( aRefSeg, track,
512  return false;
513  }
514  }
515  else // segments quelconques entre eux
516  {
517  // calcul de la "surface de securite du segment de reference
518  // First rought 'and fast) test : the track segment is like a rectangle
519 
520  m_xcliplo = m_ycliplo = -w_dist;
521  m_xcliphi = m_segmLength + w_dist;
522  m_ycliphi = w_dist;
523 
524  // A fine test is needed because a serment is not exactly a
525  // rectangle, it has rounded ends
526  if( !checkLine( segStartPoint, segEndPoint ) )
527  {
528  /* 2eme passe : the track has rounded ends.
529  * we must a fine test for each rounded end and the
530  * rectangular zone
531  */
532 
533  m_xcliplo = 0;
535 
536  if( !checkLine( segStartPoint, segEndPoint ) )
537  {
538  m_currentMarker = fillMarker( aRefSeg, track,
540  return false;
541  }
542  else // The drc error is due to the starting or the ending point of the reference segment
543  {
544  // Test the starting and the ending point
545  segStartPoint = track->GetStart();
546  segEndPoint = track->GetEnd();
547  delta = segEndPoint - segStartPoint;
548 
549  // Compute the segment orientation (angle) en 0,1 degre
550  double angle = ArcTangente( delta.y, delta.x );
551 
552  // Compute the segment length: delta.x = length after rotation
553  RotatePoint( &delta, angle );
554 
555  /* Comute the reference segment coordinates relatives to a
556  * X axis = current tested segment
557  */
558  wxPoint relStartPos = aRefSeg->GetStart() - segStartPoint;
559  wxPoint relEndPos = aRefSeg->GetEnd() - segStartPoint;
560 
561  RotatePoint( &relStartPos, angle );
562  RotatePoint( &relEndPos, angle );
563 
564  if( !checkMarginToCircle( relStartPos, w_dist, delta.x ) )
565  {
566  m_currentMarker = fillMarker( aRefSeg, track,
568  return false;
569  }
570 
571  if( !checkMarginToCircle( relEndPos, w_dist, delta.x ) )
572  {
573  m_currentMarker = fillMarker( aRefSeg, track,
575  return false;
576  }
577  }
578  }
579  }
580  }
581 
582  return true;
583 }
584 
585 
586 /* test DRC between 2 pads.
587  * this function can be also used to test DRC between a pad and a hole,
588  * because a hole is like a round or oval pad.
589  */
590 bool DRC::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad )
591 {
592  int dist;
593  double pad_angle;
594 
595  // Get the clearance between the 2 pads. this is the min distance between aRefPad and aPad
596  int dist_min = aRefPad->GetClearance( aPad );
597 
598  // relativePadPos is the aPad shape position relative to the aRefPad shape position
599  wxPoint relativePadPos = aPad->ShapePos() - aRefPad->ShapePos();
600 
601  dist = KiROUND( EuclideanNorm( relativePadPos ) );
602 
603  // Quick test: Clearance is OK if the bounding circles are further away than "dist_min"
604  if( (dist - aRefPad->GetBoundingRadius() - aPad->GetBoundingRadius()) >= dist_min )
605  return true;
606 
607  /* Here, pads are near and DRC depend on the pad shapes
608  * We must compare distance using a fine shape analysis
609  * Because a circle or oval shape is the easier shape to test, try to have
610  * aRefPad shape type = PAD_SHAPE_CIRCLE or PAD_SHAPE_OVAL.
611  * if aRefPad = TRAP. and aPad = RECT, also swap pads
612  * Swap aRefPad and aPad if needed
613  */
614  bool swap_pads;
615  swap_pads = false;
616 
617  // swap pads to make comparisons easier
618  // Note also a ROUNDRECT pad with a corner radius = r can be considered as
619  // a smaller RECT (size - 2*r) with a clearance increased by r
620  // priority is aRefPad = ROUND then OVAL then RECT/ROUNDRECT then other
621  if( aRefPad->GetShape() != aPad->GetShape() && aRefPad->GetShape() != PAD_SHAPE_CIRCLE )
622  {
623  // pad ref shape is here oval, rect, roundrect, trapezoid or custom
624  switch( aPad->GetShape() )
625  {
626  case PAD_SHAPE_CIRCLE:
627  swap_pads = true;
628  break;
629 
630  case PAD_SHAPE_OVAL:
631  swap_pads = true;
632  break;
633 
634  case PAD_SHAPE_RECT:
635  case PAD_SHAPE_ROUNDRECT:
636  if( aRefPad->GetShape() != PAD_SHAPE_OVAL )
637  swap_pads = true;
638  break;
639 
640  default:
641  break;
642  }
643  }
644 
645  if( swap_pads )
646  {
647  std::swap( aRefPad, aPad );
648  relativePadPos = -relativePadPos;
649  }
650 
651  // corners of aRefPad (used only for rect/roundrect/trap pad)
652  wxPoint polyref[4];
653  // corners of aRefPad (used only for custom pad)
654  SHAPE_POLY_SET polysetref;
655 
656  // corners of aPad (used only for rect/roundrect/trap pad)
657  wxPoint polycompare[4];
658  // corners of aPad (used only custom pad)
659  SHAPE_POLY_SET polysetcompare;
660 
661  /* Because pad exchange, aRefPad shape is PAD_SHAPE_CIRCLE or PAD_SHAPE_OVAL,
662  * if one of the 2 pads was a PAD_SHAPE_CIRCLE or PAD_SHAPE_OVAL.
663  * Therefore, if aRefPad is a PAD_SHAPE_RECT, PAD_SHAPE_ROUNDRECT or a PAD_SHAPE_TRAPEZOID,
664  * aPad is also a PAD_SHAPE_RECT, PAD_SHAPE_ROUNDRECT or a PAD_SHAPE_TRAPEZOID
665  */
666  bool diag = true;
667 
668  switch( aRefPad->GetShape() )
669  {
670  case PAD_SHAPE_CIRCLE:
671 
672  /* One can use checkClearanceSegmToPad to test clearance
673  * aRefPad is like a track segment with a null length and a witdth = GetSize().x
674  */
675  m_segmLength = 0;
676  m_segmAngle = 0;
677 
678  m_segmEnd.x = m_segmEnd.y = 0;
679 
680  m_padToTestPos = relativePadPos;
681  diag = checkClearanceSegmToPad( aPad, aRefPad->GetSize().x, dist_min );
682  break;
683 
684  case PAD_SHAPE_TRAPEZOID:
685  case PAD_SHAPE_ROUNDRECT:
686  case PAD_SHAPE_RECT:
687  // pad_angle = pad orient relative to the aRefPad orient
688  pad_angle = aRefPad->GetOrientation() + aPad->GetOrientation();
689  NORMALIZE_ANGLE_POS( pad_angle );
690 
691  if( aRefPad->GetShape() == PAD_SHAPE_ROUNDRECT )
692  {
693  int padRadius = aRefPad->GetRoundRectCornerRadius();
694  dist_min += padRadius;
695  GetRoundRectCornerCenters( polyref, padRadius, wxPoint( 0, 0 ),
696  aRefPad->GetSize(), aRefPad->GetOrientation() );
697  }
698  else
699  aRefPad->BuildPadPolygon( polyref, wxSize( 0, 0 ), aRefPad->GetOrientation() );
700 
701  switch( aPad->GetShape() )
702  {
703  case PAD_SHAPE_ROUNDRECT:
704  case PAD_SHAPE_RECT:
705  case PAD_SHAPE_TRAPEZOID:
706  if( aPad->GetShape() == PAD_SHAPE_ROUNDRECT )
707  {
708  int padRadius = aPad->GetRoundRectCornerRadius();
709  dist_min += padRadius;
710  GetRoundRectCornerCenters( polycompare, padRadius, relativePadPos,
711  aPad->GetSize(), aPad->GetOrientation() );
712  }
713  else
714  {
715  aPad->BuildPadPolygon( polycompare, wxSize( 0, 0 ), aPad->GetOrientation() );
716 
717  // Move aPad shape to relativePadPos
718  for( int ii = 0; ii < 4; ii++ )
719  polycompare[ii] += relativePadPos;
720  }
721 
722  // And now test polygons:
723  if( polysetref.OutlineCount() )
724  {
725  const SHAPE_LINE_CHAIN& refpoly = polysetref.COutline( 0 );
726  // And now test polygons:
727  if( !poly2polyDRC( (wxPoint*) &refpoly.CPoint( 0 ), refpoly.PointCount(),
728  polycompare, 4, dist_min ) )
729  diag = false;
730  }
731  else if( !poly2polyDRC( polyref, 4, polycompare, 4, dist_min ) )
732  diag = false;
733  break;
734 
735  default:
736  wxLogDebug( wxT( "DRC::checkClearancePadToPad: unexpected pad shape %d" ), aPad->GetShape() );
737  break;
738  }
739  break;
740 
741  case PAD_SHAPE_OVAL: /* an oval pad is like a track segment */
742  {
743  /* Create a track segment with same dimensions as the oval aRefPad
744  * and use checkClearanceSegmToPad function to test aPad to aRefPad clearance
745  */
746  int segm_width;
747  m_segmAngle = aRefPad->GetOrientation(); // Segment orient.
748 
749  if( aRefPad->GetSize().y < aRefPad->GetSize().x ) // Build an horizontal equiv segment
750  {
751  segm_width = aRefPad->GetSize().y;
752  m_segmLength = aRefPad->GetSize().x - aRefPad->GetSize().y;
753  }
754  else // Vertical oval: build an horizontal equiv segment and rotate 90.0 deg
755  {
756  segm_width = aRefPad->GetSize().x;
757  m_segmLength = aRefPad->GetSize().y - aRefPad->GetSize().x;
758  m_segmAngle += 900;
759  }
760 
761  /* the start point must be 0,0 and currently relativePadPos
762  * is relative the center of pad coordinate */
763  wxPoint segstart;
764  segstart.x = -m_segmLength / 2; // Start point coordinate of the horizontal equivalent segment
765 
766  RotatePoint( &segstart, m_segmAngle ); // actual start point coordinate of the equivalent segment
767  // Calculate segment end position relative to the segment origin
768  m_segmEnd.x = -2 * segstart.x;
769  m_segmEnd.y = -2 * segstart.y;
770 
771  // Recalculate the equivalent segment angle in 0,1 degrees
772  // to prepare a call to checkClearanceSegmToPad()
774 
775  // move pad position relative to the segment origin
776  m_padToTestPos = relativePadPos - segstart;
777 
778  // Use segment to pad check to test the second pad:
779  diag = checkClearanceSegmToPad( aPad, segm_width, dist_min );
780  break;
781  }
782 
783  default:
784  wxLogDebug( wxT( "DRC::checkClearancePadToPad: unknown pad shape" ) );
785  break;
786  }
787 
788  return diag;
789 }
790 
791 
792 /* test if distance between a segment is > aMinDist
793  * segment start point is assumed in (0,0) and segment start point in m_segmEnd
794  * and its orientation is m_segmAngle (m_segmAngle must be already initialized)
795  * and have aSegmentWidth.
796  */
797 bool DRC::checkClearanceSegmToPad( const D_PAD* aPad, int aSegmentWidth, int aMinDist )
798 {
799  wxSize padHalfsize; // half dimension of the pad
800  int r;
801 
802  int segmHalfWidth = aSegmentWidth / 2;
803  int distToLine = segmHalfWidth + aMinDist;
804 
805  padHalfsize.x = aPad->GetSize().x >> 1;
806  padHalfsize.y = aPad->GetSize().y >> 1;
807 
808  if( aPad->GetShape() == PAD_SHAPE_TRAPEZOID ) // The size is bigger, due to GetDelta() extra size
809  {
810  padHalfsize.x += std::abs(aPad->GetDelta().y) / 2; // Remember: GetDelta().y is the GetSize().x change
811  padHalfsize.y += std::abs(aPad->GetDelta().x) / 2; // Remember: GetDelta().x is the GetSize().y change
812  }
813 
814  if( aPad->GetShape() == PAD_SHAPE_CIRCLE )
815  {
816  /* Easy case: just test the distance between segment and pad centre
817  * calculate pad coordinates in the X,Y axis with X axis = segment to test
818  */
820  return checkMarginToCircle( m_padToTestPos, distToLine + padHalfsize.x, m_segmLength );
821  }
822 
823  /* calculate the bounding box of the pad, including the clearance and the segment width
824  * if the line from 0 to m_segmEnd does not intersect this bounding box,
825  * the clearance is always OK
826  * But if intersect, a better analysis of the pad shape must be done.
827  */
828  m_xcliplo = m_padToTestPos.x - distToLine - padHalfsize.x;
829  m_ycliplo = m_padToTestPos.y - distToLine - padHalfsize.y;
830  m_xcliphi = m_padToTestPos.x + distToLine + padHalfsize.x;
831  m_ycliphi = m_padToTestPos.y + distToLine + padHalfsize.y;
832 
833  wxPoint startPoint;
834  wxPoint endPoint = m_segmEnd;
835 
836  double orient = aPad->GetOrientation();
837 
838  RotatePoint( &startPoint, m_padToTestPos, -orient );
839  RotatePoint( &endPoint, m_padToTestPos, -orient );
840 
841  if( checkLine( startPoint, endPoint ) )
842  return true;
843 
844  /* segment intersects the bounding box. But there is not always a DRC error.
845  * A fine analysis of the pad shape must be done.
846  */
847  switch( aPad->GetShape() )
848  {
849  default:
850  return false;
851 
852  case PAD_SHAPE_OVAL:
853  {
854  /* an oval is a complex shape, but is a rectangle and 2 circles
855  * these 3 basic shapes are more easy to test.
856  *
857  * In calculations we are using a vertical oval shape
858  * (i.e. a vertical rounded segment)
859  * for horizontal oval shapes, swap x and y size and rotate the shape
860  */
861  if( padHalfsize.x > padHalfsize.y )
862  {
863  std::swap( padHalfsize.x, padHalfsize.y );
864  orient = AddAngles( orient, 900 );
865  }
866 
867  // here, padHalfsize.x is the radius of rounded ends.
868 
869  int deltay = padHalfsize.y - padHalfsize.x;
870  // here: padHalfsize.x = radius,
871  // deltay = dist between the centre pad and the centre of a rounded end
872 
873  // Test the rectangular area between the two circles (the rounded ends)
874  m_xcliplo = m_padToTestPos.x - distToLine - padHalfsize.x;
875  m_ycliplo = m_padToTestPos.y - deltay;
876  m_xcliphi = m_padToTestPos.x + distToLine + padHalfsize.x;
877  m_ycliphi = m_padToTestPos.y + deltay;
878 
879  if( !checkLine( startPoint, endPoint ) )
880  {
881  return false;
882  }
883 
884  // test the first circle
885  startPoint.x = m_padToTestPos.x; // startPoint = centre of the upper circle of the oval shape
886  startPoint.y = m_padToTestPos.y + deltay;
887 
888  // Calculate the actual position of the circle, given the pad orientation:
889  RotatePoint( &startPoint, m_padToTestPos, orient );
890 
891  // Calculate the actual position of the circle in the new X,Y axis:
892  RotatePoint( &startPoint, m_segmAngle );
893 
894  if( !checkMarginToCircle( startPoint, padHalfsize.x + distToLine, m_segmLength ) )
895  {
896  return false;
897  }
898 
899  // test the second circle
900  startPoint.x = m_padToTestPos.x; // startPoint = centre of the lower circle of the oval shape
901  startPoint.y = m_padToTestPos.y - deltay;
902  RotatePoint( &startPoint, m_padToTestPos, orient );
903  RotatePoint( &startPoint, m_segmAngle );
904 
905  if( !checkMarginToCircle( startPoint, padHalfsize.x + distToLine, m_segmLength ) )
906  {
907  return false;
908  }
909  }
910  break;
911 
912  case PAD_SHAPE_ROUNDRECT:
913  // a round rect is a smaller rect, with a clearance augmented by the corners radius
914  r = aPad->GetRoundRectCornerRadius();
915  padHalfsize.x -= r;
916  padHalfsize.y -= r;
917  distToLine += r;
918  // Fall through
919  case PAD_SHAPE_RECT:
920  // the area to test is a rounded rectangle.
921  // this can be done by testing 2 rectangles and 4 circles (the corners)
922 
923  // Testing the first rectangle dimx + distToLine, dimy:
924  m_xcliplo = m_padToTestPos.x - padHalfsize.x - distToLine;
925  m_ycliplo = m_padToTestPos.y - padHalfsize.y;
926  m_xcliphi = m_padToTestPos.x + padHalfsize.x + distToLine;
927  m_ycliphi = m_padToTestPos.y + padHalfsize.y;
928 
929  if( !checkLine( startPoint, endPoint ) )
930  return false;
931 
932  // Testing the second rectangle dimx , dimy + distToLine
933  m_xcliplo = m_padToTestPos.x - padHalfsize.x;
934  m_ycliplo = m_padToTestPos.y - padHalfsize.y - distToLine;
935  m_xcliphi = m_padToTestPos.x + padHalfsize.x;
936  m_ycliphi = m_padToTestPos.y + padHalfsize.y + distToLine;
937 
938  if( !checkLine( startPoint, endPoint ) )
939  return false;
940 
941  // testing the 4 circles which are the clearance area of each corner:
942 
943  // testing the left top corner of the rectangle
944  startPoint.x = m_padToTestPos.x - padHalfsize.x;
945  startPoint.y = m_padToTestPos.y - padHalfsize.y;
946  RotatePoint( &startPoint, m_padToTestPos, orient );
947  RotatePoint( &startPoint, m_segmAngle );
948 
949  if( !checkMarginToCircle( startPoint, distToLine, m_segmLength ) )
950  return false;
951 
952  // testing the right top corner of the rectangle
953  startPoint.x = m_padToTestPos.x + padHalfsize.x;
954  startPoint.y = m_padToTestPos.y - padHalfsize.y;
955  RotatePoint( &startPoint, m_padToTestPos, orient );
956  RotatePoint( &startPoint, m_segmAngle );
957 
958  if( !checkMarginToCircle( startPoint, distToLine, m_segmLength ) )
959  return false;
960 
961  // testing the left bottom corner of the rectangle
962  startPoint.x = m_padToTestPos.x - padHalfsize.x;
963  startPoint.y = m_padToTestPos.y + padHalfsize.y;
964  RotatePoint( &startPoint, m_padToTestPos, orient );
965  RotatePoint( &startPoint, m_segmAngle );
966 
967  if( !checkMarginToCircle( startPoint, distToLine, m_segmLength ) )
968  return false;
969 
970  // testing the right bottom corner of the rectangle
971  startPoint.x = m_padToTestPos.x + padHalfsize.x;
972  startPoint.y = m_padToTestPos.y + padHalfsize.y;
973  RotatePoint( &startPoint, m_padToTestPos, orient );
974  RotatePoint( &startPoint, m_segmAngle );
975 
976  if( !checkMarginToCircle( startPoint, distToLine, m_segmLength ) )
977  return false;
978 
979  break;
980 
981  case PAD_SHAPE_TRAPEZOID:
982  {
983  wxPoint poly[4];
984  aPad->BuildPadPolygon( poly, wxSize( 0, 0 ), orient );
985 
986  // Move shape to m_padToTestPos
987  for( int ii = 0; ii < 4; ii++ )
988  {
989  poly[ii] += m_padToTestPos;
990  RotatePoint( &poly[ii], m_segmAngle );
991  }
992 
993  if( !poly2segmentDRC( poly, 4, wxPoint( 0, 0 ), wxPoint(m_segmLength,0), distToLine ) )
994  return false;
995 
996  break;
997  }
998  }
999 
1000  return true;
1001 }
1002 
1003 
1010 bool DRC::checkMarginToCircle( wxPoint aCentre, int aRadius, int aLength )
1011 {
1012  if( abs( aCentre.y ) >= aRadius ) // trivial case
1013  return true;
1014 
1015  // Here, distance between aCentre and X axis is < aRadius
1016  if( (aCentre.x > -aRadius ) && ( aCentre.x < (aLength + aRadius) ) )
1017  {
1018  if( (aCentre.x >= 0) && (aCentre.x <= aLength) )
1019  return false; // aCentre is between the starting point and the ending point of the segm
1020 
1021  if( aCentre.x > aLength ) // aCentre is after the ending point
1022  aCentre.x -= aLength; // move aCentre to the starting point of the segment
1023 
1024  if( EuclideanNorm( aCentre ) < aRadius )
1025  // distance between aCentre and the starting point or the ending point is < aRadius
1026  return false;
1027  }
1028 
1029  return true;
1030 }
1031 
1032 
1033 // Helper function used in checkLine::
1034 static inline int USCALE( unsigned arg, unsigned num, unsigned den )
1035 {
1036  int ii;
1037 
1038  ii = KiROUND( ( (double) arg * num ) / den );
1039  return ii;
1040 }
1041 
1042 
1048 bool DRC::checkLine( wxPoint aSegStart, wxPoint aSegEnd )
1049 {
1050 #define WHEN_OUTSIDE return true
1051 #define WHEN_INSIDE
1052  int temp;
1053 
1054  if( aSegStart.x > aSegEnd.x )
1055  std::swap( aSegStart, aSegEnd );
1056 
1057  if( (aSegEnd.x < m_xcliplo) || (aSegStart.x > m_xcliphi) )
1058  {
1059  WHEN_OUTSIDE;
1060  }
1061 
1062  if( aSegStart.y < aSegEnd.y )
1063  {
1064  if( (aSegEnd.y < m_ycliplo) || (aSegStart.y > m_ycliphi) )
1065  {
1066  WHEN_OUTSIDE;
1067  }
1068 
1069  if( aSegStart.y < m_ycliplo )
1070  {
1071  temp = USCALE( (aSegEnd.x - aSegStart.x), (m_ycliplo - aSegStart.y),
1072  (aSegEnd.y - aSegStart.y) );
1073 
1074  if( (aSegStart.x += temp) > m_xcliphi )
1075  {
1076  WHEN_OUTSIDE;
1077  }
1078 
1079  aSegStart.y = m_ycliplo;
1080  WHEN_INSIDE;
1081  }
1082 
1083  if( aSegEnd.y > m_ycliphi )
1084  {
1085  temp = USCALE( (aSegEnd.x - aSegStart.x), (aSegEnd.y - m_ycliphi),
1086  (aSegEnd.y - aSegStart.y) );
1087 
1088  if( (aSegEnd.x -= temp) < m_xcliplo )
1089  {
1090  WHEN_OUTSIDE;
1091  }
1092 
1093  aSegEnd.y = m_ycliphi;
1094  WHEN_INSIDE;
1095  }
1096 
1097  if( aSegStart.x < m_xcliplo )
1098  {
1099  temp = USCALE( (aSegEnd.y - aSegStart.y), (m_xcliplo - aSegStart.x),
1100  (aSegEnd.x - aSegStart.x) );
1101  aSegStart.y += temp;
1102  aSegStart.x = m_xcliplo;
1103  WHEN_INSIDE;
1104  }
1105 
1106  if( aSegEnd.x > m_xcliphi )
1107  {
1108  temp = USCALE( (aSegEnd.y - aSegStart.y), (aSegEnd.x - m_xcliphi),
1109  (aSegEnd.x - aSegStart.x) );
1110  aSegEnd.y -= temp;
1111  aSegEnd.x = m_xcliphi;
1112  WHEN_INSIDE;
1113  }
1114  }
1115  else
1116  {
1117  if( (aSegStart.y < m_ycliplo) || (aSegEnd.y > m_ycliphi) )
1118  {
1119  WHEN_OUTSIDE;
1120  }
1121 
1122  if( aSegStart.y > m_ycliphi )
1123  {
1124  temp = USCALE( (aSegEnd.x - aSegStart.x), (aSegStart.y - m_ycliphi),
1125  (aSegStart.y - aSegEnd.y) );
1126 
1127  if( (aSegStart.x += temp) > m_xcliphi )
1128  {
1129  WHEN_OUTSIDE;
1130  }
1131 
1132  aSegStart.y = m_ycliphi;
1133  WHEN_INSIDE;
1134  }
1135 
1136  if( aSegEnd.y < m_ycliplo )
1137  {
1138  temp = USCALE( (aSegEnd.x - aSegStart.x), (m_ycliplo - aSegEnd.y),
1139  (aSegStart.y - aSegEnd.y) );
1140 
1141  if( (aSegEnd.x -= temp) < m_xcliplo )
1142  {
1143  WHEN_OUTSIDE;
1144  }
1145 
1146  aSegEnd.y = m_ycliplo;
1147  WHEN_INSIDE;
1148  }
1149 
1150  if( aSegStart.x < m_xcliplo )
1151  {
1152  temp = USCALE( (aSegStart.y - aSegEnd.y), (m_xcliplo - aSegStart.x),
1153  (aSegEnd.x - aSegStart.x) );
1154  aSegStart.y -= temp;
1155  aSegStart.x = m_xcliplo;
1156  WHEN_INSIDE;
1157  }
1158 
1159  if( aSegEnd.x > m_xcliphi )
1160  {
1161  temp = USCALE( (aSegStart.y - aSegEnd.y), (aSegEnd.x - m_xcliphi),
1162  (aSegEnd.x - aSegStart.x) );
1163  aSegEnd.y += temp;
1164  aSegEnd.x = m_xcliphi;
1165  WHEN_INSIDE;
1166  }
1167  }
1168 
1169  if( ( (aSegEnd.x + aSegStart.x) / 2 <= m_xcliphi )
1170  && ( (aSegEnd.x + aSegStart.x) / 2 >= m_xcliplo ) \
1171  && ( (aSegEnd.y + aSegStart.y) / 2 <= m_ycliphi )
1172  && ( (aSegEnd.y + aSegStart.y) / 2 >= m_ycliplo ) )
1173  {
1174  return false;
1175  }
1176  else
1177  {
1178  return true;
1179  }
1180 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:104
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Function AllCuMask returns a mask holding the requested number of Cu LAYER_IDs.
Definition: lset.cpp:638
KICAD_T Type() const
Function Type()
Definition: base_struct.h:198
#define DRCE_TRACK_SEGMENTS_TOO_CLOSE
2 parallel track segments too close: segm ends between segref ends
Definition: drc_stuff.h:51
static int USCALE(unsigned arg, unsigned num, unsigned den)
#define WHEN_OUTSIDE
static int KiROUND(double v)
KiROUND rounds a floating point number to an int using "round halfway cases away from zero"...
Definition: common.h:107
MARKER_PCB * fillMarker(const TRACK *aTrack, BOARD_ITEM *aItem, int aErrorCode, MARKER_PCB *fillMe)
Function fillMarker optionally creates a marker and fills it in with information, but does not add it...
int m_ycliplo
Definition: drc_stuff.h:200
#define DRCE_ENDS_PROBLEM1
track ends are too close
Definition: drc_stuff.h:53
#define DRCE_TRACK_ENDS1
2 parallel track segments too close: fine start point test
Definition: drc_stuff.h:47
void BuildPadPolygon(wxPoint aCoord[4], wxSize aInflateValue, double aRotation) const
Function BuildPadPolygon Has meaning only for polygonal pads (trapezoid and rectangular) Build the Co...
int PointCount() const
Function PointCount()
bool TestForIntersectionOfStraightLineSegments(int x1i, int y1i, int x1f, int y1f, int x2i, int y2i, int x2f, int y2f, int *x, int *y, double *d)
Function TestForIntersectionOfStraightLineSegments Test for intersection of line segments If lines ar...
#define DRCE_TOO_SMALL_MICROVIA_DRILL
Too small micro via drill.
Definition: drc_stuff.h:70
#define DRCE_TRACK_NEAR_VIA
track too close to via
Definition: drc_stuff.h:44
Class BOARD to handle a board.
int GetRoundRectCornerRadius() const
Function GetRoundRectCornerRadius Has meaning only for rounded rect pads.
Definition: class_pad.h:351
int m_ycliphi
Definition: drc_stuff.h:202
static const int dist[10][10]
Definition: dist.cpp:57
bool poly2segmentDRC(wxPoint *aTref, int aTrefCount, wxPoint aSegStart, wxPoint aSegEnd, int aDist)
int m_segmLength
Definition: drc_stuff.h:194
void SetPosition(const wxPoint &aPos) override
Definition: class_pad.h:169
Classes to handle copper zones.
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: class_pad.h:221
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:317
int OutlineCount() const
Returns the number of outlines in the set
void NORMALIZE_ANGLE_POS(T &Angle)
Definition: trigo.h:222
const wxSize & GetDrillSize() const
Definition: class_pad.h:188
#define DRCE_TRACKS_CROSSING
tracks are crossing
Definition: drc_stuff.h:52
wxPoint m_padToTestPos
Definition: drc_stuff.h:185
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:166
#define DRCE_ENDS_PROBLEM2
track ends are too close
Definition: drc_stuff.h:54
#define abs(a)
Definition: auxiliary.h:84
#define DRCE_TOO_SMALL_MICROVIA
Too small micro via size.
Definition: drc_stuff.h:68
static const int delta[8][2]
Definition: solve.cpp:112
const wxPoint & GetEnd() const
Definition: class_track.h:117
Functions relatives to tracks, vias and segments used to fill zones.
BOARD * m_pcb
Definition: drc_stuff.h:205
bool checkLine(wxPoint aSegStart, wxPoint aSegEnd)
Function checkLine (helper function used in drc calculations to see if one track is in contact with a...
#define DRCE_ENDS_PROBLEM5
track ends are too close
Definition: drc_stuff.h:57
Markers used to show a drc problem on boards.
Class LSET is a set of LAYER_IDs.
int GetCopperLayerCount() const
Function GetCopperLayerCount.
bool TestPointInsidePolygon(const CPOLYGONS_LIST &aPolysList, int aIdxstart, int aIdxend, int aRefx, int aRefy)
Function TestPointInsidePolygon test if a point is inside or outside a polygon.
VIATYPE_T GetViaType() const
Definition: class_track.h:442
double ArcTangente(int dy, int dx)
Definition: trigo.cpp:271
#define DRCE_VIA_NEAR_TRACK
via too close to track
Definition: drc_stuff.h:46
std::shared_ptr< NETCLASS > GetNetClass() const
Function GetNetClass returns the NETCLASS for this item.
T AddAngles(T a1, T2 a2)
Add two angles (keeping the result normalized). T2 is here.
Definition: trigo.h:246
int GetBoundingRadius() const
Function GetBoundingRadius returns the radius of a minimum sized circle which fully encloses this pad...
Definition: class_pad.h:428
Class SHAPE_POLY_SET.
const wxPoint & GetStart() const
Definition: class_track.h:120
const wxPoint & GetPosition() const override
Definition: class_pad.h:170
int m_TrackMinWidth
track min value for width ((min copper size value
int m_ViasMinSize
vias (not micro vias) min diameter
LSET GetLayerSet() const override
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
Definition: class_pad.h:235
bool convex2pointDRC(wxPoint *aTref, int aTrefCount, wxPoint aPcompare, int aDist)
int m_ViasMinDrill
vias (not micro vias) min drill diameter
virtual LSET GetLayerSet() const
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
const wxSize & GetSize() const
Definition: class_pad.h:182
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:530
void SetSize(const wxSize &aSize)
Definition: class_pad.h:181
static bool checkMarginToCircle(wxPoint aCentre, int aRadius, int aLength)
Helper function checkMarginToCircle Check the distance from a point to a segment. ...
#define DRCE_TRACK_NEAR_PAD
pad too close to track
Definition: drc_stuff.h:43
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
static bool intersect(const SEGMENT_WITH_NORMALS &aSeg, const SFVEC2F &aStart, const SFVEC2F &aEnd)
Definition: cpolygon2d.cpp:293
virtual int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
int m_xcliphi
Definition: drc_stuff.h:201
int m_MicroViasMinSize
micro vias (not vias) min diameter
D_PAD * GetPad(unsigned aIndex) const
Function GetPad.
Definition: class_board.h:750
unsigned GetPadCount() const
Function GetPadCount.
Definition: class_board.h:741
bool checkClearancePadToPad(D_PAD *aRefPad, D_PAD *aPad)
Function checkClearancePadToPad.
int GetNetCode() const
Function GetNetCode.
MARKER_PCB * m_currentMarker
Definition: drc_stuff.h:176
#define DRCE_TOO_SMALL_TRACK_WIDTH
Too small track width.
Definition: drc_stuff.h:66
#define WHEN_INSIDE
bool checkClearanceSegmToPad(const D_PAD *aPad, int aSegmentWidth, int aMinDist)
Function checkClearanceSegmToPad check the distance from a pad to segment.
wxPoint m_segmEnd
Definition: drc_stuff.h:186
void LayerPair(LAYER_ID *top_layer, LAYER_ID *bottom_layer) const
Function LayerPair Return the 2 layers used by the via (the via actually uses all layers between thes...
void SetLayerSet(LSET aLayerMask)
Definition: class_pad.h:234
TRACK * Next() const
Definition: class_track.h:97
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
LAYER_ID
Enum LAYER_ID is the set of PCB layers.
Class SHAPE_LINE_CHAIN.
int GetWidth() const
Definition: class_track.h:114
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
#define DRCE_ENDS_PROBLEM3
track ends are too close
Definition: drc_stuff.h:55
#define DRCE_TRACK_ENDS4
2 parallel track segments too close: fine end point test
Definition: drc_stuff.h:50
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees, but soon degrees.
Definition: class_pad.h:214
const wxSize & GetDelta() const
Definition: class_pad.h:185
bool poly2polyDRC(wxPoint *aTref, int aTrefCount, wxPoint *aTcompare, int aTcompareCount, int aDist)
DRC control: these functions make a DRC between pads, tracks and pads versus tracks.
void GetRoundRectCornerCenters(wxPoint aCenters[4], int aRadius, const wxPoint &aPosition, const wxSize &aSize, double aRotation)
Helper function GetRoundRectCornerCenters Has meaning only for rounded rect Returns the centers of th...
#define DRCE_VIA_NEAR_VIA
via too close to via
Definition: drc_stuff.h:45
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
Definition: class_pad.cpp:455
void SetShape(PAD_SHAPE_T aShape)
Definition: class_pad.h:167
wxPoint ShapePos() const
Definition: class_pad.cpp:367
void SetOrientation(double aAngle)
Function SetOrientation sets the rotation angle of the pad.
Definition: class_pad.cpp:306
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:108
bool doTrackDrc(TRACK *aRefSeg, TRACK *aStart, bool doPads=true)
Function DoTrackDrc tests the current segment.
Module description (excepted pads)
int m_MicroViasMinDrill
micro vias (not vias) min drill diameter
bool TestSegmentHit(const wxPoint &aRefPoint, wxPoint aStart, wxPoint aEnd, int aDist)
Function TestSegmentHit test for hit on line segment i.e.
Definition: trigo.cpp:142
#define DRCE_TRACK_ENDS2
2 parallel track segments too close: fine start point test
Definition: drc_stuff.h:48
#define DRCE_TRACK_ENDS3
2 parallel track segments too close: fine end point test
Definition: drc_stuff.h:49
#define DRCE_ENDS_PROBLEM4
track ends are too close
Definition: drc_stuff.h:56
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
int m_xcliplo
Definition: drc_stuff.h:199
#define DRCE_MICRO_VIA_INCORRECT_LAYER_PAIR
micro via's layer pair incorrect (layers must be adjacent)
Definition: drc_stuff.h:60
double m_segmAngle
Definition: drc_stuff.h:193
#define DRCE_TRACK_NEAR_THROUGH_HOLE
thru hole is too close to track
Definition: drc_stuff.h:42
#define DRCE_VIA_HOLE_BIGGER
via's hole is bigger than its diameter
Definition: drc_stuff.h:59
Class BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.
#define DRCE_TOO_SMALL_VIA_DRILL
Too small via drill.
Definition: drc_stuff.h:69
#define DRCE_TOO_SMALL_VIA
Too small via size.
Definition: drc_stuff.h:67