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