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