KiCad PCB EDA Suite
Loading...
Searching...
No Matches
odb_feature.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 * Author: SYSUEric <[email protected]>.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include "odb_feature.h"
22
23#include <sstream>
24#include <map>
25
26#include <wx/log.h>
27
28#include "footprint.h"
29#include "pad.h"
30#include "pcb_shape.h"
31#include "odb_defines.h"
32#include "pcb_track.h"
33#include "pcb_textbox.h"
34#include "pcb_table.h"
35#include "pcb_barcode.h"
36#include "pcb_dimension.h"
37#include "zone.h"
38#include "board.h"
40#include "geometry/eda_angle.h"
46#include "odb_eda_data.h"
47#include "pcb_io_odbpp.h"
48#include <callback_gal.h>
49#include <string_utils.h>
50
51
52void FEATURES_MANAGER::AddFeatureLine( const VECTOR2I& aStart, const VECTOR2I& aEnd,
53 uint64_t aWidth )
54{
55 AddFeature<ODB_LINE>( ODB::AddXY( aStart ), ODB::AddXY( aEnd ),
57}
58
59
60void FEATURES_MANAGER::AddFeatureArc( const VECTOR2I& aStart, const VECTOR2I& aEnd,
61 const VECTOR2I& aCenter, uint64_t aWidth,
62 ODB_DIRECTION aDirection )
63{
64 AddFeature<ODB_ARC>( ODB::AddXY( aStart ), ODB::AddXY( aEnd ), ODB::AddXY( aCenter ),
65 AddCircleSymbol( ODB::SymDouble2String( aWidth ) ), aDirection );
66}
67
68
69void FEATURES_MANAGER::AddPadCircle( const VECTOR2I& aCenter, uint64_t aDiameter,
70 const EDA_ANGLE& aAngle, bool aMirror,
71 double aResize /*= 1.0 */ )
72{
74 AddCircleSymbol( ODB::SymDouble2String( aDiameter ) ), aAngle, aMirror,
75 aResize );
76}
77
78
79bool FEATURES_MANAGER::AddContour( const SHAPE_POLY_SET& aPolySet, int aOutline /*= 0*/,
80 FILL_T aFillType /*= FILL_T::FILLED_SHAPE*/ )
81{
82 // todo: args modify aPolySet.Polygon( aOutline ) instead of aPolySet
83
84 if( aPolySet.OutlineCount() < ( aOutline + 1 ) )
85 return false;
86
87 AddFeatureSurface( aPolySet.Polygon( aOutline ), aFillType );
88
89 return true;
90}
91
92
94{
95 int stroke_width = aShape.GetWidth();
96
97 switch( aShape.GetShape() )
98 {
99 case SHAPE_T::CIRCLE:
100 {
101 int diameter = aShape.GetRadius() * 2;
103 wxString innerDim = ODB::SymDouble2String( ( diameter - stroke_width / 2 ) );
104 wxString outerDim = ODB::SymDouble2String( ( stroke_width + diameter ) );
105
106 if( aShape.IsSolidFill() )
108 else
109 AddFeature<ODB_PAD>( ODB::AddXY( center ), AddRoundDonutSymbol( outerDim, innerDim ) );
110
111 break;
112 }
113
115 {
116 // ODB++ donut_rc symbols degenerate when the corner radius is smaller than half the
117 // line width, and some viewers drop the feature entirely. Emit the rectangle as a
118 // filled pad for the fill (if any) plus four line segments for the stroke, matching
119 // how a rectangle drawn with the line tool is exported.
120 if( aShape.IsSolidFill() )
121 {
122 int width = std::abs( aShape.GetRectangleWidth() );
123 int height = std::abs( aShape.GetRectangleHeight() );
125
128 ODB::SymDouble2String( height ) ) );
129 }
130
131 if( stroke_width > 0 )
132 {
133 std::vector<VECTOR2I> corners = aShape.GetRectCorners();
134
135 for( size_t ii = 0; ii < corners.size(); ++ii )
136 AddFeatureLine( corners[ii], corners[( ii + 1 ) % corners.size()], stroke_width );
137 }
138
139 break;
140 }
141
142 case SHAPE_T::POLY:
143 {
144 int soldermask_min_thickness = 0;
145
146 // TODO: check if soldermask_min_thickness should be Stroke width
147
148 if( aLayer != UNDEFINED_LAYER && LSET( { F_Mask, B_Mask } ).Contains( aLayer ) )
149 soldermask_min_thickness = stroke_width;
150
151 int maxError = m_board->GetDesignSettings().m_MaxError;
152 SHAPE_POLY_SET poly_set;
153
154 if( soldermask_min_thickness == 0 )
155 {
156 poly_set = aShape.GetPolyShape().CloneDropTriangulation();
157 poly_set.Fracture();
158 }
159 else
160 {
161 SHAPE_POLY_SET initialPolys;
162
163 // add shapes inflated by aMinThickness/2 in areas
164 aShape.TransformShapeToPolygon( initialPolys, aLayer, 0, maxError, ERROR_OUTSIDE );
165 aShape.TransformShapeToPolygon( poly_set, aLayer, soldermask_min_thickness / 2 - 1,
166 maxError, ERROR_OUTSIDE );
167
168 poly_set.Simplify();
169 poly_set.Deflate( soldermask_min_thickness / 2 - 1,
171 poly_set.BooleanAdd( initialPolys );
172 poly_set.Fracture();
173 }
174
175 // ODB++ surface features can only represent closed polygons. We add a surface for
176 // the fill of the shape, if present, and add line segments for the outline, if present.
177 if( aShape.IsSolidFill() )
178 {
179 for( int ii = 0; ii < poly_set.OutlineCount(); ++ii )
180 {
181 AddContour( poly_set, ii, FILL_T::FILLED_SHAPE );
182
183 if( stroke_width != 0 )
184 {
185 for( int jj = 0; jj < poly_set.COutline( ii ).SegmentCount(); ++jj )
186 {
187 const SEG& seg = poly_set.COutline( ii ).CSegment( jj );
188 AddFeatureLine( seg.A, seg.B, stroke_width );
189 }
190 }
191 }
192 }
193 else
194 {
195 for( int ii = 0; ii < poly_set.OutlineCount(); ++ii )
196 {
197 for( int jj = 0; jj < poly_set.COutline( ii ).SegmentCount(); ++jj )
198 {
199 const SEG& seg = poly_set.COutline( ii ).CSegment( jj );
200 AddFeatureLine( seg.A, seg.B, stroke_width );
201 }
202 }
203 }
204
205 break;
206 }
207
208 case SHAPE_T::ARC:
209 {
211
212 AddFeatureArc( aShape.GetStart(), aShape.GetEnd(), aShape.GetCenter(), stroke_width, dir );
213 break;
214 }
215
216 case SHAPE_T::BEZIER:
217 {
218 const std::vector<VECTOR2I>& points = aShape.GetBezierPoints();
219
220 for( size_t i = 0; i < points.size() - 1; i++ )
221 AddFeatureLine( points[i], points[i + 1], stroke_width );
222
223 break;
224 }
225
226 case SHAPE_T::SEGMENT:
227 AddFeatureLine( aShape.GetStart(), aShape.GetEnd(), stroke_width );
228 break;
229
230 case SHAPE_T::ELLIPSE:
231 {
232 int maxError = m_board->GetDesignSettings().m_MaxError;
233
235 aShape.GetEllipseRotation() );
236
238 chain.SetClosed( true );
239
240 if( aShape.IsSolidFill() )
241 {
242 SHAPE_POLY_SET poly_set;
243 poly_set.AddOutline( chain );
244 poly_set.Fracture();
245
246 for( int ii = 0; ii < poly_set.OutlineCount(); ++ii )
247 AddContour( poly_set, ii, FILL_T::FILLED_SHAPE );
248 }
249
250 if( stroke_width > 0 )
251 {
252 for( int ii = 0; ii < chain.SegmentCount(); ++ii )
253 {
254 const SEG& seg = chain.CSegment( ii );
255 AddFeatureLine( seg.A, seg.B, stroke_width );
256 }
257 }
258
259 break;
260 }
261
263 {
264 int maxError = m_board->GetDesignSettings().m_MaxError;
265
267 aShape.GetEllipseRotation(), aShape.GetEllipseStartAngle(), aShape.GetEllipseEndAngle() );
268
270
271 for( int ii = 0; ii < chain.SegmentCount(); ++ii )
272 {
273 const SEG& seg = chain.CSegment( ii );
274 AddFeatureLine( seg.A, seg.B, stroke_width );
275 }
276
277 break;
278 }
279
280 default:
281 wxLogError( wxT( "Unknown shape when adding ODB++ layer feature" ) );
282 break;
283 }
284
285 if( aShape.IsHatchedFill() )
286 {
287 for( int ii = 0; ii < aShape.GetHatching().OutlineCount(); ++ii )
289 }
290}
291
292
294 FILL_T aFillType /*= FILL_T::FILLED_SHAPE */ )
295{
296 AddFeature<ODB_SURFACE>( aPolygon, aFillType );
297}
298
299
301{
302 FOOTPRINT* fp = aPad.GetParentFootprint();
303 bool mirror = false;
304
305 if( aPad.GetOrientation() != ANGLE_0 )
306 {
307 if( fp && fp->IsFlipped() )
308 mirror = true;
309 }
310
311 int maxError = m_board->GetDesignSettings().m_MaxError;
312
313 VECTOR2I expansion{ 0, 0 };
314
315 if( aLayer != UNDEFINED_LAYER && LSET( { F_Mask, B_Mask } ).Contains( aLayer ) )
316 expansion.x = expansion.y = aPad.GetSolderMaskExpansion( aLayer );
317
318 if( aLayer != UNDEFINED_LAYER && LSET( { F_Paste, B_Paste } ).Contains( aLayer ) )
319 expansion = aPad.GetSolderPasteMargin( aLayer );
320
321 int mask_clearance = expansion.x;
322
323 VECTOR2I plotSize = aPad.GetSize( aLayer ) + 2 * expansion;
324
325 VECTOR2I center = aPad.ShapePos( aLayer );
326
327 wxString width = ODB::SymDouble2String( std::abs( plotSize.x ) );
328 wxString height = ODB::SymDouble2String( std::abs( plotSize.y ) );
329
330 switch( aPad.GetShape( aLayer ) )
331 {
333 {
334 wxString diam = ODB::SymDouble2String( plotSize.x );
335
337 mirror );
338
339 break;
340 }
342 {
343 if( mask_clearance > 0 )
344 {
345 wxString rad = ODB::SymDouble2String( mask_clearance );
346
347 AddFeature<ODB_PAD>( ODB::AddXY( center ), AddRoundRectSymbol( width, height, rad ),
348 aPad.GetOrientation(), mirror );
349 }
350 else
351 {
353 aPad.GetOrientation(), mirror );
354 }
355
356 break;
357 }
358 case PAD_SHAPE::OVAL:
359 {
361 aPad.GetOrientation(), mirror );
362 break;
363 }
365 {
366 wxString rad = ODB::SymDouble2String( aPad.GetRoundRectCornerRadius( aLayer ) );
367
368 AddFeature<ODB_PAD>( ODB::AddXY( center ), AddRoundRectSymbol( width, height, rad ),
369 aPad.GetOrientation(), mirror );
370
371 break;
372 }
374 {
375 int shorterSide = std::min( plotSize.x, plotSize.y );
376 int chamfer = std::max(
377 0, KiROUND( aPad.GetChamferRectRatio( aLayer ) * shorterSide ) );
378 wxString rad = ODB::SymDouble2String( chamfer );
379 int positions = aPad.GetChamferPositions( aLayer );
380
382 AddChamferRectSymbol( width, height, rad, positions ),
383 aPad.GetOrientation(), mirror );
384
385 break;
386 }
388 {
389 SHAPE_POLY_SET outline;
390
391 aPad.TransformShapeToPolygon( outline, aLayer, 0, maxError, ERROR_INSIDE );
392
393 // Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
394 // which can create bad shapes if margin.x is < 0
395
396 if( mask_clearance )
397 {
399 maxError );
400 }
401
402 for( int ii = 0; ii < outline.OutlineCount(); ++ii )
403 AddContour( outline, ii );
404
405 break;
406 }
408 {
409 SHAPE_POLY_SET shape;
410 aPad.MergePrimitivesAsPolygon( aLayer, &shape );
411
412 // as for custome shape, odb++ don't rotate the polygon,
413 // so we rotate the polygon in kicad anticlockwise
414
415 shape.Rotate( aPad.GetOrientation() );
416 shape.Move( center );
417
418 if( expansion != VECTOR2I( 0, 0 ) )
419 {
420 shape.InflateWithLinkedHoles( std::max( expansion.x, expansion.y ),
422 }
423
424 for( int ii = 0; ii < shape.OutlineCount(); ++ii )
425 AddContour( shape, ii );
426
427 break;
428 }
429 default: wxLogError( wxT( "Unknown pad type" ) ); break;
430 }
431}
432
433
434void FEATURES_MANAGER::InitFeatureList( PCB_LAYER_ID aLayer, std::vector<BOARD_ITEM*>& aItems )
435{
436 auto add_track = [&]( PCB_TRACK* track )
437 {
438 auto iter = GetODBPlugin()->GetViaTraceSubnetMap().find( track );
439
440 if( iter == GetODBPlugin()->GetViaTraceSubnetMap().end() )
441 {
442 wxLogError( wxT( "Failed to get subnet track data" ) );
443 return;
444 }
445
446 auto subnet = iter->second;
447
448 if( track->Type() == PCB_TRACE_T )
449 {
450 PCB_SHAPE shape( nullptr, SHAPE_T::SEGMENT );
451 shape.SetStart( track->GetStart() );
452 shape.SetEnd( track->GetEnd() );
453 shape.SetWidth( track->GetWidth() );
454
455 AddShape( shape );
456 subnet->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER, m_layerName,
457 m_featuresList.size() - 1 );
458 }
459 else if( track->Type() == PCB_ARC_T )
460 {
461 PCB_ARC* arc = static_cast<PCB_ARC*>( track );
462 PCB_SHAPE shape( nullptr, SHAPE_T::ARC );
463 shape.SetArcGeometry( arc->GetStart(), arc->GetMid(), arc->GetEnd() );
464 shape.SetWidth( arc->GetWidth() );
465
466 AddShape( shape );
467
468 subnet->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER, m_layerName,
469 m_featuresList.size() - 1 );
470 }
471 else
472 {
473 // add via
474 PCB_VIA* via = static_cast<PCB_VIA*>( track );
475
476 bool hole = false;
477
478 if( aLayer != PCB_LAYER_ID::UNDEFINED_LAYER )
479 {
480 hole = m_layerName.Contains( "plugging" );
481 }
482 else
483 {
484 hole = m_layerName.Contains( "drill" ) || m_layerName.Contains( "filling" )
485 || m_layerName.Contains( "capping" );
486 }
487
488 if( hole )
489 {
490 AddViaDrillHole( via, aLayer );
491 subnet->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::HOLE, m_layerName,
492 m_featuresList.size() - 1 );
493
494 // TODO: confirm TOOLING_HOLE
495 // AddSystemAttribute( *m_featuresList.back(), ODB_ATTR::PAD_USAGE::TOOLING_HOLE );
496
497 if( !m_featuresList.empty() )
498 {
501 *m_featuresList.back(),
502 ODB_ATTR::GEOMETRY{ "VIA_RoundD" + std::to_string( via->GetWidth( aLayer ) ) } );
503 }
504 }
505 else
506 {
507 // to draw via copper shape on copper layer
508 AddVia( via, aLayer );
509 subnet->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER, m_layerName,
510 m_featuresList.size() - 1 );
511
512 if( !m_featuresList.empty() )
513 {
516 *m_featuresList.back(),
517 ODB_ATTR::GEOMETRY{ "VIA_RoundD" + std::to_string( via->GetWidth( aLayer ) ) } );
518 }
519 }
520 }
521 };
522
523 auto add_zone = [&]( ZONE* zone )
524 {
525 SHAPE_POLY_SET zone_shape = zone->GetFilledPolysList( aLayer )->CloneDropTriangulation();
526
527 for( int ii = 0; ii < zone_shape.OutlineCount(); ++ii )
528 {
529 AddContour( zone_shape, ii );
530
531 auto iter = GetODBPlugin()->GetPlaneSubnetMap().find( std::make_pair( aLayer, zone ) );
532
533 if( iter == GetODBPlugin()->GetPlaneSubnetMap().end() )
534 {
535 wxLogError( wxT( "Failed to get subnet plane data" ) );
536 return;
537 }
538
539 iter->second->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER, m_layerName,
540 m_featuresList.size() - 1 );
541
542 if( zone->IsTeardropArea() && !m_featuresList.empty() )
543 AddSystemAttribute( *m_featuresList.back(), ODB_ATTR::TEAR_DROP{ true } );
544 }
545 };
546
547 auto add_text = [&]( BOARD_ITEM* item )
548 {
549 EDA_TEXT* text_item = nullptr;
550
551 if( PCB_TEXT* tmp_text = dynamic_cast<PCB_TEXT*>( item ) )
552 text_item = static_cast<EDA_TEXT*>( tmp_text );
553 else if( PCB_TEXTBOX* tmp_textbox = dynamic_cast<PCB_TEXTBOX*>( item ) )
554 text_item = static_cast<EDA_TEXT*>( tmp_textbox );
555
556 if( !text_item || !text_item->IsVisible() || text_item->GetShownText( false ).empty() )
557 return;
558
559 auto plot_text = [&]( const VECTOR2I& aPos, const wxString& aTextString,
560 const TEXT_ATTRIBUTES& aAttributes, KIFONT::FONT* aFont,
561 const KIFONT::METRICS& aFontMetrics )
562 {
564
565 TEXT_ATTRIBUTES attributes = aAttributes;
566 int penWidth = attributes.m_StrokeWidth;
567
568 if( penWidth == 0 && attributes.m_Bold ) // Use default values if aPenWidth == 0
569 penWidth =
570 GetPenSizeForBold( std::min( attributes.m_Size.x, attributes.m_Size.y ) );
571
572 if( penWidth < 0 )
573 penWidth = -penWidth;
574
575 attributes.m_StrokeWidth = penWidth;
576
577 std::list<VECTOR2I> pts;
578
579 auto push_pts = [&]()
580 {
581 if( pts.size() < 2 )
582 return;
583
584 // Polylines are only allowed for more than 3 points.
585 // Otherwise, we have to use a line
586
587 if( pts.size() < 3 )
588 {
589 PCB_SHAPE shape( nullptr, SHAPE_T::SEGMENT );
590 shape.SetStart( pts.front() );
591 shape.SetEnd( pts.back() );
592 shape.SetWidth( attributes.m_StrokeWidth );
593
594 AddShape( shape );
596 ODB_ATTR::STRING{ aTextString.ToStdString() } );
597 }
598 else
599 {
600 for( auto it = pts.begin(); std::next( it ) != pts.end(); ++it )
601 {
602 auto it2 = std::next( it );
603 PCB_SHAPE shape( nullptr, SHAPE_T::SEGMENT );
604 shape.SetStart( *it );
605 shape.SetEnd( *it2 );
606 shape.SetWidth( attributes.m_StrokeWidth );
607 AddShape( shape );
608
609 if( !m_featuresList.empty() )
610 {
612 ODB_ATTR::STRING{ aTextString.ToStdString() } );
613 }
614 }
615 }
616
617 pts.clear();
618 };
619
620 CALLBACK_GAL callback_gal(
621 empty_opts,
622 // Stroke callback
623 [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
624 {
625 if( !pts.empty() )
626 {
627 if( aPt1 == pts.back() )
628 pts.push_back( aPt2 );
629 else if( aPt2 == pts.front() )
630 pts.push_front( aPt1 );
631 else if( aPt1 == pts.front() )
632 pts.push_front( aPt2 );
633 else if( aPt2 == pts.back() )
634 pts.push_back( aPt1 );
635 else
636 {
637 push_pts();
638 pts.push_back( aPt1 );
639 pts.push_back( aPt2 );
640 }
641 }
642 else
643 {
644 pts.push_back( aPt1 );
645 pts.push_back( aPt2 );
646 }
647 },
648 // Polygon callback
649 [&]( const SHAPE_LINE_CHAIN& aPoly )
650 {
651 if( aPoly.PointCount() < 3 )
652 return;
653
654 SHAPE_POLY_SET poly_set;
655 poly_set.AddOutline( aPoly );
656
657 for( int ii = 0; ii < poly_set.OutlineCount(); ++ii )
658 {
659 AddContour( poly_set, ii, FILL_T::FILLED_SHAPE );
660
661 if( !m_featuresList.empty() )
662 {
664 ODB_ATTR::STRING{ aTextString.ToStdString() } );
665 }
666 }
667 } );
668
669 aFont->Draw( &callback_gal, aTextString, aPos, aAttributes, aFontMetrics );
670
671 if( !pts.empty() )
672 push_pts();
673 };
674
675 bool isKnockout = false;
676
677 if( item->Type() == PCB_TEXT_T || item->Type() == PCB_FIELD_T )
678 isKnockout = static_cast<PCB_TEXT*>( item )->IsKnockout();
679 else if( item->Type() == PCB_TEXTBOX_T )
680 isKnockout = static_cast<PCB_TEXTBOX*>( item )->IsKnockout();
681
682 const KIFONT::METRICS& fontMetrics = item->GetFontMetrics();
683 KIFONT::FONT* font = text_item->GetDrawFont( nullptr );
684 wxString shownText( text_item->GetShownText( true ) );
685
686 if( shownText.IsEmpty() )
687 return;
688
689 VECTOR2I pos = text_item->GetTextPos();
690
691 TEXT_ATTRIBUTES attrs = text_item->GetAttributes();
692 attrs.m_StrokeWidth = text_item->GetEffectiveTextPenWidth();
693 attrs.m_Angle = text_item->GetDrawRotation();
694 attrs.m_Multiline = false;
695
696 if( isKnockout )
697 {
698 PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
699 SHAPE_POLY_SET finalpolyset;
700
701 text->TransformTextToPolySet( finalpolyset, 0, m_board->GetDesignSettings().m_MaxError,
702 ERROR_INSIDE );
703 finalpolyset.Fracture();
704
705 for( int ii = 0; ii < finalpolyset.OutlineCount(); ++ii )
706 {
707 AddContour( finalpolyset, ii, FILL_T::FILLED_SHAPE );
708
709 if( !m_featuresList.empty() )
710 {
712 ODB_ATTR::STRING{ shownText.ToStdString() } );
713 }
714 }
715 }
716 else if( text_item->IsMultilineAllowed() )
717 {
718 std::vector<VECTOR2I> positions;
719 wxArrayString strings_list;
720 wxStringSplit( shownText, strings_list, '\n' );
721 positions.reserve( strings_list.Count() );
722
723 text_item->GetLinePositions( nullptr, positions, strings_list.Count() );
724
725 for( unsigned ii = 0; ii < strings_list.Count(); ii++ )
726 {
727 wxString& txt = strings_list.Item( ii );
728 plot_text( positions[ii], txt, attrs, font, fontMetrics );
729 }
730 }
731 else
732 {
733 plot_text( pos, shownText, attrs, font, fontMetrics );
734 }
735 };
736
737
738 auto add_shape = [&]( PCB_SHAPE* shape )
739 {
740 // FOOTPRINT* fp = shape->GetParentFootprint();
741 AddShape( *shape, aLayer );
742 };
743
744 auto add_dimension = [&]( PCB_DIMENSION_BASE* dimension )
745 {
746 // A dimension is a PCB_TEXT subclass, so the value text is plotted via add_text.
747
748 add_text( dimension );
749
750 PCB_SHAPE temp_shape;
751 temp_shape.SetStroke( STROKE_PARAMS( dimension->GetLineThickness(), LINE_STYLE::SOLID ) );
752 temp_shape.SetLayer( dimension->GetLayer() );
753
754 for( const std::shared_ptr<SHAPE>& shape : dimension->GetShapes() )
755 {
756 switch( shape->Type() )
757 {
758 case SH_SEGMENT:
759 {
760 const SEG& seg = static_cast<const SHAPE_SEGMENT*>( shape.get() )->GetSeg();
761
762 temp_shape.SetShape( SHAPE_T::SEGMENT );
763 temp_shape.SetStart( seg.A );
764 temp_shape.SetEnd( seg.B );
765
766 add_shape( &temp_shape );
767 break;
768 }
769
770 case SH_CIRCLE:
771 {
772 VECTOR2I center( shape->Centre() );
773 int radius = static_cast<const SHAPE_CIRCLE*>( shape.get() )->GetRadius();
774
775 temp_shape.SetShape( SHAPE_T::CIRCLE );
776 temp_shape.SetFilled( false );
777 temp_shape.SetStart( center );
778 temp_shape.SetEnd( VECTOR2I( center.x + radius, center.y ) );
779
780 add_shape( &temp_shape );
781 break;
782 }
783
784 default:
785 break;
786 }
787 }
788 };
789
790 auto add_pad = [&]( PAD* pad )
791 {
792 auto iter = GetODBPlugin()->GetPadSubnetMap().find( pad );
793
794 if( iter == GetODBPlugin()->GetPadSubnetMap().end() )
795 {
796 wxLogError( wxT( "Failed to get subnet top data" ) );
797 return;
798 }
799
800 if( aLayer != PCB_LAYER_ID::UNDEFINED_LAYER )
801 {
802 // FOOTPRINT* fp = pad->GetParentFootprint();
803
804 AddPadShape( *pad, aLayer );
805
806 iter->second->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER, m_layerName,
807 m_featuresList.size() - 1 );
808 if( !m_featuresList.empty() )
810
811 if( !pad->HasHole() && !m_featuresList.empty() )
812 AddSystemAttribute( *m_featuresList.back(), ODB_ATTR::SMD{ true } );
813 }
814 else
815 {
816 // drill layer round hole or slot hole
817 if( m_layerName.Contains( "drill" ) )
818 {
819 // here we exchange round hole or slot hole into pad to draw in drill layer
820 PAD dummy( *pad );
821 dummy.Padstack().SetMode( PADSTACK::MODE::NORMAL );
822
823 if( pad->GetDrillSizeX() == pad->GetDrillSizeY() )
824 dummy.SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::CIRCLE ); // round hole shape
825 else
826 dummy.SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::OVAL ); // slot hole shape
827
828 dummy.SetOffset( PADSTACK::ALL_LAYERS,
829 VECTOR2I( 0, 0 ) ); // use hole position not pad position
830 dummy.SetSize( PADSTACK::ALL_LAYERS, pad->GetDrillSize() );
831
832 AddPadShape( dummy, aLayer );
833
834 if( pad->GetAttribute() == PAD_ATTRIB::PTH )
835 {
836 // only plated holes link to subnet
837 iter->second->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::HOLE, m_layerName,
838 m_featuresList.size() - 1 );
839
840 if( !m_featuresList.empty() )
842 }
843 else
844 {
845 if( !m_featuresList.empty() )
847 }
848 }
849 }
850 // AddSystemAttribute( *m_featuresList.back(),
851 // ODB_ATTR::GEOMETRY{ "PAD_xxxx" } );
852 };
853
854 for( BOARD_ITEM* item : aItems )
855 {
856 switch( item->Type() )
857 {
858 case PCB_TRACE_T:
859 case PCB_ARC_T:
860 case PCB_VIA_T:
861 add_track( static_cast<PCB_TRACK*>( item ) );
862 break;
863
864 case PCB_ZONE_T:
865 add_zone( static_cast<ZONE*>( item ) );
866 break;
867
868 case PCB_PAD_T:
869 add_pad( static_cast<PAD*>( item ) );
870 break;
871
872 case PCB_SHAPE_T:
873 add_shape( static_cast<PCB_SHAPE*>( item ) );
874 break;
875
876 case PCB_TEXT_T:
877 case PCB_FIELD_T:
878 add_text( item );
879 break;
880
881 case PCB_TEXTBOX_T:
882 add_text( item );
883
884 if( static_cast<PCB_TEXTBOX*>( item )->IsBorderEnabled() )
885 add_shape( static_cast<PCB_TEXTBOX*>( item ) );
886
887 break;
888
889 case PCB_TABLE_T:
890 {
891 PCB_TABLE* table = static_cast<PCB_TABLE*>( item );
892
893 for( PCB_TABLECELL* cell : table->GetCells() )
894 add_text( cell );
895
896 table->DrawBorders(
897 [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2, const STROKE_PARAMS& aStroke )
898 {
899 int lineWidth = aStroke.GetWidth();
900
901 if( lineWidth > 0 )
902 AddFeatureLine( aPt1, aPt2, lineWidth );
903 } );
904
905 break;
906 }
907
909 case PCB_DIM_LEADER_T:
910 case PCB_DIM_CENTER_T:
911 case PCB_DIM_RADIAL_T:
913 add_dimension( static_cast<PCB_DIMENSION_BASE*>( item ) );
914 break;
915
916 case PCB_TARGET_T:
917 //TODO: Add support for targets
918 break;
919
920 case PCB_BARCODE_T:
921 {
922 const PCB_BARCODE* barcode = static_cast<const PCB_BARCODE*>( item );
923 SHAPE_POLY_SET poly_set;
924
925 barcode->TransformShapeToPolygon( poly_set, aLayer, 0, m_board->GetDesignSettings().m_MaxError,
926 ERROR_INSIDE );
927 poly_set.Fracture();
928
929 for( int ii = 0; ii < poly_set.OutlineCount(); ++ii )
930 AddContour( poly_set, ii, FILL_T::FILLED_SHAPE );
931
932 break;
933 }
934
935 default:
936 break;
937 }
938 }
939}
940
941
943{
944 if( !aVia->FlashLayer( aLayer ) )
945 return;
946
947 PAD dummy( nullptr ); // default pad shape is circle
948 dummy.SetPadstack( aVia->Padstack() );
949 dummy.SetPosition( aVia->GetStart() );
950
951 AddPadShape( dummy, aLayer );
952}
953
954
956{
957 PAD dummy( nullptr ); // default pad shape is circle
958 int hole = aVia->GetDrillValue();
959 dummy.SetPosition( aVia->GetStart() );
960 dummy.SetSize( PADSTACK::ALL_LAYERS, VECTOR2I( hole, hole ) );
961
962 AddPadShape( dummy, aLayer );
963}
964
965
966void FEATURES_MANAGER::GenerateProfileFeatures( std::ostream& ost ) const
967{
968 ost << "UNITS=" << PCB_IO_ODBPP::m_unitsStr << std::endl;
969 ost << "#\n#Num Features\n#" << std::endl;
970 ost << "F " << m_featuresList.size() << std::endl;
971
972 if( m_featuresList.empty() )
973 return;
974
975 ost << "#\n#Layer features\n#" << std::endl;
976
977 for( const auto& feat : m_featuresList )
978 {
979 feat->WriteFeatures( ost );
980 }
981}
982
983
984void FEATURES_MANAGER::GenerateFeatureFile( std::ostream& ost ) const
985{
986 ost << "UNITS=" << PCB_IO_ODBPP::m_unitsStr << std::endl;
987 ost << "#\n#Num Features\n#" << std::endl;
988 ost << "F " << m_featuresList.size() << std::endl << std::endl;
989
990 if( m_featuresList.empty() )
991 return;
992
993 ost << "#\n#Feature symbol names\n#" << std::endl;
994
995 for( const auto& [n, name] : m_allSymMap )
996 {
997 ost << "$" << n << " " << name << std::endl;
998 }
999
1000 WriteAttributes( ost );
1001
1002 ost << "#\n#Layer features\n#" << std::endl;
1003
1004 for( const auto& feat : m_featuresList )
1005 {
1006 feat->WriteFeatures( ost );
1007 }
1008}
1009
1010
1011void ODB_FEATURE::WriteFeatures( std::ostream& ost )
1012{
1013 switch( GetFeatureType() )
1014 {
1015 case FEATURE_TYPE::LINE: ost << "L "; break;
1016
1017 case FEATURE_TYPE::ARC: ost << "A "; break;
1018
1019 case FEATURE_TYPE::PAD: ost << "P "; break;
1020
1021 case FEATURE_TYPE::SURFACE: ost << "S "; break;
1022 default: return;
1023 }
1024
1025 WriteRecordContent( ost );
1026 ost << std::endl;
1027}
1028
1029
1030void ODB_LINE::WriteRecordContent( std::ostream& ost )
1031{
1032 ost << m_start.first << " " << m_start.second << " " << m_end.first << " " << m_end.second
1033 << " " << m_symIndex << " P 0";
1034
1035 WriteAttributes( ost );
1036}
1037
1038
1039void ODB_ARC::WriteRecordContent( std::ostream& ost )
1040{
1041 ost << m_start.first << " " << m_start.second << " " << m_end.first << " " << m_end.second
1042 << " " << m_center.first << " " << m_center.second << " " << m_symIndex << " P 0 "
1043 << ( m_direction == ODB_DIRECTION::CW ? "Y" : "N" );
1044
1045 WriteAttributes( ost );
1046}
1047
1048
1049void ODB_PAD::WriteRecordContent( std::ostream& ost )
1050{
1051 ost << m_center.first << " " << m_center.second << " ";
1052
1053 // TODO: support resize symbol
1054 // ost << "-1" << " " << m_symIndex << " "
1055 // << m_resize << " P 0 ";
1056
1057 ost << m_symIndex << " P 0 ";
1058
1059 if( m_mirror )
1060 ost << "9 " << ODB::Double2String( m_angle.Normalize().AsDegrees() );
1061 else
1062 ost << "8 " << ODB::Double2String( ( ANGLE_360 - m_angle ).Normalize().AsDegrees() );
1063
1064 WriteAttributes( ost );
1065}
1066
1067
1068ODB_SURFACE::ODB_SURFACE( uint32_t aIndex, const SHAPE_POLY_SET::POLYGON& aPolygon,
1069 FILL_T aFillType /*= FILL_T::FILLED_SHAPE*/ ) : ODB_FEATURE( aIndex )
1070{
1071 if( !aPolygon.empty() && aPolygon[0].PointCount() >= 3 )
1072 {
1073 m_surfaces = std::make_unique<ODB_SURFACE_DATA>( aPolygon );
1074 if( aFillType != FILL_T::NO_FILL )
1075 {
1076 m_surfaces->AddPolygonHoles( aPolygon );
1077 }
1078 }
1079 else
1080 {
1081 delete this;
1082 }
1083}
1084
1085
1086void ODB_SURFACE::WriteRecordContent( std::ostream& ost )
1087{
1088 ost << "P 0";
1089 WriteAttributes( ost );
1090 ost << std::endl;
1091 m_surfaces->WriteData( ost );
1092 ost << "SE";
1093}
1094
1095
1097{
1098 const std::vector<VECTOR2I>& pts = aPolygon[0].CPoints();
1099 if( !pts.empty() )
1100 {
1101 if( m_polygons.empty() )
1102 {
1103 m_polygons.resize( 1 );
1104 }
1105
1106 m_polygons.at( 0 ).reserve( pts.size() );
1107 m_polygons.at( 0 ).emplace_back( pts.back() );
1108
1109 for( size_t jj = 0; jj < pts.size(); ++jj )
1110 {
1111 m_polygons.at( 0 ).emplace_back( pts.at( jj ) );
1112 }
1113 }
1114}
1115
1116
1118{
1119 for( size_t ii = 1; ii < aPolygon.size(); ++ii )
1120 {
1121 wxCHECK2( aPolygon[ii].PointCount() >= 3, continue );
1122
1123 const std::vector<VECTOR2I>& hole = aPolygon[ii].CPoints();
1124
1125 if( hole.empty() )
1126 continue;
1127
1128 if( m_polygons.size() <= ii )
1129 {
1130 m_polygons.resize( ii + 1 );
1131
1132 m_polygons[ii].reserve( hole.size() );
1133 }
1134
1135 m_polygons.at( ii ).emplace_back( hole.back() );
1136
1137 for( size_t jj = 0; jj < hole.size(); ++jj )
1138 {
1139 m_polygons.at( ii ).emplace_back( hole[jj] );
1140 }
1141 }
1142}
1143
1144
1145void ODB_SURFACE_DATA::WriteData( std::ostream& ost ) const
1146{
1147 ODB::CHECK_ONCE is_island;
1148
1149 for( const auto& contour : m_polygons )
1150 {
1151 if( contour.empty() )
1152 continue;
1153
1154 ost << "OB " << ODB::AddXY( contour.back().m_end ).first << " "
1155 << ODB::AddXY( contour.back().m_end ).second << " ";
1156
1157 if( is_island() )
1158 ost << "I";
1159 else
1160 ost << "H";
1161 ost << std::endl;
1162
1163 for( const auto& line : contour )
1164 {
1165 if( SURFACE_LINE::LINE_TYPE::SEGMENT == line.m_type )
1166 ost << "OS " << ODB::AddXY( line.m_end ).first << " "
1167 << ODB::AddXY( line.m_end ).second << std::endl;
1168 else
1169 ost << "OC " << ODB::AddXY( line.m_end ).first << " "
1170 << ODB::AddXY( line.m_end ).second << " " << ODB::AddXY( line.m_center ).first
1171 << " " << ODB::AddXY( line.m_center ).second << " "
1172 << ( line.m_direction == ODB_DIRECTION::CW ? "Y" : "N" ) << std::endl;
1173 }
1174 ost << "OE" << std::endl;
1175 }
1176}
const char * name
@ ERROR_OUTSIDE
@ ERROR_INSIDE
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
void WriteAttributes(std::ostream &ost, const std::string &prefix="") const
void AddSystemAttribute(Tr &r, Ta v)
void WriteAttributes(std::ostream &ost) const
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
FOOTPRINT * GetParentFootprint() const
int GetEllipseMinorRadius() const
Definition eda_shape.h:306
const VECTOR2I & GetEllipseCenter() const
Definition eda_shape.h:288
const SHAPE_POLY_SET & GetHatching() const
EDA_ANGLE GetEllipseEndAngle() const
Definition eda_shape.h:334
int GetEllipseMajorRadius() const
Definition eda_shape.h:297
int GetRectangleWidth() const
SHAPE_POLY_SET & GetPolyShape()
EDA_ANGLE GetEllipseRotation() const
Definition eda_shape.h:315
int GetRadius() const
SHAPE_T GetShape() const
Definition eda_shape.h:189
bool IsHatchedFill() const
Definition eda_shape.h:144
virtual void SetFilled(bool aFlag)
Definition eda_shape.h:156
bool IsSolidFill() const
Definition eda_shape.h:137
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:236
void SetStart(const VECTOR2I &aStart)
Definition eda_shape.h:198
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:194
void SetShape(SHAPE_T aShape)
Definition eda_shape.h:188
std::vector< VECTOR2I > GetRectCorners() const
EDA_ANGLE GetEllipseStartAngle() const
Definition eda_shape.h:325
const std::vector< VECTOR2I > & GetBezierPoints() const
Definition eda_shape.h:400
void SetEnd(const VECTOR2I &aEnd)
Definition eda_shape.h:240
void SetArcGeometry(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Set the three controlling points for an arc.
int GetRectangleHeight() const
bool IsClockwiseArc() const
void SetWidth(int aWidth)
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:93
const VECTOR2I & GetTextPos() const
Definition eda_text.h:298
bool IsMultilineAllowed() const
Definition eda_text.h:222
virtual bool IsVisible() const
Definition eda_text.h:212
virtual EDA_ANGLE GetDrawRotation() const
Definition eda_text.h:404
virtual KIFONT::FONT * GetDrawFont(const RENDER_SETTINGS *aSettings) const
Definition eda_text.cpp:670
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
void GetLinePositions(const RENDER_SETTINGS *aSettings, std::vector< VECTOR2I > &aPositions, int aLineCount) const
Populate aPositions with the position of each line of a multiline text, according to the vertical jus...
Definition eda_text.cpp:945
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
void AddPadShape(const PAD &aPad, PCB_LAYER_ID aLayer)
void AddShape(const PCB_SHAPE &aShape, PCB_LAYER_ID aLayer=UNDEFINED_LAYER)
uint32_t AddRectSymbol(const wxString &aWidth, const wxString &aHeight)
void AddVia(const PCB_VIA *aVia, PCB_LAYER_ID aLayer)
PCB_IO_ODBPP * GetODBPlugin()
void InitFeatureList(PCB_LAYER_ID aLayer, std::vector< BOARD_ITEM * > &aItems)
void AddFeatureLine(const VECTOR2I &aStart, const VECTOR2I &aEnd, uint64_t aWidth)
void AddFeatureArc(const VECTOR2I &aStart, const VECTOR2I &aEnd, const VECTOR2I &aCenter, uint64_t aWidth, ODB_DIRECTION aDirection)
std::map< uint32_t, wxString > m_allSymMap
void GenerateFeatureFile(std::ostream &ost) const
void AddViaDrillHole(const PCB_VIA *aVia, PCB_LAYER_ID aLayer)
void AddPadCircle(const VECTOR2I &aCenter, uint64_t aDiameter, const EDA_ANGLE &aAngle, bool aMirror, double aResize=1.0)
void AddFeatureSurface(const SHAPE_POLY_SET::POLYGON &aPolygon, FILL_T aFillType=FILL_T::FILLED_SHAPE)
uint32_t AddRoundRectSymbol(const wxString &aWidth, const wxString &aHeight, const wxString &aRadius)
wxString m_layerName
uint32_t AddOvalSymbol(const wxString &aWidth, const wxString &aHeight)
void GenerateProfileFeatures(std::ostream &ost) const
std::list< std::unique_ptr< ODB_FEATURE > > m_featuresList
void AddFeature(Args &&... args)
uint32_t AddCircleSymbol(const wxString &aDiameter)
Definition odb_feature.h:96
uint32_t AddChamferRectSymbol(const wxString &aWidth, const wxString &aHeight, const wxString &aRadius, int aPositions)
uint32_t AddRoundDonutSymbol(const wxString &aOuterDim, const wxString &aInnerDim)
bool AddContour(const SHAPE_POLY_SET &aPolySet, int aOutline=0, FILL_T aFillType=FILL_T::FILLED_SHAPE)
bool IsFlipped() const
Definition footprint.h:602
FONT is an abstract base class for both outline and stroke fonts.
Definition font.h:98
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
Definition lset.h:63
std::pair< wxString, wxString > m_end
std::pair< wxString, wxString > m_start
uint32_t m_symIndex
virtual void WriteRecordContent(std::ostream &ost) override
ODB_DIRECTION m_direction
std::pair< wxString, wxString > m_center
virtual void WriteRecordContent(std::ostream &ost)=0
virtual void WriteFeatures(std::ostream &ost)
virtual FEATURE_TYPE GetFeatureType()=0
ODB_FEATURE(uint32_t aIndex)
virtual void WriteRecordContent(std::ostream &ost) override
std::pair< wxString, wxString > m_start
std::pair< wxString, wxString > m_end
uint32_t m_symIndex
uint32_t m_symIndex
virtual void WriteRecordContent(std::ostream &ost) override
bool m_mirror
EDA_ANGLE m_angle
std::pair< wxString, wxString > m_center
void WriteData(std::ostream &ost) const
std::vector< std::vector< SURFACE_LINE > > m_polygons
ODB_SURFACE_DATA(const SHAPE_POLY_SET::POLYGON &aPolygon)
void AddPolygonHoles(const SHAPE_POLY_SET::POLYGON &aPolygon)
std::unique_ptr< ODB_SURFACE_DATA > m_surfaces
virtual void WriteRecordContent(std::ostream &ost) override
ODB_SURFACE(uint32_t aIndex, const SHAPE_POLY_SET::POLYGON &aPolygon, FILL_T aFillType=FILL_T::FILLED_SHAPE)
@ NORMAL
Shape is the same on all layers.
Definition padstack.h:171
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition padstack.h:177
Definition pad.h:65
void MergePrimitivesAsPolygon(PCB_LAYER_ID aLayer, SHAPE_POLY_SET *aMergedPolygon, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Merge all basic shapes to a SHAPE_POLY_SET.
Definition pad.cpp:3279
int GetRoundRectCornerRadius(PCB_LAYER_ID aLayer) const
Definition pad.cpp:894
PAD_SHAPE GetShape(PCB_LAYER_ID aLayer) const
Definition pad.h:206
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:2613
int GetSolderMaskExpansion(PCB_LAYER_ID aLayer) const
Definition pad.cpp:1683
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition pad.h:440
int GetChamferPositions(PCB_LAYER_ID aLayer) const
Definition pad.h:868
double GetChamferRectRatio(PCB_LAYER_ID aLayer) const
Definition pad.h:851
VECTOR2I GetSolderPasteMargin(PCB_LAYER_ID aLayer) const
Usually < 0 (mask shape smaller than pad)because the margin can be dependent on the pad size,...
Definition pad.cpp:1746
VECTOR2I ShapePos(PCB_LAYER_ID aLayer) const
Definition pad.cpp:1562
const VECTOR2I & GetSize(PCB_LAYER_ID aLayer) const
Definition pad.h:274
const VECTOR2I & GetMid() const
Definition pcb_track.h:290
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 barcode (text + symbol shapes) to polygonal geometry suitable for filling/collision tests...
Abstract dimension API.
std::map< std::pair< PCB_LAYER_ID, ZONE * >, EDA_DATA::SUB_NET_PLANE * > & GetPlaneSubnetMap()
std::map< PCB_TRACK *, EDA_DATA::SUB_NET * > & GetViaTraceSubnetMap()
std::map< const PAD *, EDA_DATA::SUB_NET_TOEPRINT * > & GetPadSubnetMap()
static std::string m_unitsStr
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
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
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.
void SetStroke(const STROKE_PARAMS &aStroke) override
Definition pcb_shape.h:98
const VECTOR2I & GetStart() const
Definition pcb_track.h:97
const VECTOR2I & GetEnd() const
Definition pcb_track.h:94
virtual int GetWidth() const
Definition pcb_track.h:91
bool FlashLayer(int aLayer) const
Check to see whether the via should have a pad on the specific layer.
const PADSTACK & Padstack() const
Definition pcb_track.h:406
int GetDrillValue() const
Calculate the drill value for vias (m_drill if > 0, or default drill value for the board).
Definition seg.h:42
VECTOR2I A
Definition seg.h:49
VECTOR2I B
Definition seg.h:50
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...
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
Represent a set of closed polygons.
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
void BooleanAdd(const SHAPE_POLY_SET &b)
Perform boolean polyset union.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
POLYGON & Polygon(int aIndex)
Return the aIndex-th subpolygon in the set.
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
std::vector< SHAPE_LINE_CHAIN > POLYGON
represents a single polygon outline with holes.
void Deflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError)
int OutlineCount() const
Return the number of outlines in the set.
void InflateWithLinkedHoles(int aFactor, CORNER_STRATEGY aCornerStrategy, int aMaxError)
Perform outline inflation/deflation, using round corners.
void Move(const VECTOR2I &aVector) override
void Fracture(bool aSimplify=true)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
SHAPE_POLY_SET CloneDropTriangulation() const
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
const SEG & GetSeg() const
Simple container to manage line stroke parameters.
int GetWidth() const
Handle a list of polygons defining a copper zone.
Definition zone.h:74
@ CHAMFER_ALL_CORNERS
All angles are chamfered.
@ ROUND_ALL_CORNERS
All angles are rounded.
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
FILL_T
Definition eda_shape.h:63
@ FILLED_SHAPE
Fill with object color.
Definition eda_shape.h:65
int GetPenSizeForBold(int aTextSize)
Definition gr_text.cpp:37
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
std::pair< wxString, wxString > AddXY(const VECTOR2I &aVec)
Definition odb_util.cpp:191
wxString Double2String(double aVal)
Definition odb_util.cpp:151
wxString SymDouble2String(double aVal)
Definition odb_util.cpp:179
VECTOR2I GetShapePosition(const PCB_SHAPE &aShape)
Definition odb_util.cpp:202
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:400
ODB_DIRECTION
Definition odb_feature.h:34
@ PTH
Plated through hole pad.
Definition padstack.h:98
@ CHAMFERED_RECT
Definition padstack.h:60
@ ROUNDRECT
Definition padstack.h:57
@ TRAPEZOID
Definition padstack.h:56
@ RECTANGLE
Definition padstack.h:54
BARCODE class definition.
@ SH_CIRCLE
circle
Definition shape.h:50
@ SH_SEGMENT
line segment
Definition shape.h:48
std::vector< FAB_LAYER_COLOR > dummy
void wxStringSplit(const wxString &aText, wxArrayString &aStrings, wxChar aSplitter)
Split aString to a string list separated at aSplitter.
std::vector< std::vector< std::string > > table
VECTOR2I center
const SHAPE_LINE_CHAIN chain
int radius
VECTOR2I end
@ 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_ZONE_T
class ZONE, a copper pour area
Definition typeinfo.h:105
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition typeinfo.h:89
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
Definition typeinfo.h:87
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
Definition typeinfo.h:98
@ PCB_TARGET_T
class PCB_TARGET, a target (graphic item)
Definition typeinfo.h:104
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition typeinfo.h:99
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition typeinfo.h:84
@ 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