KiCad PCB EDA Suite
graphpcb.cpp
Go to the documentation of this file.
1 
6 /*
7  * This program source code file is part of KiCad, a free EDA CAD application.
8  *
9  * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
10  * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
11  * Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
12  *
13  * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors.
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, you may find one here:
27  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
28  * or you may search the http://www.gnu.org website for the version 2 license,
29  * or you may write to the Free Software Foundation, Inc.,
30  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
31  */
32 
33 #include <fctsys.h>
34 #include <common.h>
35 #include <macros.h>
36 #include <trigo.h>
37 #include <math_for_graphics.h>
38 #include <class_board.h>
39 #include <class_track.h>
40 #include <class_drawsegment.h>
41 
42 #include <pcbnew.h>
43 #include <autorout.h>
44 #include <cell.h>
45 
46 void TracePcbLine( int x0, int y0, int x1, int y1, LAYER_NUM layer, int color );
47 
48 void TraceArc( int ux0, int uy0,
49  int ux1, int uy1,
50  double ArcAngle,
51  int lg, LAYER_NUM layer, int color,
52  int op_logic );
53 
54 
55 static void DrawSegmentQcq( int ux0, int uy0,
56  int ux1, int uy1,
57  int lg, LAYER_NUM layer, int color,
58  int op_logic );
59 
60 static void TraceFilledCircle( int cx, int cy, int radius,
61  LSET aLayerMask,
62  int color,
63  int op_logic );
64 
65 static void TraceCircle( int ux0, int uy0, int ux1, int uy1, int lg, LAYER_NUM layer,
66  int color, int op_logic );
67 
68 // Macro call to update cell.
69 #define OP_CELL( layer, dy, dx ) \
70  { \
71  if( layer == UNDEFINED_LAYER ) \
72  { \
73  RoutingMatrix.WriteCell( dy, dx, BOTTOM, color ); \
74  if( RoutingMatrix.m_RoutingLayersCount > 1 ) \
75  RoutingMatrix.WriteCell( dy, dx, TOP, color ); \
76  } \
77  else \
78  { \
79  if( layer == g_Route_Layer_BOTTOM ) \
80  RoutingMatrix.WriteCell( dy, dx, BOTTOM, color ); \
81  if( RoutingMatrix.m_RoutingLayersCount > 1 ) \
82  if( layer == g_Route_Layer_TOP ) \
83  RoutingMatrix.WriteCell( dy, dx, TOP, color ); \
84  } \
85  }
86 
87 void PlacePad( D_PAD* aPad, int color, int marge, int op_logic )
88 {
89  int dx, dy;
90  wxPoint shape_pos = aPad->ShapePos();
91 
92  dx = aPad->GetSize().x / 2;
93  dx += marge;
94 
95  if( aPad->GetShape() == PAD_SHAPE_CIRCLE )
96  {
97  TraceFilledCircle( shape_pos.x, shape_pos.y, dx,
98  aPad->GetLayerSet(), color, op_logic );
99  return;
100  }
101 
102  dy = aPad->GetSize().y / 2;
103  dy += marge;
104 
105  if( aPad->GetShape() == PAD_SHAPE_TRAPEZOID )
106  {
107  dx += abs( aPad->GetDelta().y ) / 2;
108  dy += abs( aPad->GetDelta().x ) / 2;
109  }
110 
111  // The pad is a rectangle ( horizontal or vertical )
112  if( int( aPad->GetOrientation() ) % 900 == 0 )
113  {
114  // Orientation turned 90 deg.
115  if( aPad->GetOrientation() == 900 || aPad->GetOrientation() == 2700 )
116  {
117  std::swap( dx, dy );
118  }
119 
120  TraceFilledRectangle( shape_pos.x - dx, shape_pos.y - dy,
121  shape_pos.x + dx, shape_pos.y + dy,
122  aPad->GetLayerSet(), color, op_logic );
123  }
124  else
125  {
126  TraceFilledRectangle( shape_pos.x - dx, shape_pos.y - dy,
127  shape_pos.x + dx, shape_pos.y + dy,
128  aPad->GetOrientation(),
129  aPad->GetLayerSet(), color, op_logic );
130  }
131 }
132 
133 
134 /* Set to color the cells included in the circle
135  * Parameters:
136  * center: cx, cy.
137  * radius: a value add to the radius or half the score pad
138  * aLayerMask: layer occupied
139  * color: mask write in cells
140  * op_logic: type of writing in the cell (WRITE, OR)
141  */
142 void TraceFilledCircle( int cx, int cy, int radius,
143  LSET aLayerMask, int color, int op_logic )
144 {
145  int row, col;
146  int ux0, uy0, ux1, uy1;
147  int row_max, col_max, row_min, col_min;
148  int trace = 0;
149  double fdistmin, fdistx, fdisty;
150  int tstwrite = 0;
151  int distmin;
152 
153  if( aLayerMask[g_Route_Layer_BOTTOM] )
154  trace = 1; // Trace on BOTTOM
155 
156  if( aLayerMask[g_Route_Layer_TOP] )
158  trace |= 2; // Trace on TOP
159 
160  if( trace == 0 )
161  return;
162 
163  RoutingMatrix.SetCellOperation( op_logic );
164 
167 
168  distmin = radius;
169 
170  // Calculate the bounding rectangle of the circle.
171  ux0 = cx - radius;
172  uy0 = cy - radius;
173  ux1 = cx + radius;
174  uy1 = cy + radius;
175 
176  // Calculate limit coordinates of cells belonging to the rectangle.
177  row_max = uy1 / RoutingMatrix.m_GridRouting;
178  col_max = ux1 / RoutingMatrix.m_GridRouting;
179  row_min = uy0 / RoutingMatrix.m_GridRouting; // if (uy0 > row_min*Board.m_GridRouting) row_min++;
180  col_min = ux0 / RoutingMatrix.m_GridRouting; // if (ux0 > col_min*Board.m_GridRouting) col_min++;
181 
182  if( row_min < 0 )
183  row_min = 0;
184 
185  if( row_max >= (RoutingMatrix.m_Nrows - 1) )
186  row_max = RoutingMatrix.m_Nrows - 1;
187 
188  if( col_min < 0 )
189  col_min = 0;
190 
191  if( col_max >= (RoutingMatrix.m_Ncols - 1) )
192  col_max = RoutingMatrix.m_Ncols - 1;
193 
194  // Calculate coordinate limits of cell belonging to the rectangle.
195  if( row_min > row_max )
196  row_max = row_min;
197 
198  if( col_min > col_max )
199  col_max = col_min;
200 
201  fdistmin = (double) distmin * distmin;
202 
203  for( row = row_min; row <= row_max; row++ )
204  {
205  fdisty = (double) ( cy - ( row * RoutingMatrix.m_GridRouting ) );
206  fdisty *= fdisty;
207 
208  for( col = col_min; col <= col_max; col++ )
209  {
210  fdistx = (double) ( cx - ( col * RoutingMatrix.m_GridRouting ) );
211  fdistx *= fdistx;
212 
213  if( fdistmin <= ( fdistx + fdisty ) )
214  continue;
215 
216  if( trace & 1 )
217  RoutingMatrix.WriteCell( row, col, BOTTOM, color );
218 
219  if( trace & 2 )
220  RoutingMatrix.WriteCell( row, col, TOP, color );
221 
222  tstwrite = 1;
223  }
224  }
225 
226  if( tstwrite )
227  return;
228 
229  /* If no cell has been written, it affects the 4 neighboring diagonal
230  * (Adverse event: pad off grid in the center of the 4 neighboring
231  * diagonal) */
232  distmin = RoutingMatrix.m_GridRouting / 2 + 1;
233  fdistmin = ( (double) distmin * distmin ) * 2; // Distance to center point diagonally
234 
235  for( row = row_min; row <= row_max; row++ )
236  {
237  fdisty = (double) ( cy - ( row * RoutingMatrix.m_GridRouting ) );
238  fdisty *= fdisty;
239 
240  for( col = col_min; col <= col_max; col++ )
241  {
242  fdistx = (double) ( cx - ( col * RoutingMatrix.m_GridRouting ) );
243  fdistx *= fdistx;
244 
245  if( fdistmin <= ( fdistx + fdisty ) )
246  continue;
247 
248  if( trace & 1 )
249  RoutingMatrix.WriteCell( row, col, BOTTOM, color );
250 
251  if( trace & 2 )
252  RoutingMatrix.WriteCell( row, col, TOP, color );
253  }
254  }
255 }
256 
257 void TraceSegmentPcb( DRAWSEGMENT* pt_segm, int color, int marge, int op_logic )
258 {
259  int half_width = ( pt_segm->GetWidth() / 2 ) + marge;
260 
261  // Calculate the bounding rectangle of the segment (if H, V or Via)
262  int ux0 = pt_segm->GetStart().x - RoutingMatrix.GetBrdCoordOrigin().x;
263  int uy0 = pt_segm->GetStart().y - RoutingMatrix.GetBrdCoordOrigin().y;
264  int ux1 = pt_segm->GetEnd().x - RoutingMatrix.GetBrdCoordOrigin().x;
265  int uy1 = pt_segm->GetEnd().y - RoutingMatrix.GetBrdCoordOrigin().y;
266 
267  LAYER_NUM layer = pt_segm->GetLayer();
268 
269  if( color == VIA_IMPOSSIBLE )
270  layer = UNDEFINED_LAYER;
271 
272  switch( pt_segm->GetShape() )
273  {
274  // The segment is here a straight line or a circle or an arc.:
275  case S_CIRCLE:
276  TraceCircle( ux0, uy0, ux1, uy1, half_width, layer, color, op_logic );
277  break;
278 
279  case S_ARC:
280  TraceArc( ux0, uy0, ux1, uy1, pt_segm->GetAngle(), half_width, layer, color, op_logic );
281  break;
282 
283  // The segment is here a line segment.
284  default:
285  DrawSegmentQcq( ux0, uy0, ux1, uy1, half_width, layer, color, op_logic );
286  break;
287  }
288 }
289 
290 void TraceSegmentPcb( TRACK* aTrack, int color, int marge, int op_logic )
291 {
292  int half_width = ( aTrack->GetWidth() / 2 ) + marge;
293 
294  // Test if VIA (filled circle need to be drawn)
295  if( aTrack->Type() == PCB_VIA_T )
296  {
297  LSET layer_mask;
298 
299  if( aTrack->IsOnLayer( g_Route_Layer_BOTTOM ) )
300  layer_mask.set( g_Route_Layer_BOTTOM );
301 
302  if( aTrack->IsOnLayer( g_Route_Layer_TOP ) )
303  {
304  if( !layer_mask.any() )
305  layer_mask = LSET( g_Route_Layer_TOP );
306  else
307  layer_mask.set();
308  }
309 
310  if( color == VIA_IMPOSSIBLE )
311  layer_mask.set();
312 
313  if( layer_mask.any() )
314  TraceFilledCircle( aTrack->GetStart().x, aTrack->GetStart().y,
315  half_width, layer_mask, color, op_logic );
316  }
317  else
318  {
319  // Calculate the bounding rectangle of the segment
320  int ux0 = aTrack->GetStart().x - RoutingMatrix.GetBrdCoordOrigin().x;
321  int uy0 = aTrack->GetStart().y - RoutingMatrix.GetBrdCoordOrigin().y;
322  int ux1 = aTrack->GetEnd().x - RoutingMatrix.GetBrdCoordOrigin().x;
323  int uy1 = aTrack->GetEnd().y - RoutingMatrix.GetBrdCoordOrigin().y;
324 
325  // Ordinary track
326  LAYER_ID layer = aTrack->GetLayer();
327 
328  if( color == VIA_IMPOSSIBLE )
329  layer = UNDEFINED_LAYER;
330 
331  DrawSegmentQcq( ux0, uy0, ux1, uy1, half_width, layer, color, op_logic );
332  }
333 }
334 
335 
336 /* Draws a line, if layer = -1 on all layers
337  */
338 void TracePcbLine( int x0, int y0, int x1, int y1, LAYER_NUM layer, int color, int op_logic )
339 {
340  int dx, dy, lim;
341  int cumul, inc, il, delta;
342 
343  RoutingMatrix.SetCellOperation( op_logic );
344 
345  if( x0 == x1 ) // Vertical.
346  {
347  if( y1 < y0 )
348  std::swap( y0, y1 );
349 
350  dy = y0 / RoutingMatrix.m_GridRouting;
351  lim = y1 / RoutingMatrix.m_GridRouting;
352  dx = x0 / RoutingMatrix.m_GridRouting;
353 
354  // Clipping limits of board.
355  if( ( dx < 0 ) || ( dx >= RoutingMatrix.m_Ncols ) )
356  return;
357 
358  if( dy < 0 )
359  dy = 0;
360 
361  if( lim >= RoutingMatrix.m_Nrows )
362  lim = RoutingMatrix.m_Nrows - 1;
363 
364  for( ; dy <= lim; dy++ )
365  {
366  OP_CELL( layer, dy, dx );
367  }
368 
369  return;
370  }
371 
372  if( y0 == y1 ) // Horizontal
373  {
374  if( x1 < x0 )
375  std::swap( x0, x1 );
376 
377  dx = x0 / RoutingMatrix.m_GridRouting;
378  lim = x1 / RoutingMatrix.m_GridRouting;
379  dy = y0 / RoutingMatrix.m_GridRouting;
380 
381  // Clipping limits of board.
382  if( ( dy < 0 ) || ( dy >= RoutingMatrix.m_Nrows ) )
383  return;
384 
385  if( dx < 0 )
386  dx = 0;
387 
388  if( lim >= RoutingMatrix.m_Ncols )
389  lim = RoutingMatrix.m_Ncols - 1;
390 
391  for( ; dx <= lim; dx++ )
392  {
393  OP_CELL( layer, dy, dx );
394  }
395 
396  return;
397  }
398 
399  // Here is some perspective: using the algorithm LUCAS.
400  if( abs( x1 - x0 ) >= abs( y1 - y0 ) ) // segment slightly inclined/
401  {
402  if( x1 < x0 )
403  {
404  std::swap( x1, x0 );
405  std::swap( y1, y0 );
406  }
407 
408  dx = x0 / RoutingMatrix.m_GridRouting;
409  lim = x1 / RoutingMatrix.m_GridRouting;
410  dy = y0 / RoutingMatrix.m_GridRouting;
411  inc = 1;
412 
413  if( y1 < y0 )
414  inc = -1;
415 
416  il = lim - dx; cumul = il / 2;
417  delta = abs( y1 - y0 ) / RoutingMatrix.m_GridRouting;
418 
419  for( ; dx <= lim; )
420  {
421  if( ( dx >= 0 ) && ( dy >= 0 ) &&
422  ( dx < RoutingMatrix.m_Ncols ) &&
423  ( dy < RoutingMatrix.m_Nrows ) )
424  {
425  OP_CELL( layer, dy, dx );
426  }
427 
428  dx++;
429  cumul += delta;
430 
431  if( cumul > il )
432  {
433  cumul -= il;
434  dy += inc;
435  }
436  }
437  }
438  else
439  {
440  if( y1 < y0 )
441  {
442  std::swap( x1, x0 );
443  std::swap( y1, y0 );
444  }
445 
446  dy = y0 / RoutingMatrix.m_GridRouting;
447  lim = y1 / RoutingMatrix.m_GridRouting;
448  dx = x0 / RoutingMatrix.m_GridRouting;
449  inc = 1;
450 
451  if( x1 < x0 )
452  inc = -1;
453 
454  il = lim - dy;
455  cumul = il / 2;
456  delta = abs( x1 - x0 ) / RoutingMatrix.m_GridRouting;
457 
458  for( ; dy <= lim; )
459  {
460  if( ( dx >= 0 ) && ( dy >= 0 ) && ( dx < RoutingMatrix.m_Ncols ) && ( dy < RoutingMatrix.m_Nrows ) )
461  {
462  OP_CELL( layer, dy, dx );
463  }
464 
465  dy++;
466  cumul += delta;
467 
468  if( cumul > il )
469  {
470  cumul -= il;
471  dx += inc;
472  }
473  }
474  }
475 }
476 
477 
478 void TraceFilledRectangle( int ux0, int uy0, int ux1, int uy1,
479  LSET aLayerMask, int color, int op_logic )
480 {
481  int row, col;
482  int row_min, row_max, col_min, col_max;
483  int trace = 0;
484 
485  if( aLayerMask[g_Route_Layer_BOTTOM] )
486  trace = 1; // Trace on BOTTOM
487 
488  if( aLayerMask[g_Route_Layer_TOP] && RoutingMatrix.m_RoutingLayersCount > 1 )
489  trace |= 2; // Trace on TOP
490 
491  if( trace == 0 )
492  return;
493 
494  RoutingMatrix.SetCellOperation( op_logic );
495 
500 
501  // Calculating limits coord cells belonging to the rectangle.
502  row_max = uy1 / RoutingMatrix.m_GridRouting;
503  col_max = ux1 / RoutingMatrix.m_GridRouting;
504  row_min = uy0 / RoutingMatrix.m_GridRouting;
505 
506  if( uy0 > row_min * RoutingMatrix.m_GridRouting )
507  row_min++;
508 
509  col_min = ux0 / RoutingMatrix.m_GridRouting;
510 
511  if( ux0 > col_min * RoutingMatrix.m_GridRouting )
512  col_min++;
513 
514  if( row_min < 0 )
515  row_min = 0;
516 
517  if( row_max >= ( RoutingMatrix.m_Nrows - 1 ) )
518  row_max = RoutingMatrix.m_Nrows - 1;
519 
520  if( col_min < 0 )
521  col_min = 0;
522 
523  if( col_max >= ( RoutingMatrix.m_Ncols - 1 ) )
524  col_max = RoutingMatrix.m_Ncols - 1;
525 
526  for( row = row_min; row <= row_max; row++ )
527  {
528  for( col = col_min; col <= col_max; col++ )
529  {
530  if( trace & 1 )
531  RoutingMatrix.WriteCell( row, col, BOTTOM, color );
532 
533  if( trace & 2 )
534  RoutingMatrix.WriteCell( row, col, TOP, color );
535  }
536  }
537 }
538 
539 
540 void TraceFilledRectangle( int ux0, int uy0, int ux1, int uy1,
541  double angle, LSET aLayerMask, int color, int op_logic )
542 {
543  int row, col;
544  int cx, cy; // Center of rectangle
545  int radius; // Radius of the circle
546  int row_min, row_max, col_min, col_max;
547  int rotrow, rotcol;
548  int trace = 0;
549 
550  if( aLayerMask[g_Route_Layer_BOTTOM] )
551  trace = 1; // Trace on BOTTOM
552 
553  if( aLayerMask[g_Route_Layer_TOP] )
554  {
556  trace |= 2; // Trace on TOP
557  }
558 
559  if( trace == 0 )
560  return;
561 
562  RoutingMatrix.SetCellOperation( op_logic );
563 
568 
569  cx = (ux0 + ux1) / 2;
570  cy = (uy0 + uy1) / 2;
571  radius = KiROUND( Distance( ux0, uy0, cx, cy ) );
572 
573  // Calculating coordinate limits belonging to the rectangle.
574  row_max = ( cy + radius ) / RoutingMatrix.m_GridRouting;
575  col_max = ( cx + radius ) / RoutingMatrix.m_GridRouting;
576  row_min = ( cy - radius ) / RoutingMatrix.m_GridRouting;
577 
578  if( uy0 > row_min * RoutingMatrix.m_GridRouting )
579  row_min++;
580 
581  col_min = ( cx - radius ) / RoutingMatrix.m_GridRouting;
582 
583  if( ux0 > col_min * RoutingMatrix.m_GridRouting )
584  col_min++;
585 
586  if( row_min < 0 )
587  row_min = 0;
588 
589  if( row_max >= ( RoutingMatrix.m_Nrows - 1 ) )
590  row_max = RoutingMatrix.m_Nrows - 1;
591 
592  if( col_min < 0 )
593  col_min = 0;
594 
595  if( col_max >= ( RoutingMatrix.m_Ncols - 1 ) )
596  col_max = RoutingMatrix.m_Ncols - 1;
597 
598  for( row = row_min; row <= row_max; row++ )
599  {
600  for( col = col_min; col <= col_max; col++ )
601  {
602  rotrow = row * RoutingMatrix.m_GridRouting;
603  rotcol = col * RoutingMatrix.m_GridRouting;
604  RotatePoint( &rotcol, &rotrow, cx, cy, -angle );
605 
606  if( rotrow <= uy0 )
607  continue;
608 
609  if( rotrow >= uy1 )
610  continue;
611 
612  if( rotcol <= ux0 )
613  continue;
614 
615  if( rotcol >= ux1 )
616  continue;
617 
618  if( trace & 1 )
619  RoutingMatrix.WriteCell( row, col, BOTTOM, color );
620 
621  if( trace & 2 )
622  RoutingMatrix.WriteCell( row, col, TOP, color );
623  }
624  }
625 }
626 
627 
628 /* Fills all cells inside a segment
629  * half-width = lg, org = ux0,uy0 end = ux1,uy1
630  * coordinates are in PCB units
631  */
632 void DrawSegmentQcq( int ux0, int uy0, int ux1, int uy1, int lg, LAYER_NUM layer,
633  int color, int op_logic )
634 {
635  int row, col;
636  int inc;
637  int row_max, col_max, row_min, col_min;
638  int demi_pas;
639 
640  int cx, cy, dx, dy;
641 
642  RoutingMatrix.SetCellOperation( op_logic );
643 
644  // Make coordinate ux1 tj > ux0 to simplify calculations
645  if( ux1 < ux0 )
646  {
647  std::swap( ux1, ux0 );
648  std::swap( uy1, uy0 );
649  }
650 
651  // Calculating the incrementing the Y axis
652  inc = 1;
653 
654  if( uy1 < uy0 )
655  inc = -1;
656 
657  demi_pas = RoutingMatrix.m_GridRouting / 2;
658 
659  col_min = ( ux0 - lg ) / RoutingMatrix.m_GridRouting;
660 
661  if( col_min < 0 )
662  col_min = 0;
663 
664  col_max = ( ux1 + lg + demi_pas ) / RoutingMatrix.m_GridRouting;
665 
666  if( col_max > ( RoutingMatrix.m_Ncols - 1 ) )
667  col_max = RoutingMatrix.m_Ncols - 1;
668 
669  if( inc > 0 )
670  {
671  row_min = ( uy0 - lg ) / RoutingMatrix.m_GridRouting;
672  row_max = ( uy1 + lg + demi_pas ) / RoutingMatrix.m_GridRouting;
673  }
674  else
675  {
676  row_min = ( uy1 - lg ) / RoutingMatrix.m_GridRouting;
677  row_max = ( uy0 + lg + demi_pas ) / RoutingMatrix.m_GridRouting;
678  }
679 
680  if( row_min < 0 )
681  row_min = 0;
682 
683  if( row_min > ( RoutingMatrix.m_Nrows - 1 ) )
684  row_min = RoutingMatrix.m_Nrows - 1;
685 
686  if( row_max < 0 )
687  row_max = 0;
688 
689  if( row_max > ( RoutingMatrix.m_Nrows - 1 ) )
690  row_max = RoutingMatrix.m_Nrows - 1;
691 
692  dx = ux1 - ux0;
693  dy = uy1 - uy0;
694 
695  double angle;
696  if( dx )
697  {
698  angle = ArcTangente( dy, dx );
699  }
700  else
701  {
702  angle = 900;
703 
704  if( dy < 0 )
705  angle = -900;
706  }
707 
708  RotatePoint( &dx, &dy, angle ); // dx = length, dy = 0
709 
710  for( col = col_min; col <= col_max; col++ )
711  {
712  int cxr;
713  cxr = ( col * RoutingMatrix.m_GridRouting ) - ux0;
714 
715  for( row = row_min; row <= row_max; row++ )
716  {
717  cy = (row * RoutingMatrix.m_GridRouting) - uy0;
718  cx = cxr;
719  RotatePoint( &cx, &cy, angle );
720 
721  if( abs( cy ) > lg )
722  continue; // The point is too far on the Y axis.
723 
724  /* This point a test is close to the segment: the position
725  * along the X axis must be tested.
726  */
727  if( ( cx >= 0 ) && ( cx <= dx ) )
728  {
729  OP_CELL( layer, row, col );
730  continue;
731  }
732 
733  // Examination of extremities are rounded.
734  if( ( cx < 0 ) && ( cx >= -lg ) )
735  {
736  if( ( ( cx * cx ) + ( cy * cy ) ) <= ( lg * lg ) )
737  OP_CELL( layer, row, col );
738 
739  continue;
740  }
741 
742  if( ( cx > dx ) && ( cx <= ( dx + lg ) ) )
743  {
744  if( ( ( ( cx - dx ) * ( cx - dx ) ) + ( cy * cy ) ) <= ( lg * lg ) )
745  OP_CELL( layer, row, col );
746 
747  continue;
748  }
749  }
750  }
751 }
752 
753 
754 /* Fills all cells of the routing matrix contained in the circle
755  * half-width = lg, center = ux0, uy0, ux1,uy1 is a point on the circle.
756  * coord are in PCB units.
757  */
758 void TraceCircle( int ux0, int uy0, int ux1, int uy1, int lg, LAYER_NUM layer,
759  int color, int op_logic )
760 {
761  int radius, nb_segm;
762  int x0, y0, // Starting point of the current segment trace.
763  x1, y1; // End point.
764  int ii;
765  int angle;
766 
767  radius = KiROUND( Distance( ux0, uy0, ux1, uy1 ) );
768 
769  x0 = x1 = radius;
770  y0 = y1 = 0;
771 
772  if( lg < 1 )
773  lg = 1;
774 
775  nb_segm = ( 2 * radius ) / lg;
776 
777  if( nb_segm < 5 )
778  nb_segm = 5;
779 
780  if( nb_segm > 100 )
781  nb_segm = 100;
782 
783  for( ii = 1; ii < nb_segm; ii++ )
784  {
785  angle = (3600 * ii) / nb_segm;
786  x1 = KiROUND( cosdecideg( radius, angle ) );
787  y1 = KiROUND( sindecideg( radius, angle ) );
788  DrawSegmentQcq( x0 + ux0, y0 + uy0, x1 + ux0, y1 + uy0, lg, layer, color, op_logic );
789  x0 = x1;
790  y0 = y1;
791  }
792 
793  DrawSegmentQcq( x1 + ux0, y1 + uy0, ux0 + radius, uy0, lg, layer, color, op_logic );
794 }
795 
796 
797 /* Fills all routing matrix cells contained in the arc
798  * angle = ArcAngle, half-width lg
799  * center = ux0,uy0, starting at ux1, uy1. Coordinates are in
800  * PCB units.
801  */
802 void TraceArc( int ux0, int uy0, int ux1, int uy1, double ArcAngle, int lg,
803  LAYER_NUM layer, int color, int op_logic )
804 {
805  int radius, nb_segm;
806  int x0, y0, // Starting point of the current segment trace
807  x1, y1; // End point
808  int ii;
809  double angle, StAngle;
810 
811 
812  radius = KiROUND( Distance( ux0, uy0, ux1, uy1 ) );
813 
814  x0 = ux1 - ux0;
815  y0 = uy1 - uy0;
816  StAngle = ArcTangente( uy1 - uy0, ux1 - ux0 );
817 
818  if( lg < 1 )
819  lg = 1;
820 
821  nb_segm = ( 2 * radius ) / lg;
822  nb_segm = ( nb_segm * std::abs( ArcAngle ) ) / 3600;
823 
824  if( nb_segm < 5 )
825  nb_segm = 5;
826 
827  if( nb_segm > 100 )
828  nb_segm = 100;
829 
830  for( ii = 1; ii <= nb_segm; ii++ )
831  {
832  angle = ( ArcAngle * ii ) / nb_segm;
833  angle += StAngle;
834 
835  NORMALIZE_ANGLE_POS( angle );
836 
837  x1 = KiROUND( cosdecideg( radius, angle ) );
838  y1 = KiROUND( cosdecideg( radius, angle ) );
839  DrawSegmentQcq( x0 + ux0, y0 + uy0, x1 + ux0, y1 + uy0, lg, layer, color, op_logic );
840  x0 = x1;
841  y0 = y1;
842  }
843 }
void PlacePad(D_PAD *aPad, int color, int marge, int op_logic)
Definition: graphpcb.cpp:87
KICAD_T Type() const
Function Type()
Definition: base_struct.h:198
#define VIA_IMPOSSIBLE
Definition: cell.h:48
long trace
Definition: solve.cpp:232
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
void TraceArc(int ux0, int uy0, int ux1, int uy1, double ArcAngle, int lg, LAYER_NUM layer, int color, int op_logic)
Definition: graphpcb.cpp:802
Class BOARD to handle a board.
LAYER_ID g_Route_Layer_TOP
Definition: pcbnew.cpp:78
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:317
void NORMALIZE_ANGLE_POS(T &Angle)
Definition: trigo.h:222
LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:166
#define abs(a)
Definition: auxiliary.h:84
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.
This file contains miscellaneous commonly used macros and functions.
void TraceSegmentPcb(DRAWSEGMENT *pt_segm, int color, int marge, int op_logic)
Definition: graphpcb.cpp:257
#define TOP
Definition: autorout.h:49
virtual bool IsOnLayer(LAYER_ID aLayer) const
Function IsOnLayer tests to see if this object is on the given layer.
STROKE_T GetShape() const
Class LSET is a set of LAYER_IDs.
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
static void DrawSegmentQcq(int ux0, int uy0, int ux1, int uy1, int lg, LAYER_NUM layer, int color, int op_logic)
Definition: graphpcb.cpp:632
double ArcTangente(int dy, int dx)
Definition: trigo.cpp:271
wxPoint GetBrdCoordOrigin()
function GetBrdCoordOrigin
Definition: autorout.h:139
void TraceFilledRectangle(int ux0, int uy0, int ux1, int uy1, LSET aLayerMask, int color, int op_logic)
Definition: graphpcb.cpp:478
const wxPoint & GetStart() const
Definition: class_track.h:120
Arcs (with rounded ends)
static void TraceFilledCircle(int cx, int cy, int radius, LSET aLayerMask, int color, int op_logic)
Definition: graphpcb.cpp:142
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
const wxSize & GetSize() const
Definition: class_pad.h:182
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
MATRIX_ROUTING_HEAD RoutingMatrix
Definition: autorout.cpp:51
double cosdecideg(double r, double a)
Circle generation utility: computes r * cos(a) Where a is in decidegrees, not in radians.
Definition: trigo.h:311
double sindecideg(double r, double a)
Circle generation utility: computes r * sin(a) Where a is in decidegrees, not in radians.
Definition: trigo.h:302
double GetAngle() const
Class to handle a graphic segment.
LAYER_ID
Enum LAYER_ID is the set of PCB layers.
int GetWidth() const
Definition: class_track.h:114
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
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
The common library.
void TracePcbLine(int x0, int y0, int x1, int y1, LAYER_NUM layer, int color)
int GetWidth() const
wxPoint ShapePos() const
Definition: class_pad.cpp:367
#define BOTTOM
Definition: autorout.h:50
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:108
double Distance(double x1, double y1, double x2, double y2)
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
void SetCellOperation(int aLogicOp)
LAYER_ID g_Route_Layer_BOTTOM
Definition: pcbnew.cpp:79
#define OP_CELL(layer, dy, dx)
Definition: graphpcb.cpp:69
static void TraceCircle(int ux0, int uy0, int ux1, int uy1, int lg, LAYER_NUM layer, int color, int op_logic)
Definition: graphpcb.cpp:758
void WriteCell(int aRow, int aCol, int aSide, MATRIX_CELL aCell)
Definition: autorout.h:129