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