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
18 * along with this program. If not, see <https://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#include <trace_helpers.h>
51
52
53void FEATURES_MANAGER::AddFeatureLine( const VECTOR2I& aStart, const VECTOR2I& aEnd,
54 uint64_t aWidth )
55{
56 AddFeature<ODB_LINE>( ODB::AddXY( aStart ), ODB::AddXY( aEnd ),
58}
59
60
61void FEATURES_MANAGER::AddFeatureArc( const VECTOR2I& aStart, const VECTOR2I& aEnd,
62 const VECTOR2I& aCenter, uint64_t aWidth,
63 ODB_DIRECTION aDirection )
64{
65 AddFeature<ODB_ARC>( ODB::AddXY( aStart ), ODB::AddXY( aEnd ), ODB::AddXY( aCenter ),
66 AddCircleSymbol( ODB::SymDouble2String( aWidth ) ), aDirection );
67}
68
69
70void FEATURES_MANAGER::AddPadCircle( const VECTOR2I& aCenter, uint64_t aDiameter,
71 const EDA_ANGLE& aAngle, bool aMirror,
72 double aResize /*= 1.0 */ )
73{
75 AddCircleSymbol( ODB::SymDouble2String( aDiameter ) ), aAngle, aMirror,
76 aResize );
77}
78
79
80bool FEATURES_MANAGER::AddContour( const SHAPE_POLY_SET& aPolySet, int aOutline /*= 0*/,
81 FILL_T aFillType /*= FILL_T::FILLED_SHAPE*/ )
82{
83 // todo: args modify aPolySet.Polygon( aOutline ) instead of aPolySet
84
85 if( aPolySet.OutlineCount() < ( aOutline + 1 ) )
86 return false;
87
88 AddFeatureSurface( aPolySet.Polygon( aOutline ), aFillType );
89
90 return true;
91}
92
93
95{
96 int stroke_width = aShape.GetWidth();
97
98 switch( aShape.GetShape() )
99 {
100 case SHAPE_T::CIRCLE:
101 {
102 // GetRadius() can reach INT_MAX / 2 rounded up, which overflows a signed int when doubled
103 int64_t diameter = static_cast<int64_t>( aShape.GetRadius() ) * 2;
105
106 // The stroke straddles the radius, so in diameter terms the whole width comes off the
107 // inner edge and goes onto the outer
108 int64_t innerDiameter = diameter - stroke_width;
109 wxString outerDim = ODB::SymDouble2String( diameter + stroke_width );
110
111 // donut_r has no spelling for a hole closed by its own stroke
112 if( aShape.IsSolidFill() || innerDiameter <= 0 )
113 {
115 }
116 else
117 {
119 AddRoundDonutSymbol( outerDim,
120 ODB::SymDouble2String( innerDiameter ) ) );
121 }
122
123 break;
124 }
125
127 {
128 // ODB++ donut_rc symbols degenerate when the corner radius is smaller than half the
129 // line width, and some viewers drop the feature entirely. Emit the rectangle as a
130 // filled pad for the fill (if any) plus four line segments for the stroke, matching
131 // how a rectangle drawn with the line tool is exported.
132 if( aShape.IsSolidFill() )
133 {
134 int width = std::abs( aShape.GetRectangleWidth() );
135 int height = std::abs( aShape.GetRectangleHeight() );
137
140 ODB::SymDouble2String( height ) ) );
141 }
142
143 if( stroke_width > 0 )
144 {
145 std::vector<VECTOR2I> corners = aShape.GetRectCorners();
146
147 for( size_t ii = 0; ii < corners.size(); ++ii )
148 AddFeatureLine( corners[ii], corners[( ii + 1 ) % corners.size()], stroke_width );
149 }
150
151 break;
152 }
153
154 case SHAPE_T::POLY:
155 {
156 int soldermask_min_thickness = 0;
157
158 // TODO: check if soldermask_min_thickness should be Stroke width
159
160 if( aLayer != UNDEFINED_LAYER && LSET( { F_Mask, B_Mask } ).Contains( aLayer ) )
161 soldermask_min_thickness = stroke_width;
162
163 int maxError = m_board->GetDesignSettings().m_MaxError;
164 SHAPE_POLY_SET poly_set;
165
166 if( soldermask_min_thickness == 0 )
167 {
168 poly_set = aShape.GetPolyShape().CloneDropTriangulation();
169 poly_set.Fracture();
170 }
171 else
172 {
173 SHAPE_POLY_SET initialPolys;
174
175 // add shapes inflated by aMinThickness/2 in areas
176 aShape.TransformShapeToPolygon( initialPolys, aLayer, 0, maxError, ERROR_OUTSIDE );
177 aShape.TransformShapeToPolygon( poly_set, aLayer, soldermask_min_thickness / 2 - 1,
178 maxError, ERROR_OUTSIDE );
179
180 poly_set.Simplify();
181 poly_set.Deflate( soldermask_min_thickness / 2 - 1,
183 poly_set.BooleanAdd( initialPolys );
184 poly_set.Fracture();
185 }
186
187 // ODB++ surface features can only represent closed polygons. We add a surface for
188 // the fill of the shape, if present, and add line segments for the outline, if present.
189 if( aShape.IsSolidFill() )
190 {
191 for( int ii = 0; ii < poly_set.OutlineCount(); ++ii )
192 {
193 AddContour( poly_set, ii, FILL_T::FILLED_SHAPE );
194
195 if( stroke_width != 0 )
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 else
206 {
207 for( int ii = 0; ii < poly_set.OutlineCount(); ++ii )
208 {
209 for( int jj = 0; jj < poly_set.COutline( ii ).SegmentCount(); ++jj )
210 {
211 const SEG& seg = poly_set.COutline( ii ).CSegment( jj );
212 AddFeatureLine( seg.A, seg.B, stroke_width );
213 }
214 }
215 }
216
217 break;
218 }
219
220 case SHAPE_T::ARC:
221 {
223
224 AddFeatureArc( aShape.GetStart(), aShape.GetEnd(), aShape.GetCenter(), stroke_width, dir );
225 break;
226 }
227
228 case SHAPE_T::BEZIER:
229 {
230 const std::vector<VECTOR2I>& points = aShape.GetBezierPoints();
231
232 for( size_t i = 0; i < points.size() - 1; i++ )
233 AddFeatureLine( points[i], points[i + 1], stroke_width );
234
235 break;
236 }
237
238 case SHAPE_T::SEGMENT:
239 AddFeatureLine( aShape.GetStart(), aShape.GetEnd(), stroke_width );
240 break;
241
242 case SHAPE_T::ELLIPSE:
243 {
244 int maxError = m_board->GetDesignSettings().m_MaxError;
245
247 aShape.GetEllipseRotation() );
248
250 chain.SetClosed( true );
251
252 if( aShape.IsSolidFill() )
253 {
254 SHAPE_POLY_SET poly_set;
255 poly_set.AddOutline( chain );
256 poly_set.Fracture();
257
258 for( int ii = 0; ii < poly_set.OutlineCount(); ++ii )
259 AddContour( poly_set, ii, FILL_T::FILLED_SHAPE );
260 }
261
262 if( stroke_width > 0 )
263 {
264 for( int ii = 0; ii < chain.SegmentCount(); ++ii )
265 {
266 const SEG& seg = chain.CSegment( ii );
267 AddFeatureLine( seg.A, seg.B, stroke_width );
268 }
269 }
270
271 break;
272 }
273
275 {
276 int maxError = m_board->GetDesignSettings().m_MaxError;
277
279 aShape.GetEllipseRotation(), aShape.GetEllipseStartAngle(), aShape.GetEllipseEndAngle() );
280
282
283 for( int ii = 0; ii < chain.SegmentCount(); ++ii )
284 {
285 const SEG& seg = chain.CSegment( ii );
286 AddFeatureLine( seg.A, seg.B, stroke_width );
287 }
288
289 break;
290 }
291
292 default:
293 wxLogTrace( traceOdbppIo, wxT( "Unknown shape when adding ODB++ layer feature" ) );
294 break;
295 }
296
297 if( aShape.IsHatchedFill() )
298 {
299 for( int ii = 0; ii < aShape.GetHatching().OutlineCount(); ++ii )
301 }
302}
303
304
306 FILL_T aFillType /*= FILL_T::FILLED_SHAPE */ )
307{
308 AddFeature<ODB_SURFACE>( aPolygon, aFillType );
309}
310
311
313{
314 FOOTPRINT* fp = aPad.GetParentFootprint();
315 bool mirror = false;
316
317 if( aPad.GetOrientation() != ANGLE_0 )
318 {
319 if( fp && fp->IsFlipped() )
320 mirror = true;
321 }
322
323 int maxError = m_board->GetDesignSettings().m_MaxError;
324
325 VECTOR2I expansion{ 0, 0 };
326
327 if( aLayer != UNDEFINED_LAYER && LSET( { F_Mask, B_Mask } ).Contains( aLayer ) )
328 expansion.x = expansion.y = aPad.GetSolderMaskExpansion( aLayer );
329
330 if( aLayer != UNDEFINED_LAYER && LSET( { F_Paste, B_Paste } ).Contains( aLayer ) )
331 expansion = aPad.GetSolderPasteMargin( aLayer );
332
333 int mask_clearance = expansion.x;
334
335 VECTOR2I plotSize = aPad.GetSize( aLayer ) + 2 * expansion;
336
337 VECTOR2I center = aPad.ShapePos( aLayer );
338
339 wxString width = ODB::SymDouble2String( std::abs( plotSize.x ) );
340 wxString height = ODB::SymDouble2String( std::abs( plotSize.y ) );
341
342 switch( aPad.GetShape( aLayer ) )
343 {
345 {
346 wxString diam = ODB::SymDouble2String( plotSize.x );
347
349 mirror );
350
351 break;
352 }
354 {
355 if( mask_clearance > 0 )
356 {
357 wxString rad = ODB::SymDouble2String( mask_clearance );
358
359 AddFeature<ODB_PAD>( ODB::AddXY( center ), AddRoundRectSymbol( width, height, rad ),
360 aPad.GetOrientation(), mirror );
361 }
362 else
363 {
365 aPad.GetOrientation(), mirror );
366 }
367
368 break;
369 }
370 case PAD_SHAPE::OVAL:
371 {
373 aPad.GetOrientation(), mirror );
374 break;
375 }
377 {
378 wxString rad = ODB::SymDouble2String( aPad.GetRoundRectCornerRadius( aLayer ) );
379
380 AddFeature<ODB_PAD>( ODB::AddXY( center ), AddRoundRectSymbol( width, height, rad ),
381 aPad.GetOrientation(), mirror );
382
383 break;
384 }
386 {
387 int shorterSide = std::min( plotSize.x, plotSize.y );
388 int chamfer = std::max(
389 0, KiROUND( aPad.GetChamferRectRatio( aLayer ) * shorterSide ) );
390 wxString rad = ODB::SymDouble2String( chamfer );
391 int positions = aPad.GetChamferPositions( aLayer );
392
394 AddChamferRectSymbol( width, height, rad, positions ),
395 aPad.GetOrientation(), mirror );
396
397 break;
398 }
400 {
401 SHAPE_POLY_SET outline;
402
403 aPad.TransformShapeToPolygon( outline, aLayer, 0, maxError, ERROR_INSIDE );
404
405 // Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
406 // which can create bad shapes if margin.x is < 0
407
408 if( mask_clearance )
409 {
411 maxError );
412 }
413
414 for( int ii = 0; ii < outline.OutlineCount(); ++ii )
415 AddContour( outline, ii );
416
417 break;
418 }
420 {
421 SHAPE_POLY_SET shape;
422 aPad.MergePrimitivesAsPolygon( aLayer, &shape );
423
424 // as for custome shape, odb++ don't rotate the polygon,
425 // so we rotate the polygon in kicad anticlockwise
426
427 shape.Rotate( aPad.GetOrientation() );
428 shape.Move( center );
429
430 if( expansion != VECTOR2I( 0, 0 ) )
431 {
432 shape.InflateWithLinkedHoles( std::max( expansion.x, expansion.y ),
434 }
435
436 for( int ii = 0; ii < shape.OutlineCount(); ++ii )
437 AddContour( shape, ii );
438
439 break;
440 }
441 default: wxLogTrace( traceOdbppIo, wxT( "Unknown pad type" ) ); break;
442 }
443}
444
445
447{
448 auto iter = GetODBPlugin()->GetViaTraceSubnetMap().find( track );
449
450 if( iter == GetODBPlugin()->GetViaTraceSubnetMap().end() )
451 {
452 wxLogTrace( traceOdbppIo, wxT( "Failed to get subnet track data" ) );
453 return;
454 }
455
456 auto subnet = iter->second;
457
458 if( track->Type() == PCB_TRACE_T )
459 {
460 PCB_SHAPE shape( nullptr, SHAPE_T::SEGMENT );
461 shape.SetStart( track->GetStart() );
462 shape.SetEnd( track->GetEnd() );
463 shape.SetWidth( track->GetWidth() );
464
465 AddShape( shape );
466 subnet->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER, m_layerName, m_featuresList.size() - 1 );
467 }
468 else if( track->Type() == PCB_ARC_T )
469 {
470 const PCB_ARC* arc = static_cast<const PCB_ARC*>( track );
471
472 // Too small arcs cannot be really handled: arc center (and arc radius)
473 // cannot be safely computed
474 if( !arc->IsDegenerated( 10 /* in IU */ ) )
475 {
476 PCB_SHAPE shape( nullptr, SHAPE_T::ARC );
477 shape.SetArcGeometry( arc->GetStart(), arc->GetMid(), arc->GetEnd() );
478 shape.SetWidth( arc->GetWidth() );
479
480 AddShape( shape );
481 }
482 else
483 {
484 // Approximate this very small arc by a segment.
485 AddFeatureLine( track->GetStart(), track->GetEnd(), track->GetWidth() );
486 }
487
488 subnet->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER, m_layerName, m_featuresList.size() - 1 );
489 }
490 else
491 {
492 // add via
493 PCB_VIA* via = static_cast<PCB_VIA*>( track );
494
495 bool hole = false;
496
497 if( aLayer != PCB_LAYER_ID::UNDEFINED_LAYER )
498 {
499 hole = m_layerName.Contains( "plugging" );
500 }
501 else
502 {
503 hole = m_layerName.Contains( "drill" )
504 || m_layerName.Contains( "filling" )
505 || m_layerName.Contains( "capping" );
506 }
507
508 if( hole )
509 {
510 AddViaDrillHole( via, aLayer );
511 subnet->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::HOLE, m_layerName, m_featuresList.size() - 1 );
512
513 // TODO: confirm TOOLING_HOLE
514 // AddSystemAttribute( *m_featuresList.back(), ODB_ATTR::PAD_USAGE::TOOLING_HOLE );
515
516 if( !m_featuresList.empty() )
517 {
520 ODB_ATTR::GEOMETRY{ "VIA_RoundD" + std::to_string( via->GetWidth( aLayer ) ) } );
521 }
522 }
523 else
524 {
525 // to draw via copper shape on copper layer
526 AddVia( via, aLayer );
527 subnet->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER, m_layerName, m_featuresList.size() - 1 );
528
529 if( !m_featuresList.empty() )
530 {
533 ODB_ATTR::GEOMETRY{ "VIA_RoundD" + std::to_string( via->GetWidth( aLayer ) ) } );
534 }
535 }
536 }
537}
538
539
541{
542 SHAPE_POLY_SET zone_shape = zone->GetFilledPolysList( aLayer )->CloneDropTriangulation();
543
544 for( int ii = 0; ii < zone_shape.OutlineCount(); ++ii )
545 {
546 AddContour( zone_shape, ii );
547
548 auto iter = GetODBPlugin()->GetPlaneSubnetMap().find( std::make_pair( aLayer, zone ) );
549
550 if( iter == GetODBPlugin()->GetPlaneSubnetMap().end() )
551 {
552 wxLogTrace( traceOdbppIo, wxT( "Failed to get subnet plane data" ) );
553 return;
554 }
555
556 iter->second->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER, m_layerName, m_featuresList.size() - 1 );
557
558 if( zone->IsTeardropArea() && !m_featuresList.empty() )
559 AddSystemAttribute( *m_featuresList.back(), ODB_ATTR::TEAR_DROP{ true } );
560 }
561};
562
563
565{
566 EDA_TEXT* text_item = nullptr;
567
568 if( PCB_TEXT* tmp_text = dynamic_cast<PCB_TEXT*>( item ) )
569 text_item = static_cast<EDA_TEXT*>( tmp_text );
570 else if( PCB_TEXTBOX* tmp_textbox = dynamic_cast<PCB_TEXTBOX*>( item ) )
571 text_item = static_cast<EDA_TEXT*>( tmp_textbox );
572
573 if( !text_item || !text_item->IsVisible() )
574 return;
575
576 wxString shownText = text_item->GetShownText( aContext );
577
578 if( shownText.empty() )
579 return;
580
581 auto plot_text =
582 [&]( const VECTOR2I& aPos, const wxString& aTextString, const TEXT_ATTRIBUTES& aAttributes,
583 KIFONT::FONT* aFont, const KIFONT::METRICS& aFontMetrics )
584 {
586
587 TEXT_ATTRIBUTES attributes = aAttributes;
588 int penWidth = attributes.m_StrokeWidth;
589
590 if( penWidth == 0 && attributes.m_Bold ) // Use default values if aPenWidth == 0
591 penWidth = GetPenSizeForBold( std::min( attributes.m_Size.x, attributes.m_Size.y ) );
592
593 if( penWidth < 0 )
594 penWidth = -penWidth;
595
596 attributes.m_StrokeWidth = penWidth;
597
598 std::list<VECTOR2I> pts;
599
600 auto push_pts =
601 [&]()
602 {
603 if( pts.size() < 2 )
604 return;
605
606 // Polylines are only allowed for more than 3 points.
607 // Otherwise, we have to use a line
608
609 if( pts.size() < 3 )
610 {
611 PCB_SHAPE shape( nullptr, SHAPE_T::SEGMENT );
612 shape.SetStart( pts.front() );
613 shape.SetEnd( pts.back() );
614 shape.SetWidth( attributes.m_StrokeWidth );
615
616 AddShape( shape );
618 ODB_ATTR::STRING{ aTextString.ToStdString() } );
619 }
620 else
621 {
622 for( auto it = pts.begin(); std::next( it ) != pts.end(); ++it )
623 {
624 auto it2 = std::next( it );
625 PCB_SHAPE shape( nullptr, SHAPE_T::SEGMENT );
626 shape.SetStart( *it );
627 shape.SetEnd( *it2 );
628 shape.SetWidth( attributes.m_StrokeWidth );
629 AddShape( shape );
630
631 if( !m_featuresList.empty() )
632 {
634 ODB_ATTR::STRING{ aTextString.ToStdString() } );
635 }
636 }
637 }
638
639 pts.clear();
640 };
641
642 CALLBACK_GAL callback_gal(
643 empty_opts,
644 // Stroke callback
645 [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
646 {
647 if( !pts.empty() )
648 {
649 if( aPt1 == pts.back() )
650 pts.push_back( aPt2 );
651 else if( aPt2 == pts.front() )
652 pts.push_front( aPt1 );
653 else if( aPt1 == pts.front() )
654 pts.push_front( aPt2 );
655 else if( aPt2 == pts.back() )
656 pts.push_back( aPt1 );
657 else
658 {
659 push_pts();
660 pts.push_back( aPt1 );
661 pts.push_back( aPt2 );
662 }
663 }
664 else
665 {
666 pts.push_back( aPt1 );
667 pts.push_back( aPt2 );
668 }
669 },
670 // Polygon callback
671 [&]( const SHAPE_LINE_CHAIN& aPoly )
672 {
673 if( aPoly.PointCount() < 3 )
674 return;
675
676 SHAPE_POLY_SET poly_set;
677 poly_set.AddOutline( aPoly );
678
679 for( int ii = 0; ii < poly_set.OutlineCount(); ++ii )
680 {
681 AddContour( poly_set, ii, FILL_T::FILLED_SHAPE );
682
683 if( !m_featuresList.empty() )
684 {
686 ODB_ATTR::STRING{ aTextString.ToStdString() } );
687 }
688 }
689 } );
690
691 aFont->Draw( &callback_gal, aTextString, aPos, aAttributes, aFontMetrics );
692
693 if( !pts.empty() )
694 push_pts();
695 };
696
697 PCB_TEXT* text = nullptr;
698 PCB_TEXTBOX* textbox = nullptr;
699 bool isKnockout = false;
700
701 if( item->Type() == PCB_TEXT_T || item->Type() == PCB_FIELD_T )
702 {
703 text = static_cast<PCB_TEXT*>( item );
704 isKnockout = text->IsKnockout();
705 }
706 else if( item->Type() == PCB_TEXTBOX_T )
707 {
708 textbox = static_cast<PCB_TEXTBOX*>( item );
709 isKnockout = textbox->IsKnockout();
710 }
711
712 const KIFONT::METRICS& fontMetrics = item->GetFontMetrics();
713 KIFONT::FONT* font = text_item->GetDrawFont( nullptr );
714
715 VECTOR2I pos = text_item->GetTextPos();
716
717 TEXT_ATTRIBUTES attrs = text_item->GetAttributes();
718 attrs.m_StrokeWidth = text_item->GetEffectiveTextPenWidth();
719 attrs.m_Angle = text_item->GetDrawRotation();
720 attrs.m_Multiline = false;
721
722 if( isKnockout )
723 {
724 SHAPE_POLY_SET finalpolyset;
725 int maxError = m_board->GetDesignSettings().m_MaxError;
726
727 if( text )
728 text->TransformTextToPolySet( finalpolyset, 0, maxError, ERROR_INSIDE );
729 else if( textbox )
730 textbox->TransformTextToPolySet( finalpolyset, 0, maxError, ERROR_INSIDE );
731
732 finalpolyset.Fracture();
733
734 for( int ii = 0; ii < finalpolyset.OutlineCount(); ++ii )
735 {
736 AddContour( finalpolyset, ii, FILL_T::FILLED_SHAPE );
737
738 if( !m_featuresList.empty() )
739 AddSystemAttribute( *m_featuresList.back(), ODB_ATTR::STRING{ shownText.ToStdString() } );
740 }
741 }
742 else if( text_item->IsMultilineAllowed() )
743 {
744 std::vector<VECTOR2I> positions;
745 wxArrayString strings_list;
746 wxStringSplit( shownText, strings_list, '\n' );
747 positions.reserve( strings_list.Count() );
748
749 text_item->GetLinePositions( nullptr, positions, strings_list.Count() );
750
751 for( unsigned ii = 0; ii < strings_list.Count(); ii++ )
752 {
753 wxString& txt = strings_list.Item( ii );
754 plot_text( positions[ii], txt, attrs, font, fontMetrics );
755 }
756 }
757 else
758 {
759 plot_text( pos, shownText, attrs, font, fontMetrics );
760 }
761};
762
763
765{
766 // FOOTPRINT* fp = shape->GetParentFootprint();
767 AddShape( *shape, aLayer );
768};
769
770
772{
773 // A dimension is a PCB_TEXT subclass, so the value text is plotted via add_text.
774
775 AddText( aLayer, dimension, FOR_CANVAS );
776
777 PCB_SHAPE temp_shape;
778 temp_shape.SetStroke( STROKE_PARAMS( dimension->GetLineThickness(), LINE_STYLE::SOLID ) );
779 temp_shape.SetLayer( dimension->GetLayer() );
780
781 for( const std::shared_ptr<SHAPE>& shape : dimension->GetShapes() )
782 {
783 switch( shape->Type() )
784 {
785 case SH_SEGMENT:
786 {
787 const SEG& seg = static_cast<const SHAPE_SEGMENT*>( shape.get() )->GetSeg();
788
789 temp_shape.SetShape( SHAPE_T::SEGMENT );
790 temp_shape.SetStart( seg.A );
791 temp_shape.SetEnd( seg.B );
792
793 AddShape( aLayer, &temp_shape );
794 break;
795 }
796
797 case SH_CIRCLE:
798 {
799 VECTOR2I center( shape->Centre() );
800 int radius = static_cast<const SHAPE_CIRCLE*>( shape.get() )->GetRadius();
801
802 temp_shape.SetShape( SHAPE_T::CIRCLE );
803 temp_shape.SetFilled( false );
804 temp_shape.SetStart( center );
805 temp_shape.SetEnd( VECTOR2I( center.x + radius, center.y ) );
806
807 AddShape( aLayer, &temp_shape );
808 break;
809 }
810
811 default:
812 break;
813 }
814 }
815};
816
817
819{
820 auto iter = GetODBPlugin()->GetPadSubnetMap().find( pad );
821
822 if( iter == GetODBPlugin()->GetPadSubnetMap().end() )
823 {
824 wxLogTrace( traceOdbppIo, wxT( "Failed to get subnet top data" ) );
825 return;
826 }
827
828 if( aLayer != PCB_LAYER_ID::UNDEFINED_LAYER )
829 {
830 // FOOTPRINT* fp = pad->GetParentFootprint();
831
832 AddPadShape( *pad, aLayer );
833
834 iter->second->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER, m_layerName, m_featuresList.size() - 1 );
835
836 if( !m_featuresList.empty() )
838
839 if( !pad->HasHole() && !m_featuresList.empty() )
840 AddSystemAttribute( *m_featuresList.back(), ODB_ATTR::SMD{ true } );
841 }
842 else
843 {
844 // drill layer round hole or slot hole
845 if( m_layerName.Contains( "drill" ) )
846 {
847 // here we exchange round hole or slot hole into pad to draw in drill layer
848 PAD dummy( *pad );
849 dummy.Padstack().SetMode( PADSTACK::MODE::NORMAL );
850
851 if( pad->GetDrillSizeX() == pad->GetDrillSizeY() )
852 dummy.SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::CIRCLE ); // round hole shape
853 else
854 dummy.SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::OVAL ); // slot hole shape
855
856 dummy.SetOffset( PADSTACK::ALL_LAYERS, VECTOR2I( 0, 0 ) ); // use hole position not pad position
857 dummy.SetSize( PADSTACK::ALL_LAYERS, pad->GetDrillSize() );
858
859 AddPadShape( dummy, aLayer );
860
861 if( pad->GetAttribute() == PAD_ATTRIB::PTH )
862 {
863 // only plated holes link to subnet
864 iter->second->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::HOLE, m_layerName,
865 m_featuresList.size() - 1 );
866
867 if( !m_featuresList.empty() )
869 }
870 else
871 {
872 if( !m_featuresList.empty() )
874 }
875 }
876 }
877 // AddSystemAttribute( *m_featuresList.back(),
878 // ODB_ATTR::GEOMETRY{ "PAD_xxxx" } );
879};
880
881void FEATURES_MANAGER::InitFeatureList( PCB_LAYER_ID aLayer, std::vector<BOARD_ITEM*>& aItems )
882{
883 for( BOARD_ITEM* item : aItems )
884 {
885 switch( item->Type() )
886 {
887 case PCB_TRACE_T:
888 case PCB_ARC_T:
889 case PCB_VIA_T:
890 AddTrack( aLayer, static_cast<PCB_TRACK*>( item ) );
891 break;
892
893 case PCB_ZONE_T:
894 AddZone( aLayer, static_cast<ZONE*>( item ) );
895 break;
896
897 case PCB_PAD_T:
898 AddPad( aLayer, static_cast<PAD*>( item ) );
899 break;
900
901 case PCB_SHAPE_T:
902 AddShape( aLayer, static_cast<PCB_SHAPE*>( item ) );
903 break;
904
905 case PCB_TEXT_T:
906 case PCB_FIELD_T:
907 AddText( aLayer, item, FOR_CANVAS );
908 break;
909
910 case PCB_TEXTBOX_T:
911 AddText( aLayer, item, FOR_CANVAS );
912
913 if( static_cast<PCB_TEXTBOX*>( item )->IsBorderEnabled() )
914 AddShape( aLayer, static_cast<PCB_TEXTBOX*>( item ) );
915
916 break;
917
918 case PCB_TABLE_T:
920 {
921 PCB_TABLE* table = static_cast<PCB_TABLE*>( item );
922
923 for( PCB_TABLECELL* cell : table->GetCells() )
924 AddText( aLayer, cell, FOR_CANVAS );
925
926 table->DrawBorders(
927 [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2, const STROKE_PARAMS& aStroke )
928 {
929 int lineWidth = aStroke.GetWidth();
930
931 if( lineWidth > 0 )
932 AddFeatureLine( aPt1, aPt2, lineWidth );
933 } );
934
935 break;
936 }
937
939 case PCB_DIM_LEADER_T:
940 case PCB_DIM_CENTER_T:
941 case PCB_DIM_RADIAL_T:
943 AddDimension( aLayer, static_cast<PCB_DIMENSION_BASE*>( item ) );
944 break;
945
946 case PCB_TARGET_T:
947 //TODO: Add support for targets
948 break;
949
950 case PCB_BARCODE_T:
951 {
952 const PCB_BARCODE* barcode = static_cast<const PCB_BARCODE*>( item );
953 SHAPE_POLY_SET poly_set;
954
955 barcode->TransformShapeToPolygon( poly_set, aLayer, 0, m_board->GetDesignSettings().m_MaxError,
956 ERROR_INSIDE );
957 poly_set.Fracture();
958
959 for( int ii = 0; ii < poly_set.OutlineCount(); ++ii )
960 AddContour( poly_set, ii, FILL_T::FILLED_SHAPE );
961
962 break;
963 }
964
965 default:
966 break;
967 }
968 }
969}
970
971
973{
974 if( !aVia->FlashLayer( aLayer ) )
975 return;
976
977 PAD dummy( nullptr ); // default pad shape is circle
978 dummy.SetPadstack( aVia->Padstack() );
979 dummy.SetPosition( aVia->GetStart() );
980
981 AddPadShape( dummy, aLayer );
982}
983
984
986{
987 PAD dummy( nullptr );
988 dummy.SetPadstackMode( PADSTACK::MODE::NORMAL );
990 dummy.SetPosition( aVia->GetStart() );
991 dummy.SetSize( PADSTACK::ALL_LAYERS, VECTOR2I( aVia->GetDrillValue(), aVia->GetDrillValue() ) );
992
993 AddPadShape( dummy, aLayer );
994}
995
996
997void FEATURES_MANAGER::GenerateProfileFeatures( std::ostream& ost ) const
998{
999 ost << "UNITS=" << PCB_IO_ODBPP::m_unitsStr << std::endl;
1000 ost << "#\n#Num Features\n#" << std::endl;
1001 ost << "F " << m_featuresList.size() << std::endl;
1002
1003 if( m_featuresList.empty() )
1004 return;
1005
1006 ost << "#\n#Layer features\n#" << std::endl;
1007
1008 for( const auto& feat : m_featuresList )
1009 {
1010 feat->WriteFeatures( ost );
1011 }
1012}
1013
1014
1015void FEATURES_MANAGER::GenerateFeatureFile( std::ostream& ost ) const
1016{
1017 ost << "UNITS=" << PCB_IO_ODBPP::m_unitsStr << std::endl;
1018 ost << "#\n#Num Features\n#" << std::endl;
1019 ost << "F " << m_featuresList.size() << std::endl << std::endl;
1020
1021 if( m_featuresList.empty() )
1022 return;
1023
1024 ost << "#\n#Feature symbol names\n#" << std::endl;
1025
1026 for( const auto& [n, name] : m_allSymMap )
1027 {
1028 ost << "$" << n << " " << name << std::endl;
1029 }
1030
1031 WriteAttributes( ost );
1032
1033 ost << "#\n#Layer features\n#" << std::endl;
1034
1035 for( const auto& feat : m_featuresList )
1036 {
1037 feat->WriteFeatures( ost );
1038 }
1039}
1040
1041
1042void ODB_FEATURE::WriteFeatures( std::ostream& ost )
1043{
1044 switch( GetFeatureType() )
1045 {
1046 case FEATURE_TYPE::LINE: ost << "L "; break;
1047
1048 case FEATURE_TYPE::ARC: ost << "A "; break;
1049
1050 case FEATURE_TYPE::PAD: ost << "P "; break;
1051
1052 case FEATURE_TYPE::SURFACE: ost << "S "; break;
1053 default: return;
1054 }
1055
1056 WriteRecordContent( ost );
1057 ost << std::endl;
1058}
1059
1060
1061void ODB_LINE::WriteRecordContent( std::ostream& ost )
1062{
1063 ost << m_start.first << " " << m_start.second << " " << m_end.first << " " << m_end.second
1064 << " " << m_symIndex << " P 0";
1065
1066 WriteAttributes( ost );
1067}
1068
1069
1070void ODB_ARC::WriteRecordContent( std::ostream& ost )
1071{
1072 ost << m_start.first << " " << m_start.second << " " << m_end.first << " " << m_end.second
1073 << " " << m_center.first << " " << m_center.second << " " << m_symIndex << " P 0 "
1074 << ( m_direction == ODB_DIRECTION::CW ? "Y" : "N" );
1075
1076 WriteAttributes( ost );
1077}
1078
1079
1080void ODB_PAD::WriteRecordContent( std::ostream& ost )
1081{
1082 ost << m_center.first << " " << m_center.second << " ";
1083
1084 // TODO: support resize symbol
1085 // ost << "-1" << " " << m_symIndex << " "
1086 // << m_resize << " P 0 ";
1087
1088 ost << m_symIndex << " P 0 ";
1089
1090 if( m_mirror )
1091 ost << "9 " << ODB::Double2String( m_angle.Normalize().AsDegrees() );
1092 else
1093 ost << "8 " << ODB::Double2String( ( ANGLE_360 - m_angle ).Normalize().AsDegrees() );
1094
1095 WriteAttributes( ost );
1096}
1097
1098
1099ODB_SURFACE::ODB_SURFACE( uint32_t aIndex, const SHAPE_POLY_SET::POLYGON& aPolygon,
1100 FILL_T aFillType /*= FILL_T::FILLED_SHAPE*/ ) : ODB_FEATURE( aIndex )
1101{
1102 if( !aPolygon.empty() && aPolygon[0].PointCount() >= 3 )
1103 {
1104 m_surfaces = std::make_unique<ODB_SURFACE_DATA>( aPolygon );
1105 if( aFillType != FILL_T::NO_FILL )
1106 {
1107 m_surfaces->AddPolygonHoles( aPolygon );
1108 }
1109 }
1110 else
1111 {
1112 delete this;
1113 }
1114}
1115
1116
1117void ODB_SURFACE::WriteRecordContent( std::ostream& ost )
1118{
1119 ost << "P 0";
1120 WriteAttributes( ost );
1121 ost << std::endl;
1122 m_surfaces->WriteData( ost );
1123 ost << "SE";
1124}
1125
1126
1128{
1129 const std::vector<VECTOR2I>& pts = aPolygon[0].CPoints();
1130 if( !pts.empty() )
1131 {
1132 if( m_polygons.empty() )
1133 {
1134 m_polygons.resize( 1 );
1135 }
1136
1137 m_polygons.at( 0 ).reserve( pts.size() );
1138 m_polygons.at( 0 ).emplace_back( pts.back() );
1139
1140 for( size_t jj = 0; jj < pts.size(); ++jj )
1141 {
1142 m_polygons.at( 0 ).emplace_back( pts.at( jj ) );
1143 }
1144 }
1145}
1146
1147
1149{
1150 for( size_t ii = 1; ii < aPolygon.size(); ++ii )
1151 {
1152 wxCHECK2( aPolygon[ii].PointCount() >= 3, continue );
1153
1154 const std::vector<VECTOR2I>& hole = aPolygon[ii].CPoints();
1155
1156 if( hole.empty() )
1157 continue;
1158
1159 if( m_polygons.size() <= ii )
1160 {
1161 m_polygons.resize( ii + 1 );
1162
1163 m_polygons[ii].reserve( hole.size() );
1164 }
1165
1166 m_polygons.at( ii ).emplace_back( hole.back() );
1167
1168 for( size_t jj = 0; jj < hole.size(); ++jj )
1169 {
1170 m_polygons.at( ii ).emplace_back( hole[jj] );
1171 }
1172 }
1173}
1174
1175
1176void ODB_SURFACE_DATA::WriteData( std::ostream& ost ) const
1177{
1178 ODB::CHECK_ONCE is_island;
1179
1180 for( const auto& contour : m_polygons )
1181 {
1182 if( contour.empty() )
1183 continue;
1184
1185 ost << "OB " << ODB::AddXY( contour.back().m_end ).first << " "
1186 << ODB::AddXY( contour.back().m_end ).second << " ";
1187
1188 if( is_island() )
1189 ost << "I";
1190 else
1191 ost << "H";
1192 ost << std::endl;
1193
1194 for( const auto& line : contour )
1195 {
1196 if( SURFACE_LINE::LINE_TYPE::SEGMENT == line.m_type )
1197 ost << "OS " << ODB::AddXY( line.m_end ).first << " "
1198 << ODB::AddXY( line.m_end ).second << std::endl;
1199 else
1200 ost << "OC " << ODB::AddXY( line.m_end ).first << " "
1201 << ODB::AddXY( line.m_end ).second << " " << ODB::AddXY( line.m_center ).first
1202 << " " << ODB::AddXY( line.m_center ).second << " "
1203 << ( line.m_direction == ODB_DIRECTION::CW ? "Y" : "N" ) << std::endl;
1204 }
1205 ost << "OE" << std::endl;
1206 }
1207}
const char * name
@ ERROR_OUTSIDE
@ ERROR_INSIDE
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:995
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
virtual bool IsKnockout() const
Definition board_item.h:413
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
FOOTPRINT * GetParentFootprint() const
const KIFONT::METRICS & GetFontMetrics() const
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
int GetEllipseMinorRadius() const
Definition eda_shape.h:395
const VECTOR2I & GetEllipseCenter() const
Definition eda_shape.h:377
const SHAPE_POLY_SET & GetHatching() const
EDA_ANGLE GetEllipseEndAngle() const
Definition eda_shape.h:423
int GetEllipseMajorRadius() const
Definition eda_shape.h:386
int GetRectangleWidth() const
SHAPE_POLY_SET & GetPolyShape()
EDA_ANGLE GetEllipseRotation() const
Definition eda_shape.h:404
int GetRadius() const
SHAPE_T GetShape() const
Definition eda_shape.h:175
bool IsHatchedFill() const
Definition eda_shape.h:130
virtual void SetFilled(bool aFlag)
Definition eda_shape.h:142
bool IsSolidFill() const
Definition eda_shape.h:123
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:325
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:275
std::vector< VECTOR2I > GetRectCorners() const
EDA_ANGLE GetEllipseStartAngle() const
Definition eda_shape.h:414
const std::vector< VECTOR2I > & GetBezierPoints() const
Definition eda_shape.h:491
int GetRectangleHeight() const
bool IsClockwiseArc() const
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:94
virtual VECTOR2I GetTextPos() const
Definition eda_text.h:313
bool IsMultilineAllowed() const
Definition eda_text.h:236
virtual bool IsVisible() const
Definition eda_text.h:226
virtual EDA_ANGLE GetDrawRotation() const
Definition eda_text.h:419
virtual wxString GetShownText(RESOLUTION_CONTEXT aContext, int aDepth=0) const
Return the string actually shown after processing of the base text.
Definition eda_text.h:128
virtual KIFONT::FONT * GetDrawFont(const RENDER_SETTINGS *aSettings) const
Definition eda_text.cpp:630
const TEXT_ATTRIBUTES & GetAttributes() const
Definition eda_text.h:270
int GetEffectiveTextPenWidth(int aDefaultPenWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
Definition eda_text.cpp:422
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:914
void AddPadShape(const PAD &aPad, PCB_LAYER_ID aLayer)
uint32_t AddRectSymbol(const wxString &aWidth, const wxString &aHeight)
void AddPad(PCB_LAYER_ID aLayer, PAD *pad)
void AddVia(const PCB_VIA *aVia, PCB_LAYER_ID aLayer)
void AddDimension(PCB_LAYER_ID aLayer, PCB_DIMENSION_BASE *dimension)
PCB_IO_ODBPP * GetODBPlugin()
void AddShape(PCB_LAYER_ID aLayer, PCB_SHAPE *shape)
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 AddTrack(PCB_LAYER_ID aLayer, PCB_TRACK *track)
void AddZone(PCB_LAYER_ID aLayer, ZONE *zone)
void AddText(PCB_LAYER_ID aLayer, BOARD_ITEM *item, RESOLUTION_CONTEXT aContext)
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)
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:660
FONT is an abstract base class for both outline and stroke fonts.
Definition font.h:94
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:170
static constexpr PCB_LAYER_ID ALL_LAYERS
! The layer identifier to use for the single defintion on normal padstacks
Definition padstack.h:179
Definition pad.h:61
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:3715
int GetRoundRectCornerRadius(PCB_LAYER_ID aLayer) const
Definition pad.cpp:1170
PAD_SHAPE GetShape(PCB_LAYER_ID aLayer) const
Definition pad.h:205
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:3010
int GetSolderMaskExpansion(PCB_LAYER_ID aLayer) const
Definition pad.cpp:1979
VECTOR2I GetSize(PCB_LAYER_ID aLayer) const
Definition pad.cpp:288
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition pad.cpp:1747
int GetChamferPositions(PCB_LAYER_ID aLayer) const
Definition pad.h:847
double GetChamferRectRatio(PCB_LAYER_ID aLayer) const
Definition pad.h:830
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:2042
VECTOR2I ShapePos(PCB_LAYER_ID aLayer) const
Definition pad.cpp:1855
bool IsDegenerated(int aThreshold=5) const
const VECTOR2I & GetMid() const
Definition pcb_track.h:287
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.
int GetLineThickness() const
const std::vector< std::shared_ptr< SHAPE > > & GetShapes() const
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:78
void SetWidth(int aWidth) override
int GetWidth() const override
void SetShape(SHAPE_T aShape) override
Definition pcb_shape.h:207
void SetEnd(const VECTOR2I &aEnd) override
void SetArcGeometry(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
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 SetStart(const VECTOR2I &aStart) override
void SetStroke(const STROKE_PARAMS &aStroke) override
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...
const VECTOR2I & GetStart() const
Definition pcb_track.h:93
const VECTOR2I & GetEnd() const
Definition pcb_track.h:90
virtual int GetWidth() const
Definition pcb_track.h:87
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:418
int GetDrillValue() const
Calculate the drill value for vias (m_drill if > 0, or default drill value for the board).
Definition seg.h:38
VECTOR2I A
Definition seg.h:45
VECTOR2I B
Definition seg.h:46
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:70
std::shared_ptr< SHAPE_POLY_SET > GetFilledPolysList(PCB_LAYER_ID aLayer) const
Definition zone.h:692
bool IsTeardropArea() const
Definition zone.h:782
RESOLUTION_CONTEXT
Definition common.h:87
@ FOR_CANVAS
Definition common.h:88
@ CHAMFER_ALL_CORNERS
All angles are chamfered.
@ ROUND_ALL_CORNERS
All angles are rounded.
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:422
static constexpr EDA_ANGLE ANGLE_360
Definition eda_angle.h:428
FILL_T
Definition eda_fill.h:29
@ FILLED_SHAPE
Fill with object color.
Definition eda_fill.h:31
@ ELLIPSE
Definition eda_shape.h:62
@ SEGMENT
Definition eda_shape.h:56
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:57
@ ELLIPSE_ARC
Definition eda_shape.h:63
int GetPenSizeForBold(int aTextSize)
Definition gr_text.cpp:33
const wxChar *const traceOdbppIo
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ F_Paste
Definition layer_ids.h:100
@ B_Mask
Definition layer_ids.h:94
@ F_Mask
Definition layer_ids.h:93
@ B_Paste
Definition layer_ids.h:101
@ UNDEFINED_LAYER
Definition layer_ids.h:57
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:411
ODB_DIRECTION
Definition odb_feature.h:34
@ PTH
Plated through hole pad.
Definition padstack.h:97
@ CHAMFERED_RECT
Definition padstack.h:59
@ ROUNDRECT
Definition padstack.h:56
@ TRAPEZOID
Definition padstack.h:55
@ RECTANGLE
Definition padstack.h:53
BARCODE class definition.
@ SH_CIRCLE
circle
Definition shape.h:46
@ SH_SEGMENT
line segment
Definition shape.h:44
std::vector< FAB_LAYER_COLOR > dummy
void wxStringSplit(const wxString &aText, wxArrayString &aStrings, wxChar aSplitter)
Split aString to a string list separated at aSplitter.
VECTOR2I center
const SHAPE_LINE_CHAIN chain
int radius
VECTOR2I end
wxLogTrace helper definitions.
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition typeinfo.h:80
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition typeinfo.h:98
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition typeinfo.h:95
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition typeinfo.h:89
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition typeinfo.h:96
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition typeinfo.h:85
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition typeinfo.h:100
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition typeinfo.h:84
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
Definition typeinfo.h:82
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
Definition typeinfo.h:93
@ PCB_TARGET_T
class PCB_TARGET, a target (graphic item)
Definition typeinfo.h:99
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition typeinfo.h:94
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition typeinfo.h:79
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition typeinfo.h:90
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
Definition typeinfo.h:86
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition typeinfo.h:88
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
Definition typeinfo.h:97
@ PCB_DRILL_CHART_T
class PCB_DRILL_CHART, a live drill chart derived from PCB_TABLE
Definition typeinfo.h:239
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683