47#include <compoundfilereader.h>
54#include <wx/docview.h>
56#include <wx/mstream.h>
57#include <wx/wfstream.h>
58#include <wx/zstream.h>
60#include <magic_enum.hpp>
82 THROW_IO_ERROR( wxString::Format( wxT(
"Component creator tries to access component id %u "
83 "of %u existing components" ),
92 const std::vector<ALTIUM_VERTICE>& aVertices )
101 double startradiant =
DEG2RAD( vertex.startangle );
102 double endradiant =
DEG2RAD( vertex.endangle );
104 -
KiROUND( std::sin( startradiant ) * vertex.radius ) );
107 -
KiROUND( std::sin( endradiant ) * vertex.radius ) );
109 VECTOR2I arcStart = vertex.center + arcStartOffset;
110 VECTOR2I arcEnd = vertex.center + arcEndOffset;
115 if( arcStart.
Distance( vertex.position )
116 < arcEnd.
Distance( vertex.position ) )
143 aLine.
Append( vertex.position );
153 auto override =
m_layermap.find( aAltiumLayer );
157 return override->second;
160 switch( aAltiumLayer )
164 case ALTIUM_LAYER::TOP_LAYER:
return F_Cu;
165 case ALTIUM_LAYER::MID_LAYER_1:
return In1_Cu;
166 case ALTIUM_LAYER::MID_LAYER_2:
return In2_Cu;
167 case ALTIUM_LAYER::MID_LAYER_3:
return In3_Cu;
168 case ALTIUM_LAYER::MID_LAYER_4:
return In4_Cu;
169 case ALTIUM_LAYER::MID_LAYER_5:
return In5_Cu;
170 case ALTIUM_LAYER::MID_LAYER_6:
return In6_Cu;
171 case ALTIUM_LAYER::MID_LAYER_7:
return In7_Cu;
172 case ALTIUM_LAYER::MID_LAYER_8:
return In8_Cu;
173 case ALTIUM_LAYER::MID_LAYER_9:
return In9_Cu;
174 case ALTIUM_LAYER::MID_LAYER_10:
return In10_Cu;
175 case ALTIUM_LAYER::MID_LAYER_11:
return In11_Cu;
176 case ALTIUM_LAYER::MID_LAYER_12:
return In12_Cu;
177 case ALTIUM_LAYER::MID_LAYER_13:
return In13_Cu;
178 case ALTIUM_LAYER::MID_LAYER_14:
return In14_Cu;
179 case ALTIUM_LAYER::MID_LAYER_15:
return In15_Cu;
180 case ALTIUM_LAYER::MID_LAYER_16:
return In16_Cu;
181 case ALTIUM_LAYER::MID_LAYER_17:
return In17_Cu;
182 case ALTIUM_LAYER::MID_LAYER_18:
return In18_Cu;
183 case ALTIUM_LAYER::MID_LAYER_19:
return In19_Cu;
184 case ALTIUM_LAYER::MID_LAYER_20:
return In20_Cu;
185 case ALTIUM_LAYER::MID_LAYER_21:
return In21_Cu;
186 case ALTIUM_LAYER::MID_LAYER_22:
return In22_Cu;
187 case ALTIUM_LAYER::MID_LAYER_23:
return In23_Cu;
188 case ALTIUM_LAYER::MID_LAYER_24:
return In24_Cu;
189 case ALTIUM_LAYER::MID_LAYER_25:
return In25_Cu;
190 case ALTIUM_LAYER::MID_LAYER_26:
return In26_Cu;
191 case ALTIUM_LAYER::MID_LAYER_27:
return In27_Cu;
192 case ALTIUM_LAYER::MID_LAYER_28:
return In28_Cu;
193 case ALTIUM_LAYER::MID_LAYER_29:
return In29_Cu;
194 case ALTIUM_LAYER::MID_LAYER_30:
return In30_Cu;
195 case ALTIUM_LAYER::BOTTOM_LAYER:
return B_Cu;
197 case ALTIUM_LAYER::TOP_OVERLAY:
return F_SilkS;
198 case ALTIUM_LAYER::BOTTOM_OVERLAY:
return B_SilkS;
199 case ALTIUM_LAYER::TOP_PASTE:
return F_Paste;
200 case ALTIUM_LAYER::BOTTOM_PASTE:
return B_Paste;
201 case ALTIUM_LAYER::TOP_SOLDER:
return F_Mask;
202 case ALTIUM_LAYER::BOTTOM_SOLDER:
return B_Mask;
221 case ALTIUM_LAYER::DRILL_GUIDE:
return Dwgs_User;
222 case ALTIUM_LAYER::KEEP_OUT_LAYER:
return Margin;
224 case ALTIUM_LAYER::MECHANICAL_1:
return User_1;
225 case ALTIUM_LAYER::MECHANICAL_2:
return User_2;
226 case ALTIUM_LAYER::MECHANICAL_3:
return User_3;
227 case ALTIUM_LAYER::MECHANICAL_4:
return User_4;
228 case ALTIUM_LAYER::MECHANICAL_5:
return User_5;
229 case ALTIUM_LAYER::MECHANICAL_6:
return User_6;
230 case ALTIUM_LAYER::MECHANICAL_7:
return User_7;
231 case ALTIUM_LAYER::MECHANICAL_8:
return User_8;
232 case ALTIUM_LAYER::MECHANICAL_9:
return User_9;
233 case ALTIUM_LAYER::MECHANICAL_10:
return Dwgs_User;
234 case ALTIUM_LAYER::MECHANICAL_11:
return Eco2_User;
235 case ALTIUM_LAYER::MECHANICAL_12:
return F_Fab;
236 case ALTIUM_LAYER::MECHANICAL_13:
return B_Fab;
241 case ALTIUM_LAYER::DRILL_DRAWING:
return Dwgs_User;
259 static std::set<ALTIUM_LAYER> altiumLayersWithWarning;
261 if( aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER || aAltiumLayer == ALTIUM_LAYER::KEEP_OUT_LAYER )
264 std::vector<PCB_LAYER_ID> layers;
265 layers.reserve( layerCount );
270 layers.emplace_back( layer );
281 wxString layerName = it !=
m_layerNames.end() ? it->second : wxString::Format( wxT(
"(%d)" ),
282 (
int) aAltiumLayer );
284 if(
m_reporter && altiumLayersWithWarning.insert( aAltiumLayer ).second )
287 _(
"Altium layer %s has no KiCad equivalent. It has been moved to KiCad "
301 const wxString& aLibrary,
const wxString& aFootprintName )
321 const unsigned PROGRESS_DELTA = 250;
339 const std::map<ALTIUM_PCB_DIR, std::string>& aFileMapping )
342 const std::vector<std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>> parserOrder = {
343 {
true, ALTIUM_PCB_DIR::FILE_HEADER,
348 {
true, ALTIUM_PCB_DIR::BOARD6,
353 {
false, ALTIUM_PCB_DIR::EXTENDPRIMITIVEINFORMATION,
358 {
true, ALTIUM_PCB_DIR::COMPONENTS6,
363 {
false, ALTIUM_PCB_DIR::MODELS,
366 std::vector<std::string> dir{ aFileMapping.at( ALTIUM_PCB_DIR::MODELS ) };
369 {
true, ALTIUM_PCB_DIR::COMPONENTBODIES6,
374 {
true, ALTIUM_PCB_DIR::NETS6,
379 {
true, ALTIUM_PCB_DIR::CLASSES6,
384 {
true, ALTIUM_PCB_DIR::RULES6,
389 {
true, ALTIUM_PCB_DIR::DIMENSIONS6,
394 {
true, ALTIUM_PCB_DIR::POLYGONS6,
399 {
true, ALTIUM_PCB_DIR::ARCS6,
404 {
true, ALTIUM_PCB_DIR::PADS6,
409 {
true, ALTIUM_PCB_DIR::VIAS6,
414 {
true, ALTIUM_PCB_DIR::TRACKS6,
419 {
false, ALTIUM_PCB_DIR::WIDESTRINGS6,
424 {
true, ALTIUM_PCB_DIR::TEXTS6,
429 {
true, ALTIUM_PCB_DIR::FILLS6,
434 {
false, ALTIUM_PCB_DIR::BOARDREGIONS,
439 {
true, ALTIUM_PCB_DIR::SHAPEBASEDREGIONS6,
444 {
true, ALTIUM_PCB_DIR::REGIONS6,
454 for(
const std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>& cur : parserOrder )
459 std::tie( isRequired,
directory, fp ) = cur;
461 if(
directory == ALTIUM_PCB_DIR::FILE_HEADER )
464 const auto& mappedDirectory = aFileMapping.find(
directory );
466 if( mappedDirectory == aFileMapping.end() )
469 const std::vector<std::string> mappedFile{ mappedDirectory->second,
"Header" };
470 const CFB::COMPOUND_FILE_ENTRY* file = altiumPcbFile.
FindStream( mappedFile );
472 if( file ==
nullptr )
476 uint32_t numOfRecords = reader.
Read<uint32_t>();
506 const auto& boardDirectory = aFileMapping.find( ALTIUM_PCB_DIR::BOARD6 );
508 if( boardDirectory != aFileMapping.end() )
510 std::vector<std::string> mappedFile{ boardDirectory->second,
"Data" };
512 const CFB::COMPOUND_FILE_ENTRY* file = altiumPcbFile.
FindStream( mappedFile );
517 "This file does not appear to be in a valid PCB Binary Version 6.0 format. In "
519 "make sure to save as \"PCB Binary Files (*.PcbDoc)\"." ) );
524 for(
const std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>& cur : parserOrder )
529 std::tie( isRequired,
directory, fp ) = cur;
531 const auto& mappedDirectory = aFileMapping.find(
directory );
533 if( mappedDirectory == aFileMapping.end() )
535 wxASSERT_MSG( !isRequired, wxString::Format( wxT(
"Altium Directory of kind %d was "
536 "expected, but no mapping is "
537 "present in the code" ),
542 std::vector<std::string> mappedFile{ mappedDirectory->second };
544 if(
directory != ALTIUM_PCB_DIR::FILE_HEADER )
545 mappedFile.emplace_back(
"Data" );
547 const CFB::COMPOUND_FILE_ENTRY* file = altiumPcbFile.
FindStream( mappedFile );
549 if( file !=
nullptr )
551 fp( altiumPcbFile, file );
553 else if( isRequired )
557 m_reporter->
Report( wxString::Format(
_(
"File not found: '%s' for directory '%s'." ),
572 if( zone->GetAssignedPriority() == 1000 )
583 zone->SetAssignedPriority( priority >= 0 ? priority : 0 );
587 for( std::pair<const ALTIUM_LAYER, ZONE*>& zone :
m_outer_plane )
588 zone.second->SetAssignedPriority( 0 );
598 if( !zone->HasFilledPolysForLayer( layer ) )
620 if( shape->
GetShape() != SHAPE_T::ARC && shape->
GetShape() != SHAPE_T::CIRCLE )
639 if( arc->
GetCenter() == dim->GetPosition() )
648 VECTOR2I radialLine = dim->GetEnd() - dim->GetStart();
653 radialLine = radialLine.
Resize( std::max( radius, 2 ) );
654 dim->SetEnd( dim->GetStart() + (
VECTOR2I) radialLine );
655 dim->SetLeaderLength( totalLength - radius );
665 int desired_x = ( w - bbbox.
GetWidth() ) / 2;
666 int desired_y = ( h - bbbox.
GetHeight() ) / 2;
668 VECTOR2I movementVector( desired_x - bbbox.
GetX(), desired_y - bbbox.
GetY() );
680 const wxString& aFootprintName )
682 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
700 std::tuple<wxString, const CFB::COMPOUND_FILE_ENTRY*> ret =
703 wxString fpDirName = std::get<0>( ret );
704 const CFB::COMPOUND_FILE_ENTRY* footprintStream = std::get<1>( ret );
706 if( fpDirName.IsEmpty() )
709 wxString::Format(
_(
"Footprint directory not found: '%s'." ), aFootprintName ) );
712 const std::vector<std::string> streamName{ fpDirName.ToStdString(),
"Data" };
713 const CFB::COMPOUND_FILE_ENTRY* footprintData = altiumLibFile.
FindStream( footprintStream, {
"Data" } );
715 if( footprintData ==
nullptr )
728 footprint->SetFPID( fpID );
730 const std::vector<std::string> parametersStreamName{ fpDirName.ToStdString(),
732 const CFB::COMPOUND_FILE_ENTRY* parametersData =
733 altiumLibFile.
FindStream( footprintStream, {
"Parameters" } );
735 if( parametersData !=
nullptr )
738 std::map<wxString, wxString> parameterProperties = parametersReader.
ReadProperties();
740 wxT(
"DESCRIPTION" ), wxT(
"" ) );
741 footprint->SetLibDescription( description );
752 footprint->SetLibDescription( wxT(
"" ) );
755 const std::vector<std::string> extendedPrimitiveInformationStreamName{
756 "ExtendedPrimitiveInformation",
"Data"
758 const CFB::COMPOUND_FILE_ENTRY* extendedPrimitiveInformationData =
759 altiumLibFile.
FindStream( footprintStream, extendedPrimitiveInformationStreamName );
761 if( extendedPrimitiveInformationData !=
nullptr )
764 footprint->SetReference( wxT(
"REF**" ) );
765 footprint->SetValue( aFootprintName );
766 footprint->Reference().SetVisible(
true );
767 footprint->Value().SetVisible(
true );
772 for(
PCB_FIELD* field : footprint->Fields() )
774 field->SetTextSize( defaultTextSize );
775 field->SetTextThickness( defaultTextThickness );
784 case ALTIUM_RECORD::ARC:
790 case ALTIUM_RECORD::PAD:
796 case ALTIUM_RECORD::VIA:
802 case ALTIUM_RECORD::TRACK:
808 case ALTIUM_RECORD::TEXT:
814 case ALTIUM_RECORD::FILL:
820 case ALTIUM_RECORD::REGION:
826 case ALTIUM_RECORD::MODEL:
833 THROW_IO_ERROR( wxString::Format(
_(
"Record of unknown type: '%d'." ), recordtype ) );
839 for(
bool changes =
true; changes; )
844 [&changes](
PAD* aPad1,
PAD* aPad2 )
846 if( !( aPad1->GetNumber().IsEmpty() ^ aPad2->GetNumber().IsEmpty() ) )
849 for( PCB_LAYER_ID layer : aPad1->GetLayerSet().Seq() )
851 std::shared_ptr<SHAPE> shape1 = aPad1->GetEffectiveShape( layer );
852 std::shared_ptr<SHAPE> shape2 = aPad2->GetEffectiveShape( layer );
854 if( shape1->Collide( shape2.get() ) )
856 if( aPad1->GetNumber().IsEmpty() )
857 aPad1->SetNumber( aPad2->GetNumber() );
859 aPad2->SetNumber( aPad1->GetNumber() );
868 footprint->AutoPositionFields();
870 if( parser.HasParsingError() )
872 THROW_IO_ERROR( wxString::Format( wxT(
"%s stream was not parsed correctly" ),
876 if( parser.GetRemainingBytes() != 0 )
878 THROW_IO_ERROR( wxString::Format( wxT(
"%s stream is not fully parsed" ),
882 return footprint.release();
893 THROW_IO_ERROR( wxString::Format( wxT(
"Netcode with id %d does not exist. Only %d nets "
905 const auto rules =
m_rules.find( aKind );
910 for(
const ARULE6& rule : rules->second )
912 if( rule.
name == aName )
921 const auto rules =
m_rules.find( aKind );
926 for(
const ARULE6& rule : rules->second )
936 const CFB::COMPOUND_FILE_ENTRY* aEntry )
954 const CFB::COMPOUND_FILE_ENTRY* aEntry )
971 THROW_IO_ERROR( wxT(
"ExtendedPrimitiveInformation stream is not fully parsed" ) );
976 const CFB::COMPOUND_FILE_ENTRY* aEntry )
993 size_t layercount = 0;
994 size_t layerid =
static_cast<size_t>( ALTIUM_LAYER::TOP_LAYER );
996 while( layerid < elem.
stackup.size() && layerid != 0 )
998 layerid = elem.
stackup[ layerid - 1 ].nextId;
1002 size_t kicadLayercount = ( layercount % 2 == 0 ) ? layercount : layercount + 1;
1012 auto it = stackup.
GetList().begin();
1020 for(
size_t altiumLayerId =
static_cast<size_t>( ALTIUM_LAYER::TOP_LAYER );
1021 altiumLayerId < elem.
stackup.size() && altiumLayerId != 0;
1022 altiumLayerId = elem.
stackup[altiumLayerId - 1].nextId )
1028 if( layer.
nextId == 0 && layercount != kicadLayercount )
1033 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
1035 ( *it )->SetThickness( 0 );
1040 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
1042 ( *it )->SetThickness( 0, 0 );
1043 ( *it )->SetThicknessLocked(
true, 0 );
1051 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
1065 if( klayer ==
B_Cu )
1068 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected id while parsing last stackup layer" ) );
1078 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
1092 for(
size_t altiumLayerId =
static_cast<size_t>( ALTIUM_LAYER::TOP_OVERLAY );
1093 altiumLayerId <= static_cast<size_t>( ALTIUM_LAYER::BOTTOM_SOLDER ); altiumLayerId++ )
1104 for(
size_t altiumLayerId =
static_cast<size_t>( ALTIUM_LAYER::MECHANICAL_1 );
1105 altiumLayerId <= static_cast<size_t>( ALTIUM_LAYER::MECHANICAL_16 ); altiumLayerId++ )
1126 std::vector<INPUT_LAYER_DESC> inputLayers;
1127 std::map<wxString, ALTIUM_LAYER> altiumLayerNameMap;
1129 for(
size_t ii = 0; ii < aStackup.size(); )
1136 && !( layer_num >= ALTIUM_LAYER::TOP_OVERLAY
1137 && layer_num <= ALTIUM_LAYER::BOTTOM_SOLDER )
1138 && !( layer_num >= ALTIUM_LAYER::MECHANICAL_1
1139 && layer_num <= ALTIUM_LAYER::MECHANICAL_16 ) )
1141 if( layer_num < ALTIUM_LAYER::BOTTOM_LAYER )
1155 inputLayers.push_back( iLdesc );
1156 altiumLayerNameMap.insert( { curLayer.
name, layer_num } );
1162 if( layer_num < ALTIUM_LAYER::BOTTOM_LAYER )
1163 ii = curLayer.
nextId - 1;
1168 if( inputLayers.size() == 0 )
1175 for( std::pair<wxString, PCB_LAYER_ID> layerPair : reMappedLayers )
1177 if( layerPair.second == PCB_LAYER_ID::UNDEFINED_LAYER )
1179 wxFAIL_MSG( wxT(
"Unexpected Layer ID" ) );
1183 ALTIUM_LAYER altiumID = altiumLayerNameMap.at( layerPair.first );
1184 m_layermap.insert_or_assign( altiumID, layerPair.second );
1185 enabledLayers |=
LSET( { layerPair.second } );
1199 LINE_STYLE::SOLID );
1206 int nextShape = lineChain.
NextShape( i );
1207 bool isLastShape = nextShape < 0;
1209 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::ARC );
1211 shape->SetStroke( stroke );
1215 m_board->
Add( shape.release(), ADD_MODE::APPEND );
1221 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
1223 shape->SetStroke( stroke );
1225 shape->SetStart( seg.
A );
1226 shape->SetEnd( seg.
B );
1228 m_board->
Add( shape.release(), ADD_MODE::APPEND );
1235 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1247 if( elem.
kind == ALTIUM_CLASS_KIND::NET_CLASS )
1249 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( elem.
name );
1251 for(
const wxString&
name : elem.
names )
1254 name, nc->GetName() );
1264 msg.Printf(
_(
"More than one Altium netclass with name '%s' found. "
1265 "Only the first one will be imported." ), elem.
name );
1284 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1291 uint16_t componentId = 0;
1298 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
1302 footprint->SetFPID( fpID );
1304 footprint->SetPosition( elem.
position );
1305 footprint->SetOrientationDegrees( elem.
rotation );
1311 if( reference.find_first_not_of(
"0123456789" ) == wxString::npos )
1312 reference.Prepend( wxT(
"UNK" ) );
1314 footprint->SetReference( reference );
1316 footprint->SetLocked( elem.
locked );
1317 footprint->Reference().SetVisible( elem.
nameon );
1318 footprint->Value().SetVisible( elem.
commenton );
1319 footprint->SetLayer( elem.
layer == ALTIUM_LAYER::TOP_LAYER ?
F_Cu :
B_Cu );
1322 m_board->
Add( footprint.release(), ADD_MODE::APPEND );
1328 THROW_IO_ERROR( wxT(
"Components6 stream is not fully parsed" ) );
1335 while( Angle < aMin )
1338 while( Angle >= aMax )
1361 m_reporter->
Report( wxString::Format( wxT(
"Model %s not found for footprint %s" ),
1374 if( file->
name.IsEmpty() )
1375 file->
name = model->first.name;
1378 std::vector<char> decompressedData;
1379 wxMemoryInputStream compressedStream( model->second.data(), model->second.size() );
1380 wxZlibInputStream zlibStream( compressedStream );
1384 decompressedData.resize( model->second.size() * 6 );
1387 while( !zlibStream.Eof() )
1389 zlibStream.Read( decompressedData.data() + offset, decompressedData.size() - offset );
1390 size_t bytesRead = zlibStream.LastRead();
1395 offset += bytesRead;
1397 if( offset >= decompressedData.size() )
1398 decompressedData.resize( 2 * decompressedData.size() );
1401 decompressedData.resize( offset );
1422 orientation = -orientation;
1434 aFootprint->
Models().push_back( modelSettings );
1439 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1456 THROW_IO_ERROR( wxString::Format( wxT(
"ComponentsBodies6 stream tries to access "
1457 "component id %d of %zu existing components" ),
1472 msg.Printf( wxT(
"ComponentsBodies6 stream tries to access model id %s which does "
1473 "not exist" ), elem.
modelId );
1486 wxMemoryInputStream compressedStream( modelData.
m_data.data(), modelData.
m_data.size() );
1487 wxZlibInputStream zlibStream( compressedStream );
1488 wxMemoryOutputStream decompressedStream;
1490 zlibStream.Read( decompressedStream );
1513 orientation = -orientation;
1526 footprint->
Models().push_back( modelSettings );
1530 THROW_IO_ERROR( wxT(
"ComponentsBodies6 stream is not fully parsed" ) );
1537 THROW_IO_ERROR( wxT(
"Incorrect number of reference points for linear dimension object" ) );
1546 _(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1547 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer ),
1560 dimension->SetLayer( klayer );
1561 dimension->SetStart( referencePoint0 );
1563 if( referencePoint0 != aElem.
xy1 )
1576 SEG segm1( referencePoint0, referencePoint0 + directionNormalVector );
1577 SEG segm2( referencePoint1, referencePoint1 + direction );
1581 THROW_IO_ERROR( wxT(
"Invalid dimension. This should never happen." ) );
1583 dimension->SetEnd( *intersection );
1587 if( ( direction.
x > 0 || direction.
y < 0 ) != ( aElem.
angle >= 180.0 ) )
1590 dimension->SetHeight( height );
1594 dimension->SetEnd( referencePoint1 );
1597 dimension->SetLineThickness( aElem.
linewidth );
1599 dimension->SetUnitsFormat( DIM_UNITS_FORMAT::NO_SUFFIX );
1603 wxRegEx units( wxS(
"(mm)|(in)|(mils)|(thou)|(')|(\")" ), wxRE_ADVANCED );
1606 dimension->SetUnitsFormat( DIM_UNITS_FORMAT::BARE_SUFFIX );
1615 dimension->Text().SetBold( aElem.
textbold );
1618 dimension->SetTextThickness( dimension->GetTextThickness() *
BOLD_FACTOR );
1623 case ALTIUM_UNIT::INCHES:
1624 dimension->SetUnits( EDA_UNITS::INCHES );
1626 case ALTIUM_UNIT::MILS:
1627 dimension->SetUnits( EDA_UNITS::MILS );
1629 case ALTIUM_UNIT::MILLIMETERS:
1630 case ALTIUM_UNIT::CENTIMETER:
1631 dimension->SetUnits( EDA_UNITS::MILLIMETRES );
1637 m_board->
Add( dimension.release(), ADD_MODE::APPEND );
1644 THROW_IO_ERROR( wxT(
"Not enough reference points for radial dimension object" ) );
1653 _(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1654 "It has been moved to KiCad layer Eco1_User." ),
1664 std::unique_ptr<PCB_DIM_RADIAL> dimension = std::make_unique<PCB_DIM_RADIAL>(
m_board );
1667 dimension->SetLayer( klayer );
1668 dimension->SetStart( referencePoint0 );
1669 dimension->SetEnd( aElem.
xy1 );
1670 dimension->SetLineThickness( aElem.
linewidth );
1671 dimension->SetKeepTextAligned(
false );
1676 dimension->SetUnitsFormat( aElem.
textsuffix.IsEmpty() ? DIM_UNITS_FORMAT::NO_SUFFIX
1677 : DIM_UNITS_FORMAT::BARE_SUFFIX );
1681 case ALTIUM_UNIT::INCHES:
1682 dimension->SetUnits( EDA_UNITS::INCHES );
1684 case ALTIUM_UNIT::MILS:
1685 dimension->SetUnits( EDA_UNITS::MILS );
1687 case ALTIUM_UNIT::MILLIMETERS:
1688 case ALTIUM_UNIT::CENTIMETER:
1689 dimension->SetUnits( EDA_UNITS::MILLIMETRES );
1699 m_reporter->
Report( wxT(
"No text position present for leader dimension object" ),
1706 dimension->SetTextPos( aElem.
textPoint.at( 0 ) );
1712 dimension->SetBold( aElem.
textbold );
1715 dimension->SetTextThickness( dimension->GetTextThickness() *
BOLD_FACTOR );
1723 int yAdjust = dimension->GetTextBox().GetCenter().y - dimension->GetTextPos().y;
1724 dimension->SetTextPos( dimension->GetTextPos() +
VECTOR2I( 0, yAdjust + aElem.
textgap ) );
1728 m_board->
Add( dimension.release(), ADD_MODE::APPEND );
1741 msg.Printf(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1742 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer );
1757 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
1759 shape->SetLayer( klayer );
1761 shape->SetStart( last );
1765 m_board->
Add( shape.release(), ADD_MODE::APPEND );
1773 if( dirVec.
x != 0 || dirVec.
y != 0 )
1781 std::unique_ptr<PCB_SHAPE> shape1 =
1782 std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
1784 shape1->SetLayer( klayer );
1786 shape1->SetStart( referencePoint0 );
1787 shape1->SetEnd( referencePoint0 + arrVec );
1789 m_board->
Add( shape1.release(), ADD_MODE::APPEND );
1795 std::unique_ptr<PCB_SHAPE> shape2 =
1796 std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
1798 shape2->SetLayer( klayer );
1800 shape2->SetStart( referencePoint0 );
1801 shape2->SetEnd( referencePoint0 + arrVec );
1803 m_board->
Add( shape2.release(), ADD_MODE::APPEND );
1813 m_reporter->
Report( wxT(
"No text position present for leader dimension object" ),
1820 std::unique_ptr<PCB_TEXT>
text = std::make_unique<PCB_TEXT>(
m_board );
1824 text->SetLayer( klayer );
1843 msg.Printf(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1844 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer );
1853 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
1855 shape->SetLayer( klayer );
1860 m_board->
Add( shape.release(), ADD_MODE::APPEND );
1874 msg.Printf(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1875 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer );
1885 std::unique_ptr<PCB_DIM_CENTER> dimension = std::make_unique<PCB_DIM_CENTER>(
m_board );
1887 dimension->SetLayer( klayer );
1888 dimension->SetLineThickness( aElem.
linewidth );
1889 dimension->SetStart( aElem.
xy1 );
1890 dimension->SetEnd( aElem.
xy1 + vec );
1892 m_board->
Add( dimension.release(), ADD_MODE::APPEND );
1897 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1911 case ALTIUM_DIMENSION_KIND::LINEAR:
1914 case ALTIUM_DIMENSION_KIND::ANGULAR:
1918 wxString::Format(
_(
"Ignored Angular dimension (not yet supported)." ) ),
1922 case ALTIUM_DIMENSION_KIND::RADIAL:
1925 case ALTIUM_DIMENSION_KIND::LEADER:
1928 case ALTIUM_DIMENSION_KIND::DATUM:
1932 wxString::Format(
_(
"Ignored Datum dimension (not yet supported)." ) ),
1937 case ALTIUM_DIMENSION_KIND::BASELINE:
1941 wxString::Format(
_(
"Ignored Baseline dimension (not yet supported)." ) ),
1945 case ALTIUM_DIMENSION_KIND::CENTER:
1948 case ALTIUM_DIMENSION_KIND::LINEAR_DIAMETER:
1952 wxString::Format(
_(
"Ignored Linear dimension (not yet supported)." ) ),
1956 case ALTIUM_DIMENSION_KIND::RADIAL_DIAMETER:
1960 wxString::Format(
_(
"Ignored Radial dimension (not yet supported)." ) ),
1968 msg.Printf(
_(
"Ignored dimension of kind %d (not yet supported)." ), elem.
kind );
1976 THROW_IO_ERROR( wxT(
"Dimensions6 stream is not fully parsed" ) );
1981 const CFB::COMPOUND_FILE_ENTRY* aEntry,
1982 const std::vector<std::string>& aRootDir )
1993 wxString invalidChars = wxFileName::GetForbiddenChars();
2000 std::vector<std::string> stepPath = aRootDir;
2001 stepPath.emplace_back( std::to_string( idx ) );
2003 bool validName = !elem.
name.IsEmpty() && elem.
name.IsAscii() &&
2004 wxString::npos == elem.
name.find_first_of( invalidChars );
2005 wxString storageName = !validName ? wxString::Format( wxT(
"model_%d" ), idx )
2010 const CFB::COMPOUND_FILE_ENTRY* stepEntry = aAltiumPcbFile.
FindStream( stepPath );
2012 if( stepEntry ==
nullptr )
2017 msg.Printf(
_(
"File not found: '%s'. 3D-model not imported." ),
2025 size_t stepSize =
static_cast<size_t>( stepEntry->size );
2026 std::vector<char> stepContent( stepSize );
2034 std::move( stepContent ) ) ) );
2043 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2055 ANET6 elem( reader );
2069 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2102 if( elem.
hatchstyle != ALTIUM_POLYGON_HATCHSTYLE::SOLID )
2112 msg.Printf(
_(
"Polygon outline count is %d, expected 1." ), outline.
OutlineCount() );
2120 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board);
2124 zone->SetPosition( elem.
vertices.at( 0 ).position );
2125 zone->SetLocked( elem.
locked );
2127 zone->Outline()->AddOutline( outline.
Outline( 0 ) );
2135 const ARULE6* zoneClearanceRule =
GetRule( ALTIUM_RULE_KIND::CLEARANCE,
2136 wxT(
"PolygonClearance" ) );
2137 int planeLayers = 0;
2138 int signalLayers = 0;
2152 if( planeLayers > 0 && planeClearanceRule )
2155 if( signalLayers > 0 && zoneClearanceRule )
2156 clearance = std::max( clearance, zoneClearanceRule->
clearanceGap );
2159 zone->SetLocalClearance( clearance );
2163 if( polygonConnectRule !=
nullptr )
2167 case ALTIUM_CONNECT_STYLE::DIRECT:
2168 zone->SetPadConnection( ZONE_CONNECTION::FULL );
2171 case ALTIUM_CONNECT_STYLE::NONE:
2172 zone->SetPadConnection( ZONE_CONNECTION::NONE );
2176 case ALTIUM_CONNECT_STYLE::RELIEF:
2177 zone->SetPadConnection( ZONE_CONNECTION::THERMAL );
2182 zone->SetThermalReliefSpokeWidth(
2193 zone->SetAssignedPriority( 1 );
2198 || zone->GetBoundingBox().Contains( outer_plane->second->GetBoundingBox() ) )
2204 if( elem.
hatchstyle != ALTIUM_POLYGON_HATCHSTYLE::SOLID
2205 && elem.
hatchstyle != ALTIUM_POLYGON_HATCHSTYLE::UNKNOWN )
2207 zone->SetFillMode( ZONE_FILL_MODE::HATCH_PATTERN );
2210 if( elem.
hatchstyle == ALTIUM_POLYGON_HATCHSTYLE::NONE )
2213 const BOX2I& bbox = zone->GetBoundingBox();
2221 if( elem.
hatchstyle == ALTIUM_POLYGON_HATCHSTYLE::DEGREE_45 )
2222 zone->SetHatchOrientation(
ANGLE_45 );
2225 zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE,
2228 m_board->
Add( zone.release(), ADD_MODE::APPEND );
2236 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2254 std::sort( val.second.begin(), val.second.end(),
2257 return lhs.priority < rhs.priority;
2270 if( trackWidthRule )
2276 if( routingViasRule )
2287 if( holeToHoleRule )
2293 if( soldermaskRule )
2304 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2320 THROW_IO_ERROR( wxT(
"BoardRegions stream is not fully parsed" ) );
2324 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2332 for(
int primitiveIndex = 0; reader.
GetRemainingBytes() >= 4; primitiveIndex++ )
2338 || elem.
kind == ALTIUM_REGION_KIND::BOARD_CUTOUT )
2351 THROW_IO_ERROR(
"ShapeBasedRegions6 stream is not fully parsed" );
2357 if( aElem.
kind == ALTIUM_REGION_KIND::BOARD_CUTOUT )
2361 else if( aElem.
kind == ALTIUM_REGION_KIND::POLYGON_CUTOUT || aElem.
is_keepout )
2375 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board );
2377 zone->SetIsRuleArea(
true );
2383 else if( aElem.
kind == ALTIUM_REGION_KIND::POLYGON_CUTOUT )
2385 zone->SetDoNotAllowCopperPour(
true );
2386 zone->SetDoNotAllowVias(
false );
2387 zone->SetDoNotAllowTracks(
false );
2388 zone->SetDoNotAllowPads(
false );
2389 zone->SetDoNotAllowFootprints(
false );
2392 zone->SetPosition( aElem.
outline.at( 0 ).position );
2393 zone->Outline()->AddOutline( linechain );
2397 zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE,
2400 m_board->
Add( zone.release(), ADD_MODE::APPEND );
2402 else if( aElem.
kind == ALTIUM_REGION_KIND::DASHED_OUTLINE )
2411 msg.Printf(
_(
"Dashed outline found on an Altium layer (%d) with no KiCad equivalent. "
2412 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer );
2431 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::POLY );
2433 shape->SetPolyShape( linechain );
2434 shape->SetFilled(
false );
2435 shape->SetLayer( klayer );
2438 m_board->
Add( shape.release(), ADD_MODE::APPEND );
2440 else if( aElem.
kind == ALTIUM_REGION_KIND::COPPER )
2448 else if( aElem.
kind == ALTIUM_REGION_KIND::BOARD_CUTOUT )
2457 msg.Printf(
_(
"Ignored polygon shape of kind %d (not yet supported)." ), aElem.
kind );
2466 const int aPrimitiveIndex )
2468 if( aElem.
kind == ALTIUM_REGION_KIND::POLYGON_CUTOUT || aElem.
is_keepout )
2482 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aFootprint );
2484 zone->SetIsRuleArea(
true );
2490 else if( aElem.
kind == ALTIUM_REGION_KIND::POLYGON_CUTOUT )
2492 zone->SetDoNotAllowCopperPour(
true );
2493 zone->SetDoNotAllowVias(
false );
2494 zone->SetDoNotAllowTracks(
false );
2495 zone->SetDoNotAllowPads(
false );
2496 zone->SetDoNotAllowFootprints(
false );
2499 zone->SetPosition( aElem.
outline.at( 0 ).position );
2500 zone->Outline()->AddOutline( linechain );
2504 zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE,
2507 aFootprint->
Add( zone.release(), ADD_MODE::APPEND );
2509 else if( aElem.
kind == ALTIUM_REGION_KIND::COPPER )
2520 else if( aElem.
kind == ALTIUM_REGION_KIND::DASHED_OUTLINE
2521 || aElem.
kind == ALTIUM_REGION_KIND::BOARD_CUTOUT )
2534 msg.Printf(
_(
"Loading library '%s':\n"
2535 "Footprint %s contains a dashed outline on Altium layer (%d) with "
2536 "no KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
2548 msg.Printf(
_(
"Footprint %s contains a dashed outline on Altium layer (%d) with "
2549 "no KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
2571 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aFootprint, SHAPE_T::POLY );
2573 shape->SetPolyShape( linechain );
2574 shape->SetFilled(
false );
2575 shape->SetLayer( klayer );
2577 if( aElem.
kind == ALTIUM_REGION_KIND::DASHED_OUTLINE )
2582 aFootprint->
Add( shape.release(), ADD_MODE::APPEND );
2591 msg.Printf(
_(
"Error loading library '%s':\n"
2592 "Footprint %s contains polygon shape of kind %d (not yet supported)." ),
2604 msg.Printf(
_(
"Footprint %s contains polygon shape of kind %d (not yet supported)." ),
2632 for(
const std::vector<ALTIUM_VERTICE>& hole : aElem.
holes )
2640 polySet.
AddHole( hole_linechain );
2643 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::POLY );
2645 shape->SetPolyShape( polySet );
2646 shape->SetFilled(
true );
2647 shape->SetLayer( aLayer );
2655 m_board->
Add( shape.release(), ADD_MODE::APPEND );
2662 const int aPrimitiveIndex )
2679 for(
const std::vector<ALTIUM_VERTICE>& hole : aElem.
holes )
2687 polySet.
AddHole( hole_linechain );
2690 if( aLayer ==
F_Cu || aLayer ==
B_Cu )
2693 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
2696 padLayers.
set( aLayer );
2698 pad->SetAttribute( PAD_ATTRIB::SMD );
2707 pad->SetPosition( anchorPos );
2710 shapePolys.
Move( -anchorPos );
2714 auto it = map.find( aPrimitiveIndex );
2716 if( it != map.end() )
2720 if(
info.pastemaskexpansionmode == ALTIUM_MODE::MANUAL )
2722 pad->SetLocalSolderPasteMargin(
2723 info.pastemaskexpansionmanual ?
info.pastemaskexpansionmanual : 1 );
2726 if(
info.soldermaskexpansionmode == ALTIUM_MODE::MANUAL )
2728 pad->SetLocalSolderMaskMargin(
2729 info.soldermaskexpansionmanual ?
info.soldermaskexpansionmanual : 1 );
2732 if(
info.pastemaskexpansionmode != ALTIUM_MODE::NONE )
2735 if(
info.soldermaskexpansionmode != ALTIUM_MODE::NONE )
2739 pad->SetLayerSet( padLayers );
2741 aFootprint->
Add(
pad.release(), ADD_MODE::APPEND );
2745 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aFootprint, SHAPE_T::POLY );
2747 shape->SetPolyShape( polySet );
2748 shape->SetFilled(
true );
2749 shape->SetLayer( aLayer );
2752 aFootprint->
Add( shape.release(), ADD_MODE::APPEND );
2758 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2774 THROW_IO_ERROR( wxString::Format(
"Region stream tries to access polygon id %d "
2775 "of %d existing polygons.",
2782 if( zone ==
nullptr )
2804 for(
const std::vector<ALTIUM_VERTICE>& hole : elem.
holes )
2811 hole_linechain.
Append( hole.at( 0 ).position );
2813 fill.
AddHole( hole_linechain );
2833 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2840 for(
int primitiveIndex = 0; reader.
GetRemainingBytes() >= 4; primitiveIndex++ )
2843 AARC6 elem( reader );
2865 aShape->
SetShape( SHAPE_T::CIRCLE );
2894 THROW_IO_ERROR( wxString::Format(
"Tracks stream tries to access polygon id %u "
2895 "of %zu existing polygons.",
2901 if( zone ==
nullptr )
2949 for(
const auto& layerExpansionMask :
2952 int width = aElem.
width + ( layerExpansionMask.second * 2 );
2956 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>(
m_board );
2959 arc->SetStroke(
STROKE_PARAMS( width, LINE_STYLE::SOLID ) );
2960 arc->SetLayer( layerExpansionMask.first );
2962 m_board->
Add( arc.release(), ADD_MODE::APPEND );
2969 const int aPrimitiveIndex,
const bool aIsBoardImport )
2973 wxFAIL_MSG( wxString::Format(
"Altium: Unexpected footprint Arc with polygon id %d",
3006 for(
const auto& layerExpansionMask :
3009 int width = aElem.
width + ( layerExpansionMask.second * 2 );
3013 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>( aFootprint );
3016 arc->SetStroke(
STROKE_PARAMS( width, LINE_STYLE::SOLID ) );
3017 arc->SetLayer( layerExpansionMask.first );
3019 aFootprint->
Add( arc.release(), ADD_MODE::APPEND );
3040 PCB_SHAPE shape(
nullptr, SHAPE_T::ARC );
3049 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board, &shapeArc );
3051 arc->SetWidth( aElem.
width );
3052 arc->SetLayer( aLayer );
3055 m_board->
Add( arc.release(), ADD_MODE::APPEND );
3060 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>(
m_board);
3064 arc->SetLayer( aLayer );
3066 m_board->
Add( arc.release(), ADD_MODE::APPEND );
3074 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>( aFootprint );
3078 arc->SetLayer( aLayer );
3080 aFootprint->
Add( arc.release(), ADD_MODE::APPEND );
3085 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3095 APAD6 elem( reader );
3117 && aElem.
layer != ALTIUM_LAYER::MULTI_LAYER )
3124 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
3125 footprint->SetPosition( aElem.
position );
3129 m_board->
Add( footprint.release(), ADD_MODE::APPEND );
3136 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
3138 pad->SetNumber(
"" );
3144 pad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
3146 pad->SetAttribute( PAD_ATTRIB::PTH );
3149 pad->SetLayerSet(
LSET().AllCuMask() );
3151 if( aElem.
viamode == ALTIUM_PAD_MODE::SIMPLE )
3155 else if( aElem.
viamode == ALTIUM_PAD_MODE::TOP_MIDDLE_BOTTOM )
3176 pad->Padstack().FrontOuterLayers().has_solder_mask =
true;
3180 pad->Padstack().FrontOuterLayers().has_solder_mask =
false;
3186 pad->Padstack().BackOuterLayers().has_solder_mask =
true;
3190 pad->Padstack().BackOuterLayers().has_solder_mask =
false;
3195 pad->SetLocked(
true );
3204 aFootprint->
Add(
pad.release(), ADD_MODE::APPEND );
3212 && aElem.
layer != ALTIUM_LAYER::MULTI_LAYER )
3225 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
3236 pad->SetAttribute( PAD_ATTRIB::SMD );
3240 if( aElem.
layer != ALTIUM_LAYER::MULTI_LAYER )
3248 msg.Printf(
_(
"Error loading library '%s':\n"
3249 "Footprint %s pad %s is not marked as multilayer, but is a TH pad." ),
3261 msg.Printf(
_(
"Footprint %s pad %s is not marked as multilayer, but is a TH pad." ),
3269 pad->SetAttribute( aElem.
plated ? PAD_ATTRIB::PTH : PAD_ATTRIB::NPTH );
3273 pad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
3280 case ALTIUM_PAD_HOLE_SHAPE::ROUND:
3281 wxFAIL_MSG( wxT(
"Round holes are handled before the switch" ) );
3284 case ALTIUM_PAD_HOLE_SHAPE::SQUARE:
3290 msg.Printf(
_(
"Loading library '%s':\n"
3291 "Footprint %s pad %s has a square hole (not yet supported)." ),
3303 msg.Printf(
_(
"Footprint %s pad %s has a square hole (not yet supported)." ),
3310 pad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
3316 case ALTIUM_PAD_HOLE_SHAPE::SLOT:
3318 pad->SetDrillShape( PAD_DRILL_SHAPE::OBLONG );
3338 msg.Printf(
_(
"Loading library '%s':\n"
3339 "Footprint %s pad %s has a hole-rotation of %f degrees. "
3340 "KiCad only supports 90 degree rotations." ),
3353 msg.Printf(
_(
"Footprint %s pad %s has a hole-rotation of %f degrees. "
3354 "KiCad only supports 90 degree rotations." ),
3367 case ALTIUM_PAD_HOLE_SHAPE::UNKNOWN:
3373 msg.Printf(
_(
"Error loading library '%s':\n"
3374 "Footprint %s pad %s uses a hole of unknown kind %d." ),
3387 msg.Printf(
_(
"Footprint %s pad %s uses a hole of unknown kind %d." ),
3395 pad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
3407 auto setCopperGeometry =
3416 case ALTIUM_PAD_SHAPE::RECT:
3417 ps.
SetShape( PAD_SHAPE::RECTANGLE, aLayer );
3420 case ALTIUM_PAD_SHAPE::CIRCLE:
3422 && aElem.
sizeAndShape->alt_shape[altLayer] == ALTIUM_PAD_SHAPE_ALT::ROUNDRECT )
3424 ps.
SetShape( PAD_SHAPE::ROUNDRECT, aLayer );
3425 double ratio = aElem.
sizeAndShape->cornerradius[altLayer] / 200.;
3430 ps.
SetShape( PAD_SHAPE::CIRCLE, aLayer );
3434 ps.
SetShape( PAD_SHAPE::OVAL, aLayer );
3439 case ALTIUM_PAD_SHAPE::OCTAGONAL:
3440 ps.
SetShape( PAD_SHAPE::CHAMFERED_RECT, aLayer );
3445 case ALTIUM_PAD_SHAPE::UNKNOWN:
3452 msg.Printf(
_(
"Error loading library '%s':\n"
3453 "Footprint %s pad %s uses an unknown pad-shape." ),
3465 msg.Printf(
_(
"Footprint %s pad %s uses an unknown pad-shape." ),
3477 case ALTIUM_PAD_MODE::SIMPLE:
3482 case ALTIUM_PAD_MODE::TOP_MIDDLE_BOTTOM:
3489 case ALTIUM_PAD_MODE::FULL_STACK:
3502 setCopperGeometry( layer, aElem.
sizeAndShape->inner_shape[i],
3512 if(
pad->GetAttribute() == PAD_ATTRIB::NPTH &&
pad->HasHole() )
3516 : PAD_SHAPE::OVAL );
3520 switch( aElem.
layer )
3522 case ALTIUM_LAYER::TOP_LAYER:
3527 case ALTIUM_LAYER::BOTTOM_LAYER:
3532 case ALTIUM_LAYER::MULTI_LAYER:
3538 pad->SetLayer( klayer );
3539 pad->SetLayerSet(
LSET( { klayer } ) );
3550 pad->SetLayerSet(
pad->GetLayerSet().reset(
F_Mask ) );
3553 pad->SetLayerSet(
pad->GetLayerSet().reset(
B_Mask ) );
3555 aFootprint->
Add(
pad.release(), ADD_MODE::APPEND );
3568 msg.Printf(
_(
"Non-copper pad %s found on an Altium layer (%d) with no KiCad "
3569 "equivalent. It has been moved to KiCad layer Eco1_User." ),
3577 std::unique_ptr<PCB_SHAPE>
pad = std::make_unique<PCB_SHAPE>(
m_board );
3596 msg.Printf(
_(
"Loading library '%s':\n"
3597 "Footprint %s non-copper pad %s found on an Altium layer (%d) with no "
3598 "KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
3611 msg.Printf(
_(
"Footprint %s non-copper pad %s found on an Altium layer (%d) with no "
3612 "KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
3623 std::unique_ptr<PCB_SHAPE>
pad = std::make_unique<PCB_SHAPE>( aFootprint );
3627 aFootprint->
Add(
pad.release(), ADD_MODE::APPEND );
3639 msg.Printf(
_(
"Non-copper pad %s is connected to a net, which is not supported." ),
3650 msg.Printf(
_(
"Non-copper pad %s has a hole, which is not supported." ), aElem.
name );
3655 if( aElem.
padmode != ALTIUM_PAD_MODE::SIMPLE )
3660 msg.Printf(
_(
"Non-copper pad %s has a complex pad stack (not yet supported)." ),
3668 case ALTIUM_PAD_SHAPE::RECT:
3687 case ALTIUM_PAD_SHAPE::CIRCLE:
3689 && aElem.
sizeAndShape->alt_shape[0] == ALTIUM_PAD_SHAPE_ALT::ROUNDRECT )
3692 int cornerradius = aElem.
sizeAndShape->cornerradius[0];
3693 int offset = ( std::min( aElem.
topsize.
x, aElem.
topsize.
y ) * cornerradius ) / 200;
3698 if( cornerradius < 100 )
3700 int offsetX = aElem.
topsize.
x / 2 - offset;
3701 int offsetY = aElem.
topsize.
y / 2 - offset;
3715 aShape->
SetShape( SHAPE_T::CIRCLE );
3724 aShape->
SetShape( SHAPE_T::SEGMENT );
3732 aShape->
SetShape( SHAPE_T::SEGMENT );
3744 aShape->
SetShape( SHAPE_T::CIRCLE );
3754 aShape->
SetShape( SHAPE_T::SEGMENT );
3757 LINE_STYLE::SOLID ) );
3777 case ALTIUM_PAD_SHAPE::OCTAGONAL:
3794 aShape->
SetPolyPoints( { p11 - chamferX, p11 - chamferY, p12 + chamferY, p12 - chamferX,
3795 p22 + chamferX, p22 + chamferY, p21 - chamferY, p21 + chamferX } );
3802 case ALTIUM_PAD_SHAPE::UNKNOWN:
3807 msg.Printf(
_(
"Non-copper pad %s uses an unknown pad-shape." ), aElem.
name );
3817 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3827 AVIA6 elem( reader );
3829 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
3838 bool start_layer_outside = elem.
layer_start == ALTIUM_LAYER::TOP_LAYER
3839 || elem.
layer_start == ALTIUM_LAYER::BOTTOM_LAYER;
3840 bool end_layer_outside = elem.
layer_end == ALTIUM_LAYER::TOP_LAYER
3841 || elem.
layer_end == ALTIUM_LAYER::BOTTOM_LAYER;
3843 if( start_layer_outside && end_layer_outside )
3845 via->SetViaType( VIATYPE::THROUGH );
3847 else if( ( !start_layer_outside ) && ( !end_layer_outside ) )
3849 via->SetViaType( VIATYPE::BLIND_BURIED );
3853 via->SetViaType( VIATYPE::MICROVIA );
3864 msg.Printf(
_(
"Via from layer %d to %d uses a non-copper layer, which is not "
3875 via->SetLayerPair( start_klayer, end_klayer );
3879 via->SetFrontTentingMode( elem.
is_tent_top ? TENTING_MODE::TENTED
3880 : TENTING_MODE::NOT_TENTED );
3882 : TENTING_MODE::NOT_TENTED );
3893 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3900 for(
int primitiveIndex = 0; reader.
GetRemainingBytes() >= 4; primitiveIndex++ )
3931 msg.Printf( wxT(
"ATRACK6 stream tries to access polygon id %u "
3932 "of %u existing polygons; skipping it" ),
3933 static_cast<unsigned>( aElem.
polygon ),
3934 static_cast<unsigned>(
m_polygons.size() ) );
3943 if( zone ==
nullptr )
3959 PCB_SHAPE shape(
nullptr, SHAPE_T::SEGMENT );
3977 PCB_SHAPE shape(
nullptr, SHAPE_T::SEGMENT );
3991 ALTIUM_RECORD::TRACK, aPrimitiveIndex, aElem.
layer ) )
3993 int width = aElem.
width + ( layerExpansionMask.second * 2 );
3996 std::unique_ptr<PCB_SHAPE> seg = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
3998 seg->SetStart( aElem.
start );
3999 seg->SetEnd( aElem.
end );
4000 seg->SetStroke(
STROKE_PARAMS( width, LINE_STYLE::SOLID ) );
4001 seg->SetLayer( layerExpansionMask.first );
4003 m_board->
Add( seg.release(), ADD_MODE::APPEND );
4010 const int aPrimitiveIndex,
4011 const bool aIsBoardImport )
4015 wxFAIL_MSG( wxString::Format(
"Altium: Unexpected footprint Track with polygon id %u",
4024 PCB_SHAPE shape(
nullptr, SHAPE_T::SEGMENT );
4049 ALTIUM_RECORD::TRACK, aPrimitiveIndex, aElem.
layer ) )
4051 int width = aElem.
width + ( layerExpansionMask.second * 2 );
4054 std::unique_ptr<PCB_SHAPE> seg = std::make_unique<PCB_SHAPE>( aFootprint, SHAPE_T::SEGMENT );
4056 seg->SetStart( aElem.
start );
4057 seg->SetEnd( aElem.
end );
4058 seg->SetStroke(
STROKE_PARAMS( width, LINE_STYLE::SOLID ) );
4059 seg->SetLayer( layerExpansionMask.first );
4061 aFootprint->
Add( seg.release(), ADD_MODE::APPEND );
4071 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
4073 track->SetStart( aElem.
start );
4074 track->SetEnd( aElem.
end );
4075 track->SetWidth( aElem.
width );
4076 track->SetLayer( aLayer );
4079 m_board->
Add( track.release(), ADD_MODE::APPEND );
4083 std::unique_ptr<PCB_SHAPE> seg = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
4085 seg->SetStart( aElem.
start );
4086 seg->SetEnd( aElem.
end );
4088 seg->SetLayer( aLayer );
4090 m_board->
Add( seg.release(), ADD_MODE::APPEND );
4098 std::unique_ptr<PCB_SHAPE> seg = std::make_unique<PCB_SHAPE>( aFootprint, SHAPE_T::SEGMENT );
4100 seg->SetStart( aElem.
start );
4101 seg->SetEnd( aElem.
end );
4103 seg->SetLayer( aLayer );
4105 aFootprint->
Add( seg.release(), ADD_MODE::APPEND );
4110 const CFB::COMPOUND_FILE_ENTRY* aEntry )
4120 THROW_IO_ERROR( wxT(
"WideStrings6 stream is not fully parsed" ) );
4124 const CFB::COMPOUND_FILE_ENTRY* aEntry )
4154 if( aElem.
fonttype == ALTIUM_TEXT_TYPE::BARCODE )
4159 msg.Printf(
_(
"Ignored barcode on Altium layer %d (not yet supported)." ),
4174 if( aElem.
fonttype == ALTIUM_TEXT_TYPE::BARCODE )
4181 msg.Printf(
_(
"Error loading library '%s':\n"
4182 "Footprint %s contains barcode on Altium layer %d (not yet supported)." ),
4194 msg.Printf(
_(
"Footprint %s contains barcode on Altium layer %d (not yet supported)." ),
4211 std::unique_ptr<PCB_TEXTBOX> pcbTextbox = std::make_unique<PCB_TEXTBOX>(
m_board );
4212 std::unique_ptr<PCB_TEXT> pcbText = std::make_unique<PCB_TEXT>(
m_board );
4216 static const std::map<wxString, wxString> variableMap = {
4217 {
"LAYER_NAME",
"LAYER" },
4218 {
"PRINT_DATE",
"CURRENT_DATE"},
4228 item = pcbTextbox.get();
4229 text = pcbTextbox.get();
4240 text->SetText( kicadText );
4245 m_board->
Add( pcbTextbox.release(), ADD_MODE::APPEND );
4247 m_board->
Add( pcbText.release(), ADD_MODE::APPEND );
4254 std::unique_ptr<PCB_TEXTBOX> fpTextbox = std::make_unique<PCB_TEXTBOX>( aFootprint );
4255 std::unique_ptr<PCB_TEXT> fpText = std::make_unique<PCB_TEXT>( aFootprint );
4272 item = &aFootprint->
Value();
4274 field = &aFootprint->
Value();
4278 item = fpText.get();
4279 text = fpText.get();
4283 static const std::map<wxString, wxString> variableMap = {
4284 {
"DESIGNATOR",
"REFERENCE" },
4285 {
"COMMENT",
"VALUE" },
4286 {
"VALUE",
"ALTIUM_VALUE" },
4287 {
"LAYER_NAME",
"LAYER" },
4288 {
"PRINT_DATE",
"CURRENT_DATE"},
4293 item = fpTextbox.get();
4294 text = fpTextbox.get();
4307 text->SetText( kicadText );
4308 text->SetKeepUpright(
false );
4315 aFootprint->
Add( fpTextbox.release(), ADD_MODE::APPEND );
4317 aFootprint->
Add( fpText.release(), ADD_MODE::APPEND );
4345 kicadMargin =
VECTOR2I( charWidth * 0.933, charHeight * 0.67 );
4347 kicadMargin =
VECTOR2I( charWidth * 0.808, charHeight * 0.844 );
4350 + kicadMargin * 2 - margin * 2 );
4352 kposition = kposition - kicadMargin + margin;
4368 : ALTIUM_TEXT_POSITION::LEFT_BOTTOM;
4370 switch( justification )
4372 case ALTIUM_TEXT_POSITION::LEFT_TOP:
4373 case ALTIUM_TEXT_POSITION::LEFT_CENTER:
4374 case ALTIUM_TEXT_POSITION::LEFT_BOTTOM:
4378 case ALTIUM_TEXT_POSITION::CENTER_TOP:
4379 case ALTIUM_TEXT_POSITION::CENTER_CENTER:
4380 case ALTIUM_TEXT_POSITION::CENTER_BOTTOM:
4384 case ALTIUM_TEXT_POSITION::RIGHT_TOP:
4385 case ALTIUM_TEXT_POSITION::RIGHT_CENTER:
4386 case ALTIUM_TEXT_POSITION::RIGHT_BOTTOM:
4394 msg.Printf(
_(
"Unknown textbox justification %d, aText %s" ), justification,
4414 int rectHeight = aElem.
height;
4417 rectWidth = -rectWidth;
4421 : ALTIUM_TEXT_POSITION::LEFT_BOTTOM;
4423 switch( justification )
4425 case ALTIUM_TEXT_POSITION::LEFT_TOP:
4429 kposition.
y -= rectHeight;
4431 case ALTIUM_TEXT_POSITION::LEFT_CENTER:
4435 kposition.
y -= rectHeight / 2;
4437 case ALTIUM_TEXT_POSITION::LEFT_BOTTOM:
4441 case ALTIUM_TEXT_POSITION::CENTER_TOP:
4445 kposition.
x += rectWidth / 2;
4446 kposition.
y -= rectHeight;
4448 case ALTIUM_TEXT_POSITION::CENTER_CENTER:
4452 kposition.
x += rectWidth / 2;
4453 kposition.
y -= rectHeight / 2;
4455 case ALTIUM_TEXT_POSITION::CENTER_BOTTOM:
4459 kposition.
x += rectWidth / 2;
4461 case ALTIUM_TEXT_POSITION::RIGHT_TOP:
4465 kposition.
x += rectWidth;
4466 kposition.
y -= rectHeight;
4468 case ALTIUM_TEXT_POSITION::RIGHT_CENTER:
4472 kposition.
x += rectWidth;
4473 kposition.
y -= rectHeight / 2;
4475 case ALTIUM_TEXT_POSITION::RIGHT_BOTTOM:
4479 kposition.
x += rectWidth;
4524 if( aElem.
fonttype == ALTIUM_TEXT_TYPE::TRUETYPE )
4532 if( font->
GetName().Contains( wxS(
"Arial" ) ) )
4547 const CFB::COMPOUND_FILE_ENTRY* aEntry )
4580 PCB_SHAPE shape(
nullptr, SHAPE_T::RECTANGLE );
4605 const bool aIsBoardImport )
4608 || aElem.
layer == ALTIUM_LAYER::KEEP_OUT_LAYER )
4611 PCB_SHAPE shape(
nullptr, SHAPE_T::RECTANGLE );
4645 std::unique_ptr<PCB_SHAPE> fill = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::RECTANGLE );
4647 fill->SetFilled(
true );
4648 fill->SetLayer( aLayer );
4651 fill->SetStart( aElem.
pos1 );
4652 fill->SetEnd( aElem.
pos2 );
4667 m_board->
Add( fill.release(), ADD_MODE::APPEND );
4674 if( aLayer ==
F_Cu || aLayer ==
B_Cu )
4676 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
4679 padLayers.
set( aLayer );
4681 pad->SetAttribute( PAD_ATTRIB::SMD );
4694 std::swap( width, height );
4697 pad->SetPosition( aElem.
pos1 / 2 + aElem.
pos2 / 2 );
4709 pad->SetPosition( anchorPos );
4720 aElem.
pos1.
y / 2 + aElem.
pos2.
y / 2 - anchorPos.
y );
4722 pad->AddPrimitivePoly(
F_Cu, shapePolys, 0,
true );
4726 pad->SetLayerSet( padLayers );
4728 aFootprint->
Add(
pad.release(), ADD_MODE::APPEND );
4732 std::unique_ptr<PCB_SHAPE> fill =
4733 std::make_unique<PCB_SHAPE>( aFootprint, SHAPE_T::RECTANGLE );
4735 fill->SetFilled(
true );
4736 fill->SetLayer( aLayer );
4739 fill->SetStart( aElem.
pos1 );
4740 fill->SetEnd( aElem.
pos2 );
4749 aFootprint->
Add( fill.release(), ADD_MODE::APPEND );
4759 layerSet.
set( klayer );
4767 bool keepoutRestrictionVia = ( aKeepoutRestrictions & 0x01 ) != 0;
4768 bool keepoutRestrictionTrack = ( aKeepoutRestrictions & 0x02 ) != 0;
4769 bool keepoutRestrictionCopper = ( aKeepoutRestrictions & 0x04 ) != 0;
4770 bool keepoutRestrictionSMDPad = ( aKeepoutRestrictions & 0x08 ) != 0;
4771 bool keepoutRestrictionTHPad = ( aKeepoutRestrictions & 0x10 ) != 0;
4783 const uint8_t aKeepoutRestrictions )
4785 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board );
4787 zone->SetIsRuleArea(
true );
4794 zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE,
4797 m_board->
Add( zone.release(), ADD_MODE::APPEND );
4804 const uint8_t aKeepoutRestrictions )
4806 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aFootprint );
4808 zone->SetIsRuleArea(
true );
4815 zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE,
4819 aFootprint->
Add( zone.release(), ADD_MODE::APPEND );
4832 if( elems.first == elems.second )
4835 std::vector<std::pair<PCB_LAYER_ID, int>> layerExpansionPairs;
4837 for(
auto it = elems.first; it != elems.second; ++it )
4841 if( pInf.
type == AEXTENDED_PRIMITIVE_INFORMATION_TYPE::MASK )
4847 if( aAltiumLayer == ALTIUM_LAYER::TOP_LAYER
4848 || aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER )
4853 if( aAltiumLayer == ALTIUM_LAYER::BOTTOM_LAYER
4854 || aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER )
4862 if( aAltiumLayer == ALTIUM_LAYER::TOP_LAYER
4863 || aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER )
4868 if( aAltiumLayer == ALTIUM_LAYER::BOTTOM_LAYER
4869 || aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER )
4877 return layerExpansionPairs;
std::string FormatPath(const std::vector< std::string > &aVectorPath)
Helper for debug logging (vector -> string)
const uint16_t ALTIUM_NET_UNCONNECTED
const uint16_t ALTIUM_POLYGON_NONE
const uint16_t ALTIUM_POLYGON_BOARD
const int ALTIUM_COMPONENT_NONE
LIB_ID AltiumToKiCadLibID(const wxString &aLibName, const wxString &aLibReference)
wxString AltiumPcbSpecialStringsToKiCadStrings(const wxString &aString, const std::map< wxString, wxString > &aOverrides)
void HelperShapeLineChainFromAltiumVertices(SHAPE_LINE_CHAIN &aLine, const std::vector< ALTIUM_VERTICE > &aVertices)
double normalizeAngleDegrees(double Angle, double aMin, double aMax)
Normalize angle to be aMin < angle <= aMax angle is in degrees.
constexpr double BOLD_FACTOR
bool IsAltiumLayerCopper(ALTIUM_LAYER aLayer)
bool IsAltiumLayerAPlane(ALTIUM_LAYER aLayer)
std::function< void(const ALTIUM_PCB_COMPOUND_FILE &, const CFB::COMPOUND_FILE_ENTRY *)> PARSE_FUNCTION_POINTER_fp
constexpr int ARC_HIGH_DEF
constexpr EDA_IU_SCALE pcbIUScale
LAYER_T
The allowed types of layers, same as Specctra DSN spec.
@ BS_ITEM_TYPE_DIELECTRIC
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
size_t GetRemainingBytes() const
std::map< uint32_t, wxString > ReadWideStringTable()
size_t ReadAndSetSubrecordLength()
std::map< wxString, wxString > ReadProperties(std::function< std::map< wxString, wxString >(const std::string &)> handleBinaryData=[](const std::string &) { return std::map< wxString, wxString >();})
const CFB::CompoundFileReader & GetCompoundFileReader() const
const CFB::COMPOUND_FILE_ENTRY * FindStream(const std::vector< std::string > &aStreamPath) const
const std::pair< AMODEL, std::vector< char > > * GetLibModel(const wxString &aModelID) const
std::tuple< wxString, const CFB::COMPOUND_FILE_ENTRY * > FindLibFootprintDirName(const wxString &aFpUnicodeName)
PROGRESS_REPORTER * m_progressReporter
optional; may be nullptr
void ParseClasses6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
std::vector< PCB_DIM_RADIAL * > m_radialDimensions
void ConvertArcs6ToFootprintItemOnLayer(FOOTPRINT *aFootprint, const AARC6 &aElem, PCB_LAYER_ID aLayer)
void ConvertTracks6ToBoardItem(const ATRACK6 &aElem, const int aPrimitiveIndex)
void ConvertTracks6ToFootprintItem(FOOTPRINT *aFootprint, const ATRACK6 &aElem, const int aPrimitiveIndex, const bool aIsBoardImport)
int m_highest_pour_index
Altium stores pour order across all layers.
void ConvertTexts6ToFootprintItemOnLayer(FOOTPRINT *aFootprint, const ATEXT6 &aElem, PCB_LAYER_ID aLayer)
std::map< ALTIUM_LAYER, PCB_LAYER_ID > m_layermap
void ConvertShapeBasedRegions6ToBoardItemOnLayer(const AREGION6 &aElem, PCB_LAYER_ID aLayer)
void ParseVias6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void HelperParseDimensions6Leader(const ADIMENSION6 &aElem)
wxString m_footprintName
for footprint library loading error reporting
std::vector< FOOTPRINT * > m_components
void ParseShapeBasedRegions6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
const ARULE6 * GetRuleDefault(ALTIUM_RULE_KIND aKind) const
void HelperParsePad6NonCopper(const APAD6 &aElem, PCB_LAYER_ID aLayer, PCB_SHAPE *aShape)
void ParseRegions6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
std::vector< PCB_LAYER_ID > GetKicadLayersToIterate(ALTIUM_LAYER aAltiumLayer) const
void ConvertShapeBasedRegions6ToFootprintItem(FOOTPRINT *aFootprint, const AREGION6 &aElem, const int aPrimitiveIndex)
void HelperPcpShapeAsFootprintKeepoutRegion(FOOTPRINT *aFootprint, const PCB_SHAPE &aShape, const ALTIUM_LAYER aAltiumLayer, const uint8_t aKeepoutRestrictions)
void ConvertArcs6ToBoardItem(const AARC6 &aElem, const int aPrimitiveIndex)
void ConvertShapeBasedRegions6ToFootprintItemOnLayer(FOOTPRINT *aFootprint, const AREGION6 &aElem, PCB_LAYER_ID aLayer, const int aPrimitiveIndex)
std::map< ALTIUM_LAYER, ZONE * > m_outer_plane
std::vector< int > m_altiumToKicadNetcodes
unsigned m_totalCount
for progress reporting
void ParseComponents6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void HelperPcpShapeAsBoardKeepoutRegion(const PCB_SHAPE &aShape, const ALTIUM_LAYER aAltiumLayer, const uint8_t aKeepoutRestrictions)
std::map< wxString, ALTIUM_EMBEDDED_MODEL_DATA > m_EmbeddedModels
void ConvertFills6ToBoardItemOnLayer(const AFILL6 &aElem, PCB_LAYER_ID aLayer)
std::vector< std::pair< PCB_LAYER_ID, int > > HelperGetSolderAndPasteMaskExpansions(const ALTIUM_RECORD aType, const int aPrimitiveIndex, const ALTIUM_LAYER aAltiumLayer)
void ConvertComponentBody6ToFootprintItem(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, FOOTPRINT *aFootprint, const ACOMPONENTBODY6 &aElem)
void HelperSetTextAlignmentAndPos(const ATEXT6 &aElem, EDA_TEXT *aEdaText)
void ParseBoard6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ConvertFills6ToFootprintItem(FOOTPRINT *aFootprint, const AFILL6 &aElem, const bool aIsBoardImport)
void ParseExtendedPrimitiveInformationData(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ParseFileHeader(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ConvertShapeBasedRegions6ToBoardItem(const AREGION6 &aElem)
void HelperCreateBoardOutline(const std::vector< ALTIUM_VERTICE > &aVertices)
std::map< ALTIUM_RULE_KIND, std::vector< ARULE6 > > m_rules
void ConvertVias6ToFootprintItem(FOOTPRINT *aFootprint, const AVIA6 &aElem)
void ParseRules6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void HelperSetZoneKeepoutRestrictions(ZONE &aZone, const uint8_t aKeepoutRestrictions)
void HelperParseDimensions6Linear(const ADIMENSION6 &aElem)
void ParseTracks6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
std::map< uint32_t, wxString > m_unicodeStrings
void ConvertTexts6ToBoardItem(const ATEXT6 &aElem)
void HelperParseDimensions6Center(const ADIMENSION6 &aElem)
void HelperParseDimensions6Radial(const ADIMENSION6 &aElem)
void ParseBoardRegionsData(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ParseArcs6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ConvertTexts6ToBoardItemOnLayer(const ATEXT6 &aElem, PCB_LAYER_ID aLayer)
void ConvertPads6ToFootprintItemOnCopper(FOOTPRINT *aFootprint, const APAD6 &aElem)
FOOTPRINT * ParseFootprint(ALTIUM_PCB_COMPOUND_FILE &altiumLibFile, const wxString &aFootprintName)
REPORTER * m_reporter
optional; may be nullptr
int GetNetCode(uint16_t aId) const
void ConvertTexts6ToEdaTextSettings(const ATEXT6 &aElem, EDA_TEXT &aEdaText)
wxString m_library
for footprint library loading error reporting
void ConvertPads6ToFootprintItemOnNonCopper(FOOTPRINT *aFootprint, const APAD6 &aElem)
void ConvertTexts6ToFootprintItem(FOOTPRINT *aFootprint, const ATEXT6 &aElem)
unsigned m_lastProgressCount
void ParseFills6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ConvertArcs6ToFootprintItem(FOOTPRINT *aFootprint, const AARC6 &aElem, const int aPrimitiveIndex, const bool aIsBoardImport)
void HelperParseDimensions6Datum(const ADIMENSION6 &aElem)
void ConvertPads6ToBoardItem(const APAD6 &aElem)
void ConvertFills6ToFootprintItemOnLayer(FOOTPRINT *aFootprint, const AFILL6 &aElem, PCB_LAYER_ID aLayer)
void ParseWideStrings6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void remapUnsureLayers(std::vector< ABOARD6_LAYER_STACKUP > &aStackup)
std::vector< ZONE * > m_polygons
void ParsePads6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ConvertArcs6ToPcbShape(const AARC6 &aElem, PCB_SHAPE *aShape)
void ConvertTracks6ToBoardItemOnLayer(const ATRACK6 &aElem, PCB_LAYER_ID aLayer)
void ConvertFills6ToBoardItem(const AFILL6 &aElem)
FOOTPRINT * HelperGetFootprint(uint16_t aComponent) const
LAYER_MAPPING_HANDLER m_layerMappingHandler
void ParsePolygons6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
PCB_LAYER_ID GetKicadLayer(ALTIUM_LAYER aAltiumLayer) const
void ParseComponentsBodies6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ConvertTracks6ToFootprintItemOnLayer(FOOTPRINT *aFootprint, const ATRACK6 &aElem, PCB_LAYER_ID aLayer)
void Parse(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const std::map< ALTIUM_PCB_DIR, std::string > &aFileMapping)
ALTIUM_PCB(BOARD *aBoard, PROGRESS_REPORTER *aProgressReporter, LAYER_MAPPING_HANDLER &aLayerMappingHandler, REPORTER *aReporter=nullptr, const wxString &aLibrary=wxEmptyString, const wxString &aFootprintName=wxEmptyString)
void ConvertArcs6ToBoardItemOnLayer(const AARC6 &aElem, PCB_LAYER_ID aLayer)
void ParseTexts6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
std::map< ALTIUM_RECORD, std::multimap< int, const AEXTENDED_PRIMITIVE_INFORMATION > > m_extendedPrimitiveInformationMaps
void ParseModelsData(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry, const std::vector< std::string > &aRootDir)
std::map< ALTIUM_LAYER, wxString > m_layerNames
void ConvertPads6ToBoardItemOnNonCopper(const APAD6 &aElem)
void HelperSetTextboxAlignmentAndPos(const ATEXT6 &aElem, PCB_TEXTBOX *aPcbTextbox)
void ParseNets6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ConvertPads6ToFootprintItem(FOOTPRINT *aFootprint, const APAD6 &aElem)
const ARULE6 * GetRule(ALTIUM_RULE_KIND aKind, const wxString &aName) const
void ParseDimensions6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void HelperSetZoneLayers(ZONE &aZone, const ALTIUM_LAYER aAltiumLayer)
static wxString ReadString(const std::map< wxString, wxString > &aProps, const wxString &aKey, const wxString &aDefault)
BASE_SET & set(size_t pos)
Container for design settings for a BOARD object.