KiCad PCB EDA Suite
Loading...
Searching...
No Matches
create_3Dgraphic_brd_items.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) 2015-2016 Mario Luzeiro <[email protected]>
5 * Copyright (C) 2023 CERN
6 * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
32#include "../3d_rendering/raytracing/shapes2D/ring_2d.h"
33#include "../3d_rendering/raytracing/shapes2D/filled_circle_2d.h"
34#include "../3d_rendering/raytracing/shapes2D/round_segment_2d.h"
35#include "../3d_rendering/raytracing/shapes2D/triangle_2d.h"
36#include <board_adapter.h>
37#include <footprint.h>
38#include <pad.h>
39#include <pcb_text.h>
40#include <pcb_textbox.h>
42#include <pcb_painter.h> // for PCB_RENDER_SETTINGS
43#include <zone.h>
45#include <trigo.h>
49#include <geometry/shape_rect.h>
51#include <utility>
52#include <vector>
53#include <wx/log.h>
54#include <macros.h>
55#include <callback_gal.h>
56
57
58#define TO_3DU( x ) ( ( x ) * m_biuTo3Dunits )
59
60#define TO_SFVEC2F( vec ) SFVEC2F( TO_3DU( vec.x ), TO_3DU( -vec.y ) )
61
62
63void addFILLED_CIRCLE_2D( CONTAINER_2D_BASE* aContainer, const SFVEC2F& aCenter, float aRadius,
64 const BOARD_ITEM& aBoardItem )
65{
66 if( aRadius > 0.0f )
67 aContainer->Add( new FILLED_CIRCLE_2D( aCenter, aRadius, aBoardItem ) );
68}
69
70
71void addRING_2D( CONTAINER_2D_BASE* aContainer, const SFVEC2F& aCenter, float aInnerRadius,
72 float aOuterRadius, const BOARD_ITEM& aBoardItem )
73{
74 if( aOuterRadius > aInnerRadius && aInnerRadius > 0.0f )
75 aContainer->Add( new RING_2D( aCenter, aInnerRadius, aOuterRadius, aBoardItem ) );
76}
77
78
79void addROUND_SEGMENT_2D( CONTAINER_2D_BASE* aContainer, const SFVEC2F& aStart, const SFVEC2F& aEnd,
80 float aWidth, const BOARD_ITEM& aBoardItem )
81{
82 if( Is_segment_a_circle( aStart, aEnd ) )
83 {
84 // Cannot add segments that have the same start and end point
85 addFILLED_CIRCLE_2D( aContainer, aStart, aWidth / 2, aBoardItem );
86 return;
87 }
88
89 if( aWidth > 0.0f )
90 aContainer->Add( new ROUND_SEGMENT_2D( aStart, aEnd, aWidth, aBoardItem ) );
91}
92
93
94void BOARD_ADAPTER::addText( const EDA_TEXT* aText, CONTAINER_2D_BASE* aContainer,
95 const BOARD_ITEM* aOwner )
96{
98 TEXT_ATTRIBUTES attrs = aText->GetAttributes();
99 float penWidth_3DU = TO_3DU( aText->GetEffectiveTextPenWidth() );
100 KIFONT::FONT* font = aText->GetFont();
101
102 if( !font )
103 font = KIFONT::FONT::GetFont( wxEmptyString, aText->IsBold(), aText->IsItalic() );
104
105 if( aOwner && aOwner->IsKnockout() )
106 {
107 SHAPE_POLY_SET finalPoly;
108 const PCB_TEXT* pcbText = static_cast<const PCB_TEXT*>( aOwner );
109
111 ERROR_INSIDE );
112
113 // Do not call finalPoly.Fracture() here: ConvertPolygonToTriangles() call it
114 // if needed, and Fracture() called twice can create bad results and is useless
115 ConvertPolygonToTriangles( finalPoly, *aContainer, m_biuTo3Dunits, *aOwner );
116 }
117 else
118 {
119 CALLBACK_GAL callback_gal( empty_opts,
120 // Stroke callback
121 [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
122 {
123 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( aPt1 ), TO_SFVEC2F( aPt2 ),
124 penWidth_3DU, *aOwner );
125 },
126 // Triangulation callback
127 [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2, const VECTOR2I& aPt3 )
128 {
129 aContainer->Add( new TRIANGLE_2D( TO_SFVEC2F( aPt1 ), TO_SFVEC2F( aPt2 ),
130 TO_SFVEC2F( aPt3 ), *aOwner ) );
131 } );
132
133 attrs.m_Angle = aText->GetDrawRotation();
134
135 font->Draw( &callback_gal, aText->GetShownText( true ), aText->GetDrawPos(), attrs,
136 aOwner->GetFontMetrics() );
137 }
138}
139
140
142 const BOARD_ITEM* aOwner )
143{
144 addText( aDimension, aContainer, aDimension );
145
146 const int linewidth = aDimension->GetLineThickness();
147
148 for( const std::shared_ptr<SHAPE>& shape : aDimension->GetShapes() )
149 {
150 switch( shape->Type() )
151 {
152 case SH_SEGMENT:
153 {
154 const SEG& seg = static_cast<const SHAPE_SEGMENT*>( shape.get() )->GetSeg();
155
156 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( seg.A ), TO_SFVEC2F( seg.B ),
157 TO_3DU( linewidth ), *aOwner );
158 break;
159 }
160
161 case SH_CIRCLE:
162 {
163 int radius = static_cast<const SHAPE_CIRCLE*>( shape.get() )->GetRadius();
164 float innerR3DU = TO_3DU( radius ) - TO_3DU( aDimension->GetLineThickness() ) / 2.0f;
165 float outerR3DU = TO_3DU( radius ) + TO_3DU( aDimension->GetLineThickness() ) / 2.0f;
166
167 addRING_2D( aContainer, TO_SFVEC2F( shape->Centre() ), innerR3DU, outerR3DU, *aOwner );
168
169 break;
170 }
171
172 default:
173 break;
174 }
175 }
176}
177
178
180 PCB_LAYER_ID aLayerId,
181 const std::bitset<LAYER_3D_END>& aVisibilityFlags )
182{
184
185 for( PCB_FIELD* field : aFootprint->GetFields() )
186 {
187 if( field->GetLayer() == aLayerId && field->IsVisible() )
188 {
189 if( !aVisibilityFlags.test( LAYER_FP_TEXT ) )
190 continue;
191 else if( field->IsReference() && !aVisibilityFlags.test( LAYER_FP_REFERENCES ) )
192 continue;
193 else if( field->IsValue() && !aVisibilityFlags.test( LAYER_FP_VALUES ) )
194 continue;
195
196 addText( field, aContainer, field );
197 }
198 }
199
200 for( BOARD_ITEM* item : aFootprint->GraphicalItems() )
201 {
202 switch( item->Type() )
203 {
204 case PCB_TEXT_T:
205 {
206 PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
207
208 if( text->GetLayer() == aLayerId && text->IsVisible() )
209 {
210 if( !aVisibilityFlags.test( LAYER_FP_TEXT ) )
211 continue;
212 else if( text->GetText() == wxT( "${REFERENCE}" ) && !aVisibilityFlags.test( LAYER_FP_REFERENCES ) )
213 continue;
214 else if( text->GetText() == wxT( "${VALUE}" ) && !aVisibilityFlags.test( LAYER_FP_VALUES ) )
215 continue;
216
217 addText( text, aContainer, text );
218 }
219
220 break;
221 }
222
223 case PCB_TEXTBOX_T:
224 {
225 PCB_TEXTBOX* textbox = static_cast<PCB_TEXTBOX*>( item );
226
227 if( textbox->GetLayer() == aLayerId )
228 {
229 if( textbox->IsBorderEnabled() )
230 addShape( textbox, aContainer, aFootprint );
231
232 addText( textbox, aContainer, aFootprint );
233 }
234
235 break;
236 }
237
239 case PCB_DIM_CENTER_T:
241 case PCB_DIM_RADIAL_T:
242 case PCB_DIM_LEADER_T:
243 {
244 PCB_DIMENSION_BASE* dimension = static_cast<PCB_DIMENSION_BASE*>( item );
245
246 if( dimension->GetLayer() == aLayerId )
247 addShape( dimension, aContainer, aFootprint );
248
249 break;
250 }
251
252 case PCB_SHAPE_T:
253 {
254 PCB_SHAPE* shape = static_cast<PCB_SHAPE*>( item );
255
256 if( shape->GetLayer() == aLayerId )
257 addShape( shape, aContainer, aFootprint );
258
259 break;
260 }
261
262 default:
263 break;
264 }
265 }
266}
267
268
270 int aMargin )
271{
272 SFVEC2F start3DU = TO_SFVEC2F( aTrack->GetStart() );
273 SFVEC2F end3DU = TO_SFVEC2F( aTrack->GetEnd() );
274 const float radius3DU = TO_3DU( ( aTrack->GetWidth() / 2.0 ) + aMargin );
275
276 addFILLED_CIRCLE_2D( aDstContainer, start3DU, radius3DU, *aTrack );
277}
278
279
280void BOARD_ADAPTER::createTrack( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDstContainer )
281{
282 SFVEC2F start3DU = TO_SFVEC2F( aTrack->GetStart() );
283 SFVEC2F end3DU = TO_SFVEC2F( aTrack->GetEnd() );
284
285 switch( aTrack->Type() )
286 {
287 case PCB_VIA_T:
288 addFILLED_CIRCLE_2D( aDstContainer, start3DU, TO_3DU( aTrack->GetWidth() / 2.0 ), *aTrack );
289 break;
290
291 case PCB_ARC_T:
292 {
293 const PCB_ARC* arc = static_cast<const PCB_ARC*>( aTrack );
294
295 if( arc->IsDegenerated() )
296 {
297 // Draw this very small arc like a track segment (a PCB_TRACE_T)
298 PCB_TRACK track( arc->GetParent() );
299 track.SetStart( arc->GetStart() );
300 track.SetEnd( arc->GetEnd() );
301 track.SetWidth( arc->GetWidth() );
302 track.SetLayer( arc->GetLayer() );
303
304 createTrack( &track, aDstContainer );
305 return;
306 }
307
308 VECTOR2I center( arc->GetCenter() );
309 EDA_ANGLE arc_angle = arc->GetAngle();
310 double radius = arc->GetRadius();
311 int arcsegcount = GetArcToSegmentCount( KiROUND( radius ), ARC_HIGH_DEF, arc_angle );
312 int circlesegcount;
313
314 // Avoid arcs that cannot be drawn
315 if( radius < std::numeric_limits<double>::min() || arc_angle.IsZero() )
316 break;
317
318 // We need a circle to segment count. However, the arc angle can be small, and the
319 // radius very big. so we calculate a reasonable value for circlesegcount.
320 if( arcsegcount <= 1 ) // The arc will be approximated by a segment
321 {
322 circlesegcount = 1;
323 }
324 else
325 {
326 circlesegcount = KiROUND( arcsegcount * 360.0 / std::abs( arc_angle.AsDegrees() ) );
327 circlesegcount = alg::clamp( 1, circlesegcount, 128 );
328 }
329
330 createArcSegments( center, arc->GetStart(), arc_angle, circlesegcount, arc->GetWidth(),
331 aDstContainer, *arc );
332 break;
333 }
334
335 case PCB_TRACE_T: // Track is a usual straight segment
336 {
337 addROUND_SEGMENT_2D( aDstContainer, start3DU, end3DU, TO_3DU( aTrack->GetWidth() ), *aTrack );
338 break;
339 }
340
341 default:
342 break;
343 }
344}
345
346
348 PCB_LAYER_ID aLayer, const VECTOR2I& aMargin ) const
349{
350 SHAPE_POLY_SET poly;
351 int maxError = GetBoard()->GetDesignSettings().m_MaxError;
352 VECTOR2I clearance = aMargin;
353
354 // Our shape-based builder can't handle negative or differing x:y clearance values (the
355 // former are common for solder paste while the later get generated when a relative paste
356 // margin is used with an oblong pad). So we apply this huge hack and fake a larger pad to
357 // run the general-purpose polygon builder on.
358 // Of course being a hack it falls down when dealing with custom shape pads (where the size
359 // is only the size of the anchor), so for those we punt and just use aMargin.x.
360
361 if( ( clearance.x < 0 || clearance.x != clearance.y )
362 && aPad->GetShape() != PAD_SHAPE::CUSTOM )
363 {
364 VECTOR2I dummySize = VECTOR2I( aPad->GetSize() ) + clearance + clearance;
365
366 if( dummySize.x <= 0 || dummySize.y <= 0 )
367 return;
368
369 PAD dummy( *aPad );
370 dummy.SetSize( VECTOR2I( dummySize.x, dummySize.y ) );
371 dummy.TransformShapeToPolygon( poly, aLayer, 0, maxError, ERROR_INSIDE );
372 clearance = { 0, 0 };
373
374 // Remove group membership from dummy item before deleting
375 dummy.SetParentGroup( nullptr );
376 }
377 else
378 {
379 auto padShapes = std::static_pointer_cast<SHAPE_COMPOUND>( aPad->GetEffectiveShape() );
380
381 for( const SHAPE* shape : padShapes->Shapes() )
382 {
383 switch( shape->Type() )
384 {
385 case SH_SEGMENT:
386 {
387 const SHAPE_SEGMENT* seg = static_cast<const SHAPE_SEGMENT*>( shape );
388
389 addROUND_SEGMENT_2D( aContainer,
390 TO_SFVEC2F( seg->GetSeg().A ),
391 TO_SFVEC2F( seg->GetSeg().B ),
392 TO_3DU( seg->GetWidth() + clearance.x * 2 ),
393 *aPad );
394 break;
395 }
396
397 case SH_CIRCLE:
398 {
399 const SHAPE_CIRCLE* circle = static_cast<const SHAPE_CIRCLE*>( shape );
400
401 addFILLED_CIRCLE_2D( aContainer,
402 TO_SFVEC2F( circle->GetCenter() ),
403 TO_3DU( circle->GetRadius() + clearance.x ),
404 *aPad );
405 break;
406 }
407
408 case SH_RECT:
409 {
410 const SHAPE_RECT* rect = static_cast<const SHAPE_RECT*>( shape );
411
412 poly.NewOutline();
413 poly.Append( rect->GetPosition() );
414 poly.Append( rect->GetPosition().x + rect->GetSize().x, rect->GetPosition().y );
415 poly.Append( rect->GetPosition() + rect->GetSize() );
416 poly.Append( rect->GetPosition().x, rect->GetPosition().y + rect->GetSize().y );
417 break;
418 }
419
420 case SH_SIMPLE:
421 poly.AddOutline( static_cast<const SHAPE_SIMPLE*>( shape )->Vertices() );
422 break;
423
424 case SH_POLY_SET:
425 poly = *(SHAPE_POLY_SET*) shape;
426 break;
427
428 case SH_ARC:
429 {
430 const SHAPE_ARC* arc = static_cast<const SHAPE_ARC*>( shape );
431 SHAPE_LINE_CHAIN l = arc->ConvertToPolyline( maxError );
432
433 for( int i = 0; i < l.SegmentCount(); i++ )
434 {
435 SHAPE_SEGMENT seg( l.Segment( i ).A, l.Segment( i ).B, arc->GetWidth() );
436
437 addROUND_SEGMENT_2D( aContainer,
438 TO_SFVEC2F( seg.GetSeg().A ),
439 TO_SFVEC2F( seg.GetSeg().B ),
440 TO_3DU( arc->GetWidth() + clearance.x * 2 ),
441 *aPad );
442 }
443
444 break;
445 }
446
447 default:
448 UNIMPLEMENTED_FOR( SHAPE_TYPE_asString( shape->Type() ) );
449 break;
450 }
451 }
452 }
453
454 if( !poly.IsEmpty() )
455 {
456 if( clearance.x )
457 poly.Inflate( clearance.x, SHAPE_POLY_SET::ROUND_ALL_CORNERS, maxError );
458
459 // Add the PAD polygon
460 ConvertPolygonToTriangles( poly, *aContainer, m_biuTo3Dunits, *aPad );
461 }
462}
463
464
466 int aInflateValue )
467{
468 if( !aPad->HasHole() )
469 {
470 wxLogTrace( m_logTrace, wxT( "BOARD_ADAPTER::createPadWithHole - found an invalid pad" ) );
471 return;
472 }
473
474 std::shared_ptr<SHAPE_SEGMENT> slot = aPad->GetEffectiveHoleShape();
475
476 addROUND_SEGMENT_2D( aDstContainer,
477 TO_SFVEC2F( slot->GetSeg().A ),
478 TO_SFVEC2F( slot->GetSeg().B ),
479 TO_3DU( slot->GetWidth() + aInflateValue * 2 ),
480 *aPad );
481}
482
483
484void BOARD_ADAPTER::addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aContainer,
485 PCB_LAYER_ID aLayerId, bool aSkipPlatedPads, bool aSkipNonPlatedPads )
486{
487 for( PAD* pad : aFootprint->Pads() )
488 {
489 if( !pad->IsOnLayer( aLayerId ) )
490 continue;
491
492 if( IsCopperLayer( aLayerId ) )
493 {
494 // Skip pad annulus when there isn't one (note: this is more discerning than
495 // pad->IsOnLayer(), which doesn't check for NPTH pads with holes that consume
496 // the entire pad).
497 if( !pad->IsOnCopperLayer() )
498 continue;
499
500 // Skip pad annulus when not connected on this layer (if removing is enabled)
501 if( !pad->FlashLayer( aLayerId ) )
502 continue;
503 }
504
505 VECTOR2I margin( 0, 0 );
506
507 switch( aLayerId )
508 {
509 case F_Cu:
510 if( aSkipPlatedPads && pad->FlashLayer( F_Mask ) )
511 continue;
512
513 if( aSkipNonPlatedPads && !pad->FlashLayer( F_Mask ) )
514 continue;
515
516 break;
517
518 case B_Cu:
519 if( aSkipPlatedPads && pad->FlashLayer( B_Mask ) )
520 continue;
521
522 if( aSkipNonPlatedPads && !pad->FlashLayer( B_Mask ) )
523 continue;
524
525 break;
526
527 case F_Mask:
528 case B_Mask:
529 margin.x += pad->GetSolderMaskExpansion();
530 margin.y += pad->GetSolderMaskExpansion();
531 break;
532
533 case F_Paste:
534 case B_Paste:
535 margin += pad->GetSolderPasteMargin();
536 break;
537
538 default:
539 break;
540 }
541
542 createPadWithMargin( pad, aContainer, aLayerId, margin );
543 }
544}
545
546
547// based on TransformArcToPolygon function from
548// common/convert_basic_shapes_to_polygon.cpp
549void BOARD_ADAPTER::createArcSegments( const VECTOR2I& aCentre, const VECTOR2I& aStart,
550 const EDA_ANGLE& aArcAngle, int aCircleToSegmentsCount,
551 int aWidth, CONTAINER_2D_BASE* aContainer,
552 const BOARD_ITEM& aOwner )
553{
554 // Don't attempt to render degenerate shapes
555 if( aWidth == 0 )
556 return;
557
558 VECTOR2I arc_start, arc_end;
559 EDA_ANGLE arcAngle( aArcAngle );
560 EDA_ANGLE delta = ANGLE_360 / aCircleToSegmentsCount; // rotate angle
561
562 arc_end = arc_start = aStart;
563
564 if( arcAngle != ANGLE_360 )
565 RotatePoint( arc_end, aCentre, -arcAngle );
566
567 if( arcAngle < ANGLE_0 )
568 {
569 std::swap( arc_start, arc_end );
570 arcAngle = -arcAngle;
571 }
572
573 // Compute the ends of segments and creates poly
574 VECTOR2I curr_end = arc_start;
575 VECTOR2I curr_start = arc_start;
576
577 for( EDA_ANGLE ii = delta; ii < arcAngle; ii += delta )
578 {
579 curr_end = arc_start;
580 RotatePoint( curr_end, aCentre, -ii );
581
582 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( curr_start ), TO_SFVEC2F( curr_end ),
583 TO_3DU( aWidth ), aOwner );
584
585 curr_start = curr_end;
586 }
587
588 if( curr_end != arc_end )
589 {
590 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( curr_end ), TO_SFVEC2F( arc_end ),
591 TO_3DU( aWidth ), aOwner );
592 }
593}
594
595
596void BOARD_ADAPTER::addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aContainer,
597 const BOARD_ITEM* aOwner )
598{
599 // The full width of the lines to create
600 const float linewidth3DU = TO_3DU( aShape->GetWidth() );
601 PLOT_DASH_TYPE lineStyle = aShape->GetStroke().GetPlotStyle();
602
603 if( lineStyle <= PLOT_DASH_TYPE::FIRST_TYPE )
604 {
605 switch( aShape->GetShape() )
606 {
607 case SHAPE_T::CIRCLE:
608 {
609 SFVEC2F center3DU = TO_SFVEC2F( aShape->GetCenter() );
610 float innerR3DU = TO_3DU( aShape->GetRadius() ) - linewidth3DU / 2.0;
611 float outerR3DU = TO_3DU( aShape->GetRadius() ) + linewidth3DU / 2.0;
612
613 if( aShape->IsFilled() )
614 addFILLED_CIRCLE_2D( aContainer, center3DU, outerR3DU, *aOwner );
615 else
616 addRING_2D( aContainer, center3DU, innerR3DU, outerR3DU, *aOwner );
617
618 break;
619 }
620
621 case SHAPE_T::RECTANGLE:
622 if( aShape->IsFilled() )
623 {
624 SHAPE_POLY_SET polyList;
625
627 ERROR_INSIDE );
628
630
631 ConvertPolygonToTriangles( polyList, *aContainer, m_biuTo3Dunits, *aOwner );
632 }
633 else
634 {
635 std::vector<VECTOR2I> pts = aShape->GetRectCorners();
636
637 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( pts[0] ), TO_SFVEC2F( pts[1] ),
638 linewidth3DU, *aOwner );
639 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( pts[1] ), TO_SFVEC2F( pts[2] ),
640 linewidth3DU, *aOwner );
641 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( pts[2] ), TO_SFVEC2F( pts[3] ),
642 linewidth3DU, *aOwner );
643 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( pts[3] ), TO_SFVEC2F( pts[0] ),
644 linewidth3DU, *aOwner );
645 }
646 break;
647
648 case SHAPE_T::ARC:
649 {
650 unsigned int segCount = GetCircleSegmentCount( aShape->GetBoundingBox().GetSizeMax() );
651
652 createArcSegments( aShape->GetCenter(), aShape->GetStart(), aShape->GetArcAngle(),
653 segCount, aShape->GetWidth(), aContainer, *aOwner );
654 break;
655 }
656
657 case SHAPE_T::SEGMENT:
658 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( aShape->GetStart() ),
659 TO_SFVEC2F( aShape->GetEnd() ), linewidth3DU, *aOwner );
660 break;
661
662 case SHAPE_T::BEZIER:
663 case SHAPE_T::POLY:
664 {
665 SHAPE_POLY_SET polyList;
666
668 ERROR_INSIDE );
669
670 // Some polygons can be a bit complex (especially when coming from a
671 // picture ot a text converted to a polygon
672 // So call Simplify before calling ConvertPolygonToTriangles, just in case.
674
675 if( polyList.IsEmpty() ) // Just for caution
676 break;
677
678 ConvertPolygonToTriangles( polyList, *aContainer, m_biuTo3Dunits, *aOwner );
679 break;
680 }
681
682 default:
683 wxFAIL_MSG( wxT( "BOARD_ADAPTER::addShape no implementation for " )
684 + aShape->SHAPE_T_asString() );
685 break;
686 }
687 }
688 else
689 {
690 std::vector<SHAPE*> shapes = aShape->MakeEffectiveShapes( true );
691 SFVEC2F a3DU;
692 SFVEC2F b3DU;
693
694 const PCB_PLOT_PARAMS& plotParams = aShape->GetBoard()->GetPlotOptions();
695 KIGFX::PCB_RENDER_SETTINGS renderSettings;
696
697 renderSettings.SetDashLengthRatio( plotParams.GetDashedLineDashRatio() );
698 renderSettings.SetGapLengthRatio( plotParams.GetDashedLineGapRatio() );
699
700 for( SHAPE* shape : shapes )
701 {
702 STROKE_PARAMS::Stroke( shape, lineStyle, aShape->GetWidth(), &renderSettings,
703 [&]( const VECTOR2I& a, const VECTOR2I& b )
704 {
705 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( a ), TO_SFVEC2F( b ),
706 linewidth3DU, *aOwner );
707 } );
708 }
709
710 for( SHAPE* shape : shapes )
711 delete shape;
712 }
713}
714
715
717 PCB_LAYER_ID aLayerId )
718{
719 // This convert the poly in outline and holes
720 ConvertPolygonToTriangles( *aZone->GetFilledPolysList( aLayerId ), *aContainer, m_biuTo3Dunits,
721 *aZone );
722}
723
724
726 int aWidth )
727{
728 if( aPad->GetShape() == PAD_SHAPE::CIRCLE ) // Draw a ring
729 {
730 const SFVEC2F center3DU = TO_SFVEC2F( aPad->ShapePos() );
731 const int radius = aPad->GetSize().x / 2;
732 const float inner_radius3DU = TO_3DU( radius - aWidth / 2.0 );
733 const float outer_radius3DU = TO_3DU( radius + aWidth / 2.0 );
734
735 addRING_2D( aContainer, center3DU, inner_radius3DU, outer_radius3DU, *aPad );
736 }
737 else
738 {
739 // For other shapes, add outlines as thick segments in polygon buffer
740 const std::shared_ptr<SHAPE_POLY_SET>& corners = aPad->GetEffectivePolygon();
741 const SHAPE_LINE_CHAIN& path = corners->COutline( 0 );
742
743 for( int j = 0; j < path.PointCount(); j++ )
744 {
745 SFVEC2F start3DU = TO_SFVEC2F( path.CPoint( j ) );
746 SFVEC2F end3DU = TO_SFVEC2F( path.CPoint( j + 1 ) );
747
748 addROUND_SEGMENT_2D( aContainer, start3DU, end3DU, TO_3DU( aWidth ), *aPad );
749 }
750 }
751}
constexpr int ARC_HIGH_DEF
Definition: base_units.h:121
void addSolidAreasShapes(const ZONE *aZone, CONTAINER_2D_BASE *aDstContainer, PCB_LAYER_ID aLayerId)
void addFootprintShapes(const FOOTPRINT *aFootprint, CONTAINER_2D_BASE *aDstContainer, PCB_LAYER_ID aLayerId, const std::bitset< LAYER_3D_END > &aVisibilityFlags)
void createArcSegments(const VECTOR2I &aCentre, const VECTOR2I &aStart, const EDA_ANGLE &aArcAngle, int aCircleToSegmentsCount, int aWidth, CONTAINER_2D_BASE *aContainer, const BOARD_ITEM &aOwner)
void createPadWithMargin(const PAD *aPad, CONTAINER_2D_BASE *aDstContainer, PCB_LAYER_ID aLayer, const VECTOR2I &aMargin) const
void addPads(const FOOTPRINT *aFootprint, CONTAINER_2D_BASE *aDstContainer, PCB_LAYER_ID aLayerId, bool aSkipPlatedPads, bool aSkipNonPlatedPads)
const BOARD * GetBoard() const noexcept
void createPadWithHole(const PAD *aPad, CONTAINER_2D_BASE *aDstContainer, int aInflateValue)
void buildPadOutlineAsSegments(const PAD *aPad, CONTAINER_2D_BASE *aDstContainer, int aWidth)
void addShape(const PCB_SHAPE *aShape, CONTAINER_2D_BASE *aContainer, const BOARD_ITEM *aOwner)
void createTrack(const PCB_TRACK *aTrack, CONTAINER_2D_BASE *aDstContainer)
unsigned int GetCircleSegmentCount(float aDiameter3DU) const
void createViaWithMargin(const PCB_TRACK *aTrack, CONTAINER_2D_BASE *aDstContainer, int aMargin)
double m_biuTo3Dunits
Scale factor to convert board internal units to 3D units normalized between -1.0 and 1....
void addText(const EDA_TEXT *aText, CONTAINER_2D_BASE *aDstContainer, const BOARD_ITEM *aOwner)
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:77
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:204
virtual bool IsKnockout() const
Definition: board_item.h:274
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:238
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:45
const KIFONT::METRICS & GetFontMetrics() const
Definition: board_item.cpp:96
BOARD_ITEM_CONTAINER * GetParent() const
Definition: board_item.h:182
const PCB_PLOT_PARAMS & GetPlotOptions() const
Definition: board.h:644
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:731
int GetSizeMax() const
Definition: box2.h:201
void Add(OBJECT_2D *aObject)
Definition: container_2d.h:49
double AsDegrees() const
Definition: eda_angle.h:149
bool IsZero() const
Definition: eda_angle.h:169
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
EDA_ANGLE GetArcAngle() const
Definition: eda_shape.cpp:658
virtual std::vector< SHAPE * > MakeEffectiveShapes(bool aEdgeOnly=false) const
Make a set of SHAPE objects representing the EDA_SHAPE.
Definition: eda_shape.h:298
bool IsFilled() const
Definition: eda_shape.h:91
int GetRadius() const
Definition: eda_shape.cpp:588
SHAPE_T GetShape() const
Definition: eda_shape.h:117
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition: eda_shape.h:149
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition: eda_shape.h:124
std::vector< VECTOR2I > GetRectCorners() const
Definition: eda_shape.cpp:1105
wxString SHAPE_T_asString() const
Definition: eda_shape.cpp:87
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:80
bool IsItalic() const
Definition: eda_text.h:141
KIFONT::FONT * GetFont() const
Definition: eda_text.h:199
virtual EDA_ANGLE GetDrawRotation() const
Definition: eda_text.h:315
virtual VECTOR2I GetDrawPos() const
Definition: eda_text.h:316
const TEXT_ATTRIBUTES & GetAttributes() const
Definition: eda_text.h:183
int GetEffectiveTextPenWidth(int aDefaultPenWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
Definition: eda_text.cpp:305
bool IsBold() const
Definition: eda_text.h:144
virtual wxString GetShownText(bool aAllowExtraText, int aDepth=0) const
Return the string actually shown after processing of the base text.
Definition: eda_text.h:106
PADS & Pads()
Definition: footprint.h:188
void GetFields(std::vector< PCB_FIELD * > &aVector, bool aVisibleOnly)
Populate a std::vector with PCB_TEXTs.
Definition: footprint.cpp:318
DRAWINGS & GraphicalItems()
Definition: footprint.h:191
FONT is an abstract base class for both outline and stroke fonts.
Definition: font.h:131
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false)
Definition: font.cpp:146
void Draw(KIGFX::GAL *aGal, const wxString &aText, const VECTOR2I &aPosition, const VECTOR2I &aCursor, const TEXT_ATTRIBUTES &aAttributes, const METRICS &aFontMetrics) const
Draw a string.
Definition: font.cpp:251
PCB specific render settings.
Definition: pcb_painter.h:76
void SetGapLengthRatio(double aRatio)
void SetDashLengthRatio(double aRatio)
Definition: pad.h:58
VECTOR2I ShapePos() const
Definition: pad.cpp:756
PAD_SHAPE GetShape() const
Definition: pad.h:189
const std::shared_ptr< SHAPE_POLY_SET > & GetEffectivePolygon() const
Definition: pad.cpp:359
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING flashPTHPads=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
Definition: pad.cpp:368
bool HasHole() const override
Definition: pad.h:105
std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const override
Return a SHAPE_SEGMENT object representing the pad's hole.
Definition: pad.cpp:405
const VECTOR2I & GetSize() const
Definition: pad.h:243
bool IsDegenerated(int aThreshold=5) const
Definition: pcb_track.cpp:1174
double GetRadius() const
Definition: pcb_track.cpp:1143
EDA_ANGLE GetAngle() const
Definition: pcb_track.cpp:1150
virtual VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition: pcb_track.h:321
Abstract dimension API.
int GetLineThickness() const
const std::vector< std::shared_ptr< SHAPE > > & GetShapes() const
Parameters and options when plotting/printing a board.
double GetDashedLineGapRatio() const
double GetDashedLineDashRatio() const
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: pcb_shape.h:112
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition: pcb_shape.h:72
int GetWidth() const override
Definition: pcb_shape.cpp:149
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the shape to a closed polygon.
Definition: pcb_shape.cpp:568
STROKE_PARAMS GetStroke() const override
Definition: pcb_shape.h:82
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: pcb_shape.h:67
bool IsBorderEnabled() const
Disables the border, this is done by changing the stroke internally.
void TransformTextToPolySet(SHAPE_POLY_SET &aBuffer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc) const
Function TransformTextToPolySet Convert the text to a polygonSet describing the actual character stro...
Definition: pcb_text.cpp:460
void SetWidth(int aWidth)
Definition: pcb_track.h:106
int GetWidth() const
Definition: pcb_track.h:107
void SetEnd(const VECTOR2I &aEnd)
Definition: pcb_track.h:109
void SetStart(const VECTOR2I &aStart)
Definition: pcb_track.h:112
const VECTOR2I & GetStart() const
Definition: pcb_track.h:113
const VECTOR2I & GetEnd() const
Definition: pcb_track.h:110
Definition: seg.h:42
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
int GetWidth() const
Definition: shape_arc.h:157
const SHAPE_LINE_CHAIN ConvertToPolyline(double aAccuracy=DefaultAccuracyForPCB(), double *aEffectiveAccuracy=nullptr) const
Construct a SHAPE_LINE_CHAIN of segments from a given arc.
Definition: shape_arc.cpp:471
int GetRadius() const
Definition: shape_circle.h:108
const VECTOR2I GetCenter() const
Definition: shape_circle.h:113
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
int SegmentCount() const
Return the number of segments in this line chain.
SEG Segment(int aIndex)
Return a copy of the aIndex-th segment in the line chain.
Represent a set of closed polygons.
@ ROUND_ALL_CORNERS
All angles are rounded.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
void Inflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify=false)
Perform outline inflation/deflation.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
void Simplify(POLYGON_MODE aFastMode)
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections) For aFastMo...
int NewOutline()
Creates a new empty polygon in the set and returns its index.
const VECTOR2I & GetPosition() const
Definition: shape_rect.h:127
const VECTOR2I GetSize() const
Definition: shape_rect.h:135
const SEG & GetSeg() const
int GetWidth() const
Represent a simple polygon consisting of a zero-thickness closed chain of connected line segments.
Definition: shape_simple.h:42
const SHAPE_LINE_CHAIN & Vertices() const
Return the list of vertices defining this simple polygon.
Definition: shape_simple.h:124
An abstract shape on 2D plane.
Definition: shape.h:126
static void Stroke(const SHAPE *aShape, PLOT_DASH_TYPE aLineStyle, int aWidth, const KIGFX::RENDER_SETTINGS *aRenderSettings, std::function< void(const VECTOR2I &a, const VECTOR2I &b)> aStroker)
PLOT_DASH_TYPE GetPlotStyle() const
Definition: stroke_params.h:94
Handle a list of polygons defining a copper zone.
Definition: zone.h:72
const std::shared_ptr< SHAPE_POLY_SET > & GetFilledPolysList(PCB_LAYER_ID aLayer) const
Definition: zone.h:615
#define TO_3DU(x)
void addFILLED_CIRCLE_2D(CONTAINER_2D_BASE *aContainer, const SFVEC2F &aCenter, float aRadius, const BOARD_ITEM &aBoardItem)
#define TO_SFVEC2F(vec)
void addROUND_SEGMENT_2D(CONTAINER_2D_BASE *aContainer, const SFVEC2F &aStart, const SFVEC2F &aEnd, float aWidth, const BOARD_ITEM &aBoardItem)
void addRING_2D(CONTAINER_2D_BASE *aContainer, const SFVEC2F &aCenter, float aInnerRadius, float aOuterRadius, const BOARD_ITEM &aBoardItem)
static constexpr EDA_ANGLE & ANGLE_360
Definition: eda_angle.h:443
static constexpr EDA_ANGLE & ANGLE_0
Definition: eda_angle.h:437
a few functions useful in geometry calculations.
@ ERROR_INSIDE
int GetArcToSegmentCount(int aRadius, int aErrorMax, const EDA_ANGLE &aArcAngle)
static const wxChar * m_logTrace
Trace mask used to enable or disable debug output for this class.
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:847
@ LAYER_FP_REFERENCES
show footprints references (when texts are visible)
Definition: layer_ids.h:212
@ LAYER_FP_TEXT
Definition: layer_ids.h:199
@ LAYER_FP_VALUES
show footprints values (when texts are visible)
Definition: layer_ids.h:211
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ F_Paste
Definition: layer_ids.h:102
@ B_Mask
Definition: layer_ids.h:107
@ B_Cu
Definition: layer_ids.h:96
@ F_Mask
Definition: layer_ids.h:108
@ B_Paste
Definition: layer_ids.h:101
@ UNDEFINED_LAYER
Definition: layer_ids.h:61
@ F_Cu
Definition: layer_ids.h:65
This file contains miscellaneous commonly used macros and functions.
#define UNIMPLEMENTED_FOR(type)
Definition: macros.h:96
T clamp(T min, T value, T max)
Definition: kicad_algo.h:204
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:426
bool Is_segment_a_circle(const SFVEC2F &aStart, const SFVEC2F &aEnd)
Check if segment start and end is very close to each other.
@ SH_POLY_SET
set of polygons (with holes, etc.)
Definition: shape.h:52
@ SH_RECT
axis-aligned rectangle
Definition: shape.h:47
@ SH_CIRCLE
circle
Definition: shape.h:50
@ SH_SIMPLE
simple polygon
Definition: shape.h:51
@ SH_SEGMENT
line segment
Definition: shape.h:48
@ SH_ARC
circular arc
Definition: shape.h:54
static wxString SHAPE_TYPE_asString(SHAPE_TYPE a)
Definition: shape.h:59
std::vector< FAB_LAYER_COLOR > dummy
PLOT_DASH_TYPE
Dashed line types.
Definition: stroke_params.h:48
constexpr int delta
void ConvertPolygonToTriangles(const SHAPE_POLY_SET &aPolyList, CONTAINER_2D_BASE &aDstContainer, float aBiuTo3dUnitsScale, const BOARD_ITEM &aBoardItem)
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Definition: trigo.cpp:183
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:88
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition: typeinfo.h:102
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition: typeinfo.h:99
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:94
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition: typeinfo.h:100
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:92
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:91
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition: typeinfo.h:98
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:95
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:93
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
Definition: typeinfo.h:101
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:85
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588
glm::vec2 SFVEC2F
Definition: xv3d_types.h:42