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 (C) 2024 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#include <sstream>
23#include "pcb_shape.h"
24#include "odb_defines.h"
25#include "pcb_track.h"
26#include "pcb_textbox.h"
27#include "zone.h"
28#include "board.h"
30#include "geometry/eda_angle.h"
31#include "odb_eda_data.h"
32#include "pcb_io_odbpp.h"
33#include <map>
34#include "wx/log.h"
35#include <callback_gal.h>
36
37
38void FEATURES_MANAGER::AddFeatureLine( const VECTOR2I& aStart, const VECTOR2I& aEnd,
39 uint64_t aWidth )
40{
41 AddFeature<ODB_LINE>( ODB::AddXY( aStart ), ODB::AddXY( aEnd ),
43}
44
45
46void FEATURES_MANAGER::AddFeatureArc( const VECTOR2I& aStart, const VECTOR2I& aEnd,
47 const VECTOR2I& aCenter, uint64_t aWidth,
48 ODB_DIRECTION aDirection )
49{
50 AddFeature<ODB_ARC>( ODB::AddXY( aStart ), ODB::AddXY( aEnd ), ODB::AddXY( aCenter ),
51 AddCircleSymbol( ODB::SymDouble2String( aWidth ) ), aDirection );
52}
53
54
55void FEATURES_MANAGER::AddPadCircle( const VECTOR2I& aCenter, uint64_t aDiameter,
56 const EDA_ANGLE& aAngle, bool aMirror,
57 double aResize /*= 1.0 */ )
58{
59 AddFeature<ODB_PAD>( ODB::AddXY( aCenter ),
60 AddCircleSymbol( ODB::SymDouble2String( aDiameter ) ), aAngle, aMirror,
61 aResize );
62}
63
64
65bool FEATURES_MANAGER::AddContour( const SHAPE_POLY_SET& aPolySet, int aOutline /*= 0*/,
66 FILL_T aFillType /*= FILL_T::FILLED_SHAPE*/ )
67{
68 // todo: args modify aPolySet.Polygon( aOutline ) instead of aPolySet
69
70 if( aPolySet.OutlineCount() < ( aOutline + 1 ) )
71 return false;
72
73 AddFeatureSurface( aPolySet.Polygon( aOutline ), aFillType );
74
75 return true;
76}
77
78
80{
81 switch( aShape.GetShape() )
82 {
83 case SHAPE_T::CIRCLE:
84 {
85 int diameter = aShape.GetRadius() * 2;
86 int width = aShape.GetWidth();
87 VECTOR2I center = ODB::GetShapePosition( aShape );
88 wxString innerDim = ODB::SymDouble2String( ( diameter - width / 2 ) );
89 wxString outerDim = ODB::SymDouble2String( ( width + diameter ) );
90
91 if( aShape.GetFillMode() == FILL_T::NO_FILL )
92 {
93 AddFeature<ODB_PAD>( ODB::AddXY( center ), AddRoundDonutSymbol( outerDim, innerDim ) );
94 }
95 else
96 {
97 AddFeature<ODB_PAD>( ODB::AddXY( center ), AddCircleSymbol( outerDim ) );
98 }
99
100 break;
101 }
102
103 case SHAPE_T::RECTANGLE:
104 {
105 int stroke_width = aShape.GetWidth();
106 int width = std::abs( aShape.GetRectangleWidth() ) + stroke_width;
107 int height = std::abs( aShape.GetRectangleHeight() ) + stroke_width;
108 wxString rad = ODB::SymDouble2String( ( stroke_width / 2.0 ) );
109 VECTOR2I center = ODB::GetShapePosition( aShape );
110
111 if( aShape.GetFillMode() == FILL_T::NO_FILL )
112 {
113 AddFeature<ODB_PAD>( ODB::AddXY( center ),
115 ODB::SymDouble2String( height ),
116 ODB::SymDouble2String( stroke_width ),
117 rad ) );
118 }
119 else
120 {
121 AddFeature<ODB_PAD>( ODB::AddXY( center ),
123 ODB::SymDouble2String( height ), rad ) );
124 }
125
126 break;
127 }
128
129 case SHAPE_T::POLY:
130 {
131 int soldermask_min_thickness = 0;
132
133 // TODO: check if soldermask_min_thickness should be Stroke width
134
135 if( aLayer != UNDEFINED_LAYER && LSET( { F_Mask, B_Mask } ).Contains( aLayer ) )
136 soldermask_min_thickness = aShape.GetWidth();
137 int maxError = m_board->GetDesignSettings().m_MaxError;
138 SHAPE_POLY_SET poly_set;
139
140 if( soldermask_min_thickness == 0 )
141 {
142 poly_set = aShape.GetPolyShape().CloneDropTriangulation();
144 }
145 else
146 {
147 SHAPE_POLY_SET initialPolys;
148
149 // add shapes inflated by aMinThickness/2 in areas
150 aShape.TransformShapeToPolygon( initialPolys, aLayer, 0, maxError, ERROR_OUTSIDE );
151 aShape.TransformShapeToPolygon( poly_set, aLayer, soldermask_min_thickness / 2 - 1,
152 maxError, ERROR_OUTSIDE );
153
155 poly_set.Deflate( soldermask_min_thickness / 2 - 1,
156 CORNER_STRATEGY::CHAMFER_ALL_CORNERS, maxError );
157 poly_set.BooleanAdd( initialPolys, SHAPE_POLY_SET::PM_FAST );
159 }
160
161 for( int ii = 0; ii < poly_set.OutlineCount(); ++ii )
162 {
163 if( aShape.GetFillMode() != FILL_T::NO_FILL )
164 {
165 AddContour( poly_set, ii, FILL_T::FILLED_SHAPE );
166 }
167
168 AddContour( poly_set, ii, FILL_T::NO_FILL );
169 }
170
171 break;
172 }
173
174 case SHAPE_T::ARC:
175 {
176 ODB_DIRECTION dir = !aShape.IsClockwiseArc() ? ODB_DIRECTION::CW : ODB_DIRECTION::CCW;
177
178 AddFeatureArc( aShape.GetStart(), aShape.GetEnd(), aShape.GetCenter(),
179 aShape.GetStroke().GetWidth(), dir );
180
181 break;
182 }
183
184 case SHAPE_T::BEZIER:
185 {
186 const std::vector<VECTOR2I>& points = aShape.GetBezierPoints();
187
188 for( size_t i = 0; i < points.size(); i++ )
189 {
190 AddFeatureLine( points[i], points[i + 1], aShape.GetStroke().GetWidth() );
191 }
192
193 break;
194 }
195
196 case SHAPE_T::SEGMENT:
197 {
198 AddFeatureLine( aShape.GetStart(), aShape.GetEnd(), aShape.GetStroke().GetWidth() );
199
200 break;
201 }
202
203 default:
204 {
205 wxLogError( wxT( "Unknown shape when adding ODB++ layer feature" ) );
206 break;
207 }
208 }
209}
210
211
213 FILL_T aFillType /*= FILL_T::FILLED_SHAPE */ )
214{
215 AddFeature<ODB_SURFACE>( aPolygon, aFillType );
216}
217
218
220{
221 FOOTPRINT* fp = aPad.GetParentFootprint();
222 bool mirror = false;
223
224 if( aPad.GetOrientation() != ANGLE_0 )
225 {
226 if( fp && fp->IsFlipped() )
227 mirror = true;
228 }
229
230 int maxError = m_board->GetDesignSettings().m_MaxError;
231
232 VECTOR2I expansion{ 0, 0 };
233
234 if( aLayer != UNDEFINED_LAYER && LSET( { F_Mask, B_Mask } ).Contains( aLayer ) )
235 expansion.x = expansion.y = aPad.GetSolderMaskExpansion( aLayer );
236
237 if( aLayer != UNDEFINED_LAYER && LSET( { F_Paste, B_Paste } ).Contains( aLayer ) )
238 expansion = aPad.GetSolderPasteMargin( aLayer );
239
240 int mask_clearance = expansion.x;
241
242 VECTOR2I plotSize = aPad.GetSize( aLayer ) + 2 * expansion;
243
244 VECTOR2I center = aPad.ShapePos( aLayer );
245
246 wxString width = ODB::SymDouble2String( std::abs( plotSize.x ) );
247 wxString height = ODB::SymDouble2String( std::abs( plotSize.y ) );
248
249 switch( aPad.GetShape( aLayer ) )
250 {
251 case PAD_SHAPE::CIRCLE:
252 {
253 wxString diam = ODB::SymDouble2String( plotSize.x );
254
255 AddFeature<ODB_PAD>( ODB::AddXY( center ), AddCircleSymbol( diam ), aPad.GetOrientation(),
256 mirror );
257
258 break;
259 }
260 case PAD_SHAPE::RECTANGLE:
261 {
262 if( mask_clearance > 0 )
263 {
264 wxString rad = ODB::SymDouble2String( mask_clearance );
265
266 AddFeature<ODB_PAD>( ODB::AddXY( center ), AddRoundRectSymbol( width, height, rad ),
267 aPad.GetOrientation(), mirror );
268 }
269 else
270 {
271 AddFeature<ODB_PAD>( ODB::AddXY( center ), AddRectSymbol( width, height ),
272 aPad.GetOrientation(), mirror );
273 }
274
275 break;
276 }
277 case PAD_SHAPE::OVAL:
278 {
279 AddFeature<ODB_PAD>( ODB::AddXY( center ), AddOvalSymbol( width, height ),
280 aPad.GetOrientation(), mirror );
281 break;
282 }
283 case PAD_SHAPE::ROUNDRECT:
284 {
285 wxString rad = ODB::SymDouble2String( aPad.GetRoundRectCornerRadius( aLayer ) );
286
287 AddFeature<ODB_PAD>( ODB::AddXY( center ), AddRoundRectSymbol( width, height, rad ),
288 aPad.GetOrientation(), mirror );
289
290 break;
291 }
292 case PAD_SHAPE::CHAMFERED_RECT:
293 {
294 int shorterSide = std::min( plotSize.x, plotSize.y );
295 int chamfer = std::max(
296 0, KiROUND( aPad.GetChamferRectRatio( aLayer ) * shorterSide ) );
297 wxString rad = ODB::SymDouble2String( chamfer );
298 int positions = aPad.GetChamferPositions( aLayer );
299
300 AddFeature<ODB_PAD>( ODB::AddXY( center ),
301 AddChamferRectSymbol( width, height, rad, positions ),
302 aPad.GetOrientation(), mirror );
303
304 break;
305 }
306 case PAD_SHAPE::TRAPEZOID:
307 {
308 SHAPE_POLY_SET outline;
309
310 aPad.TransformShapeToPolygon( outline, aLayer, 0, maxError, ERROR_INSIDE );
311
312 // Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
313 // which can create bad shapes if margin.x is < 0
314
315 if( mask_clearance )
316 {
317 outline.InflateWithLinkedHoles( expansion.x, CORNER_STRATEGY::ROUND_ALL_CORNERS,
318 maxError, SHAPE_POLY_SET::PM_FAST );
319 }
320
321 for( int ii = 0; ii < outline.OutlineCount(); ++ii )
322 AddContour( outline, ii );
323
324 break;
325 }
326 case PAD_SHAPE::CUSTOM:
327 {
328 SHAPE_POLY_SET shape;
329 aPad.MergePrimitivesAsPolygon( aLayer, &shape );
330
331 // as for custome shape, odb++ don't rotate the polygon,
332 // so we rotate the polygon in kicad anticlockwise
333
334 shape.Rotate( aPad.GetOrientation() );
335 shape.Move( center );
336
337 if( expansion != VECTOR2I( 0, 0 ) )
338 {
339 shape.InflateWithLinkedHoles( std::max( expansion.x, expansion.y ),
340 CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError,
342 }
343
344 for( int ii = 0; ii < shape.OutlineCount(); ++ii )
345 AddContour( shape, ii );
346
347 break;
348 }
349 default: wxLogError( wxT( "Unknown pad type" ) ); break;
350 }
351}
352
353
354void FEATURES_MANAGER::InitFeatureList( PCB_LAYER_ID aLayer, std::vector<BOARD_ITEM*>& aItems )
355{
356 auto add_track = [&]( PCB_TRACK* track )
357 {
358 auto iter = GetODBPlugin()->GetViaTraceSubnetMap().find( track );
359
360 if( iter == GetODBPlugin()->GetViaTraceSubnetMap().end() )
361 {
362 wxLogError( wxT( "Failed to get subnet trace data" ) );
363 return;
364 }
365
366 auto subnet = iter->second;
367
368 if( track->Type() == PCB_TRACE_T )
369 {
370 PCB_SHAPE shape( nullptr, SHAPE_T::SEGMENT );
371 shape.SetStart( track->GetStart() );
372 shape.SetEnd( track->GetEnd() );
373 shape.SetWidth( track->GetWidth() );
374
375 AddShape( shape );
376 subnet->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER, m_layerName,
377 m_featuresList.size() - 1 );
378 }
379 else if( track->Type() == PCB_ARC_T )
380 {
381 PCB_ARC* arc = static_cast<PCB_ARC*>( track );
382 PCB_SHAPE shape( nullptr, SHAPE_T::ARC );
383 shape.SetArcGeometry( arc->GetStart(), arc->GetMid(), arc->GetEnd() );
384 shape.SetWidth( arc->GetWidth() );
385
386 AddShape( shape );
387
388 subnet->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER, m_layerName,
389 m_featuresList.size() - 1 );
390 }
391 else
392 {
393 // add via
394 PCB_VIA* via = static_cast<PCB_VIA*>( track );
395
396 if( aLayer != PCB_LAYER_ID::UNDEFINED_LAYER )
397 {
398 // to draw via copper shape on copper layer
399 AddVia( via, aLayer );
400 subnet->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER, m_layerName,
401 m_featuresList.size() - 1 );
402
403 if( !m_featuresList.empty() )
404 {
407 *m_featuresList.back(),
408 ODB_ATTR::GEOMETRY{ "VIA_RoundD"
409 + std::to_string( via->GetWidth( aLayer ) ) } );
410 }
411 }
412 else
413 {
414 // to draw via drill hole on drill layer
415
416 if( m_layerName.Contains( "drill" ) )
417 {
418 AddViaDrillHole( via, aLayer );
419 subnet->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::HOLE, m_layerName,
420 m_featuresList.size() - 1 );
421
422 // TODO: confirm TOOLING_HOLE
423 // AddFeatureAttribute( *m_featuresList.back(), ODB_ATTR::PAD_USAGE::TOOLING_HOLE );
424
425 if( !m_featuresList.empty() )
426 {
429 *m_featuresList.back(),
430 ODB_ATTR::GEOMETRY{ "VIA_RoundD"
431 + std::to_string( via->GetWidth( aLayer ) ) } );
432 }
433 }
434 }
435 }
436 };
437
438 auto add_zone = [&]( ZONE* zone )
439 {
440 SHAPE_POLY_SET zone_shape = zone->GetFilledPolysList( aLayer )->CloneDropTriangulation();
441
442 for( int ii = 0; ii < zone_shape.OutlineCount(); ++ii )
443 {
444 AddContour( zone_shape, ii );
445
446 auto iter = GetODBPlugin()->GetPlaneSubnetMap().find( std::make_pair( aLayer, zone ) );
447
448 if( iter == GetODBPlugin()->GetPlaneSubnetMap().end() )
449 {
450 wxLogError( wxT( "Failed to get subnet plane data" ) );
451 return;
452 }
453
454 iter->second->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER, m_layerName,
455 m_featuresList.size() - 1 );
456
457 if( zone->IsTeardropArea() && !m_featuresList.empty() )
458 AddFeatureAttribute( *m_featuresList.back(), ODB_ATTR::TEAR_DROP{ true } );
459 }
460 };
461
462 auto add_text = [&]( BOARD_ITEM* item )
463 {
464 EDA_TEXT* text_item = nullptr;
465
466 if( PCB_TEXT* tmp_text = dynamic_cast<PCB_TEXT*>( item ) )
467 text_item = static_cast<EDA_TEXT*>( tmp_text );
468 else if( PCB_TEXTBOX* tmp_text = dynamic_cast<PCB_TEXTBOX*>( item ) )
469 text_item = static_cast<EDA_TEXT*>( tmp_text );
470
471 if( !text_item->IsVisible() || text_item->GetShownText( false ).empty() )
472 return;
473
474 auto plot_text = [&]( const VECTOR2I& aPos, const wxString& aTextString,
475 const TEXT_ATTRIBUTES& aAttributes, KIFONT::FONT* aFont,
476 const KIFONT::METRICS& aFontMetrics )
477 {
479
480 TEXT_ATTRIBUTES attributes = aAttributes;
481 int penWidth = attributes.m_StrokeWidth;
482
483 if( penWidth == 0 && attributes.m_Bold ) // Use default values if aPenWidth == 0
484 penWidth =
485 GetPenSizeForBold( std::min( attributes.m_Size.x, attributes.m_Size.y ) );
486
487 if( penWidth < 0 )
488 penWidth = -penWidth;
489
490 attributes.m_StrokeWidth = penWidth;
491
492 std::list<VECTOR2I> pts;
493
494 auto push_pts = [&]()
495 {
496 if( pts.size() < 2 )
497 return;
498
499 // Polylines are only allowed for more than 3 points.
500 // Otherwise, we have to use a line
501
502 if( pts.size() < 3 )
503 {
504 PCB_SHAPE shape( nullptr, SHAPE_T::SEGMENT );
505 shape.SetStart( pts.front() );
506 shape.SetEnd( pts.back() );
507 shape.SetWidth( attributes.m_StrokeWidth );
508
509 AddShape( shape );
511 ODB_ATTR::STRING{ aTextString.ToStdString() } );
512 }
513 else
514 {
515 for( auto it = pts.begin(); std::next( it ) != pts.end(); ++it )
516 {
517 auto it2 = std::next( it );
518 PCB_SHAPE shape( nullptr, SHAPE_T::SEGMENT );
519 shape.SetStart( *it );
520 shape.SetEnd( *it2 );
521 shape.SetWidth( attributes.m_StrokeWidth );
522 AddShape( shape );
523 if( !m_featuresList.empty() )
525 ODB_ATTR::STRING{ aTextString.ToStdString() } );
526 }
527 }
528
529 pts.clear();
530 };
531
532 CALLBACK_GAL callback_gal(
533 empty_opts,
534 // Stroke callback
535 [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
536 {
537 if( !pts.empty() )
538 {
539 if( aPt1 == pts.back() )
540 pts.push_back( aPt2 );
541 else if( aPt2 == pts.front() )
542 pts.push_front( aPt1 );
543 else if( aPt1 == pts.front() )
544 pts.push_front( aPt2 );
545 else if( aPt2 == pts.back() )
546 pts.push_back( aPt1 );
547 else
548 {
549 push_pts();
550 pts.push_back( aPt1 );
551 pts.push_back( aPt2 );
552 }
553 }
554 else
555 {
556 pts.push_back( aPt1 );
557 pts.push_back( aPt2 );
558 }
559 },
560 // Polygon callback
561 [&]( const SHAPE_LINE_CHAIN& aPoly )
562 {
563 if( aPoly.PointCount() < 3 )
564 return;
565
566 SHAPE_POLY_SET poly_set;
567 poly_set.AddOutline( aPoly );
568
569 for( int ii = 0; ii < poly_set.OutlineCount(); ++ii )
570 {
571 AddContour( poly_set, ii, FILL_T::FILLED_SHAPE );
572
573 if( !m_featuresList.empty() )
575 *m_featuresList.back(),
576 ODB_ATTR::STRING{ aTextString.ToStdString() } );
577 }
578 } );
579
580 aFont->Draw( &callback_gal, aTextString, aPos, aAttributes, aFontMetrics );
581
582 if( !pts.empty() )
583 push_pts();
584 };
585
586 bool isKnockout = false;
587
588 if( item->Type() == PCB_TEXT_T || item->Type() == PCB_FIELD_T )
589 isKnockout = static_cast<PCB_TEXT*>( item )->IsKnockout();
590 else if( item->Type() == PCB_TEXTBOX_T )
591 isKnockout = static_cast<PCB_TEXTBOX*>( item )->IsKnockout();
592
593 const KIFONT::METRICS& fontMetrics = item->GetFontMetrics();
594
595 KIFONT::FONT* font = text_item->GetFont();
596
597 if( !font )
598 {
599 wxString defaultFontName; // empty string is the KiCad stroke font
600
601 font = KIFONT::FONT::GetFont( defaultFontName, text_item->IsBold(),
602 text_item->IsItalic() );
603 }
604
605 wxString shownText( text_item->GetShownText( true ) );
606
607 if( shownText.IsEmpty() )
608 return;
609
610 VECTOR2I pos = text_item->GetTextPos();
611
612 TEXT_ATTRIBUTES attrs = text_item->GetAttributes();
613 attrs.m_StrokeWidth = text_item->GetEffectiveTextPenWidth();
614 attrs.m_Angle = text_item->GetDrawRotation();
615 attrs.m_Multiline = false;
616
617 if( isKnockout )
618 {
619 PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
620 SHAPE_POLY_SET finalpolyset;
621
622 text->TransformTextToPolySet( finalpolyset, 0, m_board->GetDesignSettings().m_MaxError,
623 ERROR_INSIDE );
624 finalpolyset.Fracture( SHAPE_POLY_SET::PM_FAST );
625
626 for( int ii = 0; ii < finalpolyset.OutlineCount(); ++ii )
627 {
628 AddContour( finalpolyset, ii, FILL_T::FILLED_SHAPE );
629
630 if( !m_featuresList.empty() )
632 ODB_ATTR::STRING{ shownText.ToStdString() } );
633 }
634 }
635 else if( text_item->IsMultilineAllowed() )
636 {
637 std::vector<VECTOR2I> positions;
638 wxArrayString strings_list;
639 wxStringSplit( shownText, strings_list, '\n' );
640 positions.reserve( strings_list.Count() );
641
642 text_item->GetLinePositions( positions, strings_list.Count() );
643
644 for( unsigned ii = 0; ii < strings_list.Count(); ii++ )
645 {
646 wxString& txt = strings_list.Item( ii );
647 plot_text( positions[ii], txt, attrs, font, fontMetrics );
648 }
649 }
650 else
651 {
652 plot_text( pos, shownText, attrs, font, fontMetrics );
653 }
654 };
655
656
657 auto add_shape = [&]( PCB_SHAPE* shape )
658 {
659 // FOOTPRINT* fp = shape->GetParentFootprint();
660 AddShape( *shape, aLayer );
661 };
662
663 auto add_pad = [&]( PAD* pad )
664 {
665 auto iter = GetODBPlugin()->GetPadSubnetMap().find( pad );
666
667 if( iter == GetODBPlugin()->GetPadSubnetMap().end() )
668 {
669 wxLogError( wxT( "Failed to get subnet top data" ) );
670 return;
671 }
672
673 if( aLayer != PCB_LAYER_ID::UNDEFINED_LAYER )
674 {
675 // FOOTPRINT* fp = pad->GetParentFootprint();
676
677 AddPadShape( *pad, aLayer );
678
679 iter->second->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER, m_layerName,
680 m_featuresList.size() - 1 );
681 if( !m_featuresList.empty() )
682 AddFeatureAttribute( *m_featuresList.back(), ODB_ATTR::PAD_USAGE::TOEPRINT );
683
684 if( !pad->HasHole() && !m_featuresList.empty() )
685 AddFeatureAttribute( *m_featuresList.back(), ODB_ATTR::SMD{ true } );
686 }
687 else
688 {
689 // drill layer round hole or slot hole
690 if( m_layerName.Contains( "drill" ) )
691 {
692 // here we exchange round hole or slot hole into pad to draw in drill layer
693 PAD dummy( *pad );
694 dummy.Padstack().SetMode( PADSTACK::MODE::NORMAL );
695
696 if( pad->GetDrillSizeX() == pad->GetDrillSizeY() )
697 dummy.SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::CIRCLE ); // round hole shape
698 else
699 dummy.SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::OVAL ); // slot hole shape
700
701 dummy.SetOffset( PADSTACK::ALL_LAYERS,
702 VECTOR2I( 0, 0 ) ); // use hole position not pad position
703 dummy.SetSize( PADSTACK::ALL_LAYERS, pad->GetDrillSize() );
704
705 AddPadShape( dummy, aLayer );
706
707 if( pad->GetAttribute() == PAD_ATTRIB::PTH )
708 {
709 // only plated holes link to subnet
710 iter->second->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::HOLE, m_layerName,
711 m_featuresList.size() - 1 );
712
713 if( !m_featuresList.empty() )
714 AddFeatureAttribute( *m_featuresList.back(), ODB_ATTR::DRILL::PLATED );
715 }
716 else
717 {
718 if( !m_featuresList.empty() )
719 AddFeatureAttribute( *m_featuresList.back(), ODB_ATTR::DRILL::NON_PLATED );
720 }
721 }
722 }
723 // AddFeatureAttribute( *m_featuresList.back(),
724 // ODB_ATTR::GEOMETRY{ "PAD_xxxx" } );
725 };
726
727 for( BOARD_ITEM* item : aItems )
728 {
729 switch( item->Type() )
730 {
731 case PCB_TRACE_T:
732 case PCB_ARC_T:
733 case PCB_VIA_T: add_track( static_cast<PCB_TRACK*>( item ) ); break;
734
735 case PCB_ZONE_T: add_zone( static_cast<ZONE*>( item ) ); break;
736
737 case PCB_PAD_T: add_pad( static_cast<PAD*>( item ) ); break;
738
739 case PCB_SHAPE_T: add_shape( static_cast<PCB_SHAPE*>( item ) ); break;
740
741 case PCB_TEXT_T:
742 case PCB_FIELD_T: add_text( item ); break;
743 case PCB_TEXTBOX_T:
744 {
745 PCB_TEXTBOX* textbox = static_cast<PCB_TEXTBOX*>( item );
746 add_text( item );
747
748 if( textbox->IsBorderEnabled() )
749 add_shape( textbox );
750 }
751 break;
752
753 case PCB_DIMENSION_T:
754 case PCB_TARGET_T:
756 case PCB_DIM_LEADER_T:
757 case PCB_DIM_CENTER_T:
758 case PCB_DIM_RADIAL_T:
760 //TODO: Add support for dimensions
761 break;
762
763 default: break;
764 }
765 }
766}
767
768
770{
771 if( !aVia->FlashLayer( aLayer ) )
772 return;
773
774 PAD dummy( nullptr ); // default pad shape is circle
775 dummy.SetPadstack( aVia->Padstack() );
776 dummy.SetPosition( aVia->GetStart() );
777
778 AddPadShape( dummy, aLayer );
779}
780
781
783{
784 PAD dummy( nullptr ); // default pad shape is circle
785 int hole = aVia->GetDrillValue();
786 dummy.SetPosition( aVia->GetStart() );
787 dummy.SetSize( PADSTACK::ALL_LAYERS, VECTOR2I( hole, hole ) );
788
789 AddPadShape( dummy, aLayer );
790}
791
792
793void FEATURES_MANAGER::GenerateProfileFeatures( std::ostream& ost ) const
794{
795 ost << "UNITS=" << PCB_IO_ODBPP::m_unitsStr << std::endl;
796 ost << "#\n#Num Features\n#" << std::endl;
797 ost << "F " << m_featuresList.size() << std::endl;
798
799 if( m_featuresList.empty() )
800 return;
801
802 ost << "#\n#Layer features\n#" << std::endl;
803
804 for( const auto& feat : m_featuresList )
805 {
806 feat->WriteFeatures( ost );
807 }
808}
809
810
811void FEATURES_MANAGER::GenerateFeatureFile( std::ostream& ost ) const
812{
813 ost << "UNITS=" << PCB_IO_ODBPP::m_unitsStr << std::endl;
814 ost << "#\n#Num Features\n#" << std::endl;
815 ost << "F " << m_featuresList.size() << std::endl << std::endl;
816
817 if( m_featuresList.empty() )
818 return;
819
820 ost << "#\n#Feature symbol names\n#" << std::endl;
821
822 for( const auto& [n, name] : m_allSymMap )
823 {
824 ost << "$" << n << " " << name << std::endl;
825 }
826
827 WriteAttributes( ost );
828
829 ost << "#\n#Layer features\n#" << std::endl;
830
831 for( const auto& feat : m_featuresList )
832 {
833 feat->WriteFeatures( ost );
834 }
835}
836
837
838void ODB_FEATURE::WriteFeatures( std::ostream& ost )
839{
840 switch( GetFeatureType() )
841 {
842 case FEATURE_TYPE::LINE: ost << "L "; break;
843
844 case FEATURE_TYPE::ARC: ost << "A "; break;
845
846 case FEATURE_TYPE::PAD: ost << "P "; break;
847
848 case FEATURE_TYPE::SURFACE: ost << "S "; break;
849 default: return;
850 }
851
852 WriteRecordContent( ost );
853 ost << std::endl;
854}
855
856
857void ODB_LINE::WriteRecordContent( std::ostream& ost )
858{
859 ost << m_start.first << " " << m_start.second << " " << m_end.first << " " << m_end.second
860 << " " << m_symIndex << " P 0";
861
862 WriteAttributes( ost );
863}
864
865
866void ODB_ARC::WriteRecordContent( std::ostream& ost )
867{
868 ost << m_start.first << " " << m_start.second << " " << m_end.first << " " << m_end.second
869 << " " << m_center.first << " " << m_center.second << " " << m_symIndex << " P 0 "
870 << ( m_direction == ODB_DIRECTION::CW ? "Y" : "N" );
871
872 WriteAttributes( ost );
873}
874
875
876void ODB_PAD::WriteRecordContent( std::ostream& ost )
877{
878 ost << m_center.first << " " << m_center.second << " ";
879
880 // TODO: support resize symbol
881 // ost << "-1" << " " << m_symIndex << " "
882 // << m_resize << " P 0 ";
883
884 ost << m_symIndex << " P 0 ";
885
886 if( m_mirror )
887 ost << "9 " << ODB::Double2String( m_angle.Normalize().AsDegrees() );
888 else
889 ost << "8 " << ODB::Double2String( ( ANGLE_360 - m_angle ).Normalize().AsDegrees() );
890
891 WriteAttributes( ost );
892}
893
894
895ODB_SURFACE::ODB_SURFACE( uint32_t aIndex, const SHAPE_POLY_SET::POLYGON& aPolygon,
896 FILL_T aFillType /*= FILL_T::FILLED_SHAPE*/ ) : ODB_FEATURE( aIndex )
897{
898 if( !aPolygon.empty() && aPolygon[0].PointCount() >= 3 )
899 {
900 m_surfaces = std::make_unique<ODB_SURFACE_DATA>( aPolygon );
901 if( aFillType != FILL_T::NO_FILL )
902 {
903 m_surfaces->AddPolygonHoles( aPolygon );
904 }
905 }
906 else
907 {
908 delete this;
909 }
910}
911
912
913void ODB_SURFACE::WriteRecordContent( std::ostream& ost )
914{
915 ost << "P 0";
916 WriteAttributes( ost );
917 ost << std::endl;
918 m_surfaces->WriteData( ost );
919 ost << "SE";
920}
921
922
924{
925 const std::vector<VECTOR2I>& pts = aPolygon[0].CPoints();
926 if( !pts.empty() )
927 {
928 if( m_polygons.empty() )
929 {
930 m_polygons.resize( 1 );
931 }
932
933 m_polygons.at( 0 ).reserve( pts.size() );
934 m_polygons.at( 0 ).emplace_back( pts.back() );
935
936 for( size_t jj = 0; jj < pts.size(); ++jj )
937 {
938 m_polygons.at( 0 ).emplace_back( pts.at( jj ) );
939 }
940 }
941}
942
943
945{
946 for( size_t ii = 1; ii < aPolygon.size(); ++ii )
947 {
948 wxCHECK2( aPolygon[ii].PointCount() >= 3, continue );
949
950 const std::vector<VECTOR2I>& hole = aPolygon[ii].CPoints();
951
952 if( hole.empty() )
953 continue;
954
955 if( m_polygons.size() <= ii )
956 {
957 m_polygons.resize( ii + 1 );
958
959 m_polygons[ii].reserve( hole.size() );
960 }
961
962 m_polygons.at( ii ).emplace_back( hole.back() );
963
964 for( size_t jj = 0; jj < hole.size(); ++jj )
965 {
966 m_polygons.at( ii ).emplace_back( hole[jj] );
967 }
968 }
969}
970
971
972void ODB_SURFACE_DATA::WriteData( std::ostream& ost ) const
973{
974 ODB::CHECK_ONCE is_island;
975
976 for( const auto& contour : m_polygons )
977 {
978 if( contour.empty() )
979 continue;
980
981 ost << "OB " << ODB::AddXY( contour.back().m_end ).first << " "
982 << ODB::AddXY( contour.back().m_end ).second << " ";
983
984 if( is_island() )
985 ost << "I";
986 else
987 ost << "H";
988 ost << std::endl;
989
990 for( const auto& line : contour )
991 {
992 if( SURFACE_LINE::LINE_TYPE::SEGMENT == line.m_type )
993 ost << "OS " << ODB::AddXY( line.m_end ).first << " "
994 << ODB::AddXY( line.m_end ).second << std::endl;
995 else
996 ost << "OC " << ODB::AddXY( line.m_end ).first << " "
997 << ODB::AddXY( line.m_end ).second << " " << ODB::AddXY( line.m_center ).first
998 << " " << ODB::AddXY( line.m_center ).second << " "
999 << ( line.m_direction == ODB_DIRECTION::CW ? "Y" : "N" ) << std::endl;
1000 }
1001 ost << "OE" << std::endl;
1002 }
1003}
const char * name
Definition: DXF_plotter.cpp:57
@ ERROR_OUTSIDE
Definition: approximation.h:33
@ ERROR_INSIDE
Definition: approximation.h:34
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition: box2.h:990
void WriteAttributes(std::ostream &ost, const std::string &prefix="") const
void AddFeatureAttribute(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:79
virtual bool IsKnockout() const
Definition: board_item.h:324
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:299
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:890
EDA_ANGLE Normalize()
Definition: eda_angle.h:221
double AsDegrees() const
Definition: eda_angle.h:113
FILL_T GetFillMode() const
Definition: eda_shape.h:107
int GetRectangleWidth() const
Definition: eda_shape.cpp:166
SHAPE_POLY_SET & GetPolyShape()
Definition: eda_shape.h:279
int GetRadius() const
Definition: eda_shape.cpp:575
SHAPE_T GetShape() const
Definition: eda_shape.h:125
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition: eda_shape.h:167
void SetStart(const VECTOR2I &aStart)
Definition: eda_shape.h:134
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition: eda_shape.h:130
const std::vector< VECTOR2I > & GetBezierPoints() const
Definition: eda_shape.h:262
void SetEnd(const VECTOR2I &aEnd)
Definition: eda_shape.h:171
void SetArcGeometry(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Set the three controlling points for an arc.
Definition: eda_shape.cpp:607
int GetRectangleHeight() const
Definition: eda_shape.cpp:153
bool IsClockwiseArc() const
Definition: eda_shape.cpp:656
void SetWidth(int aWidth)
Definition: eda_shape.h:114
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:79
virtual bool IsVisible() const
Definition: eda_text.h:170
virtual wxString GetShownText(bool aAllowExtraText, int aDepth=0) const
Return the string actually shown after processing of the base text.
Definition: eda_text.h:105
void AddPadShape(const PAD &aPad, PCB_LAYER_ID aLayer)
uint32_t AddRoundRectDonutSymbol(const wxString &aOuterWidth, const wxString &aOuterHeight, const wxString &aLineWidth, const wxString &aRadius)
Definition: odb_feature.h:123
void AddShape(const PCB_SHAPE &aShape, PCB_LAYER_ID aLayer=UNDEFINED_LAYER)
Definition: odb_feature.cpp:79
uint32_t AddRectSymbol(const wxString &aWidth, const wxString &aHeight)
Definition: odb_feature.h:104
void AddVia(const PCB_VIA *aVia, PCB_LAYER_ID aLayer)
PCB_IO_ODBPP * GetODBPlugin()
Definition: odb_feature.h:188
void InitFeatureList(PCB_LAYER_ID aLayer, std::vector< BOARD_ITEM * > &aItems)
void AddFeatureLine(const VECTOR2I &aStart, const VECTOR2I &aEnd, uint64_t aWidth)
Definition: odb_feature.cpp:38
void AddFeatureArc(const VECTOR2I &aStart, const VECTOR2I &aEnd, const VECTOR2I &aCenter, uint64_t aWidth, ODB_DIRECTION aDirection)
Definition: odb_feature.cpp:46
std::map< uint32_t, wxString > m_allSymMap
Definition: odb_feature.h:178
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)
Definition: odb_feature.cpp:55
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)
Definition: odb_feature.h:116
wxString m_layerName
Definition: odb_feature.h:192
uint32_t AddOvalSymbol(const wxString &aWidth, const wxString &aHeight)
Definition: odb_feature.h:110
void GenerateProfileFeatures(std::ostream &ost) const
std::list< std::unique_ptr< ODB_FEATURE > > m_featuresList
Definition: odb_feature.h:195
uint32_t AddCircleSymbol(const wxString &aDiameter)
Definition: odb_feature.h:93
uint32_t AddChamferRectSymbol(const wxString &aWidth, const wxString &aHeight, const wxString &aRadius, int aPositions)
Definition: odb_feature.h:131
uint32_t AddRoundDonutSymbol(const wxString &aOuterDim, const wxString &aInnerDim)
Definition: odb_feature.h:98
bool AddContour(const SHAPE_POLY_SET &aPolySet, int aOutline=0, FILL_T aFillType=FILL_T::FILLED_SHAPE)
Definition: odb_feature.cpp:65
bool IsFlipped() const
Definition: footprint.h:391
FONT is an abstract base class for both outline and stroke fonts.
Definition: font.h:131
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false, const std::vector< wxString > *aEmbeddedFiles=nullptr, bool aForDrawingSheet=false)
Definition: font.cpp:146
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:36
std::pair< wxString, wxString > m_end
Definition: odb_feature.h:266
std::pair< wxString, wxString > m_start
Definition: odb_feature.h:265
uint32_t m_symIndex
Definition: odb_feature.h:268
virtual void WriteRecordContent(std::ostream &ost) override
ODB_DIRECTION m_direction
Definition: odb_feature.h:269
std::pair< wxString, wxString > m_center
Definition: odb_feature.h:267
virtual void WriteRecordContent(std::ostream &ost)=0
virtual void WriteFeatures(std::ostream &ost)
virtual FEATURE_TYPE GetFeatureType()=0
virtual void WriteRecordContent(std::ostream &ost) override
std::pair< wxString, wxString > m_start
Definition: odb_feature.h:240
std::pair< wxString, wxString > m_end
Definition: odb_feature.h:241
uint32_t m_symIndex
Definition: odb_feature.h:242
uint32_t m_symIndex
Definition: odb_feature.h:289
virtual void WriteRecordContent(std::ostream &ost) override
bool m_mirror
Definition: odb_feature.h:291
EDA_ANGLE m_angle
Definition: odb_feature.h:290
std::pair< wxString, wxString > m_center
Definition: odb_feature.h:288
void WriteData(std::ostream &ost) const
std::vector< std::vector< SURFACE_LINE > > m_polygons
Definition: odb_feature.h:345
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
Definition: odb_feature.h:306
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.
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition: padstack.h:138
Definition: pad.h:54
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.
int GetRoundRectCornerRadius(PCB_LAYER_ID aLayer) const
Definition: pad.cpp:439
PAD_SHAPE GetShape(PCB_LAYER_ID aLayer) const
Definition: pad.h:193
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:1874
int GetSolderMaskExpansion(PCB_LAYER_ID aLayer) const
Definition: pad.cpp:1075
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition: pad.h:410
int GetChamferPositions(PCB_LAYER_ID aLayer) const
Definition: pad.h:688
double GetChamferRectRatio(PCB_LAYER_ID aLayer) const
Definition: pad.h:671
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:1121
VECTOR2I ShapePos(PCB_LAYER_ID aLayer) const
Definition: pad.cpp:966
const VECTOR2I & GetSize(PCB_LAYER_ID aLayer) const
Definition: pad.h:266
const VECTOR2I & GetMid() const
Definition: pcb_track.h:299
std::map< std::pair< PCB_LAYER_ID, ZONE * >, EDA_DATA::SUB_NET_PLANE * > & GetPlaneSubnetMap()
Definition: pcb_io_odbpp.h:119
std::map< PCB_TRACK *, EDA_DATA::SUB_NET * > & GetViaTraceSubnetMap()
Definition: pcb_io_odbpp.h:124
static std::string m_unitsStr
Definition: pcb_io_odbpp.h:144
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition: pcb_shape.h:79
int GetWidth() const override
Definition: pcb_shape.cpp:457
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the shape to a closed polygon.
Definition: pcb_shape.cpp:930
STROKE_PARAMS GetStroke() const override
Definition: pcb_shape.h:89
bool IsBorderEnabled() const
Disables the border, this is done by changing the stroke internally.
const VECTOR2I & GetStart() const
Definition: pcb_track.h:122
const VECTOR2I & GetEnd() const
Definition: pcb_track.h:119
virtual int GetWidth() const
Definition: pcb_track.h:116
bool FlashLayer(int aLayer) const
Check to see whether the via should have a pad on the specific layer.
Definition: pcb_track.cpp:1201
const PADSTACK & Padstack() const
Definition: pcb_track.h:403
int GetDrillValue() const
Calculate the drill value for vias (m_drill if > 0, or default drill value for the board).
Definition: pcb_track.cpp:589
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
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 InflateWithLinkedHoles(int aFactor, CORNER_STRATEGY aCornerStrategy, int aMaxError, POLYGON_MODE aFastMode)
Perform outline inflation/deflation, using round corners.
void Fracture(POLYGON_MODE aFastMode)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
void BooleanAdd(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset union For aFastMode meaning, see function booleanOp.
POLYGON & Polygon(int aIndex)
Return the aIndex-th subpolygon in the set.
std::vector< SHAPE_LINE_CHAIN > POLYGON
represents a single polygon outline with holes.
void Simplify(POLYGON_MODE aFastMode)
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections) For aFastMo...
void Deflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError)
int OutlineCount() const
Return the number of outlines in the set.
void Move(const VECTOR2I &aVector) override
SHAPE_POLY_SET CloneDropTriangulation() const
int GetWidth() const
Definition: stroke_params.h:89
Handle a list of polygons defining a copper zone.
Definition: zone.h:73
static constexpr EDA_ANGLE ANGLE_0
Definition: eda_angle.h:401
static constexpr EDA_ANGLE ANGLE_360
Definition: eda_angle.h:407
FILL_T
Definition: eda_shape.h:55
int GetPenSizeForBold(int aTextSize)
Definition: gr_text.cpp:40
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:158
wxString Double2String(double aVal)
Definition: odb_util.cpp:118
wxString SymDouble2String(double aVal)
Definition: odb_util.cpp:146
VECTOR2I GetShapePosition(const PCB_SHAPE &aShape)
Definition: odb_util.cpp:169
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:390
ODB_DIRECTION
Definition: odb_feature.h:35
@ PTH
Plated through hole pad.
std::vector< FAB_LAYER_COLOR > dummy
void wxStringSplit(const wxString &aText, wxArrayString &aStrings, wxChar aSplitter)
Split aString to a string list separated at aSplitter.
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:88
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition: typeinfo.h:105
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition: typeinfo.h:102
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition: typeinfo.h:103
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:93
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition: typeinfo.h:107
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:92
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
Definition: typeinfo.h:90
@ PCB_TARGET_T
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:106
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition: typeinfo.h:101
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:98
@ PCB_DIMENSION_T
class PCB_DIMENSION_BASE: abstract dimension meta-type
Definition: typeinfo.h:100
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:96
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
Definition: typeinfo.h:104
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:691