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 The 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
31
36#include <board_adapter.h>
37#include <board.h>
38#include <footprint.h>
39#include <pad.h>
40#include <pcb_text.h>
41#include <pcb_textbox.h>
42#include <pcb_table.h>
43#include <pcb_track.h>
44#include <pcb_painter.h> // for PCB_RENDER_SETTINGS
45#include <zone.h>
47#include <trigo.h>
51#include <geometry/roundrect.h>
52#include <geometry/shape_rect.h>
55#include <utility>
56#include <vector>
57#include <wx/log.h>
58#include <macros.h>
59#include <callback_gal.h>
60#include <pcb_barcode.h>
61
62
63#define TO_3DU( x ) ( ( x ) * m_biuTo3Dunits )
64
65#define TO_SFVEC2F( vec ) SFVEC2F( TO_3DU( vec.x ), TO_3DU( -vec.y ) )
66
67
68void addFILLED_CIRCLE_2D( CONTAINER_2D_BASE* aContainer, const SFVEC2F& aCenter, float aRadius,
69 const BOARD_ITEM& aBoardItem )
70{
71 if( aRadius > 0.0f )
72 aContainer->Add( new FILLED_CIRCLE_2D( aCenter, aRadius, aBoardItem ) );
73}
74
75
76void addRING_2D( CONTAINER_2D_BASE* aContainer, const SFVEC2F& aCenter, float aInnerRadius,
77 float aOuterRadius, const BOARD_ITEM& aBoardItem )
78{
79 if( aOuterRadius > aInnerRadius && aInnerRadius > 0.0f )
80 aContainer->Add( new RING_2D( aCenter, aInnerRadius, aOuterRadius, aBoardItem ) );
81}
82
83
84void addROUND_SEGMENT_2D( CONTAINER_2D_BASE* aContainer, const SFVEC2F& aStart, const SFVEC2F& aEnd,
85 float aWidth, const BOARD_ITEM& aBoardItem )
86{
87 if( Is_segment_a_circle( aStart, aEnd ) )
88 {
89 // Cannot add segments that have the same start and end point
90 addFILLED_CIRCLE_2D( aContainer, aStart, aWidth / 2, aBoardItem );
91 return;
92 }
93
94 if( aWidth > 0.0f )
95 aContainer->Add( new ROUND_SEGMENT_2D( aStart, aEnd, aWidth, aBoardItem ) );
96}
97
98
99void BOARD_ADAPTER::addText( const EDA_TEXT* aText, CONTAINER_2D_BASE* aContainer,
100 const BOARD_ITEM* aOwner )
101{
103 TEXT_ATTRIBUTES attrs = aText->GetAttributes();
104 float penWidth_3DU = TO_3DU( aText->GetEffectiveTextPenWidth() );
105 KIFONT::FONT* font = aText->GetFont();
106 wxString shownText = aText->GetShownText( true );
107
108 if( !font )
109 font = KIFONT::FONT::GetFont( wxEmptyString, aText->IsBold(), aText->IsItalic() );
110
111 if( aOwner && aOwner->IsKnockout() )
112 {
113 SHAPE_POLY_SET finalPoly;
114
115 if( const PCB_TEXTBOX* pcbTextBox = dynamic_cast<const PCB_TEXTBOX*>( aOwner ) )
116 pcbTextBox->TransformTextToPolySet( finalPoly, 0, aOwner->GetMaxError(), ERROR_INSIDE );
117 else if( const PCB_TEXT* pcbText = dynamic_cast<const PCB_TEXT*>( aOwner ) )
118 pcbText->TransformTextToPolySet( finalPoly, 0, aOwner->GetMaxError(), ERROR_INSIDE );
119
120 // Do not call finalPoly.Fracture() here: ConvertPolygonToTriangles() call it
121 // if needed, and Fracture() called twice can create bad results and is useless
122 ConvertPolygonToTriangles( finalPoly, *aContainer, m_biuTo3Dunits, *aOwner );
123 }
124 else
125 {
126 CALLBACK_GAL callback_gal( empty_opts,
127 // Stroke callback
128 [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
129 {
130 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( aPt1 ), TO_SFVEC2F( aPt2 ),
131 penWidth_3DU, *aOwner );
132 },
133 // Triangulation callback
134 [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2, const VECTOR2I& aPt3 )
135 {
136 aContainer->Add( new TRIANGLE_2D( TO_SFVEC2F( aPt1 ), TO_SFVEC2F( aPt2 ),
137 TO_SFVEC2F( aPt3 ), *aOwner ) );
138 } );
139
140 attrs.m_Angle = aText->GetDrawRotation();
141
142 if( auto* cache = aText->GetRenderCache( font, shownText ) )
143 {
144 callback_gal.DrawGlyphs( *cache );
145 }
146 else
147 {
148 font->Draw( &callback_gal, shownText, aText->GetDrawPos(), attrs,
149 aOwner->GetFontMetrics() );
150 }
151 }
152}
153
154
155void BOARD_ADAPTER::addBarCode( const PCB_BARCODE* aBarCode, CONTAINER_2D_BASE* aDstContainer,
156 const BOARD_ITEM* aOwner )
157{
158 SHAPE_POLY_SET shape;
159 aBarCode->TransformShapeToPolySet( shape, aBarCode->GetLayer(), 0, 0, ERROR_INSIDE );
160 shape.Simplify();
161
162 ConvertPolygonToTriangles( shape, *aDstContainer, m_biuTo3Dunits, *aOwner );
163}
164
165
167 const BOARD_ITEM* aOwner )
168{
169 addText( aDimension, aContainer, aDimension );
170
171 const int linewidth = aDimension->GetLineThickness();
172
173 for( const std::shared_ptr<SHAPE>& shape : aDimension->GetShapes() )
174 {
175 switch( shape->Type() )
176 {
177 case SH_SEGMENT:
178 {
179 const SEG& seg = static_cast<const SHAPE_SEGMENT*>( shape.get() )->GetSeg();
180
181 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( seg.A ), TO_SFVEC2F( seg.B ),
182 TO_3DU( linewidth ), *aOwner );
183 break;
184 }
185
186 case SH_CIRCLE:
187 {
188 int radius = static_cast<const SHAPE_CIRCLE*>( shape.get() )->GetRadius();
189 float innerR3DU = TO_3DU( radius ) - TO_3DU( aDimension->GetLineThickness() ) / 2.0f;
190 float outerR3DU = TO_3DU( radius ) + TO_3DU( aDimension->GetLineThickness() ) / 2.0f;
191
192 addRING_2D( aContainer, TO_SFVEC2F( shape->Centre() ), innerR3DU, outerR3DU, *aOwner );
193
194 break;
195 }
196
197 default:
198 break;
199 }
200 }
201}
202
203
205 PCB_LAYER_ID aLayerId,
206 const std::bitset<LAYER_3D_END>& aFlags )
207{
209
210 for( PCB_FIELD* field : aFootprint->GetFields() )
211 {
212 if( !aFlags.test( LAYER_FP_TEXT ) )
213 continue;
214
215 wxCHECK2( field, continue );
216
217 if( field->IsReference() && !aFlags.test( LAYER_FP_REFERENCES ) )
218 continue;
219
220 if( field->IsValue() && !aFlags.test( LAYER_FP_VALUES ) )
221 continue;
222
223 if( field->GetLayer() == aLayerId && field->IsVisible() )
224 addText( field, aContainer, field );
225 }
226
227 for( BOARD_ITEM* item : aFootprint->GraphicalItems() )
228 {
229 switch( item->Type() )
230 {
231 case PCB_TEXT_T:
232 {
233 PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
234
235 if( !aFlags.test( LAYER_FP_TEXT ) )
236 continue;
237
238 if( text->GetText() == wxT( "${REFERENCE}" ) && !aFlags.test( LAYER_FP_REFERENCES ) )
239 continue;
240
241 if( text->GetText() == wxT( "${VALUE}" ) && !aFlags.test( LAYER_FP_VALUES ) )
242 continue;
243
244 if( text->GetLayer() == aLayerId )
245 addText( text, aContainer, text );
246
247 break;
248 }
249
250 case PCB_TEXTBOX_T:
251 {
252 PCB_TEXTBOX* textbox = static_cast<PCB_TEXTBOX*>( item );
253
254 if( textbox->GetLayer() == aLayerId )
255 addShape( textbox, aContainer, aFootprint );
256
257 break;
258 }
259
260 case PCB_TABLE_T:
261 {
262 PCB_TABLE* table = static_cast<PCB_TABLE*>( item );
263
264 if( table->GetLayer() == aLayerId )
265 addTable( table, aContainer, aFootprint );
266
267 break;
268 }
269
271 case PCB_DIM_CENTER_T:
273 case PCB_DIM_RADIAL_T:
274 case PCB_DIM_LEADER_T:
275 {
276 PCB_DIMENSION_BASE* dimension = static_cast<PCB_DIMENSION_BASE*>( item );
277
278 if( dimension->GetLayer() == aLayerId )
279 addShape( dimension, aContainer, aFootprint );
280
281 break;
282 }
283
284 case PCB_SHAPE_T:
285 {
286 PCB_SHAPE* shape = static_cast<PCB_SHAPE*>( item );
287
288 if( shape->IsOnLayer( aLayerId ) )
289 addShape( shape, aContainer, aFootprint, aLayerId );
290
291 break;
292 }
293
294 case PCB_BARCODE_T:
295 {
296 PCB_BARCODE* barcode = static_cast<PCB_BARCODE*>( item );
297
298 if( barcode->GetLayer() == aLayerId )
299 addBarCode( barcode, aContainer, aFootprint );
300
301 break;
302 }
303
304 default:
305 break;
306 }
307 }
308}
309
310
312 PCB_LAYER_ID aLayer, int aMargin )
313{
314 SFVEC2F start3DU = TO_SFVEC2F( aTrack->GetStart() );
315 SFVEC2F end3DU = TO_SFVEC2F( aTrack->GetEnd() );
316
317 switch( aTrack->Type() )
318 {
319 case PCB_VIA_T:
320 {
321 const PCB_VIA* via = static_cast<const PCB_VIA*>( aTrack );
322 float width3DU = TO_3DU( via->GetWidth( aLayer ) + aMargin * 2 );
323
324 addFILLED_CIRCLE_2D( aDstContainer, start3DU, width3DU / 2.0, *aTrack );
325 break;
326 }
327
328 case PCB_ARC_T:
329 {
330 const PCB_ARC* arc = static_cast<const PCB_ARC*>( aTrack );
331
332 if( arc->IsDegenerated() )
333 {
334 // Draw this very small arc like a track segment (a PCB_TRACE_T)
335 PCB_TRACK track( arc->GetParent() );
336 track.SetStart( arc->GetStart() );
337 track.SetEnd( arc->GetEnd() );
338 track.SetWidth( arc->GetWidth() );
339 track.SetLayer( arc->GetLayer() );
340
341 createTrackWithMargin( &track, aDstContainer, aLayer, aMargin );
342 return;
343 }
344
345 VECTOR2I center( arc->GetCenter() );
346 EDA_ANGLE arc_angle = arc->GetAngle();
347 double radius = arc->GetRadius();
348 int arcsegcount = GetArcToSegmentCount( KiROUND( radius ), arc->GetMaxError(), arc_angle );
349 int circlesegcount;
350
351 // Avoid arcs that cannot be drawn
352 if( radius < std::numeric_limits<double>::min() || arc_angle.IsZero() )
353 break;
354
355 // We need a circle to segment count. However, the arc angle can be small, and the
356 // radius very big. so we calculate a reasonable value for circlesegcount.
357 if( arcsegcount <= 1 ) // The arc will be approximated by a segment
358 {
359 circlesegcount = 1;
360 }
361 else
362 {
363 circlesegcount = KiROUND( arcsegcount * 360.0 / std::abs( arc_angle.AsDegrees() ) );
364 circlesegcount = std::clamp( circlesegcount, 1, 128 );
365 }
366
367 createArcSegments( center, arc->GetStart(), arc_angle, circlesegcount,
368 arc->GetWidth() + aMargin * 2, aDstContainer, *arc );
369 break;
370 }
371
372 case PCB_TRACE_T: // Track is a usual straight segment
373 {
374 float width3DU = TO_3DU( aTrack->GetWidth() + aMargin * 2 );
375 addROUND_SEGMENT_2D( aDstContainer, start3DU, end3DU, width3DU, *aTrack );
376 break;
377 }
378
379 default:
380 break;
381 }
382}
383
384
386 PCB_LAYER_ID aLayer, const VECTOR2I& aMargin ) const
387{
388 SHAPE_POLY_SET poly;
389 VECTOR2I clearance = aMargin;
390
391 // Our shape-based builder can't handle negative or differing x:y clearance values (the
392 // former are common for solder paste while the later get generated when a relative paste
393 // margin is used with an oblong pad). So we apply this huge hack and fake a larger pad to
394 // run the general-purpose polygon builder on.
395 // Of course being a hack it falls down when dealing with custom shape pads (where the size
396 // is only the size of the anchor), so for those we punt and just use aMargin.x.
397
398 if( ( clearance.x < 0 || clearance.x != clearance.y ) && aPad->GetShape( aLayer ) != PAD_SHAPE::CUSTOM )
399 {
400 VECTOR2I dummySize = VECTOR2I( aPad->GetSize( aLayer ) ) + clearance + clearance;
401
402 if( dummySize.x <= 0 || dummySize.y <= 0 )
403 return;
404
405 PAD dummy( *aPad );
406 dummy.SetSize( aLayer, VECTOR2I( dummySize.x, dummySize.y ) );
407 dummy.TransformShapeToPolygon( poly, aLayer, 0, aPad->GetMaxError(), ERROR_INSIDE );
408 clearance = { 0, 0 };
409 }
410 else if( aPad->GetShape( aLayer ) == PAD_SHAPE::CUSTOM )
411 {
412 // A custom pad can have many complex subshape items. To avoid issues, use its
413 // final polygon shape, not its basic shape set. One cannot apply the clearance
414 // to each subshape: it does no work
415 aPad->TransformShapeToPolygon( poly, aLayer, 0, aPad->GetMaxError() );
416 }
417 else
418 {
419 auto padShapes = std::static_pointer_cast<SHAPE_COMPOUND>( aPad->GetEffectiveShape( aLayer ) );
420
421 for( const SHAPE* shape : padShapes->Shapes() )
422 {
423 switch( shape->Type() )
424 {
425 case SH_SEGMENT:
426 {
427 const SHAPE_SEGMENT* seg = static_cast<const SHAPE_SEGMENT*>( shape );
428
429 addROUND_SEGMENT_2D( aContainer,
430 TO_SFVEC2F( seg->GetSeg().A ),
431 TO_SFVEC2F( seg->GetSeg().B ),
432 TO_3DU( seg->GetWidth() + clearance.x * 2 ),
433 *aPad );
434 break;
435 }
436
437 case SH_CIRCLE:
438 {
439 const SHAPE_CIRCLE* circle = static_cast<const SHAPE_CIRCLE*>( shape );
440
441 addFILLED_CIRCLE_2D( aContainer,
442 TO_SFVEC2F( circle->GetCenter() ),
443 TO_3DU( circle->GetRadius() + clearance.x ),
444 *aPad );
445 break;
446 }
447
448 case SH_RECT:
449 {
450 const SHAPE_RECT* rect = static_cast<const SHAPE_RECT*>( shape );
451
452 poly.NewOutline();
453 poly.Append( rect->GetPosition() );
454 poly.Append( rect->GetPosition().x + rect->GetSize().x, rect->GetPosition().y );
455 poly.Append( rect->GetPosition() + rect->GetSize() );
456 poly.Append( rect->GetPosition().x, rect->GetPosition().y + rect->GetSize().y );
457 break;
458 }
459
460 case SH_SIMPLE:
461 poly.AddOutline( static_cast<const SHAPE_SIMPLE*>( shape )->Vertices() );
462 break;
463
464 case SH_POLY_SET:
465 poly.Append( *static_cast<const SHAPE_POLY_SET*>( shape ) );
466 break;
467
468 case SH_ARC:
469 {
470 const SHAPE_ARC* arc = static_cast<const SHAPE_ARC*>( shape );
472
473 for( int i = 0; i < l.SegmentCount(); i++ )
474 {
475 SHAPE_SEGMENT seg( l.Segment( i ).A, l.Segment( i ).B, arc->GetWidth() );
476
477 addROUND_SEGMENT_2D( aContainer,
478 TO_SFVEC2F( seg.GetSeg().A ),
479 TO_SFVEC2F( seg.GetSeg().B ),
480 TO_3DU( arc->GetWidth() + clearance.x * 2 ),
481 *aPad );
482 }
483
484 break;
485 }
486
487 case SH_ELLIPSE:
488 {
489 const SHAPE_ELLIPSE* ellipse = static_cast<const SHAPE_ELLIPSE*>( shape );
490 SHAPE_LINE_CHAIN l = ellipse->ConvertToPolyline( aPad->GetMaxError() );
491 const int width = ellipse->GetWidth();
492
493 for( int i = 0; i < l.SegmentCount(); i++ )
494 {
495 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( l.Segment( i ).A ), TO_SFVEC2F( l.Segment( i ).B ),
496 TO_3DU( width + clearance.x * 2 ), *aPad );
497 }
498
499 break;
500 }
501
502 default:
503 UNIMPLEMENTED_FOR( SHAPE_TYPE_asString( shape->Type() ) );
504 break;
505 }
506 }
507 }
508
509 if( !poly.IsEmpty() )
510 {
511 if( clearance.x )
513
514 // Add the PAD polygon
515 ConvertPolygonToTriangles( poly, *aContainer, m_biuTo3Dunits, *aPad );
516 }
517}
518
519
521 int aInflateValue )
522{
523 if( !aPad->HasHole() )
524 {
525 wxLogTrace( m_logTrace, wxT( "BOARD_ADAPTER::createPadHole pad has no hole" ) );
526 return;
527 }
528
529 std::shared_ptr<SHAPE_SEGMENT> slot = aPad->GetEffectiveHoleShape();
530
531 addROUND_SEGMENT_2D( aDstContainer,
532 TO_SFVEC2F( slot->GetSeg().A ),
533 TO_SFVEC2F( slot->GetSeg().B ),
534 TO_3DU( slot->GetWidth() + aInflateValue * 2 ),
535 *aPad );
536}
537
538
539void BOARD_ADAPTER::addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aContainer,
540 PCB_LAYER_ID aLayerId )
541{
542 for( PAD* pad : aFootprint->Pads() )
543 {
544 if( !pad->IsOnLayer( aLayerId ) )
545 continue;
546
547 if( IsCopperLayer( aLayerId ) )
548 {
549 // Skip pad annulus when there isn't one (note: this is more discerning than
550 // pad->IsOnLayer(), which doesn't check for NPTH pads with holes that consume
551 // the entire pad).
552 if( !pad->IsOnCopperLayer() )
553 continue;
554
555 // Skip pad annulus when not connected on this layer (if removing is enabled)
556 if( !pad->FlashLayer( aLayerId ) )
557 continue;
558 }
559
560 VECTOR2I margin( 0, 0 );
561
562 switch( aLayerId )
563 {
564 case F_Mask:
565 case B_Mask:
566 margin.x += pad->GetSolderMaskExpansion( aLayerId );
567 margin.y += pad->GetSolderMaskExpansion( aLayerId );
568 break;
569
570 case F_Paste:
571 case B_Paste:
572 margin += pad->GetSolderPasteMargin( aLayerId );
573 break;
574
575 default:
576 break;
577 }
578
579 createPadWithMargin( pad, aContainer, aLayerId, margin );
580 }
581}
582
583
584// based on TransformArcToPolygon function from
585// common/convert_basic_shapes_to_polygon.cpp
586void BOARD_ADAPTER::createArcSegments( const VECTOR2I& aCentre, const VECTOR2I& aStart,
587 const EDA_ANGLE& aArcAngle, int aCircleToSegmentsCount,
588 int aWidth, CONTAINER_2D_BASE* aContainer,
589 const BOARD_ITEM& aOwner )
590{
591 // Don't attempt to render degenerate shapes
592 if( aWidth == 0 )
593 return;
594
595 VECTOR2I arc_start, arc_end;
596 EDA_ANGLE arcAngle( aArcAngle );
597 EDA_ANGLE delta = ANGLE_360 / aCircleToSegmentsCount; // rotate angle
598
599 arc_end = arc_start = aStart;
600
601 if( arcAngle != ANGLE_360 )
602 RotatePoint( arc_end, aCentre, -arcAngle );
603
604 if( arcAngle < ANGLE_0 )
605 {
606 std::swap( arc_start, arc_end );
607 arcAngle = -arcAngle;
608 }
609
610 // Compute the ends of segments and creates poly
611 VECTOR2I curr_end = arc_start;
612 VECTOR2I curr_start = arc_start;
613
614 for( EDA_ANGLE ii = delta; ii < arcAngle; ii += delta )
615 {
616 curr_end = arc_start;
617 RotatePoint( curr_end, aCentre, -ii );
618
619 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( curr_start ), TO_SFVEC2F( curr_end ),
620 TO_3DU( aWidth ), aOwner );
621
622 curr_start = curr_end;
623 }
624
625 if( curr_end != arc_end )
626 {
627 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( curr_end ), TO_SFVEC2F( arc_end ),
628 TO_3DU( aWidth ), aOwner );
629 }
630}
631
632
633void BOARD_ADAPTER::addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aContainer,
634 const BOARD_ITEM* aOwner, PCB_LAYER_ID aLayer )
635{
636 LINE_STYLE lineStyle = aShape->GetStroke().GetLineStyle();
637 int linewidth = aShape->GetWidth();
638 int margin = 0;
639 bool isSolidFill = aShape->IsSolidFill();
640 bool isHatchedFill = aShape->IsHatchedFill();
641
642 if( IsSolderMaskLayer( aLayer )
643 && aShape->HasSolderMask()
644 && IsExternalCopperLayer( aShape->GetLayer() ) )
645 {
646 margin = aShape->GetSolderMaskExpansion();
647 linewidth += margin * 2;
648 lineStyle = LINE_STYLE::SOLID;
649
650 if( isHatchedFill )
651 {
652 isSolidFill = true;
653 isHatchedFill = false;
654 }
655 }
656
657 float linewidth3DU = TO_3DU( linewidth );
658
659 if( lineStyle <= LINE_STYLE::FIRST_TYPE || isSolidFill )
660 {
661 switch( aShape->GetShape() )
662 {
663 case SHAPE_T::CIRCLE:
664 {
665 SFVEC2F center3DU = TO_SFVEC2F( aShape->GetCenter() );
666 float innerR3DU = TO_3DU( aShape->GetRadius() ) - linewidth3DU / 2.0;
667 float outerR3DU = TO_3DU( aShape->GetRadius() ) + linewidth3DU / 2.0;
668
669 if( isSolidFill || innerR3DU <= 0.0 )
670 {
671 // For a filled circle with a line style not a simple line, ignore line width
672 // the outline will be drawn later
673 if( lineStyle > LINE_STYLE::FIRST_TYPE )
674 addFILLED_CIRCLE_2D( aContainer, center3DU, TO_3DU( aShape->GetRadius() ), *aOwner );
675 else
676 addFILLED_CIRCLE_2D( aContainer, center3DU, outerR3DU, *aOwner );
677 }
678 else
679 addRING_2D( aContainer, center3DU, innerR3DU, outerR3DU, *aOwner );
680
681 break;
682 }
683
685 if( isSolidFill )
686 {
687 SHAPE_POLY_SET polyList;
688
689 // For a filled rect with a line style not a simple line, ignore line width
690 // the outline will be drawn later
691 bool ignoreLineWidth = lineStyle > LINE_STYLE::FIRST_TYPE;
692
693 aShape->TransformShapeToPolygon( polyList, UNDEFINED_LAYER, 0, aShape->GetMaxError(),
694 ERROR_INSIDE, ignoreLineWidth );
695
696 polyList.Simplify();
697
698 if( margin != 0 )
699 {
700 polyList.Inflate( margin, CORNER_STRATEGY::ROUND_ALL_CORNERS, aShape->GetMaxError() );
701 }
702
703 ConvertPolygonToTriangles( polyList, *aContainer, m_biuTo3Dunits, *aOwner );
704 }
705 else
706 {
707 if( aShape->GetCornerRadius() > 0 )
708 {
709 ROUNDRECT rr( SHAPE_RECT( aShape->GetPosition(),
710 aShape->GetRectangleWidth(),
711 aShape->GetRectangleHeight() ),
712 aShape->GetCornerRadius() );
713 SHAPE_POLY_SET poly;
714 rr.TransformToPolygon( poly, aShape->GetMaxError() );
715 SHAPE_LINE_CHAIN& r_outline = poly.Outline( 0 );
716 r_outline.SetClosed( true );
717
718 for( int ii = 0; ii < r_outline.PointCount(); ii++ )
719 {
720 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( r_outline.CPoint( ii ) ),
721 TO_SFVEC2F( r_outline.CPoint( ii+1 ) ),
722 linewidth3DU, *aOwner );
723 }
724
725 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( r_outline.CLastPoint() ),
726 TO_SFVEC2F( r_outline.CPoint( 0 ) ), linewidth3DU, *aOwner );
727 }
728 else
729 {
730 std::vector<VECTOR2I> pts = aShape->GetRectCorners();
731
732 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( pts[0] ), TO_SFVEC2F( pts[1] ),
733 linewidth3DU, *aOwner );
734 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( pts[1] ), TO_SFVEC2F( pts[2] ),
735 linewidth3DU, *aOwner );
736 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( pts[2] ), TO_SFVEC2F( pts[3] ),
737 linewidth3DU, *aOwner );
738 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( pts[3] ), TO_SFVEC2F( pts[0] ),
739 linewidth3DU, *aOwner );
740 }
741 }
742 break;
743
744 case SHAPE_T::ARC:
745 {
746 unsigned int segCount = GetCircleSegmentCount( aShape->GetBoundingBox().GetSizeMax() );
747
748 createArcSegments( aShape->GetCenter(), aShape->GetStart(), aShape->GetArcAngle(),
749 segCount, linewidth, aContainer, *aOwner );
750 break;
751 }
752
753 case SHAPE_T::SEGMENT:
754 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( aShape->GetStart() ),
755 TO_SFVEC2F( aShape->GetEnd() ), linewidth3DU, *aOwner );
756 break;
757
758 case SHAPE_T::BEZIER:
759 {
760 SHAPE_POLY_SET polyList;
761
762 aShape->TransformShapeToPolygon( polyList, UNDEFINED_LAYER, 0, aShape->GetMaxError(),
763 ERROR_INSIDE );
764
765 // Some polygons can be a bit complex (especially when coming from a
766 // picture of a text converted to a polygon
767 // So call Simplify before calling ConvertPolygonToTriangles, just in case.
768 polyList.Simplify();
769
770 if( polyList.IsEmpty() ) // Just for caution
771 break;
772
773 if( margin != 0 )
774 {
777
778 polyList.Inflate( margin, cornerStr, aShape->GetMaxError() );
779 }
780
781 ConvertPolygonToTriangles( polyList, *aContainer, m_biuTo3Dunits, *aOwner );
782 break;
783 }
784
785 case SHAPE_T::POLY:
786 {
787 if( isSolidFill )
788 {
789 SHAPE_POLY_SET polyList;
790
791 // For a filled poly with a line style not a simple line, ignore line width
792 // the outline will be drawn later
793 bool ignoreLineWidth = lineStyle > LINE_STYLE::FIRST_TYPE;
794
795 aShape->TransformShapeToPolygon( polyList, UNDEFINED_LAYER, 0, aShape->GetMaxError(),
796 ERROR_INSIDE, ignoreLineWidth );
797
798 // Some polygons can be a bit complex (especially when coming from a
799 // picture of a text converted to a polygon
800 // So call Simplify before calling ConvertPolygonToTriangles, just in case.
801 polyList.Simplify();
802
803 if( polyList.IsEmpty() ) // Just for caution
804 break;
805
806 if( margin != 0 )
807 {
810
811 polyList.Inflate( margin, cornerStr, aShape->GetMaxError() );
812 }
813
814 ConvertPolygonToTriangles( polyList, *aContainer, m_biuTo3Dunits, *aOwner );
815 }
816 else
817 {
818 std::vector<VECTOR2I> pts = aShape->GetCorners();
819
820 for( int i = 0; i < pts.size() - 1; i++ )
821 {
822 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( pts[i] ), TO_SFVEC2F( pts[i + 1] ), linewidth3DU,
823 *aOwner );
824 }
825
826 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( pts[pts.size() - 1] ), TO_SFVEC2F( pts[0] ), linewidth3DU,
827 *aOwner );
828 }
829 break;
830 }
831
832 case SHAPE_T::ELLIPSE:
834 {
835 if( isSolidFill )
836 {
837 SHAPE_POLY_SET polyList;
838
839 aShape->TransformShapeToPolygon( polyList, UNDEFINED_LAYER, 0, aShape->GetMaxError(), ERROR_INSIDE );
840
841 polyList.Simplify();
842
843 if( polyList.IsEmpty() )
844 break;
845
846 if( margin != 0 )
847 {
848 CORNER_STRATEGY cornerStr =
850 polyList.Inflate( margin, cornerStr, aShape->GetMaxError() );
851 }
852
853 ConvertPolygonToTriangles( polyList, *aContainer, m_biuTo3Dunits, *aOwner );
854 }
855 else
856 {
857 // Hatched fill: draw only the elliptical outline so the hatch polygons
858 // added below remain visible.
859 std::vector<SHAPE*> shapes = aShape->MakeEffectiveShapes( true );
860
861 for( SHAPE* shape : shapes )
862 {
863 if( shape->Type() == SH_SEGMENT )
864 {
865 const SEG& seg = static_cast<const SHAPE_SEGMENT*>( shape )->GetSeg();
866 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( seg.A ), TO_SFVEC2F( seg.B ), linewidth3DU,
867 *aOwner );
868 }
869 }
870
871 for( SHAPE* shape : shapes )
872 delete shape;
873 }
874 break;
875 }
876
877 default:
878 wxFAIL_MSG( wxT( "BOARD_ADAPTER::addShape no implementation for " )
879 + aShape->SHAPE_T_asString() );
880 break;
881 }
882 }
883
884 if( lineStyle > LINE_STYLE::FIRST_TYPE )
885 {
886 std::vector<SHAPE*> shapes = aShape->MakeEffectiveShapes( true );
887 SFVEC2F a3DU;
888 SFVEC2F b3DU;
889
890 const PCB_PLOT_PARAMS& plotParams = aShape->GetBoard()->GetPlotOptions();
891 KIGFX::PCB_RENDER_SETTINGS renderSettings;
892
893 renderSettings.SetDashLengthRatio( plotParams.GetDashedLineDashRatio() );
894 renderSettings.SetGapLengthRatio( plotParams.GetDashedLineGapRatio() );
895
896 for( SHAPE* shape : shapes )
897 {
898 STROKE_PARAMS::Stroke( shape, lineStyle, aShape->GetWidth(), &renderSettings,
899 [&]( const VECTOR2I& a, const VECTOR2I& b )
900 {
901 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( a ), TO_SFVEC2F( b ),
902 linewidth3DU, *aOwner );
903 } );
904 }
905
906 for( SHAPE* shape : shapes )
907 delete shape;
908 }
909
910 if( isHatchedFill )
911 ConvertPolygonToTriangles( aShape->GetHatching(), *aContainer, m_biuTo3Dunits, *aOwner );
912}
913
914
915void BOARD_ADAPTER::addShape( const PCB_TEXTBOX* aTextBox, CONTAINER_2D_BASE* aContainer,
916 const BOARD_ITEM* aOwner )
917{
918 addText( aTextBox, aContainer, aOwner );
919
920 if( !aTextBox->IsBorderEnabled() )
921 return;
922
923 // We cannot use PCB_TEXTBOX::TransformShapeToPolygon because it convert the textbox
924 // as filled polygon even if there's no background colour.
925 // So for polygon, we use PCB_SHAPE::TransformShapeToPolygon
926
927 if( aTextBox->GetShape() == SHAPE_T::RECTANGLE )
928 {
929 addShape( static_cast<const PCB_SHAPE*>( aTextBox ), aContainer, aOwner, UNDEFINED_LAYER );
930 }
931 else
932 {
933 SHAPE_POLY_SET polyList;
934
935 aTextBox->PCB_SHAPE::TransformShapeToPolygon( polyList, UNDEFINED_LAYER, 0, aTextBox->GetMaxError(),
936 ERROR_INSIDE );
937
938 ConvertPolygonToTriangles( polyList, *aContainer, m_biuTo3Dunits, *aOwner );
939 }
940}
941
942
943void BOARD_ADAPTER::addTable( const PCB_TABLE* aTable, CONTAINER_2D_BASE* aContainer,
944 const BOARD_ITEM* aOwner )
945{
946 aTable->DrawBorders(
947 [&]( const VECTOR2I& ptA, const VECTOR2I& ptB, const STROKE_PARAMS& stroke )
948 {
949 addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( ptA ), TO_SFVEC2F( ptB ),
950 TO_3DU( stroke.GetWidth() ), *aOwner );
951 } );
952
953 for( PCB_TABLECELL* cell : aTable->GetCells() )
954 {
955 if( cell->GetColSpan() > 0 && cell->GetRowSpan() > 0 )
956 addText( cell, aContainer, aOwner );
957 }
958}
959
960
962 PCB_LAYER_ID aLayerId )
963{
964 // This convert the poly in outline and holes
965 ConvertPolygonToTriangles( *aZone->GetFilledPolysList( aLayerId ), *aContainer, m_biuTo3Dunits, *aZone );
966}
967
968
970 CONTAINER_2D_BASE* aContainer, int aWidth )
971{
972 if( aPad->GetShape( aLayer ) == PAD_SHAPE::CIRCLE ) // Draw a ring
973 {
974 const SFVEC2F center3DU = TO_SFVEC2F( aPad->ShapePos( aLayer ) );
975 const int radius = aPad->GetSize( aLayer ).x / 2;
976 const float inner_radius3DU = TO_3DU( radius - aWidth / 2.0 );
977 const float outer_radius3DU = TO_3DU( radius + aWidth / 2.0 );
978
979 addRING_2D( aContainer, center3DU, inner_radius3DU, outer_radius3DU, *aPad );
980 }
981 else
982 {
983 // For other shapes, add outlines as thick segments in polygon buffer
984 const std::shared_ptr<SHAPE_POLY_SET>& corners = aPad->GetEffectivePolygon( aLayer, ERROR_INSIDE );
985 const SHAPE_LINE_CHAIN& path = corners->COutline( 0 );
986
987 for( int j = 0; j < path.PointCount(); j++ )
988 {
989 SFVEC2F start3DU = TO_SFVEC2F( path.CPoint( j ) );
990 SFVEC2F end3DU = TO_SFVEC2F( path.CPoint( j + 1 ) );
991
992 addROUND_SEGMENT_2D( aContainer, start3DU, end3DU, TO_3DU( aWidth ), *aPad );
993 }
994 }
995}
@ ERROR_INSIDE
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
void addPads(const FOOTPRINT *aFootprint, CONTAINER_2D_BASE *aDstContainer, PCB_LAYER_ID aLayerId)
void createTrackWithMargin(const PCB_TRACK *aTrack, CONTAINER_2D_BASE *aDstContainer, PCB_LAYER_ID aLayer, int aMargin=0)
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 addBarCode(const PCB_BARCODE *aBarCode, CONTAINER_2D_BASE *aDstContainer, const BOARD_ITEM *aOwner)
void buildPadOutlineAsSegments(const PAD *aPad, PCB_LAYER_ID aLayer, CONTAINER_2D_BASE *aDstContainer, int aWidth)
void addTable(const PCB_TABLE *aTable, CONTAINER_2D_BASE *aContainer, const BOARD_ITEM *aOwner)
void createPadHoleShape(const PAD *aPad, CONTAINER_2D_BASE *aDstContainer, int aInflateValue)
unsigned int GetCircleSegmentCount(float aDiameter3DU) const
void addShape(const PCB_SHAPE *aShape, CONTAINER_2D_BASE *aContainer, const BOARD_ITEM *aOwner, PCB_LAYER_ID aLayer)
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)
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition board_item.h:268
virtual bool IsKnockout() const
Definition board_item.h:355
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
virtual void TransformShapeToPolySet(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, KIGFX::RENDER_SETTINGS *aRenderSettings=nullptr) const
Convert the item shape to a polyset.
Definition board_item.h:461
const KIFONT::METRICS & GetFontMetrics() const
BOARD_ITEM_CONTAINER * GetParent() const
Definition board_item.h:234
int GetMaxError() const
const PCB_PLOT_PARAMS & GetPlotOptions() const
Definition board.h:810
constexpr int GetSizeMax() const
Definition box2.h:235
void Add(OBJECT_2D *aObject)
double AsDegrees() const
Definition eda_angle.h:116
bool IsZero() const
Definition eda_angle.h:136
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:112
EDA_ANGLE GetArcAngle() const
const SHAPE_POLY_SET & GetHatching() const
int GetRectangleWidth() const
virtual std::vector< SHAPE * > MakeEffectiveShapes(bool aEdgeOnly=false) const
Make a set of SHAPE objects representing the EDA_SHAPE.
Definition eda_shape.h:457
int GetRadius() const
SHAPE_T GetShape() const
Definition eda_shape.h:189
bool IsHatchedFill() const
Definition eda_shape.h:144
bool IsSolidFill() const
Definition eda_shape.h:137
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:236
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:194
std::vector< VECTOR2I > GetRectCorners() const
wxString SHAPE_T_asString() const
int GetRectangleHeight() const
int GetCornerRadius() const
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:93
bool IsItalic() const
Definition eda_text.h:194
KIFONT::FONT * GetFont() const
Definition eda_text.h:272
std::vector< std::unique_ptr< KIFONT::GLYPH > > * GetRenderCache(const KIFONT::FONT *aFont, const wxString &forResolvedText, const VECTOR2I &aOffset={ 0, 0 }) const
Definition eda_text.cpp:702
virtual EDA_ANGLE GetDrawRotation() const
Definition eda_text.h:404
virtual VECTOR2I GetDrawPos() const
Definition eda_text.h:405
const TEXT_ATTRIBUTES & GetAttributes() const
Definition eda_text.h:256
int GetEffectiveTextPenWidth(int aDefaultPenWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
Definition eda_text.cpp:465
bool IsBold() const
Definition eda_text.h:209
virtual wxString GetShownText(bool aAllowExtraText, int aDepth=0) const
Return the string actually shown after processing of the base text.
Definition eda_text.h:125
std::deque< PAD * > & Pads()
Definition footprint.h:377
void GetFields(std::vector< PCB_FIELD * > &aVector, bool aVisibleOnly) const
Populate a std::vector with PCB_TEXTs.
DRAWINGS & GraphicalItems()
Definition footprint.h:380
FONT is an abstract base class for both outline and stroke fonts.
Definition font.h:98
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false, const std::vector< wxString > *aEmbeddedFiles=nullptr, bool aForDrawingSheet=false)
Definition font.cpp:147
void Draw(KIGFX::GAL *aGal, const wxString &aText, const VECTOR2I &aPosition, const VECTOR2I &aCursor, const TEXT_ATTRIBUTES &aAttributes, const METRICS &aFontMetrics, std::optional< VECTOR2I > aMousePos=std::nullopt, wxString *aActiveUrl=nullptr) const
Draw a string.
Definition font.cpp:250
PCB specific render settings.
Definition pcb_painter.h:82
void SetGapLengthRatio(double aRatio)
void SetDashLengthRatio(double aRatio)
Definition pad.h:55
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer, FLASHING flashPTHPads=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
Definition pad.cpp:962
PAD_SHAPE GetShape(PCB_LAYER_ID aLayer) const
Definition pad.h:196
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc=ERROR_INSIDE, bool ignoreLineWidth=false) const override
Convert the pad shape to a closed polygon.
Definition pad.cpp:2609
const std::shared_ptr< SHAPE_POLY_SET > & GetEffectivePolygon(PCB_LAYER_ID aLayer, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Definition pad.cpp:948
bool HasHole() const override
Definition pad.h:107
VECTOR2I ShapePos(PCB_LAYER_ID aLayer) const
Definition pad.cpp:1558
std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const override
Return a SHAPE_SEGMENT object representing the pad's hole.
Definition pad.cpp:1066
const VECTOR2I & GetSize(PCB_LAYER_ID aLayer) const
Definition pad.h:264
bool IsDegenerated(int aThreshold=5) const
double GetRadius() const
EDA_ANGLE GetAngle() const
virtual VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition pcb_track.h:297
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:127
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
bool HasSolderMask() const
Definition pcb_shape.h:213
int GetSolderMaskExpansion() const
virtual std::vector< VECTOR2I > GetCorners() const
Return 4 corners for a rectangle or rotated rectangle (stored as a poly).
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.
STROKE_PARAMS GetStroke() const override
Definition pcb_shape.h:97
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Test to see if this object is on the given layer.
VECTOR2I GetPosition() const override
Definition pcb_shape.h:79
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition pcb_shape.h:71
std::vector< PCB_TABLECELL * > GetCells() const
Definition pcb_table.h:160
void DrawBorders(const std::function< void(const VECTOR2I &aPt1, const VECTOR2I &aPt2, const STROKE_PARAMS &aStroke)> &aCallback) const
bool IsBorderEnabled() const
Disables the border, this is done by changing the stroke internally.
void SetEnd(const VECTOR2I &aEnd)
Definition pcb_track.h:93
void SetStart(const VECTOR2I &aStart)
Definition pcb_track.h:96
const VECTOR2I & GetStart() const
Definition pcb_track.h:97
const VECTOR2I & GetEnd() const
Definition pcb_track.h:94
virtual void SetWidth(int aWidth)
Definition pcb_track.h:90
virtual int GetWidth() const
Definition pcb_track.h:91
A round rectangle shape, based on a rectangle and a radius.
Definition roundrect.h:36
void TransformToPolygon(SHAPE_POLY_SET &aBuffer, int aMaxError) const
Get the polygonal representation of the roundrect.
Definition roundrect.cpp:83
Definition seg.h:42
VECTOR2I A
Definition seg.h:49
VECTOR2I B
Definition seg.h:50
int GetWidth() const override
Definition shape_arc.h:215
const SHAPE_LINE_CHAIN ConvertToPolyline(int aMaxError=DefaultAccuracyForPCB(), int *aActualError=nullptr) const
Construct a SHAPE_LINE_CHAIN of segments from a given arc.
int GetRadius() const
SHAPE_LINE_CHAIN ConvertToPolyline(int aMaxError) const
Build a polyline approximation of the ellipse or arc.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
int PointCount() const
Return the number of points (vertices) in this line chain.
SEG Segment(int aIndex) const
Return a copy of the aIndex-th segment in the line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
int SegmentCount() const
Return the number of segments in this line chain.
const VECTOR2I & CLastPoint() const
Return the last point in the line chain.
Represent a set of closed polygons.
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()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
const VECTOR2I & GetPosition() const
Definition shape_rect.h:169
const VECTOR2I GetSize() const
Definition shape_rect.h:177
const SEG & GetSeg() const
int GetWidth() const override
Represent a simple polygon consisting of a zero-thickness closed chain of connected line segments.
An abstract shape on 2D plane.
Definition shape.h:128
virtual int GetWidth() const
Definition shape.h:291
Simple container to manage line stroke parameters.
int GetWidth() const
LINE_STYLE GetLineStyle() const
static void Stroke(const SHAPE *aShape, LINE_STYLE aLineStyle, int aWidth, const KIGFX::RENDER_SETTINGS *aRenderSettings, const std::function< void(const VECTOR2I &a, const VECTOR2I &b)> &aStroker)
Handle a list of polygons defining a copper zone.
Definition zone.h:74
std::shared_ptr< SHAPE_POLY_SET > GetFilledPolysList(PCB_LAYER_ID aLayer) const
Definition zone.h:688
CORNER_STRATEGY
define how inflate transform build inflated polygon
@ ROUND_ALL_CORNERS
All angles are rounded.
@ ALLOW_ACUTE_CORNERS
just inflate the polygon. Acute angles create spikes
#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_0
Definition eda_angle.h:411
static constexpr EDA_ANGLE ANGLE_360
Definition eda_angle.h:417
@ ELLIPSE
Definition eda_shape.h:56
@ SEGMENT
Definition eda_shape.h:50
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:51
@ ELLIPSE_ARC
Definition eda_shape.h:57
a few functions useful in geometry calculations.
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 IsSolderMaskLayer(int aLayer)
Definition layer_ids.h:750
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition layer_ids.h:679
@ LAYER_FP_REFERENCES
Show footprints references (when texts are visible).
Definition layer_ids.h:266
@ LAYER_FP_TEXT
Definition layer_ids.h:240
@ LAYER_FP_VALUES
Show footprints values (when texts are visible).
Definition layer_ids.h:263
bool IsExternalCopperLayer(int aLayerId)
Test whether a layer is an external (F_Cu or B_Cu) copper layer.
Definition layer_ids.h:690
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:60
@ F_Paste
Definition layer_ids.h:104
@ B_Mask
Definition layer_ids.h:98
@ F_Mask
Definition layer_ids.h:97
@ B_Paste
Definition layer_ids.h:105
@ UNDEFINED_LAYER
Definition layer_ids.h:61
This file contains miscellaneous commonly used macros and functions.
#define UNIMPLEMENTED_FOR(type)
Definition macros.h:96
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:400
BARCODE class definition.
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_ELLIPSE
ellipse or elliptical arc
Definition shape.h:57
@ 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:60
std::vector< FAB_LAYER_COLOR > dummy
LINE_STYLE
Dashed line types.
std::string path
std::vector< std::vector< std::string > > table
VECTOR2I center
int radius
SHAPE_CIRCLE circle(c.m_circle_center, c.m_circle_radius)
int clearance
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)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition trigo.cpp:229
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition typeinfo.h:85
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition typeinfo.h:103
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition typeinfo.h:100
@ 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:101
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition typeinfo.h:90
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition typeinfo.h:89
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
Definition typeinfo.h:98
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition typeinfo.h:99
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition typeinfo.h:95
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
Definition typeinfo.h:91
@ 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:102
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687
glm::vec2 SFVEC2F
Definition xv3d_types.h:42