KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcb_io_autotrax.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 * Format interpretation derived from pcb-rnd src_plugins/io_autotrax:
5 * Copyright (C) 2016, 2017, 2018, 2020 Tibor 'Igor2' Palinkas
6 * Copyright (C) 2016, 2017 Erich S. Heinzle
7 * Used under GPL v2-or-later.
8 *
9 * Copyright (C) 2026 KiCad Developers, see AUTHORS.txt for contributors.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <https://www.gnu.org/licenses/>.
23 */
24
25#include "pcb_io_autotrax.h"
26#include "autotrax_parser.h"
27
28#include <board.h>
30#include <footprint.h>
31#include <pad.h>
32#include <pcb_track.h>
33#include <pcb_shape.h>
34#include <pcb_text.h>
35#include <zone.h>
36#include <netinfo.h>
38#include <geometry/eda_angle.h>
40#include <reporter.h>
41#include <math/util.h>
42#include <math/vector2d.h>
43
45
46#include <algorithm>
47#include <cmath>
48#include <fstream>
49#include <sstream>
50
51using AUTOTRAX::ARC;
53using AUTOTRAX::FILL;
55using AUTOTRAX::TEXT;
56using AUTOTRAX::TRACK;
57using AUTOTRAX::VIA;
58
59// AUTOTRAX::PAD and AUTOTRAX::COMPONENT collide with KiCad's global PAD class and
60// board.h's COMPONENT class, so both are always spelled out with the namespace
61// prefix here and the KiCad PAD class is reached as ::PAD.
62
63
65 PCB_IO( wxS( "Protel Autotrax" ) )
66{
67}
68
69
73
74
81static bool readFile( const wxString& aFileName, wxString& aOut, size_t aLimit = 0 )
82{
83 std::ifstream file( aFileName.fn_str(), std::ios::binary );
84
85 if( !file.is_open() )
86 return false;
87
88 std::string raw;
89
90 if( aLimit > 0 )
91 {
92 raw.resize( aLimit );
93 file.read( raw.data(), aLimit );
94 raw.resize( static_cast<size_t>( file.gcount() ) );
95 }
96 else
97 {
98 std::ostringstream ss;
99 ss << file.rdbuf();
100 raw = ss.str();
101 }
102
103 aOut = wxString::FromUTF8( raw.data(), raw.size() );
104
105 if( aOut.IsEmpty() && !raw.empty() )
106 aOut = wxString::From8BitData( raw.data(), raw.size() );
107
108 return true;
109}
110
111
112bool PCB_IO_AUTOTRAX::CanReadBoard( const wxString& aFileName ) const
113{
114 if( !PCB_IO::CanReadBoard( aFileName ) )
115 return false;
116
117 // The magic header is in the first non-blank line, so a small prefix read is
118 // enough to disambiguate from the gEDA .pcb files sharing this extension.
119 wxString contents;
120
121 if( !readFile( aFileName, contents, 4096 ) )
122 return false;
123
124 return AUTOTRAX_PARSER::Sniff( contents );
125}
126
127
128BOARD* PCB_IO_AUTOTRAX::LoadBoard( const wxString& aFileName, BOARD* aAppendToMe,
129 const std::map<std::string, UTF8>* aProperties, PROJECT* aProject )
130{
131 m_props = aProperties;
132 m_board = aAppendToMe ? aAppendToMe : new BOARD();
133
134 // Own a freshly-allocated board until parsing succeeds so a thrown IO_ERROR
135 // does not leak it. An appended board belongs to the caller.
136 std::unique_ptr<BOARD> boardDeleter( aAppendToMe ? nullptr : m_board );
137
138 m_nets.clear();
139 m_maxY = 0;
140
141 if( !aAppendToMe )
142 m_board->SetFileName( aFileName );
143
144 wxString contents;
145
146 if( !readFile( aFileName, contents ) )
147 THROW_IO_ERROR( wxString::Format( _( "Could not read file '%s'." ), aFileName ) );
148
150 BOARD_DATA data;
151
152 AUTOTRAX_PARSER parser( &reporter );
153
154 if( !parser.Parse( contents, data ) )
155 THROW_IO_ERROR( wxString::Format( _( "'%s' is not a valid Protel Autotrax file." ), aFileName ) );
156
157 buildBoard( data );
158
159 boardDeleter.release();
160 return m_board;
161}
162
163
164bool PCB_IO_AUTOTRAX::mapLayer( int aLayer, PCB_LAYER_ID& aResult ) const
165{
166 using namespace AUTOTRAX;
167
168 switch( aLayer )
169 {
170 case LAYER_TOP_COPPER: aResult = F_Cu; return true;
171 case LAYER_MID1: aResult = In1_Cu; return true;
172 case LAYER_MID2: aResult = In2_Cu; return true;
173 case LAYER_MID3: aResult = In3_Cu; return true;
174 case LAYER_MID4: aResult = In4_Cu; return true;
175 case LAYER_BOTTOM_COPPER: aResult = B_Cu; return true;
176 case LAYER_TOP_SILK: aResult = F_SilkS; return true;
177 case LAYER_BOTTOM_SILK: aResult = B_SilkS; return true;
178 case LAYER_GND_PLANE: aResult = In5_Cu; return true;
179 case LAYER_POWER_PLANE: aResult = In6_Cu; return true;
180 case LAYER_BOARD: aResult = Edge_Cuts; return true;
181 case LAYER_MULTI: aResult = F_Cu; return true; // through-all features
182 default:
183 // 0 (unset) and 12 (keepout) have no KiCad target and are dropped.
184 return false;
185 }
186}
187
188
189NETINFO_ITEM* PCB_IO_AUTOTRAX::getNet( const wxString& aNetName )
190{
191 if( aNetName.IsEmpty() )
192 return nullptr;
193
194 auto it = m_nets.find( aNetName );
195
196 if( it != m_nets.end() )
197 return it->second;
198
199 // Reuse a net already on the board (e.g. when appending) so codes and names
200 // are never duplicated.
201 if( NETINFO_ITEM* existing = m_board->FindNet( aNetName ) )
202 {
203 m_nets[aNetName] = existing;
204 return existing;
205 }
206
207 NETINFO_ITEM* net = new NETINFO_ITEM( m_board, aNetName );
208 m_board->Add( net );
209 m_nets[aNetName] = net;
210 return net;
211}
212
213
215{
216 return aFootprint ? static_cast<BOARD_ITEM*>( aFootprint ) : static_cast<BOARD_ITEM*>( m_board );
217}
218
219
221{
222 if( aFootprint )
223 aFootprint->Add( aItem );
224 else
225 m_board->Add( aItem, ADD_MODE::APPEND );
226}
227
228
232{
233 double startDeg;
234 double deltaDeg;
235};
236
237
241static std::vector<ARC_SPAN> arcSpansFromSegments( int aSegments )
242{
243 switch( aSegments )
244 {
245 case 1: return { { 90.0, 90.0 } }; // RU quadrant
246 case 2: return { { 0.0, 90.0 } }; // LU quadrant
247 case 4: return { { 270.0, 90.0 } }; // LL quadrant
248 case 8: return { { 180.0, 90.0 } }; // RL quadrant
249 case 3: return { { 0.0, 180.0 } }; // upper half
250 case 6: return { { 270.0, 180.0 } }; // left half
251 case 12: return { { 180.0, 180.0 } }; // lower half
252 case 9: return { { 90.0, 180.0 } }; // right half
253 case 14: return { { 180.0, 270.0 } }; // not RU
254 case 13: return { { 90.0, 270.0 } }; // not LU
255 case 11: return { { 0.0, 270.0 } }; // not LL
256 case 7: return { { 270.0, 270.0 } }; // not RL
257 case 5: return { { 270.0, 90.0 }, { 90.0, 90.0 } }; // RU + LL quadrants
258 case 10: return { { 180.0, 90.0 }, { 0.0, 90.0 } }; // LU + RL quadrants
259 default: return { { 0.0, 360.0 } }; // full circle
260 }
261}
262
263
264void PCB_IO_AUTOTRAX::emitTrack( const TRACK& aTrack, FOOTPRINT* aFootprint )
265{
266 PCB_LAYER_ID layer;
267
268 if( !mapLayer( aTrack.layer, layer ) )
269 return;
270
271 // A free copper segment becomes a routed PCB_TRACK. Everything else, and any
272 // segment owned by a footprint, becomes a graphic PCB_SHAPE so it stays with
273 // the footprint (KiCad footprints cannot own PCB_TRACK objects).
274 if( IsCopperLayer( layer ) && !aFootprint )
275 {
276 PCB_TRACK* track = new PCB_TRACK( m_board );
277 track->SetStart( toBoard( aTrack.x1, aTrack.y1 ) );
278 track->SetEnd( toBoard( aTrack.x2, aTrack.y2 ) );
279 track->SetWidth( std::max( 1, toIU( aTrack.width ) ) );
280 track->SetLayer( layer );
281 m_board->Add( track, ADD_MODE::APPEND );
282 return;
283 }
284
285 PCB_SHAPE* shape = new PCB_SHAPE( parentOf( aFootprint ), SHAPE_T::SEGMENT );
286 shape->SetLayer( layer );
287 shape->SetStart( toBoard( aTrack.x1, aTrack.y1 ) );
288 shape->SetEnd( toBoard( aTrack.x2, aTrack.y2 ) );
289 shape->SetWidth( std::max( 1, toIU( aTrack.width ) ) );
290 addItem( shape, aFootprint );
291}
292
293
294void PCB_IO_AUTOTRAX::emitArc( const ARC& aArc, FOOTPRINT* aFootprint )
295{
296 PCB_LAYER_ID layer;
297
298 if( !mapLayer( aArc.layer, layer ) )
299 return;
300
301 int r = toIU( aArc.radius );
302 int width = std::max( 1, toIU( aArc.width ) );
303 VECTOR2I center = toBoard( aArc.centerX, aArc.centerY );
304
305 // A point on the circle for an angle in the Y-down file frame. toBoard()
306 // applies the Y flip so the resulting geometry lands in KiCad space.
307 auto pointAt = [&]( double aDeg )
308 {
309 double rad = aDeg * M_PI / 180.0;
310 return toBoard( aArc.centerX + aArc.radius * std::cos( rad ), aArc.centerY + aArc.radius * std::sin( rad ) );
311 };
312
313 for( const ARC_SPAN& span : arcSpansFromSegments( aArc.segments ) )
314 {
315 PCB_SHAPE* shape = new PCB_SHAPE( parentOf( aFootprint ) );
316 shape->SetLayer( layer );
317 shape->SetWidth( width );
318
319 if( span.deltaDeg >= 360.0 )
320 {
321 shape->SetShape( SHAPE_T::CIRCLE );
322 shape->SetCenter( center );
323 shape->SetEnd( VECTOR2I( center.x + r, center.y ) );
324 }
325 else
326 {
327 shape->SetShape( SHAPE_T::ARC );
328 shape->SetArcGeometry( pointAt( span.startDeg ), pointAt( span.startDeg + span.deltaDeg / 2.0 ),
329 pointAt( span.startDeg + span.deltaDeg ) );
330 }
331
332 addItem( shape, aFootprint );
333 }
334}
335
336
337void PCB_IO_AUTOTRAX::emitVia( const VIA& aVia, FOOTPRINT* aFootprint )
338{
339 int drill = std::max( 1, toIU( aVia.drill ) );
340 int diameter = std::max( drill + 2, toIU( aVia.diameter ) );
341
342 if( aFootprint )
343 {
344 // A via inside a component becomes a through-hole pad so it travels with
345 // the footprint.
347 pad.x = aVia.x;
348 pad.y = aVia.y;
349 pad.xSize = aVia.diameter;
350 pad.ySize = aVia.diameter;
351 pad.shape = 1;
352 pad.drill = aVia.drill;
354 emitPad( pad, aFootprint );
355 return;
356 }
357
358 PCB_VIA* via = new PCB_VIA( m_board );
359 via->SetPosition( toBoard( aVia.x, aVia.y ) );
360 via->SetDrill( drill );
361 via->SetWidth( PADSTACK::ALL_LAYERS, diameter );
362 via->SetViaType( VIATYPE::THROUGH );
363 via->SetLayerPair( F_Cu, B_Cu );
365}
366
367
368void PCB_IO_AUTOTRAX::emitPad( const AUTOTRAX::PAD& aPad, FOOTPRINT* aFootprint )
369{
370 // Layer 11 ("board") pads and the unsupported target shapes are dropped.
371 if( aPad.layer == AUTOTRAX::LAYER_BOARD || aPad.shape == 5 || aPad.shape == 6 )
372 return;
373
374 // Autotrax only places pads on the top (1), bottom (6) or multi/through (13)
375 // layers; other pad layers are unsupported and dropped.
377 && aPad.layer != AUTOTRAX::LAYER_MULTI )
378 {
379 return;
380 }
381
382 PCB_LAYER_ID layer;
383
384 if( !mapLayer( aPad.layer, layer ) )
385 return;
386
387 // A free pad with no owning footprint still needs a footprint container so
388 // KiCad can hold the pad; create a throwaway one anchored at the pad.
389 FOOTPRINT* owner = aFootprint;
390 bool standalone = false;
391
392 if( !owner )
393 {
394 owner = new FOOTPRINT( m_board );
395 owner->SetPosition( toBoard( aPad.x, aPad.y ) );
396 standalone = true;
397 }
398
399 ::PAD* pad = new ::PAD( owner );
400 pad->SetNumber( aPad.name );
401 pad->SetPosition( toBoard( aPad.x, aPad.y ) );
402
403 VECTOR2I size( std::max( 1, toIU( aPad.xSize ) ), std::max( 1, toIU( aPad.ySize ) ) );
404 pad->SetSize( PADSTACK::ALL_LAYERS, size );
405
406 switch( aPad.shape )
407 {
408 case 2: pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::RECTANGLE ); break;
409
410 case 3: // octagon, approximated by chamfering all four corners
412 pad->SetChamferRectRatio( PADSTACK::ALL_LAYERS, 0.25 );
413 pad->SetChamferPositions( PADSTACK::ALL_LAYERS, RECT_CHAMFER_ALL );
414 break;
415
416 case 4: pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::ROUNDRECT ); break;
417
418 default:
419 pad->SetShape( PADSTACK::ALL_LAYERS, ( aPad.xSize == aPad.ySize ) ? PAD_SHAPE::CIRCLE : PAD_SHAPE::OVAL );
420 break;
421 }
422
423 int drill = toIU( aPad.drill );
424
425 if( drill > 0 )
426 {
427 pad->SetAttribute( PAD_ATTRIB::PTH );
428 pad->SetDrillSize( VECTOR2I( drill, drill ) );
429 pad->SetLayerSet( ::PAD::PTHMask() );
430 }
431 else
432 {
433 pad->SetAttribute( PAD_ATTRIB::SMD );
434
435 LSET smdMask = ::PAD::SMDMask();
436
437 if( layer == B_Cu )
438 smdMask.FlipStandardLayers();
439
440 pad->SetLayerSet( smdMask );
441 }
442
443 owner->Add( pad );
444
445 if( standalone )
446 m_board->Add( owner, ADD_MODE::APPEND );
447}
448
449
450void PCB_IO_AUTOTRAX::emitFill( const FILL& aFill, FOOTPRINT* aFootprint )
451{
452 PCB_LAYER_ID layer;
453
454 if( !mapLayer( aFill.layer, layer ) )
455 return;
456
457 VECTOR2I p1 = toBoard( aFill.x1, aFill.y1 );
458 VECTOR2I p2 = toBoard( aFill.x2, aFill.y2 );
459
460 int minX = std::min( p1.x, p2.x );
461 int maxX = std::max( p1.x, p2.x );
462 int minY = std::min( p1.y, p2.y );
463 int maxY = std::max( p1.y, p2.y );
464
465 // Autotrax fills are rectangular pours. On copper layers they become a zone;
466 // elsewhere a filled rectangle graphic.
467 if( IsCopperLayer( layer ) && !aFootprint )
468 {
469 SHAPE_POLY_SET poly;
470 SHAPE_LINE_CHAIN outline;
471 outline.Append( VECTOR2I( minX, minY ) );
472 outline.Append( VECTOR2I( maxX, minY ) );
473 outline.Append( VECTOR2I( maxX, maxY ) );
474 outline.Append( VECTOR2I( minX, maxY ) );
475 outline.SetClosed( true );
476 poly.AddOutline( outline );
477
478 ZONE* zone = new ZONE( m_board );
479 zone->SetLayer( layer );
480 zone->SetOutline( new SHAPE_POLY_SET( poly ) );
481 zone->SetAssignedPriority( 0 );
482 m_board->Add( zone, ADD_MODE::APPEND );
483 return;
484 }
485
486 PCB_SHAPE* shape = new PCB_SHAPE( parentOf( aFootprint ), SHAPE_T::RECTANGLE );
487 shape->SetLayer( layer );
488 shape->SetStart( VECTOR2I( minX, minY ) );
489 shape->SetEnd( VECTOR2I( maxX, maxY ) );
490 shape->SetFilled( true );
491 shape->SetWidth( 0 );
492 addItem( shape, aFootprint );
493}
494
495
496void PCB_IO_AUTOTRAX::emitText( const TEXT& aText, FOOTPRINT* aFootprint )
497{
498 PCB_LAYER_ID layer;
499
500 if( !mapLayer( aText.layer, layer ) )
501 return;
502
503 PCB_TEXT* text = new PCB_TEXT( parentOf( aFootprint ) );
504 text->SetText( aText.text );
505 text->SetLayer( layer );
506 text->SetPosition( toBoard( aText.x, aText.y ) );
507
508 int height = std::max( 1, toIU( aText.height ) );
509 text->SetTextSize( VECTOR2I( height, height ) );
510 text->SetTextThickness( std::max( 1, toIU( aText.width ) ) );
511
512 // Direction is 0..3 in 90 degree steps. The Y flip mirrors the rotation, so
513 // negate it to keep the text reading the same way it did in Autotrax.
514 text->SetTextAngle( EDA_ANGLE( -90.0 * aText.direction, DEGREES_T ) );
515
516 if( layer == B_Cu || layer == B_SilkS )
517 text->SetMirrored( true );
518
519 addItem( text, aFootprint );
520}
521
522
524{
525 FOOTPRINT* fp = new FOOTPRINT( m_board );
526 fp->SetPosition( toBoard( aComp.x, aComp.y ) );
527
528 if( !aComp.refdes.IsEmpty() )
529 fp->SetReference( aComp.refdes );
530
531 if( !aComp.value.IsEmpty() )
532 fp->SetValue( aComp.value );
533
534 if( !aComp.name.IsEmpty() )
535 fp->SetFPID( LIB_ID( wxEmptyString, aComp.name ) );
536
537 for( const TRACK& t : aComp.tracks )
538 emitTrack( t, fp );
539
540 for( const ARC& a : aComp.arcs )
541 emitArc( a, fp );
542
543 for( const VIA& v : aComp.vias )
544 emitVia( v, fp );
545
546 for( const AUTOTRAX::PAD& p : aComp.pads )
547 emitPad( p, fp );
548
549 for( const FILL& f : aComp.fills )
550 emitFill( f, fp );
551
552 for( const TEXT& s : aComp.texts )
553 emitText( s, fp );
554
555 m_board->Add( fp, ADD_MODE::APPEND );
556}
557
558
560{
561 // A single walk over every primitive (free and component-owned) collects two
562 // things needed before any item is emitted: the deepest inner copper layer
563 // referenced, and the Y extent of the data.
564 //
565 // mapLayer() places the four inner copper layers on In1..In4 and the GND and
566 // Power planes on In5/In6, so the board must enable enough copper layers for
567 // the deepest inner layer actually referenced (otherwise items land on a
568 // disabled layer). A two-sided board keeps just F_Cu/B_Cu.
569 //
570 // The Y extent drives the Y-down -> Y-up flip about the data bounding box
571 // so all coordinates stay positive.
572 int innerNeeded = 0;
573 double maxYmils = 0.0;
574
575 auto noteLayer = [&]( int aLayer )
576 {
577 switch( aLayer )
578 {
579 case AUTOTRAX::LAYER_MID1: innerNeeded = std::max( innerNeeded, 1 ); break;
580 case AUTOTRAX::LAYER_MID2: innerNeeded = std::max( innerNeeded, 2 ); break;
581 case AUTOTRAX::LAYER_MID3: innerNeeded = std::max( innerNeeded, 3 ); break;
582 case AUTOTRAX::LAYER_MID4: innerNeeded = std::max( innerNeeded, 4 ); break;
583 case AUTOTRAX::LAYER_GND_PLANE: innerNeeded = std::max( innerNeeded, 5 ); break;
584 case AUTOTRAX::LAYER_POWER_PLANE: innerNeeded = std::max( innerNeeded, 6 ); break;
585 default: break;
586 }
587 };
588
589 // BOARD_DATA and COMPONENT share the same six primitive members, so one
590 // generic walk covers both the free primitives and each component's.
591 auto scan = [&]( const auto& aContainer )
592 {
593 for( const TRACK& t : aContainer.tracks )
594 {
595 noteLayer( t.layer );
596 maxYmils = std::max( { maxYmils, t.y1, t.y2 } );
597 }
598
599 for( const ARC& a : aContainer.arcs )
600 {
601 noteLayer( a.layer );
602 maxYmils = std::max( maxYmils, a.centerY + a.radius );
603 }
604
605 for( const VIA& v : aContainer.vias )
606 maxYmils = std::max( maxYmils, v.y );
607
608 for( const AUTOTRAX::PAD& p : aContainer.pads )
609 {
610 noteLayer( p.layer );
611 maxYmils = std::max( maxYmils, p.y );
612 }
613
614 for( const FILL& f : aContainer.fills )
615 {
616 noteLayer( f.layer );
617 maxYmils = std::max( { maxYmils, f.y1, f.y2 } );
618 }
619
620 for( const TEXT& s : aContainer.texts )
621 maxYmils = std::max( maxYmils, s.y );
622 };
623
624 scan( aData );
625
626 for( const AUTOTRAX::COMPONENT& c : aData.components )
627 scan( c );
628
629 m_board->SetCopperLayerCount( 2 + innerNeeded );
630 m_maxY = toIU( maxYmils );
631
632 // Pre-create nets so pads/tracks can reference them by name.
633 for( const NET_NODE& node : aData.netNodes )
634 getNet( node.netName );
635
636 for( const TRACK& t : aData.tracks )
637 emitTrack( t, nullptr );
638
639 for( const ARC& a : aData.arcs )
640 emitArc( a, nullptr );
641
642 for( const VIA& v : aData.vias )
643 emitVia( v, nullptr );
644
645 for( const AUTOTRAX::PAD& p : aData.pads )
646 emitPad( p, nullptr );
647
648 for( const FILL& f : aData.fills )
649 emitFill( f, nullptr );
650
651 for( const TEXT& s : aData.texts )
652 emitText( s, nullptr );
653
654 for( const AUTOTRAX::COMPONENT& c : aData.components )
655 buildComponent( c );
656}
Line-oriented parser for Protel Autotrax / Easytrax PCB files.
static bool Sniff(const wxString &aContents)
Cheap content sniff: the first non-blank, non-comment line is the magic header "PCB FILE 4" (Autotrax...
bool Parse(const wxString &aContents, AUTOTRAX::BOARD_DATA &aBoard)
Parse aContents into aBoard.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:81
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:372
void SetCenter(const VECTOR2I &aCenter)
virtual void SetFilled(bool aFlag)
Definition eda_shape.h:152
void SetPosition(const VECTOR2I &aPos) override
void SetFPID(const LIB_ID &aFPID)
Definition footprint.h:442
void SetReference(const wxString &aReference)
Definition footprint.h:847
void SetValue(const wxString &aValue)
Definition footprint.h:868
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
REPORTER * m_reporter
Reporter to log errors/warnings to, may be nullptr.
Definition io_base.h:237
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
LSET & FlipStandardLayers(int aCopperLayersCount=0)
Flip the layers in this set.
Definition lset.cpp:481
Handle the data for a net.
Definition netinfo.h:46
static REPORTER & GetInstance()
Definition reporter.cpp:120
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition padstack.h:177
Definition pad.h:61
static LSET PTHMask()
layer set for a through hole pad
Definition pad.cpp:579
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition pad.cpp:586
void buildComponent(const AUTOTRAX::COMPONENT &aComp)
NETINFO_ITEM * getNet(const wxString &aNetName)
bool CanReadBoard(const wxString &aFileName) const override
Checks if this PCB_IO can read the specified board file.
std::map< wxString, NETINFO_ITEM * > m_nets
static int toIU(double aMils)
Convert a mil value to KiCad internal units (nm).
void buildBoard(const AUTOTRAX::BOARD_DATA &aData)
BOARD_ITEM * parentOf(FOOTPRINT *aFootprint) const
Parent for a primitive: the owning footprint, or the board for free items.
void addItem(BOARD_ITEM *aItem, FOOTPRINT *aFootprint)
Attach an item to its footprint, or append it to the board.
int m_maxY
board Y extent in IU, used to flip the Y axis
~PCB_IO_AUTOTRAX() override
BOARD * LoadBoard(const wxString &aFileName, BOARD *aAppendToMe, const std::map< std::string, UTF8 > *aProperties=nullptr, PROJECT *aProject=nullptr) override
Load information from some input file format that this PCB_IO implementation knows about into either ...
VECTOR2I toBoard(double aX, double aY) const
Convert an Autotrax point (mils, Y-down) to a board point (nm, Y-up).
void emitTrack(const AUTOTRAX::TRACK &aTrack, FOOTPRINT *aFootprint)
void emitFill(const AUTOTRAX::FILL &aFill, FOOTPRINT *aFootprint)
void emitPad(const AUTOTRAX::PAD &aPad, FOOTPRINT *aFootprint)
void emitArc(const AUTOTRAX::ARC &aArc, FOOTPRINT *aFootprint)
bool mapLayer(int aLayer, PCB_LAYER_ID &aResult) const
Map an Autotrax layer number to a KiCad layer.
void emitText(const AUTOTRAX::TEXT &aText, FOOTPRINT *aFootprint)
void emitVia(const AUTOTRAX::VIA &aVia, FOOTPRINT *aFootprint)
BOARD * m_board
The board BOARD being worked on, no ownership here.
Definition pcb_io.h:349
virtual bool CanReadBoard(const wxString &aFileName) const
Checks if this PCB_IO can read the specified board file.
Definition pcb_io.cpp:38
PCB_IO(const wxString &aName)
Definition pcb_io.h:342
const std::map< std::string, UTF8 > * m_props
Properties passed via Save() or Load(), no ownership, may be NULL.
Definition pcb_io.h:352
void SetWidth(int aWidth) override
void SetShape(SHAPE_T aShape) override
Definition pcb_shape.h:200
void SetEnd(const VECTOR2I &aEnd) override
void SetArcGeometry(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void SetStart(const VECTOR2I &aStart) override
void SetEnd(const VECTOR2I &aEnd)
Definition pcb_track.h:89
void SetStart(const VECTOR2I &aStart)
Definition pcb_track.h:92
virtual void SetWidth(int aWidth)
Definition pcb_track.h:86
Container for project specific data.
Definition project.h:62
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:71
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
Represent a set of closed polygons.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
Handle a list of polygons defining a copper zone.
Definition zone.h:70
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition zone.cpp:599
void SetAssignedPriority(unsigned aPriority)
Definition zone.h:117
void SetOutline(SHAPE_POLY_SET *aOutline)
Definition zone.h:421
#define _(s)
@ DEGREES_T
Definition eda_angle.h:31
@ SEGMENT
Definition eda_shape.h:46
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:47
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition layer_ids.h:675
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ Edge_Cuts
Definition layer_ids.h:108
@ B_Cu
Definition layer_ids.h:61
@ In2_Cu
Definition layer_ids.h:63
@ F_SilkS
Definition layer_ids.h:96
@ In4_Cu
Definition layer_ids.h:65
@ In1_Cu
Definition layer_ids.h:62
@ B_SilkS
Definition layer_ids.h:97
@ In6_Cu
Definition layer_ids.h:67
@ In5_Cu
Definition layer_ids.h:66
@ In3_Cu
Definition layer_ids.h:64
@ F_Cu
Definition layer_ids.h:60
@ LAYER_BOTTOM_COPPER
@ SMD
Smd pad, appears on the solder paste layer (default)
Definition padstack.h:99
@ PTH
Plated through hole pad.
Definition padstack.h:98
@ CHAMFERED_RECT
Definition padstack.h:60
@ ROUNDRECT
Definition padstack.h:57
@ RECTANGLE
Definition padstack.h:54
static std::vector< ARC_SPAN > arcSpansFromSegments(int aSegments)
Translate an Autotrax arc quadrant bitmask into the arc spans it represents.
static bool readFile(const wxString &aFileName, wxString &aOut, size_t aLimit=0)
Read a file into aOut.
One arc as a (start angle, signed sweep) pair in the file's native Y-down frame.
Free or component arc (FA / CA).
int segments
quadrant bitmask; 15 = full circle
Everything parsed out of an Autotrax/Easytrax file, before any KiCad object is created.
std::vector< COMPONENT > components
std::vector< VIA > vias
std::vector< NET_NODE > netNodes
std::vector< PAD > pads
std::vector< TRACK > tracks
std::vector< TEXT > texts
std::vector< ARC > arcs
std::vector< FILL > fills
A placed component (COMP .. ENDCOMP) holding its own primitives.
std::vector< ARC > arcs
std::vector< TRACK > tracks
std::vector< VIA > vias
std::vector< PAD > pads
std::vector< FILL > fills
std::vector< TEXT > texts
Free or component rectangular fill (FF / CF), Autotrax's only pour.
One refdes -> net membership row collected from the NETDEF section.
Free or component pad/pin (FP / CP).
int shape
1 round, 2 rect, 3 octagon, 4 round-rect
Free or component string (FS / CS).
int direction
0..3, multiplied by 90 degrees
Free or component track segment (FT / CT). All coordinates are in mils.
Free or component via (FV / CV).
IbisParser parser & reporter
VECTOR2I center
#define M_PI
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683