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 "ar_cell.h"
30 
31 #include <common.h>
32 #include <math/util.h> // for KiROUND
33 #include <math_for_graphics.h>
34 #include <trigo.h>
35 
36 #include <class_drawsegment.h>
37 #include <class_pad.h>
38 #include <class_track.h>
39 
41 {
42  m_BoardSide[0] = nullptr;
43  m_BoardSide[1] = nullptr;
44  m_DistSide[0] = nullptr;
45  m_DistSide[1] = nullptr;
46  m_DirSide[0] = nullptr;
47  m_DirSide[1] = nullptr;
48  m_opWriteCell = nullptr;
49  m_InitMatrixDone = false;
50  m_Nrows = 0;
51  m_Ncols = 0;
52  m_MemSize = 0;
54  m_GridRouting = 0;
55  m_RouteCount = 0;
58 }
59 
60 
62 {
63 }
64 
65 // was: bool AR_MATRIX::ComputeMatrixSize( BOARD* aPcb, bool aUseBoardEdgesOnly )
66 // aUseBoardEdgesOnly ? aPcb->GetBoardEdgesBoundingBox() : aPcb->GetBoundingBox();
67 
68 bool AR_MATRIX::ComputeMatrixSize( const EDA_RECT& aBoundingBox )
69 {
70  // The boundary box must have its start point on routing grid:
71  m_BrdBox = aBoundingBox;
72 
75 
76  // The boundary box must have its end point on routing grid:
77  wxPoint end = m_BrdBox.GetEnd();
78 
79  end.x -= end.x % m_GridRouting;
80  end.x += m_GridRouting;
81 
82  end.y -= end.y % m_GridRouting;
83  end.y += m_GridRouting;
84 
85  m_BrdBox.SetEnd( end );
86 
89 
90  // gives a small margin
91  m_Ncols += 1;
92  m_Nrows += 1;
93 
94  return true;
95 }
96 
97 
99 {
100  if( m_Nrows <= 0 || m_Ncols <= 0 )
101  return 0;
102 
103  m_InitMatrixDone = true; // we have been called
104 
105  // give a small margin for memory allocation:
106  int ii = ( m_Nrows + 1 ) * ( m_Ncols + 1 );
107 
108  int side = AR_SIDE_BOTTOM;
109  for( int jj = 0; jj < m_RoutingLayersCount; jj++ ) // m_RoutingLayersCount = 1 or 2
110  {
111  m_BoardSide[side] = nullptr;
112  m_DistSide[side] = nullptr;
113  m_DirSide[side] = nullptr;
114 
115  // allocate matrix & initialize everything to empty
116  m_BoardSide[side] = (MATRIX_CELL*) operator new( ii * sizeof( MATRIX_CELL ) );
117  memset( m_BoardSide[side], 0, ii * sizeof( MATRIX_CELL ) );
118 
119  if( m_BoardSide[side] == nullptr )
120  return -1;
121 
122  // allocate Distances
123  m_DistSide[side] = (DIST_CELL*) operator new( ii * sizeof( DIST_CELL ) );
124  memset( m_DistSide[side], 0, ii * sizeof( DIST_CELL ) );
125 
126  if( m_DistSide[side] == nullptr )
127  return -1;
128 
129  // allocate Dir (chars)
130  m_DirSide[side] = (char*) operator new( ii );
131  memset( m_DirSide[side], 0, ii );
132 
133  if( m_DirSide[side] == nullptr )
134  return -1;
135 
136  side = AR_SIDE_TOP;
137  }
138 
139  m_MemSize =
140  m_RouteCount * ii * ( sizeof( MATRIX_CELL ) + sizeof( DIST_CELL ) + sizeof( char ) );
141 
142  return m_MemSize;
143 }
144 
145 
147 {
148  int ii;
149 
150  m_InitMatrixDone = false;
151 
152  for( ii = 0; ii < AR_MAX_ROUTING_LAYERS_COUNT; ii++ )
153  {
154  // de-allocate Dir matrix
155  if( m_DirSide[ii] )
156  {
157  delete m_DirSide[ii];
158  m_DirSide[ii] = nullptr;
159  }
160 
161  // de-allocate Distances matrix
162  if( m_DistSide[ii] )
163  {
164  delete m_DistSide[ii];
165  m_DistSide[ii] = nullptr;
166  }
167 
168  // de-allocate cells matrix
169  if( m_BoardSide[ii] )
170  {
171  delete m_BoardSide[ii];
172  m_BoardSide[ii] = nullptr;
173  }
174  }
175 
176  m_Nrows = m_Ncols = 0;
177 }
178 
179 // Initialize m_opWriteCell member to make the aLogicOp
181 {
182  switch( aLogicOp )
183  {
184  default:
186 
188 
190 
192 
194  }
195 }
196 
197 
198 /* return the value stored in a cell
199  */
200 AR_MATRIX::MATRIX_CELL AR_MATRIX::GetCell( int aRow, int aCol, int aSide )
201 {
202  MATRIX_CELL* p;
203 
204  p = m_BoardSide[aSide];
205  return p[aRow * m_Ncols + aCol];
206 }
207 
208 
209 /* basic cell operation : WRITE operation
210  */
211 void AR_MATRIX::SetCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
212 {
213  MATRIX_CELL* p;
214 
215  p = m_BoardSide[aSide];
216  p[aRow * m_Ncols + aCol] = x;
217 }
218 
219 
220 /* basic cell operation : OR operation
221  */
222 void AR_MATRIX::OrCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
223 {
224  MATRIX_CELL* p;
225 
226  p = m_BoardSide[aSide];
227  p[aRow * m_Ncols + aCol] |= x;
228 }
229 
230 
231 /* basic cell operation : XOR operation
232  */
233 void AR_MATRIX::XorCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
234 {
235  MATRIX_CELL* p;
236 
237  p = m_BoardSide[aSide];
238  p[aRow * m_Ncols + aCol] ^= x;
239 }
240 
241 
242 /* basic cell operation : AND operation
243  */
244 void AR_MATRIX::AndCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
245 {
246  MATRIX_CELL* p;
247 
248  p = m_BoardSide[aSide];
249  p[aRow * m_Ncols + aCol] &= x;
250 }
251 
252 
253 /* basic cell operation : ADD operation
254  */
255 void AR_MATRIX::AddCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
256 {
257  MATRIX_CELL* p;
258 
259  p = m_BoardSide[aSide];
260  p[aRow * m_Ncols + aCol] += x;
261 }
262 
263 
264 // fetch distance cell
265 AR_MATRIX::DIST_CELL AR_MATRIX::GetDist( int aRow, int aCol, int aSide ) // fetch distance cell
266 {
267  DIST_CELL* p;
268 
269  p = m_DistSide[aSide];
270  return p[aRow * m_Ncols + aCol];
271 }
272 
273 
274 // store distance cell
275 void AR_MATRIX::SetDist( int aRow, int aCol, int aSide, DIST_CELL x )
276 {
277  DIST_CELL* p;
278 
279  p = m_DistSide[aSide];
280  p[aRow * m_Ncols + aCol] = x;
281 }
282 
283 
284 // fetch direction cell
285 int AR_MATRIX::GetDir( int aRow, int aCol, int aSide )
286 {
287  DIR_CELL* p;
288 
289  p = m_DirSide[aSide];
290  return (int) ( p[aRow * m_Ncols + aCol] );
291 }
292 
293 
294 // store direction cell
295 void AR_MATRIX::SetDir( int aRow, int aCol, int aSide, int x )
296 {
297  DIR_CELL* p;
298 
299  p = m_DirSide[aSide];
300  p[aRow * m_Ncols + aCol] = (char) x;
301 }
302 
303 /* The tables of distances and keep out areas are established on the basis of a
304  * 50 units grid size (the pitch between the cells is 50 units).
305  * The actual distance could be computed by a scaling factor, but this is
306  * not needed, we can use only reduced values
307  */
308 
309 /* calculate approximate distance (manhattan distance)
310  */
311 int AR_MATRIX::GetApxDist( int r1, int c1, int r2, int c2 )
312 {
313  int d1, d2; /* row and column deltas */
314 
315  if( ( d1 = r1 - r2 ) < 0 ) /* get absolute row delta */
316  d1 = -d1;
317 
318  if( ( d2 = c1 - c2 ) < 0 ) /* get absolute column delta */
319  d2 = -d2;
320 
321  return ( d1 + d2 ) * 50;
322 }
323 
324 
325 /* distance to go thru a cell (en mils) */
326 static const int dist[10][10] = { /* OT=Otherside, OR=Origin (source) cell */
327  /*..........N, NE, E, SE, S, SW, W, NW, OT, OR */
328  /* N */ { 50, 60, 35, 60, 99, 60, 35, 60, 12, 12 },
329  /* NE */ { 60, 71, 60, 71, 60, 99, 60, 71, 23, 23 },
330  /* E */ { 35, 60, 50, 60, 35, 60, 99, 60, 12, 12 },
331  /* SE */ { 60, 71, 60, 71, 60, 71, 60, 99, 23, 23 },
332  /* S */ { 99, 60, 35, 60, 50, 60, 35, 60, 12, 12 },
333  /* SW */ { 60, 99, 60, 71, 60, 71, 60, 71, 23, 23 },
334  /* W */ { 35, 60, 99, 60, 35, 60, 50, 60, 12, 12 },
335  /* NW */ { 60, 71, 60, 99, 60, 71, 60, 71, 23, 23 },
336 
337  /* OT */ { 12, 23, 12, 23, 12, 23, 12, 23, 99, 99 },
338  /* OR */ { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99 }
339 };
340 
341 
342 /* penalty for extraneous holes and corners, scaled by sharpness of turn */
343 static const int penalty[10][10] = { /* OT=Otherside, OR=Origin (source) cell */
344  /*......... N, NE, E, SE, S, SW, W, NW, OT, OR */
345  /* N */ { 0, 5, 10, 15, 20, 15, 10, 5, 50, 0 },
346  /* NE */ { 5, 0, 5, 10, 15, 20, 15, 10, 50, 0 },
347  /* E */ { 10, 5, 0, 5, 10, 15, 20, 15, 50, 0 },
348  /* SE */ { 15, 10, 5, 0, 5, 10, 15, 20, 50, 0 },
349  /* S */ { 20, 15, 10, 5, 0, 5, 10, 15, 50, 0 },
350  /* SW */ { 15, 20, 15, 10, 5, 0, 5, 10, 50, 0 },
351  /* W */ { 10, 15, 20, 15, 10, 5, 0, 5, 50, 0 },
352  /* NW */ { 5, 10, 15, 20, 15, 10, 5, 0, 50, 0 },
353 
354  /* OT */ { 50, 50, 50, 50, 50, 50, 50, 50, 100, 0 },
355  /* OR */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
356 };
357 
358 
359 /* penalty pour directions preferencielles */
360 #define PN 20
361 static const int dir_penalty_TOP[10][10] = {
362  /* OT=Otherside, OR=Origin (source) cell */
363  /*......... N, NE, E, SE, S, SW, W, NW, OT, OR */
364  /* N */ { PN, 0, 0, 0, PN, 0, 0, 0, 0, 0 },
365  /* NE */ { PN, 0, 0, 0, PN, 0, 0, 0, 0, 0 },
366  /* E */ { PN, 0, 0, 0, PN, 0, 0, 0, 0, 0 },
367  /* SE */ { PN, 0, 0, 0, PN, 0, 0, 0, 0, 0 },
368  /* S */ { PN, 0, 0, 0, PN, 0, 0, 0, 0, 0 },
369  /* SW */ { PN, 0, 0, 0, PN, 0, 0, 0, 0, 0 },
370  /* W */ { PN, 0, 0, 0, PN, 0, 0, 0, 0, 0 },
371  /* NW */ { PN, 0, 0, 0, PN, 0, 0, 0, 0, 0 },
372 
373  /* OT */ { PN, 0, 0, 0, PN, 0, 0, 0, 0, 0 },
374  /* OR */ { PN, 0, 0, 0, PN, 0, 0, 0, 0, 0 }
375 };
376 
377 
378 static int dir_penalty_BOTTOM[10][10] = {
379  /* OT=Otherside, OR=Origin (source) cell */
380  /*......... N, NE, E, SE, S, SW, W, NW, OT, OR */
381  /* N */ { 0, 0, PN, 0, 0, 0, PN, 0, 0, 0 },
382  /* NE */ { 0, 0, PN, 0, 0, 0, PN, 0, 0, 0 },
383  /* E */ { 0, 0, PN, 0, 0, 0, PN, 0, 0, 0 },
384  /* SE */ { 0, 0, PN, 0, 0, 0, PN, 0, 0, 0 },
385  /* S */ { 0, 0, PN, 0, 0, 0, PN, 0, 0, 0 },
386  /* SW */ { 0, 0, PN, 0, 0, 0, PN, 0, 0, 0 },
387  /* W */ { 0, 0, PN, 0, 0, 0, PN, 0, 0, 0 },
388  /* NW */ { 0, 0, PN, 0, 0, 0, PN, 0, 0, 0 },
389 
390  /* OT */ { 0, 0, PN, 0, 0, 0, PN, 0, 0, 0 },
391  /* OR */ { 0, 0, PN, 0, 0, 0, PN, 0, 0, 0 }
392 };
393 
394 /*
395 ** x is the direction to enter the cell of interest.
396 ** y is the direction to exit the cell of interest.
397 ** z is the direction to really exit the cell, if y=FROM_OTHERSIDE.
398 **
399 ** return the distance of the trace through the cell of interest.
400 ** the calculation is driven by the tables above.
401 */
402 
403 
404 /* calculate distance (with penalty) of a trace through a cell
405 */
406 int AR_MATRIX::CalcDist( int x, int y, int z, int side )
407 {
408  int adjust, ldist;
409 
410  adjust = 0; /* set if hole is encountered */
411 
412  if( x == CELL_IS_EMPTY )
413  x = 10;
414 
415  if( y == CELL_IS_EMPTY )
416  {
417  y = 10;
418  }
419  else if( y == FROM_OTHERSIDE )
420  {
421  if( z == CELL_IS_EMPTY )
422  z = 10;
423 
424  adjust = penalty[x - 1][z - 1];
425  }
426 
427  ldist = dist[x - 1][y - 1] + penalty[x - 1][y - 1] + adjust;
428 
429  if( m_RouteCount > 1 )
430  {
431  if( side == AR_SIDE_BOTTOM )
432  ldist += dir_penalty_TOP[x - 1][y - 1];
433 
434  if( side == AR_SIDE_TOP )
435  ldist += dir_penalty_BOTTOM[x - 1][y - 1];
436  }
437 
438  return ldist * 10;
439 }
440 
441 
442 #define OP_CELL( layer, dy, dx ) \
443  { \
444  if( layer == UNDEFINED_LAYER ) \
445  { \
446  WriteCell( dy, dx, AR_SIDE_BOTTOM, color ); \
447  if( m_RoutingLayersCount > 1 ) \
448  WriteCell( dy, dx, AR_SIDE_TOP, color ); \
449  } \
450  else \
451  { \
452  if( layer == m_routeLayerBottom ) \
453  WriteCell( dy, dx, AR_SIDE_BOTTOM, color ); \
454  if( m_RoutingLayersCount > 1 ) \
455  if( layer == m_routeLayerTop ) \
456  WriteCell( dy, dx, AR_SIDE_TOP, color ); \
457  } \
458  }
459 
460 /* Fills all cells inside a segment
461  * half-width = lg, org = ux0,uy0 end = ux1,uy1
462  * coordinates are in PCB units
463  */
464 void AR_MATRIX::drawSegmentQcq( int ux0, int uy0, int ux1, int uy1, int lg, LAYER_NUM layer,
465  int color, AR_MATRIX::CELL_OP op_logic )
466 {
467  int64_t row, col;
468  int64_t inc;
469  int64_t row_max, col_max, row_min, col_min;
470  int64_t demi_pas;
471 
472  int cx, cy, dx, dy;
473 
474 
475  //printf("segmQcq %d %d %d %d\n", ux0, uy0, ux1, uy1);
476 
477  SetCellOperation( op_logic );
478 
479  // Make coordinate ux1 tj > ux0 to simplify calculations
480  if( ux1 < ux0 )
481  {
482  std::swap( ux1, ux0 );
483  std::swap( uy1, uy0 );
484  }
485 
486  // Calculating the incrementing the Y axis
487  inc = 1;
488 
489  if( uy1 < uy0 )
490  inc = -1;
491 
492  demi_pas = m_GridRouting / 2;
493 
494  col_min = ( ux0 - lg ) / m_GridRouting;
495 
496  if( col_min < 0 )
497  col_min = 0;
498 
499  col_max = ( ux1 + lg + demi_pas ) / m_GridRouting;
500 
501  if( col_max > ( m_Ncols - 1 ) )
502  col_max = m_Ncols - 1;
503 
504  if( inc > 0 )
505  {
506  row_min = ( uy0 - lg ) / m_GridRouting;
507  row_max = ( uy1 + lg + demi_pas ) / m_GridRouting;
508  }
509  else
510  {
511  row_min = ( uy1 - lg ) / m_GridRouting;
512  row_max = ( uy0 + lg + demi_pas ) / m_GridRouting;
513  }
514 
515  if( row_min < 0 )
516  row_min = 0;
517 
518  if( row_min > ( m_Nrows - 1 ) )
519  row_min = m_Nrows - 1;
520 
521  if( row_max < 0 )
522  row_max = 0;
523 
524  if( row_max > ( m_Nrows - 1 ) )
525  row_max = m_Nrows - 1;
526 
527  dx = ux1 - ux0;
528  dy = uy1 - uy0;
529 
530  double angle;
531  if( dx )
532  {
533  angle = ArcTangente( dy, dx );
534  }
535  else
536  {
537  angle = 900;
538 
539  if( dy < 0 )
540  angle = -900;
541  }
542 
543  RotatePoint( &dx, &dy, angle ); // dx = length, dy = 0
544 
545 
546  //printf("col_min %d max %d row_min %d max %d\n", col_min, col_max, row_min, row_max);
547 
548  for( col = col_min; col <= col_max; col++ )
549  {
550  int64_t cxr;
551  cxr = ( col * m_GridRouting ) - ux0;
552 
553  for( row = row_min; row <= row_max; row++ )
554  {
555  cy = ( row * m_GridRouting ) - uy0;
556  cx = cxr;
557  RotatePoint( &cx, &cy, angle );
558 
559  if( abs( cy ) > lg )
560  continue; // The point is too far on the Y axis.
561 
562  /* This point a test is close to the segment: the position
563  * along the X axis must be tested.
564  */
565  if( ( cx >= 0 ) && ( cx <= dx ) )
566  {
567  OP_CELL( layer, row, col );
568  continue;
569  }
570 
571  // Examination of extremities are rounded.
572  if( ( cx < 0 ) && ( cx >= -lg ) )
573  {
574  if( ( ( cx * cx ) + ( cy * cy ) ) <= ( lg * lg ) )
575  OP_CELL( layer, row, col );
576 
577  continue;
578  }
579 
580  if( ( cx > dx ) && ( cx <= ( dx + lg ) ) )
581  {
582  if( ( ( ( cx - dx ) * ( cx - dx ) ) + ( cy * cy ) ) <= ( lg * lg ) )
583  OP_CELL( layer, row, col );
584 
585  continue;
586  }
587  }
588  }
589 }
590 
591 
592 /* Fills all cells of the routing matrix contained in the circle
593  * half-width = lg, center = ux0, uy0, ux1,uy1 is a point on the circle.
594  * coord are in PCB units.
595  */
596 void AR_MATRIX::traceCircle( int ux0, int uy0, int ux1, int uy1, int lg, LAYER_NUM layer, int color,
597  AR_MATRIX::CELL_OP op_logic )
598 {
599  int radius, nb_segm;
600  int x0, y0, // Starting point of the current segment trace.
601  x1, y1; // End point.
602  int ii;
603  int angle;
604 
605  radius = KiROUND( Distance( ux0, uy0, ux1, uy1 ) );
606 
607  x0 = x1 = radius;
608  y0 = y1 = 0;
609 
610  if( lg < 1 )
611  lg = 1;
612 
613  nb_segm = ( 2 * radius ) / lg;
614 
615  if( nb_segm < 5 )
616  nb_segm = 5;
617 
618  if( nb_segm > 100 )
619  nb_segm = 100;
620 
621  for( ii = 1; ii < nb_segm; ii++ )
622  {
623  angle = ( 3600 * ii ) / nb_segm;
624  x1 = KiROUND( cosdecideg( radius, angle ) );
625  y1 = KiROUND( sindecideg( radius, angle ) );
626  drawSegmentQcq( x0 + ux0, y0 + uy0, x1 + ux0, y1 + uy0, lg, layer, color, op_logic );
627  x0 = x1;
628  y0 = y1;
629  }
630 
631  drawSegmentQcq( x1 + ux0, y1 + uy0, ux0 + radius, uy0, lg, layer, color, op_logic );
632 }
633 
634 
636  int cx, int cy, int radius, LSET aLayerMask, int color, AR_MATRIX::CELL_OP op_logic )
637 {
638  int row, col;
639  int ux0, uy0, ux1, uy1;
640  int row_max, col_max, row_min, col_min;
641  int trace = 0;
642  double fdistmin, fdistx, fdisty;
643  int tstwrite = 0;
644  int distmin;
645 
646  if( aLayerMask[m_routeLayerBottom] )
647  trace = 1; // Trace on BOTTOM
648 
649  if( aLayerMask[m_routeLayerTop] )
650  if( m_RoutingLayersCount > 1 )
651  trace |= 2; // Trace on TOP
652 
653  if( trace == 0 )
654  return;
655 
656  SetCellOperation( op_logic );
657 
658  cx -= GetBrdCoordOrigin().x;
659  cy -= GetBrdCoordOrigin().y;
660 
661  distmin = radius;
662 
663  // Calculate the bounding rectangle of the circle.
664  ux0 = cx - radius;
665  uy0 = cy - radius;
666  ux1 = cx + radius;
667  uy1 = cy + radius;
668 
669  // Calculate limit coordinates of cells belonging to the rectangle.
670  row_max = uy1 / m_GridRouting;
671  col_max = ux1 / m_GridRouting;
672  row_min = uy0 / m_GridRouting; // if (uy0 > row_min*Board.m_GridRouting) row_min++;
673  col_min = ux0 / m_GridRouting; // if (ux0 > col_min*Board.m_GridRouting) col_min++;
674 
675  if( row_min < 0 )
676  row_min = 0;
677 
678  if( row_max >= ( m_Nrows - 1 ) )
679  row_max = m_Nrows - 1;
680 
681  if( col_min < 0 )
682  col_min = 0;
683 
684  if( col_max >= ( m_Ncols - 1 ) )
685  col_max = m_Ncols - 1;
686 
687  // Calculate coordinate limits of cell belonging to the rectangle.
688  if( row_min > row_max )
689  row_max = row_min;
690 
691  if( col_min > col_max )
692  col_max = col_min;
693 
694  fdistmin = (double) distmin * distmin;
695 
696  for( row = row_min; row <= row_max; row++ )
697  {
698  fdisty = (double) ( cy - ( row * m_GridRouting ) );
699  fdisty *= fdisty;
700 
701  for( col = col_min; col <= col_max; col++ )
702  {
703  fdistx = (double) ( cx - ( col * m_GridRouting ) );
704  fdistx *= fdistx;
705 
706  if( fdistmin <= ( fdistx + fdisty ) )
707  continue;
708 
709  if( trace & 1 )
710  WriteCell( row, col, AR_SIDE_BOTTOM, color );
711 
712  if( trace & 2 )
713  WriteCell( row, col, AR_SIDE_TOP, color );
714 
715  tstwrite = 1;
716  }
717  }
718 
719  if( tstwrite )
720  return;
721 
722  /* If no cell has been written, it affects the 4 neighboring diagonal
723  * (Adverse event: pad off grid in the center of the 4 neighboring
724  * diagonal) */
725  distmin = m_GridRouting / 2 + 1;
726  fdistmin = ( (double) distmin * distmin ) * 2; // Distance to center point diagonally
727 
728  for( row = row_min; row <= row_max; row++ )
729  {
730  fdisty = (double) ( cy - ( row * m_GridRouting ) );
731  fdisty *= fdisty;
732 
733  for( col = col_min; col <= col_max; col++ )
734  {
735  fdistx = (double) ( cx - ( col * m_GridRouting ) );
736  fdistx *= fdistx;
737 
738  if( fdistmin <= ( fdistx + fdisty ) )
739  continue;
740 
741  if( trace & 1 )
742  WriteCell( row, col, AR_SIDE_BOTTOM, color );
743 
744  if( trace & 2 )
745  WriteCell( row, col, AR_SIDE_TOP, color );
746  }
747  }
748 }
749 
750 
751 /* Fills all routing matrix cells contained in the arc
752  * angle = ArcAngle, half-width lg
753  * center = ux0,uy0, starting at ux1, uy1. Coordinates are in
754  * PCB units.
755  */
756 void AR_MATRIX::traceArc( int ux0, int uy0, int ux1, int uy1, double ArcAngle, int lg,
757  LAYER_NUM layer, int color, AR_MATRIX::CELL_OP op_logic )
758 {
759  int radius, nb_segm;
760  int x0, y0, // Starting point of the current segment trace
761  x1, y1; // End point
762  int ii;
763  double angle, StAngle;
764 
765 
766  radius = KiROUND( Distance( ux0, uy0, ux1, uy1 ) );
767 
768  x0 = ux1 - ux0;
769  y0 = uy1 - uy0;
770  StAngle = ArcTangente( uy1 - uy0, ux1 - ux0 );
771 
772  if( lg < 1 )
773  lg = 1;
774 
775  nb_segm = ( 2 * radius ) / lg;
776  nb_segm = ( nb_segm * std::abs( ArcAngle ) ) / 3600;
777 
778  if( nb_segm < 5 )
779  nb_segm = 5;
780 
781  if( nb_segm > 100 )
782  nb_segm = 100;
783 
784  for( ii = 1; ii <= nb_segm; ii++ )
785  {
786  angle = ( ArcAngle * ii ) / nb_segm;
787  angle += StAngle;
788 
790 
791  x1 = KiROUND( cosdecideg( radius, angle ) );
792  y1 = KiROUND( cosdecideg( radius, angle ) );
793  drawSegmentQcq( x0 + ux0, y0 + uy0, x1 + ux0, y1 + uy0, lg, layer, color, op_logic );
794  x0 = x1;
795  y0 = y1;
796  }
797 }
798 
799 
800 void AR_MATRIX::TraceFilledRectangle( int ux0, int uy0, int ux1, int uy1, double angle,
801  LSET aLayerMask, int color, AR_MATRIX::CELL_OP op_logic )
802 {
803  int row, col;
804  int cx, cy; // Center of rectangle
805  int radius; // Radius of the circle
806  int row_min, row_max, col_min, col_max;
807  int rotrow, rotcol;
808  int trace = 0;
809 
810  if( aLayerMask[m_routeLayerBottom] )
811  trace = 1; // Trace on BOTTOM
812 
813  if( aLayerMask[m_routeLayerTop] )
814  {
815  if( m_RoutingLayersCount > 1 )
816  trace |= 2; // Trace on TOP
817  }
818 
819  if( trace == 0 )
820  return;
821 
822  SetCellOperation( op_logic );
823 
824  ux0 -= GetBrdCoordOrigin().x;
825  uy0 -= GetBrdCoordOrigin().y;
826  ux1 -= GetBrdCoordOrigin().x;
827  uy1 -= GetBrdCoordOrigin().y;
828 
829  cx = ( ux0 + ux1 ) / 2;
830  cy = ( uy0 + uy1 ) / 2;
831  radius = KiROUND( Distance( ux0, uy0, cx, cy ) );
832 
833  // Calculating coordinate limits belonging to the rectangle.
834  row_max = ( cy + radius ) / m_GridRouting;
835  col_max = ( cx + radius ) / m_GridRouting;
836  row_min = ( cy - radius ) / m_GridRouting;
837 
838  if( uy0 > row_min * m_GridRouting )
839  row_min++;
840 
841  col_min = ( cx - radius ) / m_GridRouting;
842 
843  if( ux0 > col_min * m_GridRouting )
844  col_min++;
845 
846  if( row_min < 0 )
847  row_min = 0;
848 
849  if( row_max >= ( m_Nrows - 1 ) )
850  row_max = m_Nrows - 1;
851 
852  if( col_min < 0 )
853  col_min = 0;
854 
855  if( col_max >= ( m_Ncols - 1 ) )
856  col_max = m_Ncols - 1;
857 
858  for( row = row_min; row <= row_max; row++ )
859  {
860  for( col = col_min; col <= col_max; col++ )
861  {
862  rotrow = row * m_GridRouting;
863  rotcol = col * m_GridRouting;
864  RotatePoint( &rotcol, &rotrow, cx, cy, -angle );
865 
866  if( rotrow <= uy0 )
867  continue;
868 
869  if( rotrow >= uy1 )
870  continue;
871 
872  if( rotcol <= ux0 )
873  continue;
874 
875  if( rotcol >= ux1 )
876  continue;
877 
878  if( trace & 1 )
879  WriteCell( row, col, AR_SIDE_BOTTOM, color );
880 
881  if( trace & 2 )
882  WriteCell( row, col, AR_SIDE_TOP, color );
883  }
884  }
885 }
886 
887 
888 void AR_MATRIX::TraceFilledRectangle( int ux0, int uy0, int ux1, int uy1, LSET aLayerMask,
889  int color, AR_MATRIX::CELL_OP op_logic )
890 {
891  int row, col;
892  int row_min, row_max, col_min, col_max;
893  int trace = 0;
894 
895  if( aLayerMask[m_routeLayerBottom] )
896  trace = 1; // Trace on BOTTOM
897 
898  if( aLayerMask[m_routeLayerTop] && m_RoutingLayersCount > 1 )
899  trace |= 2; // Trace on TOP
900 
901  if( trace == 0 )
902  return;
903 
904  SetCellOperation( op_logic );
905 
906  ux0 -= GetBrdCoordOrigin().x;
907  uy0 -= GetBrdCoordOrigin().y;
908  ux1 -= GetBrdCoordOrigin().x;
909  uy1 -= GetBrdCoordOrigin().y;
910 
911  // Calculating limits coord cells belonging to the rectangle.
912  row_max = uy1 / m_GridRouting;
913  col_max = ux1 / m_GridRouting;
914  row_min = uy0 / m_GridRouting;
915 
916  if( uy0 > row_min * m_GridRouting )
917  row_min++;
918 
919  col_min = ux0 / m_GridRouting;
920 
921  if( ux0 > col_min * m_GridRouting )
922  col_min++;
923 
924  if( row_min < 0 )
925  row_min = 0;
926 
927  if( row_max >= ( m_Nrows - 1 ) )
928  row_max = m_Nrows - 1;
929 
930  if( col_min < 0 )
931  col_min = 0;
932 
933  if( col_max >= ( m_Ncols - 1 ) )
934  col_max = m_Ncols - 1;
935 
936  for( row = row_min; row <= row_max; row++ )
937  {
938  for( col = col_min; col <= col_max; col++ )
939  {
940  if( trace & 1 )
941  WriteCell( row, col, AR_SIDE_BOTTOM, color );
942 
943  if( trace & 2 )
944  WriteCell( row, col, AR_SIDE_TOP, color );
945  }
946  }
947 }
948 
949 
950 /* Draws a line, if layer = -1 on all layers
951  */
953  int x0, int y0, int x1, int y1, LAYER_NUM layer, int color, AR_MATRIX::CELL_OP op_logic )
954 {
955  int dx, dy, lim;
956  int cumul, inc, il, delta;
957 
958  SetCellOperation( op_logic );
959 
960  if( x0 == x1 ) // Vertical.
961  {
962  if( y1 < y0 )
963  std::swap( y0, y1 );
964 
965  dy = y0 / m_GridRouting;
966  lim = y1 / m_GridRouting;
967  dx = x0 / m_GridRouting;
968 
969  // Clipping limits of board.
970  if( ( dx < 0 ) || ( dx >= m_Ncols ) )
971  return;
972 
973  if( dy < 0 )
974  dy = 0;
975 
976  if( lim >= m_Nrows )
977  lim = m_Nrows - 1;
978 
979  for( ; dy <= lim; dy++ )
980  {
981  OP_CELL( layer, dy, dx );
982  }
983 
984  return;
985  }
986 
987  if( y0 == y1 ) // Horizontal
988  {
989  if( x1 < x0 )
990  std::swap( x0, x1 );
991 
992  dx = x0 / m_GridRouting;
993  lim = x1 / m_GridRouting;
994  dy = y0 / m_GridRouting;
995 
996  // Clipping limits of board.
997  if( ( dy < 0 ) || ( dy >= m_Nrows ) )
998  return;
999 
1000  if( dx < 0 )
1001  dx = 0;
1002 
1003  if( lim >= m_Ncols )
1004  lim = m_Ncols - 1;
1005 
1006  for( ; dx <= lim; dx++ )
1007  {
1008  OP_CELL( layer, dy, dx );
1009  }
1010 
1011  return;
1012  }
1013 
1014  // Here is some perspective: using the algorithm LUCAS.
1015  if( abs( x1 - x0 ) >= abs( y1 - y0 ) ) // segment slightly inclined/
1016  {
1017  if( x1 < x0 )
1018  {
1019  std::swap( x1, x0 );
1020  std::swap( y1, y0 );
1021  }
1022 
1023  dx = x0 / m_GridRouting;
1024  lim = x1 / m_GridRouting;
1025  dy = y0 / m_GridRouting;
1026  inc = 1;
1027 
1028  if( y1 < y0 )
1029  inc = -1;
1030 
1031  il = lim - dx;
1032  cumul = il / 2;
1033  delta = abs( y1 - y0 ) / m_GridRouting;
1034 
1035  for( ; dx <= lim; )
1036  {
1037  if( ( dx >= 0 ) && ( dy >= 0 ) && ( dx < m_Ncols ) && ( dy < m_Nrows ) )
1038  {
1039  OP_CELL( layer, dy, dx );
1040  }
1041 
1042  dx++;
1043  cumul += delta;
1044 
1045  if( cumul > il )
1046  {
1047  cumul -= il;
1048  dy += inc;
1049  }
1050  }
1051  }
1052  else
1053  {
1054  if( y1 < y0 )
1055  {
1056  std::swap( x1, x0 );
1057  std::swap( y1, y0 );
1058  }
1059 
1060  dy = y0 / m_GridRouting;
1061  lim = y1 / m_GridRouting;
1062  dx = x0 / m_GridRouting;
1063  inc = 1;
1064 
1065  if( x1 < x0 )
1066  inc = -1;
1067 
1068  il = lim - dy;
1069  cumul = il / 2;
1070  delta = abs( x1 - x0 ) / m_GridRouting;
1071 
1072  for( ; dy <= lim; )
1073  {
1074  if( ( dx >= 0 ) && ( dy >= 0 ) && ( dx < m_Ncols ) && ( dy < m_Nrows ) )
1075  {
1076  OP_CELL( layer, dy, dx );
1077  }
1078 
1079  dy++;
1080  cumul += delta;
1081 
1082  if( cumul > il )
1083  {
1084  cumul -= il;
1085  dx += inc;
1086  }
1087  }
1088  }
1089 }
1090 
1092  DRAWSEGMENT* pt_segm, int color, int marge, AR_MATRIX::CELL_OP op_logic )
1093 {
1094  int half_width = ( pt_segm->GetWidth() / 2 ) + marge;
1095 
1096  // Calculate the bounding rectangle of the segment (if H, V or Via)
1097  int ux0 = pt_segm->GetStart().x - GetBrdCoordOrigin().x;
1098  int uy0 = pt_segm->GetStart().y - GetBrdCoordOrigin().y;
1099  int ux1 = pt_segm->GetEnd().x - GetBrdCoordOrigin().x;
1100  int uy1 = pt_segm->GetEnd().y - GetBrdCoordOrigin().y;
1101 
1102  //printf("traceSegm %d %d %d %d\n", ux0, uy0, ux1, uy1);
1103 
1104  LAYER_NUM layer = pt_segm->GetLayer();
1105 
1106  //if( color == VIA_IMPOSSIBLE )
1107  layer = UNDEFINED_LAYER;
1108 
1109 
1110  switch( pt_segm->GetShape() )
1111  {
1112  // The segment is here a straight line or a circle or an arc.:
1113  case S_CIRCLE: traceCircle( ux0, uy0, ux1, uy1, half_width, layer, color, op_logic ); break;
1114 
1115  case S_ARC:
1116  traceArc( ux0, uy0, ux1, uy1, pt_segm->GetAngle(), half_width, layer, color, op_logic );
1117  break;
1118 
1119  // The segment is here a line segment.
1120  default: drawSegmentQcq( ux0, uy0, ux1, uy1, half_width, layer, color, op_logic ); break;
1121  }
1122 }
1123 
1124 
1125 void AR_MATRIX::TraceSegmentPcb( TRACK* aTrack, int color, int marge, AR_MATRIX::CELL_OP op_logic )
1126 {
1127  int half_width = ( aTrack->GetWidth() / 2 ) + marge;
1128 
1129  // Test if VIA (filled circle need to be drawn)
1130  if( aTrack->Type() == PCB_VIA_T )
1131  {
1132  LSET layer_mask;
1133 
1134  if( aTrack->IsOnLayer( m_routeLayerBottom ) )
1135  layer_mask.set( m_routeLayerBottom );
1136 
1137  if( aTrack->IsOnLayer( m_routeLayerTop ) )
1138  {
1139  if( !layer_mask.any() )
1140  layer_mask = LSET( m_routeLayerTop );
1141  else
1142  layer_mask.set();
1143  }
1144 
1145  if( color == VIA_IMPOSSIBLE )
1146  layer_mask.set();
1147 
1148  if( layer_mask.any() )
1149  traceFilledCircle( aTrack->GetStart().x, aTrack->GetStart().y, half_width, layer_mask,
1150  color, op_logic );
1151  }
1152  else
1153  {
1154  // Calculate the bounding rectangle of the segment
1155  int ux0 = aTrack->GetStart().x - GetBrdCoordOrigin().x;
1156  int uy0 = aTrack->GetStart().y - GetBrdCoordOrigin().y;
1157  int ux1 = aTrack->GetEnd().x - GetBrdCoordOrigin().x;
1158  int uy1 = aTrack->GetEnd().y - GetBrdCoordOrigin().y;
1159 
1160  // Ordinary track
1161  PCB_LAYER_ID layer = aTrack->GetLayer();
1162 
1163  if( color == VIA_IMPOSSIBLE )
1164  layer = UNDEFINED_LAYER;
1165 
1166  drawSegmentQcq( ux0, uy0, ux1, uy1, half_width, layer, color, op_logic );
1167  }
1168 }
1169 
1170 
1182  int ux0, int uy0, int ux1, int uy1, int marge, int aKeepOut, LSET aLayerMask )
1183 {
1184  int row, col;
1185  int row_min, row_max, col_min, col_max, pmarge;
1186  int trace = 0;
1187  DIST_CELL data, LocalKeepOut;
1188  int lgain, cgain;
1189 
1190  if( aLayerMask[m_routeLayerBottom] )
1191  trace = 1; // Trace on bottom layer.
1192 
1193  if( aLayerMask[m_routeLayerTop] && m_RoutingLayersCount )
1194  trace |= 2; // Trace on top layer.
1195 
1196  if( trace == 0 )
1197  return;
1198 
1199  ux0 -= m_BrdBox.GetX();
1200  uy0 -= m_BrdBox.GetY();
1201  ux1 -= m_BrdBox.GetX();
1202  uy1 -= m_BrdBox.GetY();
1203 
1204  ux0 -= marge;
1205  ux1 += marge;
1206  uy0 -= marge;
1207  uy1 += marge;
1208 
1209  pmarge = marge / m_GridRouting;
1210 
1211  if( pmarge < 1 )
1212  pmarge = 1;
1213 
1214  // Calculate the coordinate limits of the rectangle.
1215  row_max = uy1 / m_GridRouting;
1216  col_max = ux1 / m_GridRouting;
1217  row_min = uy0 / m_GridRouting;
1218 
1219  if( uy0 > row_min * m_GridRouting )
1220  row_min++;
1221 
1222  col_min = ux0 / m_GridRouting;
1223 
1224  if( ux0 > col_min * m_GridRouting )
1225  col_min++;
1226 
1227  if( row_min < 0 )
1228  row_min = 0;
1229 
1230  if( row_max >= ( m_Nrows - 1 ) )
1231  row_max = m_Nrows - 1;
1232 
1233  if( col_min < 0 )
1234  col_min = 0;
1235 
1236  if( col_max >= ( m_Ncols - 1 ) )
1237  col_max = m_Ncols - 1;
1238 
1239  for( row = row_min; row <= row_max; row++ )
1240  {
1241  lgain = 256;
1242 
1243  if( row < pmarge )
1244  lgain = ( 256 * row ) / pmarge;
1245  else if( row > row_max - pmarge )
1246  lgain = ( 256 * ( row_max - row ) ) / pmarge;
1247 
1248  for( col = col_min; col <= col_max; col++ )
1249  {
1250  // RoutingMatrix Dist map containt the "cost" of the cell
1251  // at position (row, col)
1252  // in autoplace this is the cost of the cell, when
1253  // a footprint overlaps it, near a "master" footprint
1254  // this cost is hight near the "master" footprint
1255  // and decrease with the distance
1256  cgain = 256;
1257  LocalKeepOut = aKeepOut;
1258 
1259  if( col < pmarge )
1260  cgain = ( 256 * col ) / pmarge;
1261  else if( col > col_max - pmarge )
1262  cgain = ( 256 * ( col_max - col ) ) / pmarge;
1263 
1264  cgain = ( cgain * lgain ) / 256;
1265 
1266  if( cgain != 256 )
1267  LocalKeepOut = ( LocalKeepOut * cgain ) / 256;
1268 
1269  if( trace & 1 )
1270  {
1271  data = GetDist( row, col, AR_SIDE_BOTTOM ) + LocalKeepOut;
1272  SetDist( row, col, AR_SIDE_BOTTOM, data );
1273  }
1274 
1275  if( trace & 2 )
1276  {
1277  data = GetDist( row, col, AR_SIDE_TOP );
1278  data = std::max( data, LocalKeepOut );
1279  SetDist( row, col, AR_SIDE_TOP, data );
1280  }
1281  }
1282  }
1283 }
1284 
1285 
1286 void AR_MATRIX::PlacePad( D_PAD* aPad, int color, int marge, AR_MATRIX::CELL_OP op_logic )
1287 {
1288  int dx, dy;
1289  wxPoint shape_pos = aPad->ShapePos();
1290 
1291  dx = aPad->GetSize().x / 2;
1292  dx += marge;
1293 
1294  if( aPad->GetShape() == PAD_SHAPE_CIRCLE )
1295  {
1296  traceFilledCircle( shape_pos.x, shape_pos.y, dx, aPad->GetLayerSet(), color, op_logic );
1297  return;
1298  }
1299 
1300  dy = aPad->GetSize().y / 2;
1301  dy += marge;
1302 
1303  if( aPad->GetShape() == PAD_SHAPE_TRAPEZOID )
1304  {
1305  dx += abs( aPad->GetDelta().y ) / 2;
1306  dy += abs( aPad->GetDelta().x ) / 2;
1307  }
1308 
1309  // The pad is a rectangle ( horizontal or vertical )
1310  if( int( aPad->GetOrientation() ) % 900 == 0 )
1311  {
1312  // Orientation turned 90 deg.
1313  if( aPad->GetOrientation() == 900 || aPad->GetOrientation() == 2700 )
1314  {
1315  std::swap( dx, dy );
1316  }
1317 
1318  TraceFilledRectangle( shape_pos.x - dx, shape_pos.y - dy, shape_pos.x + dx,
1319  shape_pos.y + dy, aPad->GetLayerSet(), color, op_logic );
1320  }
1321  else
1322  {
1323  TraceFilledRectangle( shape_pos.x - dx, shape_pos.y - dy, shape_pos.x + dx,
1324  shape_pos.y + dy, aPad->GetOrientation(), aPad->GetLayerSet(), color, op_logic );
1325  }
1326 }
int GetApxDist(int r1, int c1, int r2, int c2)
Definition: ar_matrix.cpp:311
#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:756
char DIR_CELL
Definition: ar_matrix.h:54
int InitRoutingMatrix()
Function InitBoard initializes the data structures.
Definition: ar_matrix.cpp:98
static const int dist[10][10]
Definition: ar_matrix.cpp:326
DIST_CELL * m_DistSide[AR_MAX_ROUTING_LAYERS_COUNT]
Definition: ar_matrix.h:57
int m_MemSize
Definition: ar_matrix.h:66
#define AR_SIDE_TOP
Definition: ar_matrix.h:42
int m_Ncols
Definition: ar_matrix.h:65
int GetX() const
Definition: eda_rect.h:111
const wxPoint & GetStart() const
Definition: class_track.h:118
STROKE_T GetShape() const
int m_GridRouting
Definition: ar_matrix.h:63
void tracePcbLine(int x0, int y0, int x1, int y1, LAYER_NUM layer, int color, AR_MATRIX::CELL_OP op_logic)
Definition: ar_matrix.cpp:952
#define FROM_OTHERSIDE
Definition: ar_cell.h:108
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:800
EDA_RECT m_BrdBox
Definition: ar_matrix.h:64
int GetWidth() const
Definition: eda_rect.h:119
int CalcDist(int x, int y, int z, int side)
Definition: ar_matrix.cpp:406
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:1181
void PlacePad(D_PAD *aPad, int color, int marge, AR_MATRIX::CELL_OP op_logic)
Definition: ar_matrix.cpp:1286
static const int penalty[10][10]
Definition: ar_matrix.cpp:343
void TraceSegmentPcb(DRAWSEGMENT *pt_segm, int color, int marge, AR_MATRIX::CELL_OP op_logic)
Definition: ar_matrix.cpp:1091
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:233
A single base class (TRACK) represents both tracks and vias, with subclasses for curved tracks (ARC) ...
const wxPoint GetEnd() const
Definition: eda_rect.h:116
PCB_LAYER_ID m_routeLayerTop
Definition: ar_matrix.h:69
PCB_LAYER_ID
A quick note on layer IDs:
#define CELL_IS_EMPTY
Definition: ar_cell.h:35
LSET is a set of PCB_LAYER_IDs.
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Function IsOnLayer tests to see if this object is on the given layer.
void WriteCell(int aRow, int aCol, int aSide, MATRIX_CELL aCell)
Definition: ar_matrix.h:89
#define VIA_IMPOSSIBLE
Definition: ar_cell.h:44
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:222
Arcs (with rounded ends)
MATRIX_CELL GetCell(int aRow, int aCol, int aSide)
Definition: ar_matrix.cpp:200
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:435
void(AR_MATRIX::* m_opWriteCell)(int aRow, int aCol, int aSide, MATRIX_CELL aCell)
Definition: ar_matrix.h:74
int m_Nrows
Definition: ar_matrix.h:65
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:180
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:211
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:464
const wxSize & GetDelta() const
Definition: class_pad.h:288
void AndCell(int aRow, int aCol, int aSide, MATRIX_CELL aCell)
Definition: ar_matrix.cpp:244
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:596
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
void UnInitRoutingMatrix()
Definition: ar_matrix.cpp:146
#define OP_CELL(layer, dy, dx)
Definition: ar_matrix.cpp:442
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
static int dir_penalty_BOTTOM[10][10]
Definition: ar_matrix.cpp:378
int GetWidth() const
Definition: class_track.h:112
Class to handle a graphic segment.
int m_RoutingLayersCount
Definition: ar_matrix.h:62
bool m_InitMatrixDone
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:411
int GetDir(int aRow, int aCol, int aSide)
Definition: ar_matrix.cpp:285
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
wxPoint GetBrdCoordOrigin()
function GetBrdCoordOrigin
Definition: ar_matrix.h:99
wxPoint ShapePos() const
Definition: class_pad.cpp:601
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:255
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:61
int GetY() const
Definition: eda_rect.h:112
void SetDir(int aRow, int aCol, int aSide, int aDir)
Definition: ar_matrix.cpp:295
void traceFilledCircle(int cx, int cy, int radius, LSET aLayerMask, int color, AR_MATRIX::CELL_OP op_logic)
Definition: ar_matrix.cpp:635
The common library.
const wxPoint & GetEnd() const
Definition: class_track.h:115
unsigned char MATRIX_CELL
Definition: ar_matrix.h:52
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:222
double ArcTangente(int dy, int dx)
Definition: trigo.cpp:162
void SetDist(int aRow, int aCol, int aSide, DIST_CELL)
Definition: ar_matrix.cpp:275
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:68
const wxSize & GetSize() const
Definition: class_pad.h:285
#define AR_MAX_ROUTING_LAYERS_COUNT
Definition: ar_matrix.h:40
static const int dir_penalty_TOP[10][10]
Definition: ar_matrix.cpp:361
int m_RouteCount
Definition: ar_matrix.h:67
DIST_CELL GetDist(int aRow, int aCol, int aSide)
Definition: ar_matrix.cpp:265
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
KICAD_T Type() const
Function Type()
Definition: base_struct.h:197
PCB_LAYER_ID m_routeLayerBottom
Definition: ar_matrix.h:70
#define PN
Definition: ar_matrix.cpp:360