KiCad PCB EDA Suite
ar_matrix.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) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
5  * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6  * Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
7  *
8  * Copyright (C) 1992-2015 KiCad Developers, see change_log.txt for contributors.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, you may find one here:
22  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
23  * or you may search the http://www.gnu.org website for the version 2 license,
24  * or you may write to the Free Software Foundation, Inc.,
25  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26  */
27 
28 #include "ar_matrix.h"
29 #include <math/util.h> // for KiROUND
30 #include <math_for_graphics.h>
31 #include <trigo.h>
32 
33 #include <class_drawsegment.h>
34 #include <class_pad.h>
35 
37 {
38  m_BoardSide[0] = nullptr;
39  m_BoardSide[1] = nullptr;
40  m_DistSide[0] = nullptr;
41  m_DistSide[1] = nullptr;
42  m_DirSide[0] = nullptr;
43  m_DirSide[1] = nullptr;
44  m_opWriteCell = nullptr;
45  m_Nrows = 0;
46  m_Ncols = 0;
47  m_MemSize = 0;
49  m_GridRouting = 0;
50  m_RouteCount = 0;
53 }
54 
55 
57 {
58 }
59 
60 // was: bool AR_MATRIX::ComputeMatrixSize( BOARD* aPcb, bool aUseBoardEdgesOnly )
61 // aUseBoardEdgesOnly ? aPcb->GetBoardEdgesBoundingBox() : aPcb->GetBoundingBox();
62 
63 bool AR_MATRIX::ComputeMatrixSize( const EDA_RECT& aBoundingBox )
64 {
65  // The boundary box must have its start point on routing grid:
66  m_BrdBox = aBoundingBox;
67 
70 
71  // The boundary box must have its end point on routing grid:
72  wxPoint end = m_BrdBox.GetEnd();
73 
74  end.x -= end.x % m_GridRouting;
75  end.x += m_GridRouting;
76 
77  end.y -= end.y % m_GridRouting;
78  end.y += m_GridRouting;
79 
80  m_BrdBox.SetEnd( end );
81 
84 
85  // gives a small margin
86  m_Ncols += 1;
87  m_Nrows += 1;
88 
89  return true;
90 }
91 
92 
94 {
95  if( m_Nrows <= 0 || m_Ncols <= 0 )
96  return 0;
97 
98  // give a small margin for memory allocation:
99  int ii = ( m_Nrows + 1 ) * ( m_Ncols + 1 );
100 
101  int side = AR_SIDE_BOTTOM;
102  for( int jj = 0; jj < m_RoutingLayersCount; jj++ ) // m_RoutingLayersCount = 1 or 2
103  {
104  m_BoardSide[side] = nullptr;
105  m_DistSide[side] = nullptr;
106  m_DirSide[side] = nullptr;
107 
108  // allocate matrix & initialize everything to empty
109  m_BoardSide[side] = (MATRIX_CELL*) operator new( ii * sizeof( MATRIX_CELL ) );
110  memset( m_BoardSide[side], 0, ii * sizeof( MATRIX_CELL ) );
111 
112  if( m_BoardSide[side] == nullptr )
113  return -1;
114 
115  // allocate Distances
116  m_DistSide[side] = (DIST_CELL*) operator new( ii * sizeof( DIST_CELL ) );
117  memset( m_DistSide[side], 0, ii * sizeof( DIST_CELL ) );
118 
119  if( m_DistSide[side] == nullptr )
120  return -1;
121 
122  // allocate Dir (chars)
123  m_DirSide[side] = (char*) operator new( ii );
124  memset( m_DirSide[side], 0, ii );
125 
126  if( m_DirSide[side] == nullptr )
127  return -1;
128 
129  side = AR_SIDE_TOP;
130  }
131 
132  m_MemSize =
133  m_RouteCount * ii * ( sizeof( MATRIX_CELL ) + sizeof( DIST_CELL ) + sizeof( char ) );
134 
135  return m_MemSize;
136 }
137 
138 
140 {
141  int ii;
142 
143  for( ii = 0; ii < AR_MAX_ROUTING_LAYERS_COUNT; ii++ )
144  {
145  // de-allocate Dir matrix
146  if( m_DirSide[ii] )
147  {
148  delete m_DirSide[ii];
149  m_DirSide[ii] = nullptr;
150  }
151 
152  // de-allocate Distances matrix
153  if( m_DistSide[ii] )
154  {
155  delete m_DistSide[ii];
156  m_DistSide[ii] = nullptr;
157  }
158 
159  // de-allocate cells matrix
160  if( m_BoardSide[ii] )
161  {
162  delete m_BoardSide[ii];
163  m_BoardSide[ii] = nullptr;
164  }
165  }
166 
167  m_Nrows = m_Ncols = 0;
168 }
169 
170 // Initialize m_opWriteCell member to make the aLogicOp
172 {
173  switch( aLogicOp )
174  {
175  default:
181  }
182 }
183 
184 
185 /* return the value stored in a cell
186  */
187 AR_MATRIX::MATRIX_CELL AR_MATRIX::GetCell( int aRow, int aCol, int aSide )
188 {
189  MATRIX_CELL* p;
190 
191  p = m_BoardSide[aSide];
192  return p[aRow * m_Ncols + aCol];
193 }
194 
195 
196 /* basic cell operation : WRITE operation
197  */
198 void AR_MATRIX::SetCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
199 {
200  MATRIX_CELL* p;
201 
202  p = m_BoardSide[aSide];
203  p[aRow * m_Ncols + aCol] = x;
204 }
205 
206 
207 /* basic cell operation : OR operation
208  */
209 void AR_MATRIX::OrCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
210 {
211  MATRIX_CELL* p;
212 
213  p = m_BoardSide[aSide];
214  p[aRow * m_Ncols + aCol] |= x;
215 }
216 
217 
218 /* basic cell operation : XOR operation
219  */
220 void AR_MATRIX::XorCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
221 {
222  MATRIX_CELL* p;
223 
224  p = m_BoardSide[aSide];
225  p[aRow * m_Ncols + aCol] ^= x;
226 }
227 
228 
229 /* basic cell operation : AND operation
230  */
231 void AR_MATRIX::AndCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
232 {
233  MATRIX_CELL* p;
234 
235  p = m_BoardSide[aSide];
236  p[aRow * m_Ncols + aCol] &= x;
237 }
238 
239 
240 /* basic cell operation : ADD operation
241  */
242 void AR_MATRIX::AddCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
243 {
244  MATRIX_CELL* p;
245 
246  p = m_BoardSide[aSide];
247  p[aRow * m_Ncols + aCol] += x;
248 }
249 
250 
251 // fetch distance cell
252 AR_MATRIX::DIST_CELL AR_MATRIX::GetDist( int aRow, int aCol, int aSide ) // fetch distance cell
253 {
254  DIST_CELL* p;
255 
256  p = m_DistSide[aSide];
257  return p[aRow * m_Ncols + aCol];
258 }
259 
260 
261 // store distance cell
262 void AR_MATRIX::SetDist( int aRow, int aCol, int aSide, DIST_CELL x )
263 {
264  DIST_CELL* p;
265 
266  p = m_DistSide[aSide];
267  p[aRow * m_Ncols + aCol] = x;
268 }
269 
270 
271 /*
272 ** x is the direction to enter the cell of interest.
273 ** y is the direction to exit the cell of interest.
274 ** z is the direction to really exit the cell, if y=FROM_OTHERSIDE.
275 **
276 ** return the distance of the trace through the cell of interest.
277 ** the calculation is driven by the tables above.
278 */
279 
280 
281 #define OP_CELL( layer, dy, dx ) \
282  { \
283  if( layer == UNDEFINED_LAYER ) \
284  { \
285  WriteCell( dy, dx, AR_SIDE_BOTTOM, color ); \
286  if( m_RoutingLayersCount > 1 ) \
287  WriteCell( dy, dx, AR_SIDE_TOP, color ); \
288  } \
289  else \
290  { \
291  if( layer == m_routeLayerBottom ) \
292  WriteCell( dy, dx, AR_SIDE_BOTTOM, color ); \
293  if( m_RoutingLayersCount > 1 ) \
294  if( layer == m_routeLayerTop ) \
295  WriteCell( dy, dx, AR_SIDE_TOP, color ); \
296  } \
297  }
298 
299 /* Fills all cells inside a segment
300  * half-width = lg, org = ux0,uy0 end = ux1,uy1
301  * coordinates are in PCB units
302  */
303 void AR_MATRIX::drawSegmentQcq( int ux0, int uy0, int ux1, int uy1, int lg, LAYER_NUM layer,
304  int color, AR_MATRIX::CELL_OP op_logic )
305 {
306  int64_t row, col;
307  int64_t inc;
308  int64_t row_max, col_max, row_min, col_min;
309  int64_t demi_pas;
310 
311  int cx, cy, dx, dy;
312 
313 
314  //printf("segmQcq %d %d %d %d\n", ux0, uy0, ux1, uy1);
315 
316  SetCellOperation( op_logic );
317 
318  // Make coordinate ux1 tj > ux0 to simplify calculations
319  if( ux1 < ux0 )
320  {
321  std::swap( ux1, ux0 );
322  std::swap( uy1, uy0 );
323  }
324 
325  // Calculating the incrementing the Y axis
326  inc = 1;
327 
328  if( uy1 < uy0 )
329  inc = -1;
330 
331  demi_pas = m_GridRouting / 2;
332 
333  col_min = ( ux0 - lg ) / m_GridRouting;
334 
335  if( col_min < 0 )
336  col_min = 0;
337 
338  col_max = ( ux1 + lg + demi_pas ) / m_GridRouting;
339 
340  if( col_max > ( m_Ncols - 1 ) )
341  col_max = m_Ncols - 1;
342 
343  if( inc > 0 )
344  {
345  row_min = ( uy0 - lg ) / m_GridRouting;
346  row_max = ( uy1 + lg + demi_pas ) / m_GridRouting;
347  }
348  else
349  {
350  row_min = ( uy1 - lg ) / m_GridRouting;
351  row_max = ( uy0 + lg + demi_pas ) / m_GridRouting;
352  }
353 
354  if( row_min < 0 )
355  row_min = 0;
356 
357  if( row_min > ( m_Nrows - 1 ) )
358  row_min = m_Nrows - 1;
359 
360  if( row_max < 0 )
361  row_max = 0;
362 
363  if( row_max > ( m_Nrows - 1 ) )
364  row_max = m_Nrows - 1;
365 
366  dx = ux1 - ux0;
367  dy = uy1 - uy0;
368 
369  double angle;
370  if( dx )
371  {
372  angle = ArcTangente( dy, dx );
373  }
374  else
375  {
376  angle = 900;
377 
378  if( dy < 0 )
379  angle = -900;
380  }
381 
382  RotatePoint( &dx, &dy, angle ); // dx = length, dy = 0
383 
384 
385  //printf("col_min %d max %d row_min %d max %d\n", col_min, col_max, row_min, row_max);
386 
387  for( col = col_min; col <= col_max; col++ )
388  {
389  int64_t cxr;
390  cxr = ( col * m_GridRouting ) - ux0;
391 
392  for( row = row_min; row <= row_max; row++ )
393  {
394  cy = ( row * m_GridRouting ) - uy0;
395  cx = cxr;
396  RotatePoint( &cx, &cy, angle );
397 
398  if( abs( cy ) > lg )
399  continue; // The point is too far on the Y axis.
400 
401  /* This point a test is close to the segment: the position
402  * along the X axis must be tested.
403  */
404  if( ( cx >= 0 ) && ( cx <= dx ) )
405  {
406  OP_CELL( layer, row, col );
407  continue;
408  }
409 
410  // Examination of extremities are rounded.
411  if( ( cx < 0 ) && ( cx >= -lg ) )
412  {
413  if( ( ( cx * cx ) + ( cy * cy ) ) <= ( lg * lg ) )
414  OP_CELL( layer, row, col );
415 
416  continue;
417  }
418 
419  if( ( cx > dx ) && ( cx <= ( dx + lg ) ) )
420  {
421  if( ( ( ( cx - dx ) * ( cx - dx ) ) + ( cy * cy ) ) <= ( lg * lg ) )
422  OP_CELL( layer, row, col );
423 
424  continue;
425  }
426  }
427  }
428 }
429 
430 
431 /* Fills all cells of the routing matrix contained in the circle
432  * half-width = lg, center = ux0, uy0, ux1,uy1 is a point on the circle.
433  * coord are in PCB units.
434  */
435 void AR_MATRIX::traceCircle( int ux0, int uy0, int ux1, int uy1, int lg, LAYER_NUM layer, int color,
436  AR_MATRIX::CELL_OP op_logic )
437 {
438  int radius, nb_segm;
439  int x0, y0, // Starting point of the current segment trace.
440  x1, y1; // End point.
441  int ii;
442  int angle;
443 
444  radius = KiROUND( Distance( ux0, uy0, ux1, uy1 ) );
445 
446  x0 = x1 = radius;
447  y0 = y1 = 0;
448 
449  if( lg < 1 )
450  lg = 1;
451 
452  nb_segm = ( 2 * radius ) / lg;
453 
454  if( nb_segm < 5 )
455  nb_segm = 5;
456 
457  if( nb_segm > 100 )
458  nb_segm = 100;
459 
460  for( ii = 1; ii < nb_segm; ii++ )
461  {
462  angle = ( 3600 * ii ) / nb_segm;
463  x1 = KiROUND( cosdecideg( radius, angle ) );
464  y1 = KiROUND( sindecideg( radius, angle ) );
465  drawSegmentQcq( x0 + ux0, y0 + uy0, x1 + ux0, y1 + uy0, lg, layer, color, op_logic );
466  x0 = x1;
467  y0 = y1;
468  }
469 
470  drawSegmentQcq( x1 + ux0, y1 + uy0, ux0 + radius, uy0, lg, layer, color, op_logic );
471 }
472 
473 
475  int cx, int cy, int radius, LSET aLayerMask, int color, AR_MATRIX::CELL_OP op_logic )
476 {
477  int row, col;
478  int ux0, uy0, ux1, uy1;
479  int row_max, col_max, row_min, col_min;
480  int trace = 0;
481  double fdistmin, fdistx, fdisty;
482  int tstwrite = 0;
483  int distmin;
484 
485  if( aLayerMask[m_routeLayerBottom] )
486  trace = 1; // Trace on BOTTOM
487 
488  if( aLayerMask[m_routeLayerTop] )
489  if( m_RoutingLayersCount > 1 )
490  trace |= 2; // Trace on TOP
491 
492  if( trace == 0 )
493  return;
494 
495  SetCellOperation( op_logic );
496 
497  cx -= GetBrdCoordOrigin().x;
498  cy -= GetBrdCoordOrigin().y;
499 
500  distmin = radius;
501 
502  // Calculate the bounding rectangle of the circle.
503  ux0 = cx - radius;
504  uy0 = cy - radius;
505  ux1 = cx + radius;
506  uy1 = cy + radius;
507 
508  // Calculate limit coordinates of cells belonging to the rectangle.
509  row_max = uy1 / m_GridRouting;
510  col_max = ux1 / m_GridRouting;
511  row_min = uy0 / m_GridRouting; // if (uy0 > row_min*Board.m_GridRouting) row_min++;
512  col_min = ux0 / m_GridRouting; // if (ux0 > col_min*Board.m_GridRouting) col_min++;
513 
514  if( row_min < 0 )
515  row_min = 0;
516 
517  if( row_max >= ( m_Nrows - 1 ) )
518  row_max = m_Nrows - 1;
519 
520  if( col_min < 0 )
521  col_min = 0;
522 
523  if( col_max >= ( m_Ncols - 1 ) )
524  col_max = m_Ncols - 1;
525 
526  // Calculate coordinate limits of cell belonging to the rectangle.
527  if( row_min > row_max )
528  row_max = row_min;
529 
530  if( col_min > col_max )
531  col_max = col_min;
532 
533  fdistmin = (double) distmin * distmin;
534 
535  for( row = row_min; row <= row_max; row++ )
536  {
537  fdisty = (double) ( cy - ( row * m_GridRouting ) );
538  fdisty *= fdisty;
539 
540  for( col = col_min; col <= col_max; col++ )
541  {
542  fdistx = (double) ( cx - ( col * m_GridRouting ) );
543  fdistx *= fdistx;
544 
545  if( fdistmin <= ( fdistx + fdisty ) )
546  continue;
547 
548  if( trace & 1 )
549  WriteCell( row, col, AR_SIDE_BOTTOM, color );
550 
551  if( trace & 2 )
552  WriteCell( row, col, AR_SIDE_TOP, color );
553 
554  tstwrite = 1;
555  }
556  }
557 
558  if( tstwrite )
559  return;
560 
561  /* If no cell has been written, it affects the 4 neighboring diagonal
562  * (Adverse event: pad off grid in the center of the 4 neighboring
563  * diagonal) */
564  distmin = m_GridRouting / 2 + 1;
565  fdistmin = ( (double) distmin * distmin ) * 2; // Distance to center point diagonally
566 
567  for( row = row_min; row <= row_max; row++ )
568  {
569  fdisty = (double) ( cy - ( row * m_GridRouting ) );
570  fdisty *= fdisty;
571 
572  for( col = col_min; col <= col_max; col++ )
573  {
574  fdistx = (double) ( cx - ( col * m_GridRouting ) );
575  fdistx *= fdistx;
576 
577  if( fdistmin <= ( fdistx + fdisty ) )
578  continue;
579 
580  if( trace & 1 )
581  WriteCell( row, col, AR_SIDE_BOTTOM, color );
582 
583  if( trace & 2 )
584  WriteCell( row, col, AR_SIDE_TOP, color );
585  }
586  }
587 }
588 
589 
590 /* Fills all routing matrix cells contained in the arc
591  * angle = ArcAngle, half-width lg
592  * center = ux0,uy0, starting at ux1, uy1. Coordinates are in
593  * PCB units.
594  */
595 void AR_MATRIX::traceArc( int ux0, int uy0, int ux1, int uy1, double ArcAngle, int lg,
596  LAYER_NUM layer, int color, AR_MATRIX::CELL_OP op_logic )
597 {
598  int radius, nb_segm;
599  int x0, y0, // Starting point of the current segment trace
600  x1, y1; // End point
601  int ii;
602  double angle, StAngle;
603 
604 
605  radius = KiROUND( Distance( ux0, uy0, ux1, uy1 ) );
606 
607  x0 = ux1 - ux0;
608  y0 = uy1 - uy0;
609  StAngle = ArcTangente( uy1 - uy0, ux1 - ux0 );
610 
611  if( lg < 1 )
612  lg = 1;
613 
614  nb_segm = ( 2 * radius ) / lg;
615  nb_segm = ( nb_segm * std::abs( ArcAngle ) ) / 3600;
616 
617  if( nb_segm < 5 )
618  nb_segm = 5;
619 
620  if( nb_segm > 100 )
621  nb_segm = 100;
622 
623  for( ii = 1; ii <= nb_segm; ii++ )
624  {
625  angle = ( ArcAngle * ii ) / nb_segm;
626  angle += StAngle;
627 
629 
630  x1 = KiROUND( cosdecideg( radius, angle ) );
631  y1 = KiROUND( cosdecideg( radius, angle ) );
632  drawSegmentQcq( x0 + ux0, y0 + uy0, x1 + ux0, y1 + uy0, lg, layer, color, op_logic );
633  x0 = x1;
634  y0 = y1;
635  }
636 }
637 
638 
639 void AR_MATRIX::TraceFilledRectangle( int ux0, int uy0, int ux1, int uy1, double angle,
640  LSET aLayerMask, int color, AR_MATRIX::CELL_OP op_logic )
641 {
642  int row, col;
643  int cx, cy; // Center of rectangle
644  int radius; // Radius of the circle
645  int row_min, row_max, col_min, col_max;
646  int rotrow, rotcol;
647  int trace = 0;
648 
649  if( aLayerMask[m_routeLayerBottom] )
650  trace = 1; // Trace on BOTTOM
651 
652  if( aLayerMask[m_routeLayerTop] )
653  {
654  if( m_RoutingLayersCount > 1 )
655  trace |= 2; // Trace on TOP
656  }
657 
658  if( trace == 0 )
659  return;
660 
661  SetCellOperation( op_logic );
662 
663  ux0 -= GetBrdCoordOrigin().x;
664  uy0 -= GetBrdCoordOrigin().y;
665  ux1 -= GetBrdCoordOrigin().x;
666  uy1 -= GetBrdCoordOrigin().y;
667 
668  cx = ( ux0 + ux1 ) / 2;
669  cy = ( uy0 + uy1 ) / 2;
670  radius = KiROUND( Distance( ux0, uy0, cx, cy ) );
671 
672  // Calculating coordinate limits belonging to the rectangle.
673  row_max = ( cy + radius ) / m_GridRouting;
674  col_max = ( cx + radius ) / m_GridRouting;
675  row_min = ( cy - radius ) / m_GridRouting;
676 
677  if( uy0 > row_min * m_GridRouting )
678  row_min++;
679 
680  col_min = ( cx - radius ) / m_GridRouting;
681 
682  if( ux0 > col_min * m_GridRouting )
683  col_min++;
684 
685  if( row_min < 0 )
686  row_min = 0;
687 
688  if( row_max >= ( m_Nrows - 1 ) )
689  row_max = m_Nrows - 1;
690 
691  if( col_min < 0 )
692  col_min = 0;
693 
694  if( col_max >= ( m_Ncols - 1 ) )
695  col_max = m_Ncols - 1;
696 
697  for( row = row_min; row <= row_max; row++ )
698  {
699  for( col = col_min; col <= col_max; col++ )
700  {
701  rotrow = row * m_GridRouting;
702  rotcol = col * m_GridRouting;
703  RotatePoint( &rotcol, &rotrow, cx, cy, -angle );
704 
705  if( rotrow <= uy0 )
706  continue;
707 
708  if( rotrow >= uy1 )
709  continue;
710 
711  if( rotcol <= ux0 )
712  continue;
713 
714  if( rotcol >= ux1 )
715  continue;
716 
717  if( trace & 1 )
718  WriteCell( row, col, AR_SIDE_BOTTOM, color );
719 
720  if( trace & 2 )
721  WriteCell( row, col, AR_SIDE_TOP, color );
722  }
723  }
724 }
725 
726 
727 void AR_MATRIX::TraceFilledRectangle( int ux0, int uy0, int ux1, int uy1, LSET aLayerMask,
728  int color, AR_MATRIX::CELL_OP op_logic )
729 {
730  int row, col;
731  int row_min, row_max, col_min, col_max;
732  int trace = 0;
733 
734  if( aLayerMask[m_routeLayerBottom] )
735  trace = 1; // Trace on BOTTOM
736 
737  if( aLayerMask[m_routeLayerTop] && m_RoutingLayersCount > 1 )
738  trace |= 2; // Trace on TOP
739 
740  if( trace == 0 )
741  return;
742 
743  SetCellOperation( op_logic );
744 
745  ux0 -= GetBrdCoordOrigin().x;
746  uy0 -= GetBrdCoordOrigin().y;
747  ux1 -= GetBrdCoordOrigin().x;
748  uy1 -= GetBrdCoordOrigin().y;
749 
750  // Calculating limits coord cells belonging to the rectangle.
751  row_max = uy1 / m_GridRouting;
752  col_max = ux1 / m_GridRouting;
753  row_min = uy0 / m_GridRouting;
754 
755  if( uy0 > row_min * m_GridRouting )
756  row_min++;
757 
758  col_min = ux0 / m_GridRouting;
759 
760  if( ux0 > col_min * m_GridRouting )
761  col_min++;
762 
763  if( row_min < 0 )
764  row_min = 0;
765 
766  if( row_max >= ( m_Nrows - 1 ) )
767  row_max = m_Nrows - 1;
768 
769  if( col_min < 0 )
770  col_min = 0;
771 
772  if( col_max >= ( m_Ncols - 1 ) )
773  col_max = m_Ncols - 1;
774 
775  for( row = row_min; row <= row_max; row++ )
776  {
777  for( col = col_min; col <= col_max; col++ )
778  {
779  if( trace & 1 )
780  WriteCell( row, col, AR_SIDE_BOTTOM, color );
781 
782  if( trace & 2 )
783  WriteCell( row, col, AR_SIDE_TOP, color );
784  }
785  }
786 }
787 
788 
790  DRAWSEGMENT* pt_segm, int color, int marge, AR_MATRIX::CELL_OP op_logic )
791 {
792  int half_width = ( pt_segm->GetWidth() / 2 ) + marge;
793 
794  // Calculate the bounding rectangle of the segment (if H, V or Via)
795  int ux0 = pt_segm->GetStart().x - GetBrdCoordOrigin().x;
796  int uy0 = pt_segm->GetStart().y - GetBrdCoordOrigin().y;
797  int ux1 = pt_segm->GetEnd().x - GetBrdCoordOrigin().x;
798  int uy1 = pt_segm->GetEnd().y - GetBrdCoordOrigin().y;
799 
800  //printf("traceSegm %d %d %d %d\n", ux0, uy0, ux1, uy1);
801 
802  LAYER_NUM layer = UNDEFINED_LAYER; // Draw on all layers
803 
804  switch( pt_segm->GetShape() )
805  {
806  case S_CIRCLE:
807  traceCircle( ux0, uy0, ux1, uy1, half_width, layer, color, op_logic );
808  break;
809 
810  case S_ARC:
811  traceArc( ux0, uy0, ux1, uy1, pt_segm->GetAngle(), half_width, layer, color, op_logic );
812  break;
813 
814  case S_SEGMENT:
815  drawSegmentQcq( ux0, uy0, ux1, uy1, half_width, layer, color, op_logic );
816  break;
817 
818  default:
819  break;
820  }
821 }
822 
823 
835  int ux0, int uy0, int ux1, int uy1, int marge, int aKeepOut, LSET aLayerMask )
836 {
837  int row, col;
838  int row_min, row_max, col_min, col_max, pmarge;
839  int trace = 0;
840  DIST_CELL data, LocalKeepOut;
841  int lgain, cgain;
842 
843  if( aLayerMask[m_routeLayerBottom] )
844  trace = 1; // Trace on bottom layer.
845 
846  if( aLayerMask[m_routeLayerTop] && m_RoutingLayersCount )
847  trace |= 2; // Trace on top layer.
848 
849  if( trace == 0 )
850  return;
851 
852  ux0 -= m_BrdBox.GetX();
853  uy0 -= m_BrdBox.GetY();
854  ux1 -= m_BrdBox.GetX();
855  uy1 -= m_BrdBox.GetY();
856 
857  ux0 -= marge;
858  ux1 += marge;
859  uy0 -= marge;
860  uy1 += marge;
861 
862  pmarge = marge / m_GridRouting;
863 
864  if( pmarge < 1 )
865  pmarge = 1;
866 
867  // Calculate the coordinate limits of the rectangle.
868  row_max = uy1 / m_GridRouting;
869  col_max = ux1 / m_GridRouting;
870  row_min = uy0 / m_GridRouting;
871 
872  if( uy0 > row_min * m_GridRouting )
873  row_min++;
874 
875  col_min = ux0 / m_GridRouting;
876 
877  if( ux0 > col_min * m_GridRouting )
878  col_min++;
879 
880  if( row_min < 0 )
881  row_min = 0;
882 
883  if( row_max >= ( m_Nrows - 1 ) )
884  row_max = m_Nrows - 1;
885 
886  if( col_min < 0 )
887  col_min = 0;
888 
889  if( col_max >= ( m_Ncols - 1 ) )
890  col_max = m_Ncols - 1;
891 
892  for( row = row_min; row <= row_max; row++ )
893  {
894  lgain = 256;
895 
896  if( row < pmarge )
897  lgain = ( 256 * row ) / pmarge;
898  else if( row > row_max - pmarge )
899  lgain = ( 256 * ( row_max - row ) ) / pmarge;
900 
901  for( col = col_min; col <= col_max; col++ )
902  {
903  // RoutingMatrix Dist map containt the "cost" of the cell
904  // at position (row, col)
905  // in autoplace this is the cost of the cell, when
906  // a footprint overlaps it, near a "master" footprint
907  // this cost is hight near the "master" footprint
908  // and decrease with the distance
909  cgain = 256;
910  LocalKeepOut = aKeepOut;
911 
912  if( col < pmarge )
913  cgain = ( 256 * col ) / pmarge;
914  else if( col > col_max - pmarge )
915  cgain = ( 256 * ( col_max - col ) ) / pmarge;
916 
917  cgain = ( cgain * lgain ) / 256;
918 
919  if( cgain != 256 )
920  LocalKeepOut = ( LocalKeepOut * cgain ) / 256;
921 
922  if( trace & 1 )
923  {
924  data = GetDist( row, col, AR_SIDE_BOTTOM ) + LocalKeepOut;
925  SetDist( row, col, AR_SIDE_BOTTOM, data );
926  }
927 
928  if( trace & 2 )
929  {
930  data = GetDist( row, col, AR_SIDE_TOP );
931  data = std::max( data, LocalKeepOut );
932  SetDist( row, col, AR_SIDE_TOP, data );
933  }
934  }
935  }
936 }
937 
938 
939 void AR_MATRIX::PlacePad( D_PAD* aPad, int color, int marge, AR_MATRIX::CELL_OP op_logic )
940 {
941  int dx, dy;
942  wxPoint shape_pos = aPad->ShapePos();
943 
944  dx = aPad->GetSize().x / 2;
945  dx += marge;
946 
947  if( aPad->GetShape() == PAD_SHAPE_CIRCLE )
948  {
949  traceFilledCircle( shape_pos.x, shape_pos.y, dx, aPad->GetLayerSet(), color, op_logic );
950  return;
951  }
952 
953  dy = aPad->GetSize().y / 2;
954  dy += marge;
955 
956  if( aPad->GetShape() == PAD_SHAPE_TRAPEZOID )
957  {
958  dx += abs( aPad->GetDelta().y ) / 2;
959  dy += abs( aPad->GetDelta().x ) / 2;
960  }
961 
962  // The pad is a rectangle ( horizontal or vertical )
963  if( int( aPad->GetOrientation() ) % 900 == 0 )
964  {
965  // Orientation turned 90 deg.
966  if( aPad->GetOrientation() == 900 || aPad->GetOrientation() == 2700 )
967  {
968  std::swap( dx, dy );
969  }
970 
971  TraceFilledRectangle( shape_pos.x - dx, shape_pos.y - dy, shape_pos.x + dx,
972  shape_pos.y + dy, aPad->GetLayerSet(), color, op_logic );
973  }
974  else
975  {
976  TraceFilledRectangle( shape_pos.x - dx, shape_pos.y - dy, shape_pos.x + dx,
977  shape_pos.y + dy, aPad->GetOrientation(), aPad->GetLayerSet(), color, op_logic );
978  }
979 }
#define AR_SIDE_BOTTOM
Definition: ar_matrix.h:43
void traceArc(int ux0, int uy0, int ux1, int uy1, double ArcAngle, int lg, LAYER_NUM layer, int color, AR_MATRIX::CELL_OP op_logic)
Definition: ar_matrix.cpp:595
int InitRoutingMatrix()
Function InitBoard initializes the data structures.
Definition: ar_matrix.cpp:93
DIST_CELL * m_DistSide[AR_MAX_ROUTING_LAYERS_COUNT]
Definition: ar_matrix.h:57
int m_MemSize
Definition: ar_matrix.h:65
#define AR_SIDE_TOP
Definition: ar_matrix.h:42
int m_Ncols
Definition: ar_matrix.h:64
int GetX() const
Definition: eda_rect.h:111
STROKE_T GetShape() const
int m_GridRouting
Definition: ar_matrix.h:62
int color
Definition: DXF_plotter.cpp:61
void TraceFilledRectangle(int ux0, int uy0, int ux1, int uy1, double angle, LSET aLayerMask, int color, AR_MATRIX::CELL_OP op_logic)
Definition: ar_matrix.cpp:639
EDA_RECT m_BrdBox
Definition: ar_matrix.h:63
int GetWidth() const
Definition: eda_rect.h:119
void CreateKeepOutRectangle(int ux0, int uy0, int ux1, int uy1, int marge, int aKeepOut, LSET aLayerMask)
Function CreateKeepOutRectangle builds the cost map: Cells ( in Dist map ) inside the rect x0,...
Definition: ar_matrix.cpp:834
void PlacePad(D_PAD *aPad, int color, int marge, AR_MATRIX::CELL_OP op_logic)
Definition: ar_matrix.cpp:939
usual segment : line with rounded ends
void TraceSegmentPcb(DRAWSEGMENT *pt_segm, int color, int marge, AR_MATRIX::CELL_OP op_logic)
Definition: ar_matrix.cpp:789
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
void NORMALIZE_ANGLE_POS(T &Angle)
Definition: trigo.h:257
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
int DIST_CELL
Definition: ar_matrix.h:53
void XorCell(int aRow, int aCol, int aSide, MATRIX_CELL aCell)
Definition: ar_matrix.cpp:220
const wxPoint GetEnd() const
Definition: eda_rect.h:116
PCB_LAYER_ID m_routeLayerTop
Definition: ar_matrix.h:68
LSET is a set of PCB_LAYER_IDs.
void WriteCell(int aRow, int aCol, int aSide, MATRIX_CELL aCell)
Definition: ar_matrix.h:88
void SetEnd(int x, int y)
Definition: eda_rect.h:192
void OrCell(int aRow, int aCol, int aSide, MATRIX_CELL aCell)
Definition: ar_matrix.cpp:209
Arcs (with rounded ends)
MATRIX_CELL GetCell(int aRow, int aCol, int aSide)
Definition: ar_matrix.cpp:187
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:335
void(AR_MATRIX::* m_opWriteCell)(int aRow, int aCol, int aSide, MATRIX_CELL aCell)
Definition: ar_matrix.h:73
int m_Nrows
Definition: ar_matrix.h:64
DIR_CELL * m_DirSide[AR_MAX_ROUTING_LAYERS_COUNT]
Definition: ar_matrix.h:59
void SetX(int val)
Definition: eda_rect.h:168
void SetCellOperation(CELL_OP aLogicOp)
Definition: ar_matrix.cpp:171
MATRIX_CELL * m_BoardSide[AR_MAX_ROUTING_LAYERS_COUNT]
Definition: ar_matrix.h:56
void SetCell(int aRow, int aCol, int aSide, MATRIX_CELL aCell)
Definition: ar_matrix.cpp:198
void drawSegmentQcq(int ux0, int uy0, int ux1, int uy1, int lg, LAYER_NUM layer, int color, CELL_OP op_logic)
Definition: ar_matrix.cpp:303
const wxSize & GetDelta() const
Definition: class_pad.h:227
void AndCell(int aRow, int aCol, int aSide, MATRIX_CELL aCell)
Definition: ar_matrix.cpp:231
int GetHeight() const
Definition: eda_rect.h:120
int GetWidth() const
Pad object description.
void SetY(int val)
Definition: eda_rect.h:174
void traceCircle(int ux0, int uy0, int ux1, int uy1, int lg, LAYER_NUM layer, int color, AR_MATRIX::CELL_OP op_logic)
Definition: ar_matrix.cpp:435
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
void UnInitRoutingMatrix()
Definition: ar_matrix.cpp:139
#define OP_CELL(layer, dy, dx)
Definition: ar_matrix.cpp:281
double cosdecideg(double r, double a)
Circle generation utility: computes r * cos(a) Where a is in decidegrees, not in radians.
Definition: trigo.h:408
double GetAngle() const
double sindecideg(double r, double a)
Circle generation utility: computes r * sin(a) Where a is in decidegrees, not in radians.
Definition: trigo.h:399
Class to handle a graphic segment.
int m_RoutingLayersCount
Definition: ar_matrix.h:61
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees,...
Definition: class_pad.h:325
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
wxPoint GetBrdCoordOrigin()
function GetBrdCoordOrigin
Definition: ar_matrix.h:98
wxPoint ShapePos() const
Definition: class_pad.cpp:563
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
void AddCell(int aRow, int aCol, int aSide, MATRIX_CELL aCell)
Definition: ar_matrix.cpp:242
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
int GetY() const
Definition: eda_rect.h:112
void traceFilledCircle(int cx, int cy, int radius, LSET aLayerMask, int color, AR_MATRIX::CELL_OP op_logic)
Definition: ar_matrix.cpp:474
unsigned char MATRIX_CELL
Definition: ar_matrix.h:52
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
PAD_SHAPE_T GetShape() const
Definition: class_pad.h:157
double ArcTangente(int dy, int dx)
Definition: trigo.cpp:162
void SetDist(int aRow, int aCol, int aSide, DIST_CELL)
Definition: ar_matrix.cpp:262
bool ComputeMatrixSize(const EDA_RECT &aBoundingBox)
Function ComputeMatrixSize calculates the number of rows and columns of dimensions of aPcb for routin...
Definition: ar_matrix.cpp:63
const wxSize & GetSize() const
Definition: class_pad.h:224
#define AR_MAX_ROUTING_LAYERS_COUNT
Definition: ar_matrix.h:40
int m_RouteCount
Definition: ar_matrix.h:66
DIST_CELL GetDist(int aRow, int aCol, int aSide)
Definition: ar_matrix.cpp:252
PCB_LAYER_ID m_routeLayerBottom
Definition: ar_matrix.h:69