KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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, [email protected]
5 * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
6 * Copyright (C) 2011 Wayne Stambaugh <[email protected]>
7 *
8 * Copyright The KiCad Developers, see AUTHORS.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, see <https://www.gnu.org/licenses/>.
22 */
23
24#include "ar_matrix.h"
25#include <lset.h>
26#include <math/util.h> // for KiROUND
27#include <trigo.h>
28
29#include <pcb_shape.h>
30#include <pad.h>
31
32
34{
35 m_BoardSide[0] = nullptr;
36 m_BoardSide[1] = nullptr;
37 m_DistSide[0] = nullptr;
38 m_DistSide[1] = nullptr;
39 m_opWriteCell = nullptr;
40 m_Nrows = 0;
41 m_Ncols = 0;
42 m_MemSize = 0;
44 m_GridRouting = 0;
45 m_RouteCount = 0;
46}
47
48
49bool AR_MATRIX::ComputeMatrixSize( const BOX2I& aBoundingBox )
50{
51 // The boundary box must have its start point on routing grid:
52 m_BrdBox = aBoundingBox;
53
54 m_BrdBox.SetX( m_BrdBox.GetX() - ( m_BrdBox.GetX() % m_GridRouting ) );
55 m_BrdBox.SetY( m_BrdBox.GetY() - ( m_BrdBox.GetY() % m_GridRouting ) );
56
57 // The boundary box must have its end point on routing grid:
58 VECTOR2I end = m_BrdBox.GetEnd();
59
60 end.x -= end.x % m_GridRouting;
61 end.x += m_GridRouting;
62
63 end.y -= end.y % m_GridRouting;
64 end.y += m_GridRouting;
65
66 m_BrdBox.SetEnd( end );
67
68 m_Nrows = KiROUND( m_BrdBox.GetHeight() / m_GridRouting );
69 m_Ncols = KiROUND( m_BrdBox.GetWidth() / m_GridRouting );
70
71 // gives a small margin
72 m_Ncols += 1;
73 m_Nrows += 1;
74
75 return true;
76}
77
78
80{
81 if( m_Nrows <= 0 || m_Ncols <= 0 )
82 return 0;
83
84 // give a small margin for memory allocation:
85 int ii = ( m_Nrows + 1 ) * ( m_Ncols + 1 );
86
87 int side = AR_SIDE_BOTTOM;
88 for( int jj = 0; jj < m_RoutingLayersCount; jj++ ) // m_RoutingLayersCount = 1 or 2
89 {
90 m_BoardSide[side] = nullptr;
91 m_DistSide[side] = nullptr;
92
93 // allocate matrix & initialize everything to empty
94 m_BoardSide[side] = new MATRIX_CELL[ ii * sizeof( MATRIX_CELL ) ];
95 memset( m_BoardSide[side], 0, ii * sizeof( MATRIX_CELL ) );
96
97 if( m_BoardSide[side] == nullptr )
98 return -1;
99
100 // allocate Distances
101 m_DistSide[side] = new DIST_CELL[ ii * sizeof( DIST_CELL ) ];
102 memset( m_DistSide[side], 0, ii * sizeof( DIST_CELL ) );
103
104 if( m_DistSide[side] == nullptr )
105 return -1;
106
107 side = AR_SIDE_TOP;
108 }
109
110 m_MemSize = m_RouteCount * ii * ( sizeof( MATRIX_CELL ) + sizeof( DIST_CELL ) );
111
112 return m_MemSize;
113}
114
115
117{
118 for( int ii = 0; ii < AR_MAX_ROUTING_LAYERS_COUNT; ii++ )
119 {
120 // de-allocate Distances matrix
121 if( m_DistSide[ii] )
122 {
123 delete[] m_DistSide[ii];
124 m_DistSide[ii] = nullptr;
125 }
126
127 // de-allocate cells matrix
128 if( m_BoardSide[ii] )
129 {
130 delete[] m_BoardSide[ii];
131 m_BoardSide[ii] = nullptr;
132 }
133 }
134
135 m_Nrows = m_Ncols = 0;
136}
137
138// Initialize m_opWriteCell member to make the aLogicOp
140{
141 switch( aLogicOp )
142 {
143 default:
149 }
150}
151
152
153/* return the value stored in a cell
154 */
155AR_MATRIX::MATRIX_CELL AR_MATRIX::GetCell( int aRow, int aCol, int aSide )
156{
157 MATRIX_CELL* p = m_BoardSide[aSide];
158 return p[aRow * m_Ncols + aCol];
159}
160
161
162/* basic cell operation : WRITE operation
163 */
164void AR_MATRIX::SetCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
165{
166 MATRIX_CELL* p = m_BoardSide[aSide];
167 p[aRow * m_Ncols + aCol] = x;
168}
169
170
171/* basic cell operation : OR operation
172 */
173void AR_MATRIX::OrCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
174{
175 MATRIX_CELL* p = m_BoardSide[aSide];
176 p[aRow * m_Ncols + aCol] |= x;
177}
178
179
180/* basic cell operation : XOR operation
181 */
182void AR_MATRIX::XorCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
183{
184 MATRIX_CELL* p = m_BoardSide[aSide];
185 p[aRow * m_Ncols + aCol] ^= x;
186}
187
188
189/* basic cell operation : AND operation
190 */
191void AR_MATRIX::AndCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
192{
193 MATRIX_CELL* p = m_BoardSide[aSide];
194 p[aRow * m_Ncols + aCol] &= x;
195}
196
197
198/* basic cell operation : ADD operation
199 */
200void AR_MATRIX::AddCell( int aRow, int aCol, int aSide, MATRIX_CELL x )
201{
202 MATRIX_CELL* p = m_BoardSide[aSide];
203 p[aRow * m_Ncols + aCol] += x;
204}
205
206
207// fetch distance cell
208AR_MATRIX::DIST_CELL AR_MATRIX::GetDist( int aRow, int aCol, int aSide ) // fetch distance cell
209{
210 DIST_CELL* p = m_DistSide[aSide];
211 return p[aRow * m_Ncols + aCol];
212}
213
214
215// store distance cell
216void AR_MATRIX::SetDist( int aRow, int aCol, int aSide, DIST_CELL x )
217{
218 DIST_CELL* p = m_DistSide[aSide];
219 p[aRow * m_Ncols + aCol] = x;
220}
221
222
223/*
224** x is the direction to enter the cell of interest.
225** y is the direction to exit the cell of interest.
226** z is the direction to really exit the cell, if y=FROM_OTHERSIDE.
227**
228** return the distance of the trace through the cell of interest.
229** the calculation is driven by the tables above.
230*/
231
232
233#define OP_CELL( layer, dy, dx ) \
234 { \
235 if( layer == UNDEFINED_LAYER || layer == B_Cu ) \
236 WriteCell( dy, dx, AR_SIDE_BOTTOM, color ); \
237 \
238 if( m_RoutingLayersCount > 1 ) \
239 { \
240 if( layer == UNDEFINED_LAYER || layer == F_Cu ) \
241 WriteCell( dy, dx, AR_SIDE_TOP, color ); \
242 } \
243 }
244
245/* Fills all cells inside a segment
246 * half-width = lg, org = ux0,uy0 end = ux1,uy1
247 * coordinates are in PCB units
248 */
249void AR_MATRIX::drawSegmentQcq( int ux0, int uy0, int ux1, int uy1, int lg, int layer, int color,
250 AR_MATRIX::CELL_OP op_logic )
251{
252 SetCellOperation( op_logic );
253
254 // Make coordinate ux1 tj > ux0 to simplify calculations
255 if( ux1 < ux0 )
256 {
257 std::swap( ux1, ux0 );
258 std::swap( uy1, uy0 );
259 }
260
261 // Calculating the incrementing the Y axis
262 int64_t inc = 1;
263
264 if( uy1 < uy0 )
265 inc = -1;
266
267 int64_t demi_pas = m_GridRouting / 2;
268
269 int col_min = ( ux0 - lg ) / m_GridRouting;
270
271 if( col_min < 0 )
272 col_min = 0;
273
274 int col_max = KiROUND( ( ux1 + lg + demi_pas ) / m_GridRouting );
275
276 if( col_max > ( m_Ncols - 1 ) )
277 col_max = m_Ncols - 1;
278
279 int row_min = KiROUND( ( ( inc > 0 ? uy0 : uy1 ) - lg ) / m_GridRouting );
280 int row_max = KiROUND( ( ( inc > 0 ? uy1 : uy0 ) + lg + demi_pas ) / m_GridRouting );
281
282 row_min = std::max( 0, std::min( row_min, m_Nrows - 1 ) );
283 row_max = std::max( 0, std::min( row_max, m_Nrows - 1 ) );
284
285 int dx = ux1 - ux0;
286 int dy = uy1 - uy0;
287
288 EDA_ANGLE angle( VECTOR2I( dx, dy ) );
289
290 RotatePoint( &dx, &dy, angle ); // dx = length, dy = 0
291
292 for( int col = col_min; col <= col_max; col++ )
293 {
294 int64_t cxr = ( col * m_GridRouting ) - ux0;
295
296 for( int row = row_min; row <= row_max; row++ )
297 {
298 int cy = ( row * m_GridRouting ) - uy0;
299 int cx = cxr;
300 RotatePoint( &cx, &cy, angle );
301
302 if( abs( cy ) > lg )
303 {
304 // The point is too far on the Y axis.
305 }
306 // This point a test is close to the segment: the position along the X axis must be tested.
307 else if( ( cx >= 0 ) && ( cx <= dx ) )
308 {
309 OP_CELL( layer, row, col );
310 }
311 // Examination of extremities are rounded.
312 else if( ( cx < 0 ) && ( cx >= -lg ) )
313 {
314 if( ( ( cx * cx ) + ( cy * cy ) ) <= ( lg * lg ) )
315 OP_CELL( layer, row, col );
316 }
317 else if( ( cx > dx ) && ( cx <= ( dx + lg ) ) )
318 {
319 if( ( ( ( cx - dx ) * ( cx - dx ) ) + ( cy * cy ) ) <= ( lg * lg ) )
320 OP_CELL( layer, row, col );
321 }
322 }
323 }
324}
325
326
327/* Fills all cells of the routing matrix contained in the circle
328 * half-width = lg, center = ux0, uy0, ux1,uy1 is a point on the circle.
329 * coord are in PCB units.
330 */
331void AR_MATRIX::traceCircle( int ux0, int uy0, int ux1, int uy1, int lg, int layer, int color,
332 AR_MATRIX::CELL_OP op_logic )
333{
334 VECTOR2I pt1( ux0, uy0 );
335 VECTOR2I pt2( ux1, uy1 );
336 int radius = KiROUND( pt1.Distance( pt2 ) );
337
338 int x0 = radius; // Starting point of the current segment
339 int y0 = 0;
340
341 lg = std::max( 1, lg );
342
343 int nb_segm = ( 2 * radius ) / lg;
344
345 nb_segm = std::max( 5, std::min( nb_segm, 100 ) );
346
347 for( int ii = 1; ii < nb_segm; ii++ )
348 {
349 EDA_ANGLE angle = ( ANGLE_360 * ii ) / nb_segm;
350 int x1 = KiROUND( radius * angle.Cos() ); // End point of the current segment
351 int y1 = KiROUND( radius * angle.Sin() );
352
353 drawSegmentQcq( x0 + ux0, y0 + uy0, x1 + ux0, y1 + uy0, lg, layer, color, op_logic );
354 x0 = x1;
355 y0 = y1;
356 }
357
358 drawSegmentQcq( x0 + ux0, y0 + uy0, ux0 + radius, uy0, lg, layer, color, op_logic );
359}
360
361
362void AR_MATRIX::traceFilledCircle( int cx, int cy, int radius, const LSET& aLayerMask, int color,
363 AR_MATRIX::CELL_OP op_logic )
364{
365 int tstwrite = 0;
366
367 if( !aLayerMask[B_Cu] && !( aLayerMask[F_Cu] && m_RoutingLayersCount > 1 ) )
368 return;
369
370 SetCellOperation( op_logic );
371
372 cx -= GetBrdCoordOrigin().x;
373 cy -= GetBrdCoordOrigin().y;
374
375 int distmin = radius;
376
377 // Calculate the bounding rectangle of the circle.
378 int ux0 = cx - radius;
379 int uy0 = cy - radius;
380 int ux1 = cx + radius;
381 int uy1 = cy + radius;
382
383 // Calculate limit coordinates of cells belonging to the rectangle.
384 int row_max = uy1 / m_GridRouting;
385 int col_max = ux1 / m_GridRouting;
386 int row_min = uy0 / m_GridRouting; // if (uy0 > row_min*Board.m_GridRouting) row_min++;
387 int col_min = ux0 / m_GridRouting; // if (ux0 > col_min*Board.m_GridRouting) col_min++;
388
389 row_min = std::max( 0, row_min );
390 row_max = std::min( row_max, m_Nrows - 1 );
391 col_min = std::max( 0, col_min );
392 col_max = std::min( col_max, m_Ncols - 1 );
393
394 // Calculate coordinate limits of cell belonging to the rectangle.
395 if( row_min > row_max )
396 row_max = row_min;
397
398 if( col_min > col_max )
399 col_max = col_min;
400
401 double fdistmin = (double) distmin * distmin;
402
403 for( int row = row_min; row <= row_max; row++ )
404 {
405 double fdisty = cy - ( row * m_GridRouting );
406 fdisty *= fdisty;
407
408 for( int col = col_min; col <= col_max; col++ )
409 {
410 double fdistx = cx - ( col * m_GridRouting );
411 fdistx *= fdistx;
412
413 if( fdistmin <= ( fdistx + fdisty ) )
414 continue;
415
416 if( aLayerMask[B_Cu] )
417 WriteCell( row, col, AR_SIDE_BOTTOM, color );
418
419 if( aLayerMask[F_Cu] && m_RoutingLayersCount > 1 )
420 WriteCell( row, col, AR_SIDE_TOP, color );
421
422 tstwrite = 1;
423 }
424 }
425
426 if( tstwrite )
427 return;
428
429 /* If no cell has been written, it affects the 4 neighboring diagonal
430 * (Adverse event: pad off grid in the center of the 4 neighboring
431 * diagonal) */
432 distmin = m_GridRouting / 2 + 1;
433 fdistmin = ( (double) distmin * distmin ) * 2; // Distance to center point diagonally
434
435 for( int row = row_min; row <= row_max; row++ )
436 {
437 double fdisty = cy - ( row * m_GridRouting );
438 fdisty *= fdisty;
439
440 for( int col = col_min; col <= col_max; col++ )
441 {
442 double fdistx = cx - ( col * m_GridRouting );
443 fdistx *= fdistx;
444
445 if( fdistmin <= ( fdistx + fdisty ) )
446 continue;
447
448 if( aLayerMask[B_Cu] )
449 WriteCell( row, col, AR_SIDE_BOTTOM, color );
450
451 if( aLayerMask[F_Cu] && m_RoutingLayersCount > 1 )
452 WriteCell( row, col, AR_SIDE_TOP, color );
453 }
454 }
455}
456
457
458/* Fills all routing matrix cells contained in the arc
459 * angle = ArcAngle, half-width lg
460 * center = ux0,uy0, starting at ux1, uy1. Coordinates are in
461 * PCB units.
462 */
463void AR_MATRIX::traceArc( int ux0, int uy0, int ux1, int uy1, const EDA_ANGLE& arcAngle, int lg, int layer,
464 int color, AR_MATRIX::CELL_OP op_logic )
465{
466 VECTOR2I pt1( ux0, uy0 );
467 VECTOR2I pt2( ux1, uy1 );
468 int radius = KiROUND( pt1.Distance( pt2 ) );
469
470 int x0 = ux1 - ux0; // Starting point of current segment
471 int y0 = uy1 - uy0;
472 EDA_ANGLE startAngle = EDA_ANGLE( VECTOR2I( ux1, uy1 ) - VECTOR2I( ux0, uy0 ) );
473
474 if( lg < 1 )
475 lg = 1;
476
477 int nb_segm = ( 2 * radius ) / lg;
478 nb_segm = KiROUND( nb_segm * std::abs( arcAngle.AsDegrees() ) / 360.0 );
479 nb_segm = std::max( 5, std::min( nb_segm, 100 ) );
480
481 for( int ii = 1; ii <= nb_segm; ii++ )
482 {
483 EDA_ANGLE angle = arcAngle * ii / nb_segm;
484 angle += startAngle;
485
486 angle.Normalize();
487
488 int x1 = KiROUND( radius * angle.Cos() ); // Ending point of current segment
489 int y1 = KiROUND( radius * angle.Cos() );
490 drawSegmentQcq( x0 + ux0, y0 + uy0, x1 + ux0, y1 + uy0, lg, layer, color, op_logic );
491 x0 = x1;
492 y0 = y1;
493 }
494}
495
496
497void AR_MATRIX::TraceFilledRectangle( int ux0, int uy0, int ux1, int uy1, const EDA_ANGLE& angle,
498 const LSET& aLayerMask, int color, AR_MATRIX::CELL_OP op_logic )
499{
500 if( !aLayerMask[B_Cu] && !( aLayerMask[F_Cu] && m_RoutingLayersCount > 1 ) )
501 return;
502
503 SetCellOperation( op_logic );
504
505 ux0 -= GetBrdCoordOrigin().x;
506 uy0 -= GetBrdCoordOrigin().y;
507 ux1 -= GetBrdCoordOrigin().x;
508 uy1 -= GetBrdCoordOrigin().y;
509
510 VECTOR2I pt1( ux0, uy0 );
511 VECTOR2I center( ( ux0 + ux1 ) / 2, ( uy0 + uy1 ) / 2 );
512 int radius = KiROUND( pt1.Distance( center ) );
513
514 // Calculating coordinate limits belonging to the rectangle.
515 int row_max = ( center.y + radius ) / m_GridRouting;
516 int col_max = ( center.x + radius ) / m_GridRouting;
517 int row_min = ( center.y - radius ) / m_GridRouting;
518
519 if( uy0 > row_min * m_GridRouting )
520 row_min++;
521
522 int col_min = ( center.x - radius ) / m_GridRouting;
523
524 if( ux0 > col_min * m_GridRouting )
525 col_min++;
526
527 row_min = std::max( 0, row_min );
528 row_max = std::min( row_max, m_Nrows - 1 );
529 col_min = std::max( 0, col_min );
530 col_max = std::min( col_max, m_Ncols - 1 );
531
532 for( int row = row_min; row <= row_max; row++ )
533 {
534 for( int col = col_min; col <= col_max; col++ )
535 {
536 int rotrow = row * m_GridRouting;
537 int rotcol = col * m_GridRouting;
538 RotatePoint( &rotcol, &rotrow, center.x, center.y, -angle );
539
540 if( rotrow <= uy0 )
541 continue;
542
543 if( rotrow >= uy1 )
544 continue;
545
546 if( rotcol <= ux0 )
547 continue;
548
549 if( rotcol >= ux1 )
550 continue;
551
552 if( aLayerMask[B_Cu] )
553 WriteCell( row, col, AR_SIDE_BOTTOM, color );
554
555 if( aLayerMask[F_Cu] && m_RoutingLayersCount > 1 )
556 WriteCell( row, col, AR_SIDE_TOP, color );
557 }
558 }
559}
560
561
562void AR_MATRIX::TraceFilledRectangle( int ux0, int uy0, int ux1, int uy1, const LSET& aLayerMask,
563 int color, AR_MATRIX::CELL_OP op_logic )
564{
565 if( !aLayerMask[B_Cu] && !( aLayerMask[F_Cu] && m_RoutingLayersCount > 1 ) )
566 return;
567
568 SetCellOperation( op_logic );
569
570 ux0 -= GetBrdCoordOrigin().x;
571 uy0 -= GetBrdCoordOrigin().y;
572 ux1 -= GetBrdCoordOrigin().x;
573 uy1 -= GetBrdCoordOrigin().y;
574
575 // Calculating limits coord cells belonging to the rectangle.
576 int row_max = uy1 / m_GridRouting;
577 int col_max = ux1 / m_GridRouting;
578 int row_min = uy0 / m_GridRouting;
579
580 if( uy0 > row_min * m_GridRouting )
581 row_min++;
582
583 int col_min = ux0 / m_GridRouting;
584
585 if( ux0 > col_min * m_GridRouting )
586 col_min++;
587
588 row_min = std::max( 0, row_min );
589 row_max = std::min( row_max, m_Nrows - 1 );
590 col_min = std::max( 0, col_min );
591 col_max = std::min( col_max, m_Ncols - 1 );
592
593 for( int row = row_min; row <= row_max; row++ )
594 {
595 for( int col = col_min; col <= col_max; col++ )
596 {
597 if( aLayerMask[B_Cu] )
598 WriteCell( row, col, AR_SIDE_BOTTOM, color );
599
600 if( aLayerMask[F_Cu] && m_RoutingLayersCount > 1 )
601 WriteCell( row, col, AR_SIDE_TOP, color );
602 }
603 }
604}
605
606
607void AR_MATRIX::TracePcbShape( PCB_SHAPE* aShape, int aColor, int aMargin, AR_MATRIX::CELL_OP op_logic )
608{
609 int half_width = ( aShape->GetWidth() / 2 ) + aMargin;
610
611 // Calculate the bounding rectangle of the segment (if H, V or Via)
612 int layer = UNDEFINED_LAYER; // Draw on all layers
613
614 if( aShape->GetShape() == SHAPE_T::CIRCLE || aShape->GetShape() == SHAPE_T::SEGMENT )
615 {
616 int ux0 = aShape->GetStart().x - GetBrdCoordOrigin().x;
617 int uy0 = aShape->GetStart().y - GetBrdCoordOrigin().y;
618 int ux1 = aShape->GetEnd().x - GetBrdCoordOrigin().x;
619 int uy1 = aShape->GetEnd().y - GetBrdCoordOrigin().y;
620
621 if( aShape->GetShape() == SHAPE_T::CIRCLE )
622 traceCircle( ux0, uy0, ux1, uy1, half_width, layer, aColor, op_logic );
623 else
624 drawSegmentQcq( ux0, uy0, ux1, uy1, half_width, layer, aColor, op_logic );
625 }
626 else if( aShape->GetShape() == SHAPE_T::ARC )
627 {
628 int ux0 = aShape->GetCenter().x - GetBrdCoordOrigin().x;
629 int uy0 = aShape->GetCenter().y - GetBrdCoordOrigin().y;
630 int ux1 = aShape->GetStart().x - GetBrdCoordOrigin().x;
631 int uy1 = aShape->GetStart().y - GetBrdCoordOrigin().y;
632
633 traceArc( ux0, uy0, ux1, uy1, aShape->GetArcAngle(), half_width, layer, aColor, op_logic );
634 }
635}
636
637
648void AR_MATRIX::CreateKeepOutRectangle( int ux0, int uy0, int ux1, int uy1, int margin, int aKeepOut,
649 const LSET& aLayerMask )
650{
651 DIST_CELL data, LocalKeepOut;
652
653 if( !aLayerMask[B_Cu] && !( aLayerMask[F_Cu] && m_RoutingLayersCount > 1 ) )
654 return;
655
656 ux0 -= m_BrdBox.GetX();
657 uy0 -= m_BrdBox.GetY();
658 ux1 -= m_BrdBox.GetX();
659 uy1 -= m_BrdBox.GetY();
660
661 ux0 -= margin;
662 ux1 += margin;
663 uy0 -= margin;
664 uy1 += margin;
665
666 int cell_margin = std::max( 1, margin / m_GridRouting );
667
668 // Calculate the coordinate limits of the rectangle.
669 int row_max = uy1 / m_GridRouting;
670 int col_max = ux1 / m_GridRouting;
671 int row_min = uy0 / m_GridRouting;
672
673 if( uy0 > row_min * m_GridRouting )
674 row_min++;
675
676 int col_min = ux0 / m_GridRouting;
677
678 if( ux0 > col_min * m_GridRouting )
679 col_min++;
680
681 row_min = std::max( 0, row_min );
682 row_max = std::min( row_max, m_Nrows - 1 );
683 col_min = std::max( 0, col_min );
684 col_max = std::min( col_max, m_Ncols - 1 );
685
686 for( int row = row_min; row <= row_max; row++ )
687 {
688 int lgain = 256;
689
690 if( row < cell_margin )
691 lgain = ( 256 * row ) / cell_margin;
692 else if( row > row_max - cell_margin )
693 lgain = ( 256 * ( row_max - row ) ) / cell_margin;
694
695 for( int col = col_min; col <= col_max; col++ )
696 {
697 // RoutingMatrix Dist map contained the "cost" of the cell at position (row, col)
698 // in autoplace this is the cost of the cell, when a footprint overlaps it, near a "master" footprint
699 // this cost is high near the "master" footprint and decrease with the distance
700 int cgain = 256;
701 LocalKeepOut = aKeepOut;
702
703 if( col < cell_margin )
704 cgain = ( 256 * col ) / cell_margin;
705 else if( col > col_max - cell_margin )
706 cgain = ( 256 * ( col_max - col ) ) / cell_margin;
707
708 cgain = ( cgain * lgain ) / 256;
709
710 if( cgain != 256 )
711 LocalKeepOut = ( LocalKeepOut * cgain ) / 256;
712
713 if( aLayerMask[B_Cu] )
714 {
715 data = GetDist( row, col, AR_SIDE_BOTTOM ) + LocalKeepOut;
716 SetDist( row, col, AR_SIDE_BOTTOM, data );
717 }
718
719 if( aLayerMask[F_Cu] && m_RoutingLayersCount > 1 )
720 {
721 data = std::max( GetDist( row, col, AR_SIDE_TOP ), LocalKeepOut );
722 SetDist( row, col, AR_SIDE_TOP, data );
723 }
724 }
725 }
726}
727
728
729void AR_MATRIX::PlacePad( PAD* aPad, int color, int margin, AR_MATRIX::CELL_OP op_logic )
730{
731 auto tracePad =
732 [&]( PCB_LAYER_ID aOutputLayer )
733 {
734 PCB_LAYER_ID effectivePadLayer = aPad->Padstack().EffectiveLayerFor( aOutputLayer );
735
736 VECTOR2I shape_pos = aPad->ShapePos( effectivePadLayer );
737 int x = ( aPad->GetSize( effectivePadLayer ).x / 2 ) + margin;
738 int y = ( aPad->GetSize( effectivePadLayer ).y / 2 ) + margin;
739
740 if( aPad->GetShape( effectivePadLayer ) == PAD_SHAPE::CIRCLE )
741 {
742 traceFilledCircle( shape_pos.x, shape_pos.y, x, { aOutputLayer }, color, op_logic );
743 }
744 else
745 {
746 // approximate pad as a rectangle
747
748 if( aPad->GetShape( effectivePadLayer ) == PAD_SHAPE::TRAPEZOID )
749 {
750 x += abs( aPad->GetDelta( effectivePadLayer ).y ) / 2;
751 y += abs( aPad->GetDelta( effectivePadLayer ).x ) / 2;
752 }
753
754 if( aPad->GetOrientation().IsCardinal() )
755 {
756 // Orientation turned 90 deg.
757 if( aPad->GetOrientation() == ANGLE_90 || aPad->GetOrientation() == ANGLE_270 )
758 std::swap( x, y );
759
760 TraceFilledRectangle( shape_pos.x - x, shape_pos.y - y, shape_pos.x + x, shape_pos.y + y,
761 { aOutputLayer }, color, op_logic );
762 }
763 else
764 {
765 TraceFilledRectangle( shape_pos.x - x, shape_pos.y - y, shape_pos.x + x, shape_pos.y + y,
766 aPad->GetOrientation(), { aOutputLayer }, color, op_logic );
767 }
768 }
769 };
770
771 if( aPad->GetLayerSet()[B_Cu] )
772 tracePad( B_Cu );
773
774 if( aPad->GetLayerSet()[F_Cu] && m_RoutingLayersCount > 1 )
775 tracePad( F_Cu );
776}
#define OP_CELL(layer, dy, dx)
#define AR_SIDE_BOTTOM
Definition ar_matrix.h:37
#define AR_MAX_ROUTING_LAYERS_COUNT
Definition ar_matrix.h:34
#define AR_SIDE_TOP
Definition ar_matrix.h:36
BOX2< VECTOR2I > BOX2I
Definition box2.h:927
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:995
void UnInitRoutingMatrix()
int m_Nrows
Definition ar_matrix.h:132
unsigned char MATRIX_CELL
Definition ar_matrix.h:45
BOX2I m_BrdBox
Definition ar_matrix.h:131
void AddCell(int aRow, int aCol, int aSide, MATRIX_CELL aCell)
void AndCell(int aRow, int aCol, int aSide, MATRIX_CELL aCell)
void SetCellOperation(CELL_OP aLogicOp)
void(AR_MATRIX::* m_opWriteCell)(int aRow, int aCol, int aSide, MATRIX_CELL aCell)
Definition ar_matrix.h:138
void TracePcbShape(PCB_SHAPE *aShape, int aColor, int aMargin, AR_MATRIX::CELL_OP op_logic)
int m_RouteCount
Definition ar_matrix.h:134
int DIST_CELL
Definition ar_matrix.h:46
int m_RoutingLayersCount
Definition ar_matrix.h:129
void SetCell(int aRow, int aCol, int aSide, MATRIX_CELL aCell)
@ WRITE_OR_CELL
Definition ar_matrix.h:51
@ WRITE_AND_CELL
Definition ar_matrix.h:53
@ WRITE_XOR_CELL
Definition ar_matrix.h:52
@ WRITE_ADD_CELL
Definition ar_matrix.h:54
void XorCell(int aRow, int aCol, int aSide, MATRIX_CELL aCell)
void SetDist(int aRow, int aCol, int aSide, DIST_CELL)
int m_MemSize
Definition ar_matrix.h:133
int InitRoutingMatrix()
Initialize the data structures.
Definition ar_matrix.cpp:79
MATRIX_CELL * m_BoardSide[AR_MAX_ROUTING_LAYERS_COUNT]
Definition ar_matrix.h:126
void drawSegmentQcq(int ux0, int uy0, int ux1, int uy1, int lg, int layer, int color, CELL_OP op_logic)
bool ComputeMatrixSize(const BOX2I &aBoundingBox)
Calculate the number of rows and columns of dimensions of aPcb for routing and automatic calculation ...
Definition ar_matrix.cpp:49
void OrCell(int aRow, int aCol, int aSide, MATRIX_CELL aCell)
int m_GridRouting
Definition ar_matrix.h:130
void traceCircle(int ux0, int uy0, int ux1, int uy1, int lg, int layer, int color, AR_MATRIX::CELL_OP op_logic)
DIST_CELL * m_DistSide[AR_MAX_ROUTING_LAYERS_COUNT]
Definition ar_matrix.h:127
DIST_CELL GetDist(int aRow, int aCol, int aSide)
void CreateKeepOutRectangle(int ux0, int uy0, int ux1, int uy1, int margin, int aKeepOut, const LSET &aLayerMask)
Function CreateKeepOutRectangle builds the cost map: Cells ( in Dist map ) inside the rect x0,...
MATRIX_CELL GetCell(int aRow, int aCol, int aSide)
void traceArc(int ux0, int uy0, int ux1, int uy1, const EDA_ANGLE &arcAngle, int lg, int layer, int color, AR_MATRIX::CELL_OP op_logic)
void TraceFilledRectangle(int ux0, int uy0, int ux1, int uy1, const EDA_ANGLE &angle, const LSET &aLayerMask, int color, AR_MATRIX::CELL_OP op_logic)
void traceFilledCircle(int cx, int cy, int radius, const LSET &aLayerMask, int color, AR_MATRIX::CELL_OP op_logic)
VECTOR2I GetBrdCoordOrigin()
Definition ar_matrix.h:69
void WriteCell(int aRow, int aCol, int aSide, MATRIX_CELL aCell)
Definition ar_matrix.h:60
int m_Ncols
Definition ar_matrix.h:132
void PlacePad(PAD *aPad, int color, int margin, AR_MATRIX::CELL_OP op_logic)
EDA_ANGLE Normalize()
Definition eda_angle.h:229
double Sin() const
Definition eda_angle.h:178
double AsDegrees() const
Definition eda_angle.h:116
bool IsCardinal() const
Definition eda_angle.cpp:40
double Cos() const
Definition eda_angle.h:197
EDA_ANGLE GetArcAngle() const
SHAPE_T GetShape() const
Definition eda_shape.h:175
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:325
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:275
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
PCB_LAYER_ID EffectiveLayerFor(PCB_LAYER_ID aLayer) const
Determines which geometry layer should be used for the given input layer.
Definition pad.h:61
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition pad.h:555
const VECTOR2I & GetDelta(PCB_LAYER_ID aLayer) const
Definition pad.h:305
PAD_SHAPE GetShape(PCB_LAYER_ID aLayer) const
Definition pad.h:205
VECTOR2I GetSize(PCB_LAYER_ID aLayer) const
Definition pad.cpp:288
const PADSTACK & Padstack() const
Definition pad.h:329
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition pad.cpp:1747
VECTOR2I ShapePos(PCB_LAYER_ID aLayer) const
Definition pad.cpp:1855
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition pcb_shape.h:78
int GetWidth() const override
double Distance(const VECTOR2< extended_type > &aVector) const
Compute the distance between two vectors.
Definition vector2d.h:549
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:424
static constexpr EDA_ANGLE ANGLE_270
Definition eda_angle.h:427
static constexpr EDA_ANGLE ANGLE_360
Definition eda_angle.h:428
@ SEGMENT
Definition eda_shape.h:56
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ B_Cu
Definition layer_ids.h:61
@ UNDEFINED_LAYER
Definition layer_ids.h:57
@ F_Cu
Definition layer_ids.h:60
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:411
@ TRAPEZOID
Definition padstack.h:55
VECTOR2I center
int radius
VECTOR2I end
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition trigo.cpp:225
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683