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