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 "zone.h"
36#include "board.h"
38#include "geometry/eda_angle.h"
42#include "odb_eda_data.h"
43#include "pcb_io_odbpp.h"
44#include <callback_gal.h>
45#include <string_utils.h>
46
47
48void FEATURES_MANAGER::AddFeatureLine( const VECTOR2I& aStart, const VECTOR2I& aEnd,
49 uint64_t aWidth )
50{
51 AddFeature<ODB_LINE>( ODB::AddXY( aStart ), ODB::AddXY( aEnd ),
53}
54
55
56void FEATURES_MANAGER::AddFeatureArc( const VECTOR2I& aStart, const VECTOR2I& aEnd,
57 const VECTOR2I& aCenter, uint64_t aWidth,
58 ODB_DIRECTION aDirection )
59{
60 AddFeature<ODB_ARC>( ODB::AddXY( aStart ), ODB::AddXY( aEnd ), ODB::AddXY( aCenter ),
61 AddCircleSymbol( ODB::SymDouble2String( aWidth ) ), aDirection );
62}
63
64
65void FEATURES_MANAGER::AddPadCircle( const VECTOR2I& aCenter, uint64_t aDiameter,
66 const EDA_ANGLE& aAngle, bool aMirror,
67 double aResize /*= 1.0 */ )
68{
70 AddCircleSymbol( ODB::SymDouble2String( aDiameter ) ), aAngle, aMirror,
71 aResize );
72}
73
74
75bool FEATURES_MANAGER::AddContour( const SHAPE_POLY_SET& aPolySet, int aOutline /*= 0*/,
76 FILL_T aFillType /*= FILL_T::FILLED_SHAPE*/ )
77{
78 // todo: args modify aPolySet.Polygon( aOutline ) instead of aPolySet
79
80 if( aPolySet.OutlineCount() < ( aOutline + 1 ) )
81 return false;
82
83 AddFeatureSurface( aPolySet.Polygon( aOutline ), aFillType );
84
85 return true;
86}
87
88
90{
91 int stroke_width = aShape.GetWidth();
92
93 switch( aShape.GetShape() )
94 {
95 case SHAPE_T::CIRCLE:
96 {
97 int diameter = aShape.GetRadius() * 2;
99 wxString innerDim = ODB::SymDouble2String( ( diameter - stroke_width / 2 ) );
100 wxString outerDim = ODB::SymDouble2String( ( stroke_width + diameter ) );
101
102 if( aShape.IsSolidFill() )
104 else
105 AddFeature<ODB_PAD>( ODB::AddXY( center ), AddRoundDonutSymbol( outerDim, innerDim ) );
106
107 break;
108 }
109
111 {
112 // ODB++ donut_rc symbols degenerate when the corner radius is smaller than half the
113 // line width, and some viewers drop the feature entirely. Emit the rectangle as a
114 // filled pad for the fill (if any) plus four line segments for the stroke, matching
115 // how a rectangle drawn with the line tool is exported.
116 if( aShape.IsSolidFill() )
117 {
118 int width = std::abs( aShape.GetRectangleWidth() );
119 int height = std::abs( aShape.GetRectangleHeight() );
121
124 ODB::SymDouble2String( height ) ) );
125 }
126
127 if( stroke_width > 0 )
128 {
129 std::vector<VECTOR2I> corners = aShape.GetRectCorners();
130
131 for( size_t ii = 0; ii < corners.size(); ++ii )
132 AddFeatureLine( corners[ii], corners[( ii + 1 ) % corners.size()], stroke_width );
133 }
134
135 break;
136 }
137
138 case SHAPE_T::POLY:
139 {
140 int soldermask_min_thickness = 0;
141
142 // TODO: check if soldermask_min_thickness should be Stroke width
143
144 if( aLayer != UNDEFINED_LAYER && LSET( { F_Mask, B_Mask } ).Contains( aLayer ) )
145 soldermask_min_thickness = stroke_width;
146
147 int maxError = m_board->GetDesignSettings().m_MaxError;
148 SHAPE_POLY_SET poly_set;
149
150 if( soldermask_min_thickness == 0 )
151 {
152 poly_set = aShape.GetPolyShape().CloneDropTriangulation();
153 poly_set.Fracture();
154 }
155 else
156 {
157 SHAPE_POLY_SET initialPolys;
158
159 // add shapes inflated by aMinThickness/2 in areas
160 aShape.TransformShapeToPolygon( initialPolys, aLayer, 0, maxError, ERROR_OUTSIDE );
161 aShape.TransformShapeToPolygon( poly_set, aLayer, soldermask_min_thickness / 2 - 1,
162 maxError, ERROR_OUTSIDE );
163
164 poly_set.Simplify();
165 poly_set.Deflate( soldermask_min_thickness / 2 - 1,
167 poly_set.BooleanAdd( initialPolys );
168 poly_set.Fracture();
169 }
170
171 // ODB++ surface features can only represent closed polygons. We add a surface for
172 // the fill of the shape, if present, and add line segments for the outline, if present.
173 if( aShape.IsSolidFill() )
174 {
175 for( int ii = 0; ii < poly_set.OutlineCount(); ++ii )
176 {
177 AddContour( poly_set, ii, FILL_T::FILLED_SHAPE );
178
179 if( stroke_width != 0 )
180 {
181 for( int jj = 0; jj < poly_set.COutline( ii ).SegmentCount(); ++jj )
182 {
183 const SEG& seg = poly_set.COutline( ii ).CSegment( jj );
184 AddFeatureLine( seg.A, seg.B, stroke_width );
185 }
186 }
187 }
188 }
189 else
190 {
191 for( int ii = 0; ii < poly_set.OutlineCount(); ++ii )
192 {
193 for( int jj = 0; jj < poly_set.COutline( ii ).SegmentCount(); ++jj )
194 {
195 const SEG& seg = poly_set.COutline( ii ).CSegment( jj );
196 AddFeatureLine( seg.A, seg.B, stroke_width );
197 }
198 }
199 }
200
201 break;
202 }
203
204 case SHAPE_T::ARC:
205 {
207
208 AddFeatureArc( aShape.GetStart(), aShape.GetEnd(), aShape.GetCenter(), stroke_width, dir );
209 break;
210 }
211
212 case SHAPE_T::BEZIER:
213 {
214 const std::vector<VECTOR2I>& points = aShape.GetBezierPoints();
215
216 for( size_t i = 0; i < points.size() - 1; i++ )
217 AddFeatureLine( points[i], points[i + 1], stroke_width );
218
219 break;
220 }
221
222 case SHAPE_T::SEGMENT:
223 AddFeatureLine( aShape.GetStart(), aShape.GetEnd(), stroke_width );
224 break;
225
226 case SHAPE_T::ELLIPSE:
227 {
228 int maxError = m_board->GetDesignSettings().m_MaxError;
229
231 aShape.GetEllipseRotation() );
232
234 chain.SetClosed( true );
235
236 if( aShape.IsSolidFill() )
237 {
238 SHAPE_POLY_SET poly_set;
239 poly_set.AddOutline( chain );
240 poly_set.Fracture();
241
242 for( int ii = 0; ii < poly_set.OutlineCount(); ++ii )
243 AddContour( poly_set, ii, FILL_T::FILLED_SHAPE );
244 }
245
246 if( stroke_width > 0 )
247 {
248 for( int ii = 0; ii < chain.SegmentCount(); ++ii )
249 {
250 const SEG& seg = chain.CSegment( ii );
251 AddFeatureLine( seg.A, seg.B, stroke_width );
252 }
253 }
254
255 break;
256 }
257
259 {
260 int maxError = m_board->GetDesignSettings().m_MaxError;
261
263 aShape.GetEllipseRotation(), aShape.GetEllipseStartAngle(), aShape.GetEllipseEndAngle() );
264
266
267 for( int ii = 0; ii < chain.SegmentCount(); ++ii )
268 {
269 const SEG& seg = chain.CSegment( ii );
270 AddFeatureLine( seg.A, seg.B, stroke_width );
271 }
272
273 break;
274 }
275
276 default:
277 wxLogError( wxT( "Unknown shape when adding ODB++ layer feature" ) );
278 break;
279 }
280
281 if( aShape.IsHatchedFill() )
282 {
283 for( int ii = 0; ii < aShape.GetHatching().OutlineCount(); ++ii )
285 }
286}
287
288
290 FILL_T aFillType /*= FILL_T::FILLED_SHAPE */ )
291{
292 AddFeature<ODB_SURFACE>( aPolygon, aFillType );
293}
294
295
297{
298 FOOTPRINT* fp = aPad.GetParentFootprint();
299 bool mirror = false;
300
301 if( aPad.GetOrientation() != ANGLE_0 )
302 {
303 if( fp && fp->IsFlipped() )
304 mirror = true;
305 }
306
307 int maxError = m_board->GetDesignSettings().m_MaxError;
308
309 VECTOR2I expansion{ 0, 0 };
310
311 if( aLayer != UNDEFINED_LAYER && LSET( { F_Mask, B_Mask } ).Contains( aLayer ) )
312 expansion.x = expansion.y = aPad.GetSolderMaskExpansion( aLayer );
313
314 if( aLayer != UNDEFINED_LAYER && LSET( { F_Paste, B_Paste } ).Contains( aLayer ) )
315 expansion = aPad.GetSolderPasteMargin( aLayer );
316
317 int mask_clearance = expansion.x;
318
319 VECTOR2I plotSize = aPad.GetSize( aLayer ) + 2 * expansion;
320
321 VECTOR2I center = aPad.ShapePos( aLayer );
322
323 wxString width = ODB::SymDouble2String( std::abs( plotSize.x ) );
324 wxString height = ODB::SymDouble2String( std::abs( plotSize.y ) );
325
326 switch( aPad.GetShape( aLayer ) )
327 {
329 {
330 wxString diam = ODB::SymDouble2String( plotSize.x );
331
333 mirror );
334
335 break;
336 }
338 {
339 if( mask_clearance > 0 )
340 {
341 wxString rad = ODB::SymDouble2String( mask_clearance );
342
343 AddFeature<ODB_PAD>( ODB::AddXY( center ), AddRoundRectSymbol( width, height, rad ),
344 aPad.GetOrientation(), mirror );
345 }
346 else
347 {
349 aPad.GetOrientation(), mirror );
350 }
351
352 break;
353 }
354 case PAD_SHAPE::OVAL:
355 {
357 aPad.GetOrientation(), mirror );
358 break;
359 }
361 {
362 wxString rad = ODB::SymDouble2String( aPad.GetRoundRectCornerRadius( aLayer ) );
363
364 AddFeature<ODB_PAD>( ODB::AddXY( center ), AddRoundRectSymbol( width, height, rad ),
365 aPad.GetOrientation(), mirror );
366
367 break;
368 }
370 {
371 int shorterSide = std::min( plotSize.x, plotSize.y );
372 int chamfer = std::max(
373 0, KiROUND( aPad.GetChamferRectRatio( aLayer ) * shorterSide ) );
374 wxString rad = ODB::SymDouble2String( chamfer );
375 int positions = aPad.GetChamferPositions( aLayer );
376
378 AddChamferRectSymbol( width, height, rad, positions ),
379 aPad.GetOrientation(), mirror );
380
381 break;
382 }
384 {
385 SHAPE_POLY_SET outline;
386
387 aPad.TransformShapeToPolygon( outline, aLayer, 0, maxError, ERROR_INSIDE );
388
389 // Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
390 // which can create bad shapes if margin.x is < 0
391
392 if( mask_clearance )
393 {
395 maxError );
396 }
397
398 for( int ii = 0; ii < outline.OutlineCount(); ++ii )
399 AddContour( outline, ii );
400
401 break;
402 }
404 {
405 SHAPE_POLY_SET shape;
406 aPad.MergePrimitivesAsPolygon( aLayer, &shape );
407
408 // as for custome shape, odb++ don't rotate the polygon,
409 // so we rotate the polygon in kicad anticlockwise
410
411 shape.Rotate( aPad.GetOrientation() );
412 shape.Move( center );
413
414 if( expansion != VECTOR2I( 0, 0 ) )
415 {
416 shape.InflateWithLinkedHoles( std::max( expansion.x, expansion.y ),
418 }
419
420 for( int ii = 0; ii < shape.OutlineCount(); ++ii )
421 AddContour( shape, ii );
422
423 break;
424 }
425 default: wxLogError( wxT( "Unknown pad type" ) ); break;
426 }
427}
428
429
430void FEATURES_MANAGER::InitFeatureList( PCB_LAYER_ID aLayer, std::vector<BOARD_ITEM*>& aItems )
431{
432 auto add_track = [&]( PCB_TRACK* track )
433 {
434 auto iter = GetODBPlugin()->GetViaTraceSubnetMap().find( track );
435
436 if( iter == GetODBPlugin()->GetViaTraceSubnetMap().end() )
437 {
438 wxLogError( wxT( "Failed to get subnet track data" ) );
439 return;
440 }
441
442 auto subnet = iter->second;
443
444 if( track->Type() == PCB_TRACE_T )
445 {
446 PCB_SHAPE shape( nullptr, SHAPE_T::SEGMENT );
447 shape.SetStart( track->GetStart() );
448 shape.SetEnd( track->GetEnd() );
449 shape.SetWidth( track->GetWidth() );
450
451 AddShape( shape );
452 subnet->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER, m_layerName,
453 m_featuresList.size() - 1 );
454 }
455 else if( track->Type() == PCB_ARC_T )
456 {
457 PCB_ARC* arc = static_cast<PCB_ARC*>( track );
458 PCB_SHAPE shape( nullptr, SHAPE_T::ARC );
459 shape.SetArcGeometry( arc->GetStart(), arc->GetMid(), arc->GetEnd() );
460 shape.SetWidth( arc->GetWidth() );
461
462 AddShape( shape );
463
464 subnet->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER, m_layerName,
465 m_featuresList.size() - 1 );
466 }
467 else
468 {
469 // add via
470 PCB_VIA* via = static_cast<PCB_VIA*>( track );
471
472 bool hole = false;
473
474 if( aLayer != PCB_LAYER_ID::UNDEFINED_LAYER )
475 {
476 hole = m_layerName.Contains( "plugging" );
477 }
478 else
479 {
480 hole = m_layerName.Contains( "drill" ) || m_layerName.Contains( "filling" )
481 || m_layerName.Contains( "capping" );
482 }
483
484 if( hole )
485 {
486 AddViaDrillHole( via, aLayer );
487 subnet->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::HOLE, m_layerName,
488 m_featuresList.size() - 1 );
489
490 // TODO: confirm TOOLING_HOLE
491 // AddSystemAttribute( *m_featuresList.back(), ODB_ATTR::PAD_USAGE::TOOLING_HOLE );
492
493 if( !m_featuresList.empty() )
494 {
497 *m_featuresList.back(),
498 ODB_ATTR::GEOMETRY{ "VIA_RoundD" + std::to_string( via->GetWidth( aLayer ) ) } );
499 }
500 }
501 else
502 {
503 // to draw via copper shape on copper layer
504 AddVia( via, aLayer );
505 subnet->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER, m_layerName,
506 m_featuresList.size() - 1 );
507
508 if( !m_featuresList.empty() )
509 {
512 *m_featuresList.back(),
513 ODB_ATTR::GEOMETRY{ "VIA_RoundD" + std::to_string( via->GetWidth( aLayer ) ) } );
514 }
515 }
516 }
517 };
518
519 auto add_zone = [&]( ZONE* zone )
520 {
521 SHAPE_POLY_SET zone_shape = zone->GetFilledPolysList( aLayer )->CloneDropTriangulation();
522
523 for( int ii = 0; ii < zone_shape.OutlineCount(); ++ii )
524 {
525 AddContour( zone_shape, ii );
526
527 auto iter = GetODBPlugin()->GetPlaneSubnetMap().find( std::make_pair( aLayer, zone ) );
528
529 if( iter == GetODBPlugin()->GetPlaneSubnetMap().end() )
530 {
531 wxLogError( wxT( "Failed to get subnet plane data" ) );
532 return;
533 }
534
535 iter->second->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER, m_layerName,
536 m_featuresList.size() - 1 );
537
538 if( zone->IsTeardropArea() && !m_featuresList.empty() )
539 AddSystemAttribute( *m_featuresList.back(), ODB_ATTR::TEAR_DROP{ true } );
540 }
541 };
542
543 auto add_text = [&]( BOARD_ITEM* item )
544 {
545 EDA_TEXT* text_item = nullptr;
546
547 if( PCB_TEXT* tmp_text = dynamic_cast<PCB_TEXT*>( item ) )
548 text_item = static_cast<EDA_TEXT*>( tmp_text );
549 else if( PCB_TEXTBOX* tmp_textbox = dynamic_cast<PCB_TEXTBOX*>( item ) )
550 text_item = static_cast<EDA_TEXT*>( tmp_textbox );
551
552 if( !text_item || !text_item->IsVisible() || text_item->GetShownText( false ).empty() )
553 return;
554
555 auto plot_text = [&]( const VECTOR2I& aPos, const wxString& aTextString,
556 const TEXT_ATTRIBUTES& aAttributes, KIFONT::FONT* aFont,
557 const KIFONT::METRICS& aFontMetrics )
558 {
560
561 TEXT_ATTRIBUTES attributes = aAttributes;
562 int penWidth = attributes.m_StrokeWidth;
563
564 if( penWidth == 0 && attributes.m_Bold ) // Use default values if aPenWidth == 0
565 penWidth =
566 GetPenSizeForBold( std::min( attributes.m_Size.x, attributes.m_Size.y ) );
567
568 if( penWidth < 0 )
569 penWidth = -penWidth;
570
571 attributes.m_StrokeWidth = penWidth;
572
573 std::list<VECTOR2I> pts;
574
575 auto push_pts = [&]()
576 {
577 if( pts.size() < 2 )
578 return;
579
580 // Polylines are only allowed for more than 3 points.
581 // Otherwise, we have to use a line
582
583 if( pts.size() < 3 )
584 {
585 PCB_SHAPE shape( nullptr, SHAPE_T::SEGMENT );
586 shape.SetStart( pts.front() );
587 shape.SetEnd( pts.back() );
588 shape.SetWidth( attributes.m_StrokeWidth );
589
590 AddShape( shape );
592 ODB_ATTR::STRING{ aTextString.ToStdString() } );
593 }
594 else
595 {
596 for( auto it = pts.begin(); std::next( it ) != pts.end(); ++it )
597 {
598 auto it2 = std::next( it );
599 PCB_SHAPE shape( nullptr, SHAPE_T::SEGMENT );
600 shape.SetStart( *it );
601 shape.SetEnd( *it2 );
602 shape.SetWidth( attributes.m_StrokeWidth );
603 AddShape( shape );
604
605 if( !m_featuresList.empty() )
606 {
608 ODB_ATTR::STRING{ aTextString.ToStdString() } );
609 }
610 }
611 }
612
613 pts.clear();
614 };
615
616 CALLBACK_GAL callback_gal(
617 empty_opts,
618 // Stroke callback
619 [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
620 {
621 if( !pts.empty() )
622 {
623 if( aPt1 == pts.back() )
624 pts.push_back( aPt2 );
625 else if( aPt2 == pts.front() )
626 pts.push_front( aPt1 );
627 else if( aPt1 == pts.front() )
628 pts.push_front( aPt2 );
629 else if( aPt2 == pts.back() )
630 pts.push_back( aPt1 );
631 else
632 {
633 push_pts();
634 pts.push_back( aPt1 );
635 pts.push_back( aPt2 );
636 }
637 }
638 else
639 {
640 pts.push_back( aPt1 );
641 pts.push_back( aPt2 );
642 }
643 },
644 // Polygon callback
645 [&]( const SHAPE_LINE_CHAIN& aPoly )
646 {
647 if( aPoly.PointCount() < 3 )
648 return;
649
650 SHAPE_POLY_SET poly_set;
651 poly_set.AddOutline( aPoly );
652
653 for( int ii = 0; ii < poly_set.OutlineCount(); ++ii )
654 {
655 AddContour( poly_set, ii, FILL_T::FILLED_SHAPE );
656
657 if( !m_featuresList.empty() )
658 {
660 ODB_ATTR::STRING{ aTextString.ToStdString() } );
661 }
662 }
663 } );
664
665 aFont->Draw( &callback_gal, aTextString, aPos, aAttributes, aFontMetrics );
666
667 if( !pts.empty() )
668 push_pts();
669 };
670
671 bool isKnockout = false;
672
673 if( item->Type() == PCB_TEXT_T || item->Type() == PCB_FIELD_T )
674 isKnockout = static_cast<PCB_TEXT*>( item )->IsKnockout();
675 else if( item->Type() == PCB_TEXTBOX_T )
676 isKnockout = static_cast<PCB_TEXTBOX*>( item )->IsKnockout();
677
678 const KIFONT::METRICS& fontMetrics = item->GetFontMetrics();
679 KIFONT::FONT* font = text_item->GetDrawFont( nullptr );
680 wxString shownText( text_item->GetShownText( true ) );
681
682 if( shownText.IsEmpty() )
683 return;
684
685 VECTOR2I pos = text_item->GetTextPos();
686
687 TEXT_ATTRIBUTES attrs = text_item->GetAttributes();
688 attrs.m_StrokeWidth = text_item->GetEffectiveTextPenWidth();
689 attrs.m_Angle = text_item->GetDrawRotation();
690 attrs.m_Multiline = false;
691
692 if( isKnockout )
693 {
694 PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
695 SHAPE_POLY_SET finalpolyset;
696
697 text->TransformTextToPolySet( finalpolyset, 0, m_board->GetDesignSettings().m_MaxError,
698 ERROR_INSIDE );
699 finalpolyset.Fracture();
700
701 for( int ii = 0; ii < finalpolyset.OutlineCount(); ++ii )
702 {
703 AddContour( finalpolyset, ii, FILL_T::FILLED_SHAPE );
704
705 if( !m_featuresList.empty() )
706 {
708 ODB_ATTR::STRING{ shownText.ToStdString() } );
709 }
710 }
711 }
712 else if( text_item->IsMultilineAllowed() )
713 {
714 std::vector<VECTOR2I> positions;
715 wxArrayString strings_list;
716 wxStringSplit( shownText, strings_list, '\n' );
717 positions.reserve( strings_list.Count() );
718
719 text_item->GetLinePositions( nullptr, positions, strings_list.Count() );
720
721 for( unsigned ii = 0; ii < strings_list.Count(); ii++ )
722 {
723 wxString& txt = strings_list.Item( ii );
724 plot_text( positions[ii], txt, attrs, font, fontMetrics );
725 }
726 }
727 else
728 {
729 plot_text( pos, shownText, attrs, font, fontMetrics );
730 }
731 };
732
733
734 auto add_shape = [&]( PCB_SHAPE* shape )
735 {
736 // FOOTPRINT* fp = shape->GetParentFootprint();
737 AddShape( *shape, aLayer );
738 };
739
740 auto add_pad = [&]( PAD* pad )
741 {
742 auto iter = GetODBPlugin()->GetPadSubnetMap().find( pad );
743
744 if( iter == GetODBPlugin()->GetPadSubnetMap().end() )
745 {
746 wxLogError( wxT( "Failed to get subnet top data" ) );
747 return;
748 }
749
750 if( aLayer != PCB_LAYER_ID::UNDEFINED_LAYER )
751 {
752 // FOOTPRINT* fp = pad->GetParentFootprint();
753
754 AddPadShape( *pad, aLayer );
755
756 iter->second->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER, m_layerName,
757 m_featuresList.size() - 1 );
758 if( !m_featuresList.empty() )
760
761 if( !pad->HasHole() && !m_featuresList.empty() )
762 AddSystemAttribute( *m_featuresList.back(), ODB_ATTR::SMD{ true } );
763 }
764 else
765 {
766 // drill layer round hole or slot hole
767 if( m_layerName.Contains( "drill" ) )
768 {
769 // here we exchange round hole or slot hole into pad to draw in drill layer
770 PAD dummy( *pad );
771 dummy.Padstack().SetMode( PADSTACK::MODE::NORMAL );
772
773 if( pad->GetDrillSizeX() == pad->GetDrillSizeY() )
774 dummy.SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::CIRCLE ); // round hole shape
775 else
776 dummy.SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::OVAL ); // slot hole shape
777
778 dummy.SetOffset( PADSTACK::ALL_LAYERS,
779 VECTOR2I( 0, 0 ) ); // use hole position not pad position
780 dummy.SetSize( PADSTACK::ALL_LAYERS, pad->GetDrillSize() );
781
782 AddPadShape( dummy, aLayer );
783
784 if( pad->GetAttribute() == PAD_ATTRIB::PTH )
785 {
786 // only plated holes link to subnet
787 iter->second->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::HOLE, m_layerName,
788 m_featuresList.size() - 1 );
789
790 if( !m_featuresList.empty() )
792 }
793 else
794 {
795 if( !m_featuresList.empty() )
797 }
798 }
799 }
800 // AddSystemAttribute( *m_featuresList.back(),
801 // ODB_ATTR::GEOMETRY{ "PAD_xxxx" } );
802 };
803
804 for( BOARD_ITEM* item : aItems )
805 {
806 switch( item->Type() )
807 {
808 case PCB_TRACE_T:
809 case PCB_ARC_T:
810 case PCB_VIA_T:
811 add_track( static_cast<PCB_TRACK*>( item ) );
812 break;
813
814 case PCB_ZONE_T:
815 add_zone( static_cast<ZONE*>( item ) );
816 break;
817
818 case PCB_PAD_T:
819 add_pad( static_cast<PAD*>( item ) );
820 break;
821
822 case PCB_SHAPE_T:
823 add_shape( static_cast<PCB_SHAPE*>( item ) );
824 break;
825
826 case PCB_TEXT_T:
827 case PCB_FIELD_T:
828 add_text( item );
829 break;
830
831 case PCB_TEXTBOX_T:
832 add_text( item );
833
834 if( static_cast<PCB_TEXTBOX*>( item )->IsBorderEnabled() )
835 add_shape( static_cast<PCB_TEXTBOX*>( item ) );
836
837 break;
838
839 case PCB_TABLE_T:
840 {
841 PCB_TABLE* table = static_cast<PCB_TABLE*>( item );
842
843 for( PCB_TABLECELL* cell : table->GetCells() )
844 add_text( cell );
845
846 table->DrawBorders(
847 [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2, const STROKE_PARAMS& aStroke )
848 {
849 int lineWidth = aStroke.GetWidth();
850
851 if( lineWidth > 0 )
852 AddFeatureLine( aPt1, aPt2, lineWidth );
853 } );
854
855 break;
856 }
857
858 case PCB_DIMENSION_T:
859 case PCB_TARGET_T:
861 case PCB_DIM_LEADER_T:
862 case PCB_DIM_CENTER_T:
863 case PCB_DIM_RADIAL_T:
865 //TODO: Add support for dimensions
866 break;
867
868 case PCB_BARCODE_T:
869 //TODO: Add support for barcodes
870 break;
871
872 default:
873 break;
874 }
875 }
876}
877
878
880{
881 if( !aVia->FlashLayer( aLayer ) )
882 return;
883
884 PAD dummy( nullptr ); // default pad shape is circle
885 dummy.SetPadstack( aVia->Padstack() );
886 dummy.SetPosition( aVia->GetStart() );
887
888 AddPadShape( dummy, aLayer );
889}
890
891
893{
894 PAD dummy( nullptr ); // default pad shape is circle
895 int hole = aVia->GetDrillValue();
896 dummy.SetPosition( aVia->GetStart() );
897 dummy.SetSize( PADSTACK::ALL_LAYERS, VECTOR2I( hole, hole ) );
898
899 AddPadShape( dummy, aLayer );
900}
901
902
903void FEATURES_MANAGER::GenerateProfileFeatures( std::ostream& ost ) const
904{
905 ost << "UNITS=" << PCB_IO_ODBPP::m_unitsStr << std::endl;
906 ost << "#\n#Num Features\n#" << std::endl;
907 ost << "F " << m_featuresList.size() << std::endl;
908
909 if( m_featuresList.empty() )
910 return;
911
912 ost << "#\n#Layer features\n#" << std::endl;
913
914 for( const auto& feat : m_featuresList )
915 {
916 feat->WriteFeatures( ost );
917 }
918}
919
920
921void FEATURES_MANAGER::GenerateFeatureFile( std::ostream& ost ) const
922{
923 ost << "UNITS=" << PCB_IO_ODBPP::m_unitsStr << std::endl;
924 ost << "#\n#Num Features\n#" << std::endl;
925 ost << "F " << m_featuresList.size() << std::endl << std::endl;
926
927 if( m_featuresList.empty() )
928 return;
929
930 ost << "#\n#Feature symbol names\n#" << std::endl;
931
932 for( const auto& [n, name] : m_allSymMap )
933 {
934 ost << "$" << n << " " << name << std::endl;
935 }
936
937 WriteAttributes( ost );
938
939 ost << "#\n#Layer features\n#" << std::endl;
940
941 for( const auto& feat : m_featuresList )
942 {
943 feat->WriteFeatures( ost );
944 }
945}
946
947
948void ODB_FEATURE::WriteFeatures( std::ostream& ost )
949{
950 switch( GetFeatureType() )
951 {
952 case FEATURE_TYPE::LINE: ost << "L "; break;
953
954 case FEATURE_TYPE::ARC: ost << "A "; break;
955
956 case FEATURE_TYPE::PAD: ost << "P "; break;
957
958 case FEATURE_TYPE::SURFACE: ost << "S "; break;
959 default: return;
960 }
961
962 WriteRecordContent( ost );
963 ost << std::endl;
964}
965
966
967void ODB_LINE::WriteRecordContent( std::ostream& ost )
968{
969 ost << m_start.first << " " << m_start.second << " " << m_end.first << " " << m_end.second
970 << " " << m_symIndex << " P 0";
971
972 WriteAttributes( ost );
973}
974
975
976void ODB_ARC::WriteRecordContent( std::ostream& ost )
977{
978 ost << m_start.first << " " << m_start.second << " " << m_end.first << " " << m_end.second
979 << " " << m_center.first << " " << m_center.second << " " << m_symIndex << " P 0 "
980 << ( m_direction == ODB_DIRECTION::CW ? "Y" : "N" );
981
982 WriteAttributes( ost );
983}
984
985
986void ODB_PAD::WriteRecordContent( std::ostream& ost )
987{
988 ost << m_center.first << " " << m_center.second << " ";
989
990 // TODO: support resize symbol
991 // ost << "-1" << " " << m_symIndex << " "
992 // << m_resize << " P 0 ";
993
994 ost << m_symIndex << " P 0 ";
995
996 if( m_mirror )
997 ost << "9 " << ODB::Double2String( m_angle.Normalize().AsDegrees() );
998 else
999 ost << "8 " << ODB::Double2String( ( ANGLE_360 - m_angle ).Normalize().AsDegrees() );
1000
1001 WriteAttributes( ost );
1002}
1003
1004
1005ODB_SURFACE::ODB_SURFACE( uint32_t aIndex, const SHAPE_POLY_SET::POLYGON& aPolygon,
1006 FILL_T aFillType /*= FILL_T::FILLED_SHAPE*/ ) : ODB_FEATURE( aIndex )
1007{
1008 if( !aPolygon.empty() && aPolygon[0].PointCount() >= 3 )
1009 {
1010 m_surfaces = std::make_unique<ODB_SURFACE_DATA>( aPolygon );
1011 if( aFillType != FILL_T::NO_FILL )
1012 {
1013 m_surfaces->AddPolygonHoles( aPolygon );
1014 }
1015 }
1016 else
1017 {
1018 delete this;
1019 }
1020}
1021
1022
1023void ODB_SURFACE::WriteRecordContent( std::ostream& ost )
1024{
1025 ost << "P 0";
1026 WriteAttributes( ost );
1027 ost << std::endl;
1028 m_surfaces->WriteData( ost );
1029 ost << "SE";
1030}
1031
1032
1034{
1035 const std::vector<VECTOR2I>& pts = aPolygon[0].CPoints();
1036 if( !pts.empty() )
1037 {
1038 if( m_polygons.empty() )
1039 {
1040 m_polygons.resize( 1 );
1041 }
1042
1043 m_polygons.at( 0 ).reserve( pts.size() );
1044 m_polygons.at( 0 ).emplace_back( pts.back() );
1045
1046 for( size_t jj = 0; jj < pts.size(); ++jj )
1047 {
1048 m_polygons.at( 0 ).emplace_back( pts.at( jj ) );
1049 }
1050 }
1051}
1052
1053
1055{
1056 for( size_t ii = 1; ii < aPolygon.size(); ++ii )
1057 {
1058 wxCHECK2( aPolygon[ii].PointCount() >= 3, continue );
1059
1060 const std::vector<VECTOR2I>& hole = aPolygon[ii].CPoints();
1061
1062 if( hole.empty() )
1063 continue;
1064
1065 if( m_polygons.size() <= ii )
1066 {
1067 m_polygons.resize( ii + 1 );
1068
1069 m_polygons[ii].reserve( hole.size() );
1070 }
1071
1072 m_polygons.at( ii ).emplace_back( hole.back() );
1073
1074 for( size_t jj = 0; jj < hole.size(); ++jj )
1075 {
1076 m_polygons.at( ii ).emplace_back( hole[jj] );
1077 }
1078 }
1079}
1080
1081
1082void ODB_SURFACE_DATA::WriteData( std::ostream& ost ) const
1083{
1084 ODB::CHECK_ONCE is_island;
1085
1086 for( const auto& contour : m_polygons )
1087 {
1088 if( contour.empty() )
1089 continue;
1090
1091 ost << "OB " << ODB::AddXY( contour.back().m_end ).first << " "
1092 << ODB::AddXY( contour.back().m_end ).second << " ";
1093
1094 if( is_island() )
1095 ost << "I";
1096 else
1097 ost << "H";
1098 ost << std::endl;
1099
1100 for( const auto& line : contour )
1101 {
1102 if( SURFACE_LINE::LINE_TYPE::SEGMENT == line.m_type )
1103 ost << "OS " << ODB::AddXY( line.m_end ).first << " "
1104 << ODB::AddXY( line.m_end ).second << std::endl;
1105 else
1106 ost << "OC " << ODB::AddXY( line.m_end ).first << " "
1107 << ODB::AddXY( line.m_end ).second << " " << ODB::AddXY( line.m_center ).first
1108 << " " << ODB::AddXY( line.m_center ).second << " "
1109 << ( line.m_direction == ODB_DIRECTION::CW ? "Y" : "N" ) << std::endl;
1110 }
1111 ost << "OE" << std::endl;
1112 }
1113}
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
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
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:666
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:941
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:55
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:3275
int GetRoundRectCornerRadius(PCB_LAYER_ID aLayer) const
Definition pad.cpp:890
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
int GetSolderMaskExpansion(PCB_LAYER_ID aLayer) const
Definition pad.cpp:1679
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition pad.h:420
int GetChamferPositions(PCB_LAYER_ID aLayer) const
Definition pad.h:845
double GetChamferRectRatio(PCB_LAYER_ID aLayer) const
Definition pad.h:828
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:1742
VECTOR2I ShapePos(PCB_LAYER_ID aLayer) const
Definition pad.cpp:1558
const VECTOR2I & GetSize(PCB_LAYER_ID aLayer) const
Definition pad.h:264
const VECTOR2I & GetMid() const
Definition pcb_track.h:290
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 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.
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
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
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
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
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_DIMENSION_T
class PCB_DIMENSION_BASE: abstract dimension meta-type
Definition typeinfo.h:97
@ 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