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, you may find one here:
23 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
24 * or you may search the http://www.gnu.org website for the version 2 license,
25 * or you may write to the Free Software Foundation, Inc.,
26 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
27 */
28
29#include "pcb_io_autotrax.h"
30#include "autotrax_parser.h"
31
32#include <board.h>
34#include <footprint.h>
35#include <pad.h>
36#include <pcb_track.h>
37#include <pcb_shape.h>
38#include <pcb_text.h>
39#include <zone.h>
40#include <netinfo.h>
42#include <geometry/eda_angle.h>
44#include <reporter.h>
45#include <math/util.h>
46#include <math/vector2d.h>
47
49
50#include <algorithm>
51#include <cmath>
52#include <fstream>
53#include <sstream>
54
55using AUTOTRAX::ARC;
57using AUTOTRAX::FILL;
59using AUTOTRAX::TEXT;
60using AUTOTRAX::TRACK;
61using AUTOTRAX::VIA;
62
63// AUTOTRAX::PAD and AUTOTRAX::COMPONENT collide with KiCad's global PAD class and
64// board.h's COMPONENT class, so both are always spelled out with the namespace
65// prefix here and the KiCad PAD class is reached as ::PAD.
66
67
69 PCB_IO( wxS( "Protel Autotrax" ) )
70{
71}
72
73
77
78
85static bool readFile( const wxString& aFileName, wxString& aOut, size_t aLimit = 0 )
86{
87 std::ifstream file( aFileName.fn_str(), std::ios::binary );
88
89 if( !file.is_open() )
90 return false;
91
92 std::string raw;
93
94 if( aLimit > 0 )
95 {
96 raw.resize( aLimit );
97 file.read( raw.data(), aLimit );
98 raw.resize( static_cast<size_t>( file.gcount() ) );
99 }
100 else
101 {
102 std::ostringstream ss;
103 ss << file.rdbuf();
104 raw = ss.str();
105 }
106
107 aOut = wxString::FromUTF8( raw.data(), raw.size() );
108
109 if( aOut.IsEmpty() && !raw.empty() )
110 aOut = wxString::From8BitData( raw.data(), raw.size() );
111
112 return true;
113}
114
115
116bool PCB_IO_AUTOTRAX::CanReadBoard( const wxString& aFileName ) const
117{
118 if( !PCB_IO::CanReadBoard( aFileName ) )
119 return false;
120
121 // The magic header is in the first non-blank line, so a small prefix read is
122 // enough to disambiguate from the gEDA .pcb files sharing this extension.
123 wxString contents;
124
125 if( !readFile( aFileName, contents, 4096 ) )
126 return false;
127
128 return AUTOTRAX_PARSER::Sniff( contents );
129}
130
131
132BOARD* PCB_IO_AUTOTRAX::LoadBoard( const wxString& aFileName, BOARD* aAppendToMe,
133 const std::map<std::string, UTF8>* aProperties, PROJECT* aProject )
134{
135 m_props = aProperties;
136 m_board = aAppendToMe ? aAppendToMe : new BOARD();
137
138 // Own a freshly-allocated board until parsing succeeds so a thrown IO_ERROR
139 // does not leak it. An appended board belongs to the caller.
140 std::unique_ptr<BOARD> boardDeleter( aAppendToMe ? nullptr : m_board );
141
142 m_nets.clear();
143 m_maxY = 0;
144
145 if( !aAppendToMe )
146 m_board->SetFileName( aFileName );
147
148 wxString contents;
149
150 if( !readFile( aFileName, contents ) )
151 THROW_IO_ERROR( wxString::Format( _( "Could not read file '%s'." ), aFileName ) );
152
154 BOARD_DATA data;
155
156 AUTOTRAX_PARSER parser( &reporter );
157
158 if( !parser.Parse( contents, data ) )
159 THROW_IO_ERROR( wxString::Format( _( "'%s' is not a valid Protel Autotrax file." ), aFileName ) );
160
161 buildBoard( data );
162
163 boardDeleter.release();
164 return m_board;
165}
166
167
168bool PCB_IO_AUTOTRAX::mapLayer( int aLayer, PCB_LAYER_ID& aResult ) const
169{
170 using namespace AUTOTRAX;
171
172 switch( aLayer )
173 {
174 case LAYER_TOP_COPPER: aResult = F_Cu; return true;
175 case LAYER_MID1: aResult = In1_Cu; return true;
176 case LAYER_MID2: aResult = In2_Cu; return true;
177 case LAYER_MID3: aResult = In3_Cu; return true;
178 case LAYER_MID4: aResult = In4_Cu; return true;
179 case LAYER_BOTTOM_COPPER: aResult = B_Cu; return true;
180 case LAYER_TOP_SILK: aResult = F_SilkS; return true;
181 case LAYER_BOTTOM_SILK: aResult = B_SilkS; return true;
182 case LAYER_GND_PLANE: aResult = In5_Cu; return true;
183 case LAYER_POWER_PLANE: aResult = In6_Cu; return true;
184 case LAYER_BOARD: aResult = Edge_Cuts; return true;
185 case LAYER_MULTI: aResult = F_Cu; return true; // through-all features
186 default:
187 // 0 (unset) and 12 (keepout) have no KiCad target and are dropped.
188 return false;
189 }
190}
191
192
193NETINFO_ITEM* PCB_IO_AUTOTRAX::getNet( const wxString& aNetName )
194{
195 if( aNetName.IsEmpty() )
196 return nullptr;
197
198 auto it = m_nets.find( aNetName );
199
200 if( it != m_nets.end() )
201 return it->second;
202
203 // Reuse a net already on the board (e.g. when appending) so codes and names
204 // are never duplicated.
205 if( NETINFO_ITEM* existing = m_board->FindNet( aNetName ) )
206 {
207 m_nets[aNetName] = existing;
208 return existing;
209 }
210
211 NETINFO_ITEM* net = new NETINFO_ITEM( m_board, aNetName );
212 m_board->Add( net );
213 m_nets[aNetName] = net;
214 return net;
215}
216
217
219{
220 return aFootprint ? static_cast<BOARD_ITEM*>( aFootprint ) : static_cast<BOARD_ITEM*>( m_board );
221}
222
223
225{
226 if( aFootprint )
227 aFootprint->Add( aItem );
228 else
229 m_board->Add( aItem, ADD_MODE::APPEND );
230}
231
232
236{
237 double startDeg;
238 double deltaDeg;
239};
240
241
245static std::vector<ARC_SPAN> arcSpansFromSegments( int aSegments )
246{
247 switch( aSegments )
248 {
249 case 1: return { { 90.0, 90.0 } }; // RU quadrant
250 case 2: return { { 0.0, 90.0 } }; // LU quadrant
251 case 4: return { { 270.0, 90.0 } }; // LL quadrant
252 case 8: return { { 180.0, 90.0 } }; // RL quadrant
253 case 3: return { { 0.0, 180.0 } }; // upper half
254 case 6: return { { 270.0, 180.0 } }; // left half
255 case 12: return { { 180.0, 180.0 } }; // lower half
256 case 9: return { { 90.0, 180.0 } }; // right half
257 case 14: return { { 180.0, 270.0 } }; // not RU
258 case 13: return { { 90.0, 270.0 } }; // not LU
259 case 11: return { { 0.0, 270.0 } }; // not LL
260 case 7: return { { 270.0, 270.0 } }; // not RL
261 case 5: return { { 270.0, 90.0 }, { 90.0, 90.0 } }; // RU + LL quadrants
262 case 10: return { { 180.0, 90.0 }, { 0.0, 90.0 } }; // LU + RL quadrants
263 default: return { { 0.0, 360.0 } }; // full circle
264 }
265}
266
267
268void PCB_IO_AUTOTRAX::emitTrack( const TRACK& aTrack, FOOTPRINT* aFootprint )
269{
270 PCB_LAYER_ID layer;
271
272 if( !mapLayer( aTrack.layer, layer ) )
273 return;
274
275 // A free copper segment becomes a routed PCB_TRACK. Everything else, and any
276 // segment owned by a footprint, becomes a graphic PCB_SHAPE so it stays with
277 // the footprint (KiCad footprints cannot own PCB_TRACK objects).
278 if( IsCopperLayer( layer ) && !aFootprint )
279 {
280 PCB_TRACK* track = new PCB_TRACK( m_board );
281 track->SetStart( toBoard( aTrack.x1, aTrack.y1 ) );
282 track->SetEnd( toBoard( aTrack.x2, aTrack.y2 ) );
283 track->SetWidth( std::max( 1, toIU( aTrack.width ) ) );
284 track->SetLayer( layer );
285 m_board->Add( track, ADD_MODE::APPEND );
286 return;
287 }
288
289 PCB_SHAPE* shape = new PCB_SHAPE( parentOf( aFootprint ), SHAPE_T::SEGMENT );
290 shape->SetLayer( layer );
291 shape->SetStart( toBoard( aTrack.x1, aTrack.y1 ) );
292 shape->SetEnd( toBoard( aTrack.x2, aTrack.y2 ) );
293 shape->SetWidth( std::max( 1, toIU( aTrack.width ) ) );
294 addItem( shape, aFootprint );
295}
296
297
298void PCB_IO_AUTOTRAX::emitArc( const ARC& aArc, FOOTPRINT* aFootprint )
299{
300 PCB_LAYER_ID layer;
301
302 if( !mapLayer( aArc.layer, layer ) )
303 return;
304
305 int r = toIU( aArc.radius );
306 int width = std::max( 1, toIU( aArc.width ) );
307 VECTOR2I center = toBoard( aArc.centerX, aArc.centerY );
308
309 // A point on the circle for an angle in the Y-down file frame. toBoard()
310 // applies the Y flip so the resulting geometry lands in KiCad space.
311 auto pointAt = [&]( double aDeg )
312 {
313 double rad = aDeg * M_PI / 180.0;
314 return toBoard( aArc.centerX + aArc.radius * std::cos( rad ), aArc.centerY + aArc.radius * std::sin( rad ) );
315 };
316
317 for( const ARC_SPAN& span : arcSpansFromSegments( aArc.segments ) )
318 {
319 PCB_SHAPE* shape = new PCB_SHAPE( parentOf( aFootprint ) );
320 shape->SetLayer( layer );
321 shape->SetWidth( width );
322
323 if( span.deltaDeg >= 360.0 )
324 {
325 shape->SetShape( SHAPE_T::CIRCLE );
326 shape->SetCenter( center );
327 shape->SetEnd( VECTOR2I( center.x + r, center.y ) );
328 }
329 else
330 {
331 shape->SetShape( SHAPE_T::ARC );
332 shape->SetArcGeometry( pointAt( span.startDeg ), pointAt( span.startDeg + span.deltaDeg / 2.0 ),
333 pointAt( span.startDeg + span.deltaDeg ) );
334 }
335
336 addItem( shape, aFootprint );
337 }
338}
339
340
341void PCB_IO_AUTOTRAX::emitVia( const VIA& aVia, FOOTPRINT* aFootprint )
342{
343 int drill = std::max( 1, toIU( aVia.drill ) );
344 int diameter = std::max( drill + 2, toIU( aVia.diameter ) );
345
346 if( aFootprint )
347 {
348 // A via inside a component becomes a through-hole pad so it travels with
349 // the footprint.
351 pad.x = aVia.x;
352 pad.y = aVia.y;
353 pad.xSize = aVia.diameter;
354 pad.ySize = aVia.diameter;
355 pad.shape = 1;
356 pad.drill = aVia.drill;
358 emitPad( pad, aFootprint );
359 return;
360 }
361
362 PCB_VIA* via = new PCB_VIA( m_board );
363 via->SetPosition( toBoard( aVia.x, aVia.y ) );
364 via->SetDrill( drill );
365 via->SetWidth( PADSTACK::ALL_LAYERS, diameter );
366 via->SetViaType( VIATYPE::THROUGH );
367 via->SetLayerPair( F_Cu, B_Cu );
369}
370
371
372void PCB_IO_AUTOTRAX::emitPad( const AUTOTRAX::PAD& aPad, FOOTPRINT* aFootprint )
373{
374 // Layer 11 ("board") pads and the unsupported target shapes are dropped.
375 if( aPad.layer == AUTOTRAX::LAYER_BOARD || aPad.shape == 5 || aPad.shape == 6 )
376 return;
377
378 // Autotrax only places pads on the top (1), bottom (6) or multi/through (13)
379 // layers; other pad layers are unsupported and dropped.
381 && aPad.layer != AUTOTRAX::LAYER_MULTI )
382 {
383 return;
384 }
385
386 PCB_LAYER_ID layer;
387
388 if( !mapLayer( aPad.layer, layer ) )
389 return;
390
391 // A free pad with no owning footprint still needs a footprint container so
392 // KiCad can hold the pad; create a throwaway one anchored at the pad.
393 FOOTPRINT* owner = aFootprint;
394 bool standalone = false;
395
396 if( !owner )
397 {
398 owner = new FOOTPRINT( m_board );
399 owner->SetPosition( toBoard( aPad.x, aPad.y ) );
400 standalone = true;
401 }
402
403 ::PAD* pad = new ::PAD( owner );
404 pad->SetNumber( aPad.name );
405 pad->SetPosition( toBoard( aPad.x, aPad.y ) );
406
407 VECTOR2I size( std::max( 1, toIU( aPad.xSize ) ), std::max( 1, toIU( aPad.ySize ) ) );
408 pad->SetSize( PADSTACK::ALL_LAYERS, size );
409
410 switch( aPad.shape )
411 {
412 case 2: pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::RECTANGLE ); break;
413
414 case 3: // octagon, approximated by chamfering all four corners
416 pad->SetChamferRectRatio( PADSTACK::ALL_LAYERS, 0.25 );
417 pad->SetChamferPositions( PADSTACK::ALL_LAYERS, RECT_CHAMFER_ALL );
418 break;
419
420 case 4: pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::ROUNDRECT ); break;
421
422 default:
423 pad->SetShape( PADSTACK::ALL_LAYERS, ( aPad.xSize == aPad.ySize ) ? PAD_SHAPE::CIRCLE : PAD_SHAPE::OVAL );
424 break;
425 }
426
427 int drill = toIU( aPad.drill );
428
429 if( drill > 0 )
430 {
431 pad->SetAttribute( PAD_ATTRIB::PTH );
432 pad->SetDrillSize( VECTOR2I( drill, drill ) );
433 pad->SetLayerSet( ::PAD::PTHMask() );
434 }
435 else
436 {
437 pad->SetAttribute( PAD_ATTRIB::SMD );
438
439 LSET smdMask = ::PAD::SMDMask();
440
441 if( layer == B_Cu )
442 smdMask.FlipStandardLayers();
443
444 pad->SetLayerSet( smdMask );
445 }
446
447 owner->Add( pad );
448
449 if( standalone )
450 m_board->Add( owner, ADD_MODE::APPEND );
451}
452
453
454void PCB_IO_AUTOTRAX::emitFill( const FILL& aFill, FOOTPRINT* aFootprint )
455{
456 PCB_LAYER_ID layer;
457
458 if( !mapLayer( aFill.layer, layer ) )
459 return;
460
461 VECTOR2I p1 = toBoard( aFill.x1, aFill.y1 );
462 VECTOR2I p2 = toBoard( aFill.x2, aFill.y2 );
463
464 int minX = std::min( p1.x, p2.x );
465 int maxX = std::max( p1.x, p2.x );
466 int minY = std::min( p1.y, p2.y );
467 int maxY = std::max( p1.y, p2.y );
468
469 // Autotrax fills are rectangular pours. On copper layers they become a zone;
470 // elsewhere a filled rectangle graphic.
471 if( IsCopperLayer( layer ) && !aFootprint )
472 {
473 SHAPE_POLY_SET poly;
474 SHAPE_LINE_CHAIN outline;
475 outline.Append( VECTOR2I( minX, minY ) );
476 outline.Append( VECTOR2I( maxX, minY ) );
477 outline.Append( VECTOR2I( maxX, maxY ) );
478 outline.Append( VECTOR2I( minX, maxY ) );
479 outline.SetClosed( true );
480 poly.AddOutline( outline );
481
482 ZONE* zone = new ZONE( m_board );
483 zone->SetLayer( layer );
484 zone->SetOutline( new SHAPE_POLY_SET( poly ) );
485 zone->SetAssignedPriority( 0 );
486 m_board->Add( zone, ADD_MODE::APPEND );
487 return;
488 }
489
490 PCB_SHAPE* shape = new PCB_SHAPE( parentOf( aFootprint ), SHAPE_T::RECTANGLE );
491 shape->SetLayer( layer );
492 shape->SetStart( VECTOR2I( minX, minY ) );
493 shape->SetEnd( VECTOR2I( maxX, maxY ) );
494 shape->SetFilled( true );
495 shape->SetWidth( 0 );
496 addItem( shape, aFootprint );
497}
498
499
500void PCB_IO_AUTOTRAX::emitText( const TEXT& aText, FOOTPRINT* aFootprint )
501{
502 PCB_LAYER_ID layer;
503
504 if( !mapLayer( aText.layer, layer ) )
505 return;
506
507 PCB_TEXT* text = new PCB_TEXT( parentOf( aFootprint ) );
508 text->SetText( aText.text );
509 text->SetLayer( layer );
510 text->SetPosition( toBoard( aText.x, aText.y ) );
511
512 int height = std::max( 1, toIU( aText.height ) );
513 text->SetTextSize( VECTOR2I( height, height ) );
514 text->SetTextThickness( std::max( 1, toIU( aText.width ) ) );
515
516 // Direction is 0..3 in 90 degree steps. The Y flip mirrors the rotation, so
517 // negate it to keep the text reading the same way it did in Autotrax.
518 text->SetTextAngle( EDA_ANGLE( -90.0 * aText.direction, DEGREES_T ) );
519
520 if( layer == B_Cu || layer == B_SilkS )
521 text->SetMirrored( true );
522
523 addItem( text, aFootprint );
524}
525
526
528{
529 FOOTPRINT* fp = new FOOTPRINT( m_board );
530 fp->SetPosition( toBoard( aComp.x, aComp.y ) );
531
532 if( !aComp.refdes.IsEmpty() )
533 fp->SetReference( aComp.refdes );
534
535 if( !aComp.value.IsEmpty() )
536 fp->SetValue( aComp.value );
537
538 if( !aComp.name.IsEmpty() )
539 fp->SetFPID( LIB_ID( wxEmptyString, aComp.name ) );
540
541 for( const TRACK& t : aComp.tracks )
542 emitTrack( t, fp );
543
544 for( const ARC& a : aComp.arcs )
545 emitArc( a, fp );
546
547 for( const VIA& v : aComp.vias )
548 emitVia( v, fp );
549
550 for( const AUTOTRAX::PAD& p : aComp.pads )
551 emitPad( p, fp );
552
553 for( const FILL& f : aComp.fills )
554 emitFill( f, fp );
555
556 for( const TEXT& s : aComp.texts )
557 emitText( s, fp );
558
559 m_board->Add( fp, ADD_MODE::APPEND );
560}
561
562
564{
565 // A single walk over every primitive (free and component-owned) collects two
566 // things needed before any item is emitted: the deepest inner copper layer
567 // referenced, and the Y extent of the data.
568 //
569 // mapLayer() places the four inner copper layers on In1..In4 and the GND and
570 // Power planes on In5/In6, so the board must enable enough copper layers for
571 // the deepest inner layer actually referenced (otherwise items land on a
572 // disabled layer). A two-sided board keeps just F_Cu/B_Cu.
573 //
574 // The Y extent drives the Y-down -> Y-up flip about the data bounding box
575 // so all coordinates stay positive.
576 int innerNeeded = 0;
577 double maxYmils = 0.0;
578
579 auto noteLayer = [&]( int aLayer )
580 {
581 switch( aLayer )
582 {
583 case AUTOTRAX::LAYER_MID1: innerNeeded = std::max( innerNeeded, 1 ); break;
584 case AUTOTRAX::LAYER_MID2: innerNeeded = std::max( innerNeeded, 2 ); break;
585 case AUTOTRAX::LAYER_MID3: innerNeeded = std::max( innerNeeded, 3 ); break;
586 case AUTOTRAX::LAYER_MID4: innerNeeded = std::max( innerNeeded, 4 ); break;
587 case AUTOTRAX::LAYER_GND_PLANE: innerNeeded = std::max( innerNeeded, 5 ); break;
588 case AUTOTRAX::LAYER_POWER_PLANE: innerNeeded = std::max( innerNeeded, 6 ); break;
589 default: break;
590 }
591 };
592
593 // BOARD_DATA and COMPONENT share the same six primitive members, so one
594 // generic walk covers both the free primitives and each component's.
595 auto scan = [&]( const auto& aContainer )
596 {
597 for( const TRACK& t : aContainer.tracks )
598 {
599 noteLayer( t.layer );
600 maxYmils = std::max( { maxYmils, t.y1, t.y2 } );
601 }
602
603 for( const ARC& a : aContainer.arcs )
604 {
605 noteLayer( a.layer );
606 maxYmils = std::max( maxYmils, a.centerY + a.radius );
607 }
608
609 for( const VIA& v : aContainer.vias )
610 maxYmils = std::max( maxYmils, v.y );
611
612 for( const AUTOTRAX::PAD& p : aContainer.pads )
613 {
614 noteLayer( p.layer );
615 maxYmils = std::max( maxYmils, p.y );
616 }
617
618 for( const FILL& f : aContainer.fills )
619 {
620 noteLayer( f.layer );
621 maxYmils = std::max( { maxYmils, f.y1, f.y2 } );
622 }
623
624 for( const TEXT& s : aContainer.texts )
625 maxYmils = std::max( maxYmils, s.y );
626 };
627
628 scan( aData );
629
630 for( const AUTOTRAX::COMPONENT& c : aData.components )
631 scan( c );
632
633 m_board->SetCopperLayerCount( 2 + innerNeeded );
634 m_maxY = toIU( maxYmils );
635
636 // Pre-create nets so pads/tracks can reference them by name.
637 for( const NET_NODE& node : aData.netNodes )
638 getNet( node.netName );
639
640 for( const TRACK& t : aData.tracks )
641 emitTrack( t, nullptr );
642
643 for( const ARC& a : aData.arcs )
644 emitArc( a, nullptr );
645
646 for( const VIA& v : aData.vias )
647 emitVia( v, nullptr );
648
649 for( const AUTOTRAX::PAD& p : aData.pads )
650 emitPad( p, nullptr );
651
652 for( const FILL& f : aData.fills )
653 emitFill( f, nullptr );
654
655 for( const TEXT& s : aData.texts )
656 emitText( s, nullptr );
657
658 for( const AUTOTRAX::COMPONENT& c : aData.components )
659 buildComponent( c );
660}
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:84
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:323
void SetCenter(const VECTOR2I &aCenter)
virtual void SetFilled(bool aFlag)
Definition eda_shape.h:156
void SetStart(const VECTOR2I &aStart)
Definition eda_shape.h:198
void SetShape(SHAPE_T aShape)
Definition eda_shape.h:188
void SetEnd(const VECTOR2I &aEnd)
Definition eda_shape.h:240
void SetArcGeometry(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Set the three controlling points for an arc.
void SetWidth(int aWidth)
void SetPosition(const VECTOR2I &aPos) override
void SetFPID(const LIB_ID &aFPID)
Definition footprint.h:430
void SetReference(const wxString &aReference)
Definition footprint.h:835
void SetValue(const wxString &aValue)
Definition footprint.h:856
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:49
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:485
Handle the data for a net.
Definition netinfo.h:50
static REPORTER & GetInstance()
Definition reporter.cpp:124
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:65
static LSET PTHMask()
layer set for a through hole pad
Definition pad.cpp:372
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition pad.cpp:379
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:353
virtual bool CanReadBoard(const wxString &aFileName) const
Checks if this PCB_IO can read the specified board file.
Definition pcb_io.cpp:42
PCB_IO(const wxString &aName)
Definition pcb_io.h:346
const std::map< std::string, UTF8 > * m_props
Properties passed via Save() or Load(), no ownership, may be NULL.
Definition pcb_io.h:356
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void SetEnd(const VECTOR2I &aEnd)
Definition pcb_track.h:93
void SetStart(const VECTOR2I &aStart)
Definition pcb_track.h:96
virtual void SetWidth(int aWidth)
Definition pcb_track.h:90
Container for project specific data.
Definition project.h:66
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:75
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:74
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition zone.cpp:603
void SetAssignedPriority(unsigned aPriority)
Definition zone.h:121
void SetOutline(SHAPE_POLY_SET *aOutline)
Definition zone.h:425
#define _(s)
@ DEGREES_T
Definition eda_angle.h:31
@ SEGMENT
Definition eda_shape.h:50
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:51
#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:679
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:60
@ Edge_Cuts
Definition layer_ids.h:112
@ B_Cu
Definition layer_ids.h:65
@ In2_Cu
Definition layer_ids.h:67
@ F_SilkS
Definition layer_ids.h:100
@ In4_Cu
Definition layer_ids.h:69
@ In1_Cu
Definition layer_ids.h:66
@ B_SilkS
Definition layer_ids.h:101
@ In6_Cu
Definition layer_ids.h:71
@ In5_Cu
Definition layer_ids.h:70
@ In3_Cu
Definition layer_ids.h:68
@ F_Cu
Definition layer_ids.h:64
@ 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:687