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