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