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
128void PCB_IO_AUTOTRAX::loadBoard( const wxString& aFileName, BOARD& aBoard, bool aIsNewLoad,
129 const std::map<std::string, UTF8>* aProperties, PROJECT* aProject )
130{
131 m_props = aProperties;
132 m_board = &aBoard;
133
134 m_nets.clear();
135 m_maxY = 0;
136
137 wxString contents;
138
139 if( !readFile( aFileName, contents ) )
140 THROW_IO_ERRORF( _( "Could not read file '%s'." ), aFileName );
141
143 BOARD_DATA data;
144
145 AUTOTRAX_PARSER parser( &reporter );
146
147 if( !parser.Parse( contents, data ) )
148 THROW_IO_ERRORF( _( "'%s' is not a valid Protel Autotrax file." ), aFileName );
149
150 buildBoard( data );
151}
152
153
154bool PCB_IO_AUTOTRAX::mapLayer( int aLayer, PCB_LAYER_ID& aResult ) const
155{
156 using namespace AUTOTRAX;
157
158 switch( aLayer )
159 {
160 case LAYER_TOP_COPPER: aResult = F_Cu; return true;
161 case LAYER_MID1: aResult = In1_Cu; return true;
162 case LAYER_MID2: aResult = In2_Cu; return true;
163 case LAYER_MID3: aResult = In3_Cu; return true;
164 case LAYER_MID4: aResult = In4_Cu; return true;
165 case LAYER_BOTTOM_COPPER: aResult = B_Cu; return true;
166 case LAYER_TOP_SILK: aResult = F_SilkS; return true;
167 case LAYER_BOTTOM_SILK: aResult = B_SilkS; return true;
168 case LAYER_GND_PLANE: aResult = In5_Cu; return true;
169 case LAYER_POWER_PLANE: aResult = In6_Cu; return true;
170 case LAYER_BOARD: aResult = Edge_Cuts; return true;
171 case LAYER_MULTI: aResult = F_Cu; return true; // through-all features
172 default:
173 // 0 (unset) and 12 (keepout) have no KiCad target and are dropped.
174 return false;
175 }
176}
177
178
179NETINFO_ITEM* PCB_IO_AUTOTRAX::getNet( const wxString& aNetName )
180{
181 if( aNetName.IsEmpty() )
182 return nullptr;
183
184 auto it = m_nets.find( aNetName );
185
186 if( it != m_nets.end() )
187 return it->second;
188
189 // Reuse a net already on the board (e.g. when appending) so codes and names
190 // are never duplicated.
191 if( NETINFO_ITEM* existing = m_board->FindNet( aNetName ) )
192 {
193 m_nets[aNetName] = existing;
194 return existing;
195 }
196
197 NETINFO_ITEM* net = new NETINFO_ITEM( m_board, aNetName );
198 m_board->Add( net );
199 m_nets[aNetName] = net;
200 return net;
201}
202
203
205{
206 return aFootprint ? static_cast<BOARD_ITEM*>( aFootprint ) : static_cast<BOARD_ITEM*>( m_board );
207}
208
209
211{
212 if( aFootprint )
213 aFootprint->Add( aItem );
214 else
215 m_board->Add( aItem, ADD_MODE::APPEND );
216}
217
218
222{
223 double startDeg;
224 double deltaDeg;
225};
226
227
231static std::vector<ARC_SPAN> arcSpansFromSegments( int aSegments )
232{
233 switch( aSegments )
234 {
235 case 1: return { { 90.0, 90.0 } }; // RU quadrant
236 case 2: return { { 0.0, 90.0 } }; // LU quadrant
237 case 4: return { { 270.0, 90.0 } }; // LL quadrant
238 case 8: return { { 180.0, 90.0 } }; // RL quadrant
239 case 3: return { { 0.0, 180.0 } }; // upper half
240 case 6: return { { 270.0, 180.0 } }; // left half
241 case 12: return { { 180.0, 180.0 } }; // lower half
242 case 9: return { { 90.0, 180.0 } }; // right half
243 case 14: return { { 180.0, 270.0 } }; // not RU
244 case 13: return { { 90.0, 270.0 } }; // not LU
245 case 11: return { { 0.0, 270.0 } }; // not LL
246 case 7: return { { 270.0, 270.0 } }; // not RL
247 case 5: return { { 270.0, 90.0 }, { 90.0, 90.0 } }; // RU + LL quadrants
248 case 10: return { { 180.0, 90.0 }, { 0.0, 90.0 } }; // LU + RL quadrants
249 default: return { { 0.0, 360.0 } }; // full circle
250 }
251}
252
253
254void PCB_IO_AUTOTRAX::emitTrack( const TRACK& aTrack, FOOTPRINT* aFootprint )
255{
256 PCB_LAYER_ID layer;
257
258 if( !mapLayer( aTrack.layer, layer ) )
259 return;
260
261 // A free copper segment becomes a routed PCB_TRACK. Everything else, and any
262 // segment owned by a footprint, becomes a graphic PCB_SHAPE so it stays with
263 // the footprint (KiCad footprints cannot own PCB_TRACK objects).
264 if( IsCopperLayer( layer ) && !aFootprint )
265 {
266 PCB_TRACK* track = new PCB_TRACK( m_board );
267 track->SetStart( toBoard( aTrack.x1, aTrack.y1 ) );
268 track->SetEnd( toBoard( aTrack.x2, aTrack.y2 ) );
269 track->SetWidth( std::max( 1, toIU( aTrack.width ) ) );
270 track->SetLayer( layer );
271 m_board->Add( track, ADD_MODE::APPEND );
272 return;
273 }
274
275 PCB_SHAPE* shape = new PCB_SHAPE( parentOf( aFootprint ), SHAPE_T::SEGMENT );
276 shape->SetLayer( layer );
277 shape->SetStart( toBoard( aTrack.x1, aTrack.y1 ) );
278 shape->SetEnd( toBoard( aTrack.x2, aTrack.y2 ) );
279 shape->SetWidth( std::max( 1, toIU( aTrack.width ) ) );
280 addItem( shape, aFootprint );
281}
282
283
284void PCB_IO_AUTOTRAX::emitArc( const ARC& aArc, FOOTPRINT* aFootprint )
285{
286 PCB_LAYER_ID layer;
287
288 if( !mapLayer( aArc.layer, layer ) )
289 return;
290
291 int r = toIU( aArc.radius );
292 int width = std::max( 1, toIU( aArc.width ) );
293 VECTOR2I center = toBoard( aArc.centerX, aArc.centerY );
294
295 // A point on the circle for an angle in the Y-down file frame. toBoard()
296 // applies the Y flip so the resulting geometry lands in KiCad space.
297 auto pointAt = [&]( double aDeg )
298 {
299 double rad = aDeg * M_PI / 180.0;
300 return toBoard( aArc.centerX + aArc.radius * std::cos( rad ), aArc.centerY + aArc.radius * std::sin( rad ) );
301 };
302
303 for( const ARC_SPAN& span : arcSpansFromSegments( aArc.segments ) )
304 {
305 PCB_SHAPE* shape = new PCB_SHAPE( parentOf( aFootprint ) );
306 shape->SetLayer( layer );
307 shape->SetWidth( width );
308
309 if( span.deltaDeg >= 360.0 )
310 {
311 shape->SetShape( SHAPE_T::CIRCLE );
312 shape->SetCenter( center );
313 shape->SetEnd( VECTOR2I( center.x + r, center.y ) );
314 }
315 else
316 {
317 shape->SetShape( SHAPE_T::ARC );
318 shape->SetArcGeometry( pointAt( span.startDeg ), pointAt( span.startDeg + span.deltaDeg / 2.0 ),
319 pointAt( span.startDeg + span.deltaDeg ) );
320 }
321
322 addItem( shape, aFootprint );
323 }
324}
325
326
327void PCB_IO_AUTOTRAX::emitVia( const VIA& aVia, FOOTPRINT* aFootprint )
328{
329 int drill = std::max( 1, toIU( aVia.drill ) );
330 int diameter = std::max( drill + 2, toIU( aVia.diameter ) );
331
332 if( aFootprint )
333 {
334 // A via inside a component becomes a through-hole pad so it travels with
335 // the footprint.
337 pad.x = aVia.x;
338 pad.y = aVia.y;
339 pad.xSize = aVia.diameter;
340 pad.ySize = aVia.diameter;
341 pad.shape = 1;
342 pad.drill = aVia.drill;
344 emitPad( pad, aFootprint );
345 return;
346 }
347
348 PCB_VIA* via = new PCB_VIA( m_board );
349 via->SetPadstackMode( PADSTACK::MODE::NORMAL ); // AutoTrax doesn't have complex padstacks
350 via->SetPosition( toBoard( aVia.x, aVia.y ) );
351 via->SetDrill( drill );
352 via->SetWidth( PADSTACK::ALL_LAYERS, diameter );
353 via->SetViaType( VIATYPE::THROUGH );
354 via->SetLayerPair( F_Cu, B_Cu );
356}
357
358
359void PCB_IO_AUTOTRAX::emitPad( const AUTOTRAX::PAD& aPad, FOOTPRINT* aFootprint )
360{
361 // Layer 11 ("board") pads and the unsupported target shapes are dropped.
362 if( aPad.layer == AUTOTRAX::LAYER_BOARD || aPad.shape == 5 || aPad.shape == 6 )
363 return;
364
365 // Autotrax only places pads on the top (1), bottom (6) or multi/through (13)
366 // layers; other pad layers are unsupported and dropped.
368 && aPad.layer != AUTOTRAX::LAYER_MULTI )
369 {
370 return;
371 }
372
373 PCB_LAYER_ID layer;
374
375 if( !mapLayer( aPad.layer, layer ) )
376 return;
377
378 // A free pad with no owning footprint still needs a footprint container so
379 // KiCad can hold the pad; create a throwaway one anchored at the pad.
380 FOOTPRINT* owner = aFootprint;
381 bool standalone = false;
382
383 if( !owner )
384 {
385 owner = new FOOTPRINT( m_board );
386 owner->SetPosition( toBoard( aPad.x, aPad.y ) );
387 standalone = true;
388 }
389
390 ::PAD* pad = new ::PAD( owner );
391 pad->SetNumber( aPad.name );
392 pad->SetPosition( toBoard( aPad.x, aPad.y ) );
393 pad->SetPadstackMode( PADSTACK::MODE::NORMAL ); // AutoTrax doesn't have complex padstacks
394
395 VECTOR2I size( std::max( 1, toIU( aPad.xSize ) ), std::max( 1, toIU( aPad.ySize ) ) );
396 pad->SetSize( PADSTACK::ALL_LAYERS, size );
397
398 switch( aPad.shape )
399 {
400 case 2: pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::RECTANGLE ); break;
401
402 case 3: // octagon, approximated by chamfering all four corners
404 pad->SetChamferRectRatio( PADSTACK::ALL_LAYERS, 0.25 );
405 pad->SetChamferPositions( PADSTACK::ALL_LAYERS, RECT_CHAMFER_ALL );
406 break;
407
408 case 4: pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::ROUNDRECT ); break;
409
410 default:
411 pad->SetShape( PADSTACK::ALL_LAYERS, ( aPad.xSize == aPad.ySize ) ? PAD_SHAPE::CIRCLE : PAD_SHAPE::OVAL );
412 break;
413 }
414
415 int drill = toIU( aPad.drill );
416
417 if( drill > 0 )
418 {
419 pad->SetAttribute( PAD_ATTRIB::PTH );
420 pad->SetDrillSize( VECTOR2I( drill, drill ) );
421 pad->SetLayerSet( ::PAD::PTHMask() );
422 }
423 else
424 {
425 pad->SetAttribute( PAD_ATTRIB::SMD );
426
427 LSET smdMask = ::PAD::SMDMask();
428
429 if( layer == B_Cu )
430 smdMask.FlipStandardLayers();
431
432 pad->SetLayerSet( smdMask );
433 }
434
435 owner->Add( pad );
436
437 if( standalone )
438 m_board->Add( owner, ADD_MODE::APPEND );
439}
440
441
442void PCB_IO_AUTOTRAX::emitFill( const FILL& aFill, FOOTPRINT* aFootprint )
443{
444 PCB_LAYER_ID layer;
445
446 if( !mapLayer( aFill.layer, layer ) )
447 return;
448
449 VECTOR2I p1 = toBoard( aFill.x1, aFill.y1 );
450 VECTOR2I p2 = toBoard( aFill.x2, aFill.y2 );
451
452 int minX = std::min( p1.x, p2.x );
453 int maxX = std::max( p1.x, p2.x );
454 int minY = std::min( p1.y, p2.y );
455 int maxY = std::max( p1.y, p2.y );
456
457 // Autotrax fills are rectangular pours. On copper layers they become a zone;
458 // elsewhere a filled rectangle graphic.
459 if( IsCopperLayer( layer ) && !aFootprint )
460 {
461 SHAPE_POLY_SET poly;
462 SHAPE_LINE_CHAIN outline;
463 outline.Append( VECTOR2I( minX, minY ) );
464 outline.Append( VECTOR2I( maxX, minY ) );
465 outline.Append( VECTOR2I( maxX, maxY ) );
466 outline.Append( VECTOR2I( minX, maxY ) );
467 outline.SetClosed( true );
468 poly.AddOutline( outline );
469
470 ZONE* zone = new ZONE( m_board );
471 zone->SetLayer( layer );
472 zone->SetOutline( new SHAPE_POLY_SET( poly ) );
473 zone->SetAssignedPriority( 0 );
474 m_board->Add( zone, ADD_MODE::APPEND );
475 return;
476 }
477
478 PCB_SHAPE* shape = new PCB_SHAPE( parentOf( aFootprint ), SHAPE_T::RECTANGLE );
479 shape->SetLayer( layer );
480 shape->SetStart( VECTOR2I( minX, minY ) );
481 shape->SetEnd( VECTOR2I( maxX, maxY ) );
482 shape->SetFilled( true );
483 shape->SetWidth( 0 );
484 addItem( shape, aFootprint );
485}
486
487
488void PCB_IO_AUTOTRAX::emitText( const TEXT& aText, FOOTPRINT* aFootprint )
489{
490 PCB_LAYER_ID layer;
491
492 if( !mapLayer( aText.layer, layer ) )
493 return;
494
495 PCB_TEXT* text = new PCB_TEXT( parentOf( aFootprint ) );
496 text->SetText( aText.text );
497 text->SetLayer( layer );
498 text->SetPosition( toBoard( aText.x, aText.y ) );
499
500 int height = std::max( 1, toIU( aText.height ) );
501 text->SetTextSize( VECTOR2I( height, height ) );
502 text->SetTextThickness( std::max( 1, toIU( aText.width ) ) );
503
504 // Direction is 0..3 in 90 degree steps. The Y flip mirrors the rotation, so
505 // negate it to keep the text reading the same way it did in Autotrax.
506 text->SetTextAngle( EDA_ANGLE( -90.0 * aText.direction, DEGREES_T ) );
507
508 if( layer == B_Cu || layer == B_SilkS )
509 text->SetMirrored( true );
510
511 addItem( text, aFootprint );
512}
513
514
516{
517 FOOTPRINT* fp = new FOOTPRINT( m_board );
518 fp->SetPosition( toBoard( aComp.x, aComp.y ) );
519
520 if( !aComp.refdes.IsEmpty() )
521 fp->SetReference( aComp.refdes );
522
523 if( !aComp.value.IsEmpty() )
524 fp->SetValue( aComp.value );
525
526 if( !aComp.name.IsEmpty() )
527 fp->SetFPID( LIB_ID( wxEmptyString, aComp.name ) );
528
529 for( const TRACK& t : aComp.tracks )
530 emitTrack( t, fp );
531
532 for( const ARC& a : aComp.arcs )
533 emitArc( a, fp );
534
535 for( const VIA& v : aComp.vias )
536 emitVia( v, fp );
537
538 for( const AUTOTRAX::PAD& p : aComp.pads )
539 emitPad( p, fp );
540
541 for( const FILL& f : aComp.fills )
542 emitFill( f, fp );
543
544 for( const TEXT& s : aComp.texts )
545 emitText( s, fp );
546
547 m_board->Add( fp, ADD_MODE::APPEND );
548}
549
550
552{
553 // A single walk over every primitive (free and component-owned) collects two
554 // things needed before any item is emitted: the deepest inner copper layer
555 // referenced, and the Y extent of the data.
556 //
557 // mapLayer() places the four inner copper layers on In1..In4 and the GND and
558 // Power planes on In5/In6, so the board must enable enough copper layers for
559 // the deepest inner layer actually referenced (otherwise items land on a
560 // disabled layer). A two-sided board keeps just F_Cu/B_Cu.
561 //
562 // The Y extent drives the Y-down -> Y-up flip about the data bounding box
563 // so all coordinates stay positive.
564 int innerNeeded = 0;
565 double maxYmils = 0.0;
566
567 auto noteLayer = [&]( int aLayer )
568 {
569 switch( aLayer )
570 {
571 case AUTOTRAX::LAYER_MID1: innerNeeded = std::max( innerNeeded, 1 ); break;
572 case AUTOTRAX::LAYER_MID2: innerNeeded = std::max( innerNeeded, 2 ); break;
573 case AUTOTRAX::LAYER_MID3: innerNeeded = std::max( innerNeeded, 3 ); break;
574 case AUTOTRAX::LAYER_MID4: innerNeeded = std::max( innerNeeded, 4 ); break;
575 case AUTOTRAX::LAYER_GND_PLANE: innerNeeded = std::max( innerNeeded, 5 ); break;
576 case AUTOTRAX::LAYER_POWER_PLANE: innerNeeded = std::max( innerNeeded, 6 ); break;
577 default: break;
578 }
579 };
580
581 // BOARD_DATA and COMPONENT share the same six primitive members, so one
582 // generic walk covers both the free primitives and each component's.
583 auto scan = [&]( const auto& aContainer )
584 {
585 for( const TRACK& t : aContainer.tracks )
586 {
587 noteLayer( t.layer );
588 maxYmils = std::max( { maxYmils, t.y1, t.y2 } );
589 }
590
591 for( const ARC& a : aContainer.arcs )
592 {
593 noteLayer( a.layer );
594 maxYmils = std::max( maxYmils, a.centerY + a.radius );
595 }
596
597 for( const VIA& v : aContainer.vias )
598 maxYmils = std::max( maxYmils, v.y );
599
600 for( const AUTOTRAX::PAD& p : aContainer.pads )
601 {
602 noteLayer( p.layer );
603 maxYmils = std::max( maxYmils, p.y );
604 }
605
606 for( const FILL& f : aContainer.fills )
607 {
608 noteLayer( f.layer );
609 maxYmils = std::max( { maxYmils, f.y1, f.y2 } );
610 }
611
612 for( const TEXT& s : aContainer.texts )
613 maxYmils = std::max( maxYmils, s.y );
614 };
615
616 scan( aData );
617
618 for( const AUTOTRAX::COMPONENT& c : aData.components )
619 scan( c );
620
621 m_board->SetCopperLayerCount( 2 + innerNeeded );
622 m_maxY = toIU( maxYmils );
623
624 // Pre-create nets so pads/tracks can reference them by name.
625 for( const NET_NODE& node : aData.netNodes )
626 getNet( node.netName );
627
628 for( const TRACK& t : aData.tracks )
629 emitTrack( t, nullptr );
630
631 for( const ARC& a : aData.arcs )
632 emitArc( a, nullptr );
633
634 for( const VIA& v : aData.vias )
635 emitVia( v, nullptr );
636
637 for( const AUTOTRAX::PAD& p : aData.pads )
638 emitPad( p, nullptr );
639
640 for( const FILL& f : aData.fills )
641 emitFill( f, nullptr );
642
643 for( const TEXT& s : aData.texts )
644 emitText( s, nullptr );
645
646 for( const AUTOTRAX::COMPONENT& c : aData.components )
647 buildComponent( c );
648}
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:409
void SetCenter(const VECTOR2I &aCenter)
virtual void SetFilled(bool aFlag)
Definition eda_shape.h:142
void SetPosition(const VECTOR2I &aPos) override
void SetFPID(const LIB_ID &aFPID)
Definition footprint.h:474
void SetReference(const wxString &aReference)
Definition footprint.h:907
void SetValue(const wxString &aValue)
Definition footprint.h:930
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:238
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:50
static REPORTER & GetInstance()
Definition reporter.cpp:207
@ NORMAL
Shape is the same on all layers.
Definition padstack.h:170
static constexpr PCB_LAYER_ID ALL_LAYERS
! The layer identifier to use for the single defintion on normal padstacks
Definition padstack.h:179
Definition pad.h:61
static LSET PTHMask()
layer set for a through hole pad
Definition pad.cpp:606
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition pad.cpp:613
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
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 loadBoard(const wxString &aFileName, BOARD &aBoard, bool aIsNewLoad, const std::map< std::string, UTF8 > *aProperties=nullptr, PROJECT *aProject=nullptr) override
Parse aFileName into aBoard.
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:368
virtual bool CanReadBoard(const wxString &aFileName) const
Checks if this PCB_IO can read the specified board file.
Definition pcb_io.cpp:40
PCB_IO(const wxString &aName)
Definition pcb_io.h:351
const std::map< std::string, UTF8 > * m_props
Properties passed via Save() or Load(), no ownership, may be NULL.
Definition pcb_io.h:371
void SetWidth(int aWidth) override
void SetShape(SHAPE_T aShape) override
Definition pcb_shape.h:207
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:63
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:73
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:641
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:56
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:57
#define THROW_IO_ERRORF(msg,...)
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition layer_ids.h:703
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:98
@ PTH
Plated through hole pad.
Definition padstack.h:97
@ CHAMFERED_RECT
Definition padstack.h:59
@ ROUNDRECT
Definition padstack.h:56
@ RECTANGLE
Definition padstack.h:53
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