43#include <compoundfilereader.h>
49#include <wx/docview.h>
51#include <wx/mstream.h>
52#include <wx/wfstream.h>
53#include <wx/zstream.h>
55#include <magic_enum.hpp>
77 THROW_IO_ERROR( wxString::Format( wxT(
"Component creator tries to access component id %d "
78 "of %d existing components" ),
87 const std::vector<ALTIUM_VERTICE>& aVertices )
96 double startradiant =
DEG2RAD( vertex.startangle );
97 double endradiant =
DEG2RAD( vertex.endangle );
99 -
KiROUND( std::sin( startradiant ) * vertex.radius ) );
102 -
KiROUND( std::sin( endradiant ) * vertex.radius ) );
104 VECTOR2I arcStart = vertex.center + arcStartOffset;
105 VECTOR2I arcEnd = vertex.center + arcEndOffset;
119 aLine.
Append( vertex.position );
129 auto override =
m_layermap.find( aAltiumLayer );
133 return override->second;
136 switch( aAltiumLayer )
140 case ALTIUM_LAYER::TOP_LAYER:
return F_Cu;
141 case ALTIUM_LAYER::MID_LAYER_1:
return In1_Cu;
142 case ALTIUM_LAYER::MID_LAYER_2:
return In2_Cu;
143 case ALTIUM_LAYER::MID_LAYER_3:
return In3_Cu;
144 case ALTIUM_LAYER::MID_LAYER_4:
return In4_Cu;
145 case ALTIUM_LAYER::MID_LAYER_5:
return In5_Cu;
146 case ALTIUM_LAYER::MID_LAYER_6:
return In6_Cu;
147 case ALTIUM_LAYER::MID_LAYER_7:
return In7_Cu;
148 case ALTIUM_LAYER::MID_LAYER_8:
return In8_Cu;
149 case ALTIUM_LAYER::MID_LAYER_9:
return In9_Cu;
150 case ALTIUM_LAYER::MID_LAYER_10:
return In10_Cu;
151 case ALTIUM_LAYER::MID_LAYER_11:
return In11_Cu;
152 case ALTIUM_LAYER::MID_LAYER_12:
return In12_Cu;
153 case ALTIUM_LAYER::MID_LAYER_13:
return In13_Cu;
154 case ALTIUM_LAYER::MID_LAYER_14:
return In14_Cu;
155 case ALTIUM_LAYER::MID_LAYER_15:
return In15_Cu;
156 case ALTIUM_LAYER::MID_LAYER_16:
return In16_Cu;
157 case ALTIUM_LAYER::MID_LAYER_17:
return In17_Cu;
158 case ALTIUM_LAYER::MID_LAYER_18:
return In18_Cu;
159 case ALTIUM_LAYER::MID_LAYER_19:
return In19_Cu;
160 case ALTIUM_LAYER::MID_LAYER_20:
return In20_Cu;
161 case ALTIUM_LAYER::MID_LAYER_21:
return In21_Cu;
162 case ALTIUM_LAYER::MID_LAYER_22:
return In22_Cu;
163 case ALTIUM_LAYER::MID_LAYER_23:
return In23_Cu;
164 case ALTIUM_LAYER::MID_LAYER_24:
return In24_Cu;
165 case ALTIUM_LAYER::MID_LAYER_25:
return In25_Cu;
166 case ALTIUM_LAYER::MID_LAYER_26:
return In26_Cu;
167 case ALTIUM_LAYER::MID_LAYER_27:
return In27_Cu;
168 case ALTIUM_LAYER::MID_LAYER_28:
return In28_Cu;
169 case ALTIUM_LAYER::MID_LAYER_29:
return In29_Cu;
170 case ALTIUM_LAYER::MID_LAYER_30:
return In30_Cu;
171 case ALTIUM_LAYER::BOTTOM_LAYER:
return B_Cu;
173 case ALTIUM_LAYER::TOP_OVERLAY:
return F_SilkS;
174 case ALTIUM_LAYER::BOTTOM_OVERLAY:
return B_SilkS;
175 case ALTIUM_LAYER::TOP_PASTE:
return F_Paste;
176 case ALTIUM_LAYER::BOTTOM_PASTE:
return B_Paste;
177 case ALTIUM_LAYER::TOP_SOLDER:
return F_Mask;
178 case ALTIUM_LAYER::BOTTOM_SOLDER:
return B_Mask;
197 case ALTIUM_LAYER::DRILL_GUIDE:
return Dwgs_User;
198 case ALTIUM_LAYER::KEEP_OUT_LAYER:
return Margin;
200 case ALTIUM_LAYER::MECHANICAL_1:
return User_1;
201 case ALTIUM_LAYER::MECHANICAL_2:
return User_2;
202 case ALTIUM_LAYER::MECHANICAL_3:
return User_3;
203 case ALTIUM_LAYER::MECHANICAL_4:
return User_4;
204 case ALTIUM_LAYER::MECHANICAL_5:
return User_5;
205 case ALTIUM_LAYER::MECHANICAL_6:
return User_6;
206 case ALTIUM_LAYER::MECHANICAL_7:
return User_7;
207 case ALTIUM_LAYER::MECHANICAL_8:
return User_8;
208 case ALTIUM_LAYER::MECHANICAL_9:
return User_9;
209 case ALTIUM_LAYER::MECHANICAL_10:
return Dwgs_User;
210 case ALTIUM_LAYER::MECHANICAL_11:
return Eco2_User;
211 case ALTIUM_LAYER::MECHANICAL_12:
return F_Fab;
212 case ALTIUM_LAYER::MECHANICAL_13:
return B_Fab;
217 case ALTIUM_LAYER::DRILL_DRAWING:
return Dwgs_User;
235 static std::set<ALTIUM_LAYER> altiumLayersWithWarning;
237 if( aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER || aAltiumLayer == ALTIUM_LAYER::KEEP_OUT_LAYER )
239 std::vector<PCB_LAYER_ID> layers;
245 layers.emplace_back( layer );
255 wxLogWarning(
_(
"Altium layer (%d) has no KiCad equivalent. It has been moved to KiCad "
256 "layer Eco1_User." ),
281 const unsigned PROGRESS_DELTA = 250;
299 const std::map<ALTIUM_PCB_DIR, std::string>& aFileMapping )
302 const std::vector<std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>> parserOrder = {
303 {
true, ALTIUM_PCB_DIR::FILE_HEADER,
308 {
true, ALTIUM_PCB_DIR::BOARD6,
313 {
false, ALTIUM_PCB_DIR::EXTENDPRIMITIVEINFORMATION,
318 {
true, ALTIUM_PCB_DIR::COMPONENTS6,
323 {
true, ALTIUM_PCB_DIR::MODELS,
326 std::vector<std::string> dir{ aFileMapping.at( ALTIUM_PCB_DIR::MODELS ) };
329 {
true, ALTIUM_PCB_DIR::COMPONENTBODIES6,
334 {
true, ALTIUM_PCB_DIR::NETS6,
339 {
true, ALTIUM_PCB_DIR::CLASSES6,
344 {
true, ALTIUM_PCB_DIR::RULES6,
349 {
true, ALTIUM_PCB_DIR::DIMENSIONS6,
354 {
true, ALTIUM_PCB_DIR::POLYGONS6,
359 {
true, ALTIUM_PCB_DIR::ARCS6,
364 {
true, ALTIUM_PCB_DIR::PADS6,
369 {
true, ALTIUM_PCB_DIR::VIAS6,
374 {
true, ALTIUM_PCB_DIR::TRACKS6,
379 {
false, ALTIUM_PCB_DIR::WIDESTRINGS6,
384 {
true, ALTIUM_PCB_DIR::TEXTS6,
389 {
true, ALTIUM_PCB_DIR::FILLS6,
394 {
false, ALTIUM_PCB_DIR::BOARDREGIONS,
399 {
true, ALTIUM_PCB_DIR::SHAPEBASEDREGIONS6,
404 {
true, ALTIUM_PCB_DIR::REGIONS6,
414 for(
const std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>& cur : parserOrder )
419 std::tie( isRequired,
directory, fp ) = cur;
421 if(
directory == ALTIUM_PCB_DIR::FILE_HEADER )
424 const auto& mappedDirectory = aFileMapping.find(
directory );
426 if( mappedDirectory == aFileMapping.end() )
429 const std::vector<std::string> mappedFile{ mappedDirectory->second,
"Header" };
430 const CFB::COMPOUND_FILE_ENTRY* file = altiumPcbFile.
FindStream( mappedFile );
432 if( file ==
nullptr )
436 uint32_t numOfRecords = reader.
Read<uint32_t>();
440 wxLogError(
_(
"'%s' was not parsed correctly." ),
FormatPath( mappedFile ) );
448 wxLogError(
_(
"'%s' was not fully parsed." ),
FormatPath( mappedFile ) );
454 const auto& boardDirectory = aFileMapping.find( ALTIUM_PCB_DIR::BOARD6 );
456 if( boardDirectory != aFileMapping.end() )
458 std::vector<std::string> mappedFile{ boardDirectory->second,
"Data" };
460 const CFB::COMPOUND_FILE_ENTRY* file = altiumPcbFile.
FindStream( mappedFile );
465 "This file does not appear to be in a valid PCB Binary Version 6.0 format. In "
467 "make sure to save as \"PCB Binary Files (*.PcbDoc)\"." ) );
472 for(
const std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>& cur : parserOrder )
477 std::tie( isRequired,
directory, fp ) = cur;
479 const auto& mappedDirectory = aFileMapping.find(
directory );
481 if( mappedDirectory == aFileMapping.end() )
483 wxASSERT_MSG( !isRequired, wxString::Format( wxT(
"Altium Directory of kind %d was "
484 "expected, but no mapping is "
485 "present in the code" ),
490 std::vector<std::string> mappedFile{ mappedDirectory->second };
492 if(
directory != ALTIUM_PCB_DIR::FILE_HEADER )
493 mappedFile.emplace_back(
"Data" );
495 const CFB::COMPOUND_FILE_ENTRY* file = altiumPcbFile.
FindStream( mappedFile );
497 if( file !=
nullptr )
499 fp( altiumPcbFile, file );
501 else if( isRequired )
503 wxLogError(
_(
"File not found: '%s' for directory '%s'." ),
FormatPath( mappedFile ),
515 if( zone->GetAssignedPriority() == 1000 )
526 zone->SetAssignedPriority( priority >= 0 ? priority : 0 );
530 for( std::pair<const ALTIUM_LAYER, ZONE*>& zone :
m_outer_plane )
531 zone.second->SetAssignedPriority( 0 );
548 if( shape->
GetShape() != SHAPE_T::ARC && shape->
GetShape() != SHAPE_T::CIRCLE )
567 if( arc->
GetCenter() == dim->GetPosition() )
576 VECTOR2I radialLine = dim->GetEnd() - dim->GetStart();
581 radialLine = radialLine.
Resize( std::max( radius, 2 ) );
582 dim->SetEnd( dim->GetStart() + (
VECTOR2I) radialLine );
583 dim->SetLeaderLength( totalLength - radius );
593 int desired_x = ( w - bbbox.
GetWidth() ) / 2;
594 int desired_y = ( h - bbbox.
GetHeight() ) / 2;
596 VECTOR2I movementVector( desired_x - bbbox.
GetX(), desired_y - bbbox.
GetY() );
608 const wxString& aFootprintName )
610 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
628 std::tuple<wxString, const CFB::COMPOUND_FILE_ENTRY*> ret = altiumLibFile.
FindLibFootprintDirName(aFootprintName);
630 wxString fpDirName = std::get<0>( ret );
631 const CFB::COMPOUND_FILE_ENTRY* footprintStream = std::get<1>( ret );
633 if( fpDirName.IsEmpty() )
636 wxString::Format(
_(
"Footprint directory not found: '%s'." ), aFootprintName ) );
639 const std::vector<std::string> streamName{ fpDirName.ToStdString(),
"Data" };
640 const CFB::COMPOUND_FILE_ENTRY* footprintData = altiumLibFile.
FindStream( footprintStream, {
"Data" } );
642 if( footprintData ==
nullptr )
655 footprint->SetFPID( fpID );
657 const std::vector<std::string> parametersStreamName{ fpDirName.ToStdString(),
659 const CFB::COMPOUND_FILE_ENTRY* parametersData =
660 altiumLibFile.
FindStream( footprintStream, {
"Parameters" } );
662 if( parametersData !=
nullptr )
664 ALTIUM_PARSER parametersReader( altiumLibFile, parametersData );
665 std::map<wxString, wxString> parameterProperties = parametersReader.
ReadProperties();
667 wxT(
"DESCRIPTION" ),
669 footprint->SetLibDescription( description );
673 wxLogError(
_(
"File not found: '%s'." ),
FormatPath( parametersStreamName ) );
674 footprint->SetLibDescription( wxT(
"" ) );
677 const std::vector<std::string> extendedPrimitiveInformationStreamName{
678 "ExtendedPrimitiveInformation",
"Data"
680 const CFB::COMPOUND_FILE_ENTRY* extendedPrimitiveInformationData =
681 altiumLibFile.
FindStream( footprintStream, extendedPrimitiveInformationStreamName );
683 if( extendedPrimitiveInformationData !=
nullptr )
686 footprint->SetReference( wxT(
"REF**" ) );
687 footprint->SetValue( aFootprintName );
688 footprint->Reference().SetVisible(
true );
689 footprint->Value().SetVisible(
true );
694 for(
PCB_FIELD* field : footprint->Fields() )
696 field->SetTextSize( defaultTextSize );
697 field->SetTextThickness( defaultTextThickness );
706 case ALTIUM_RECORD::ARC:
712 case ALTIUM_RECORD::PAD:
718 case ALTIUM_RECORD::VIA:
724 case ALTIUM_RECORD::TRACK:
730 case ALTIUM_RECORD::TEXT:
736 case ALTIUM_RECORD::FILL:
742 case ALTIUM_RECORD::REGION:
748 case ALTIUM_RECORD::MODEL:
755 THROW_IO_ERROR( wxString::Format(
_(
"Record of unknown type: '%d'." ), recordtype ) );
760 footprint->AutoPositionFields();
764 THROW_IO_ERROR( wxString::Format( wxT(
"%s stream was not parsed correctly" ),
770 THROW_IO_ERROR( wxString::Format( wxT(
"%s stream is not fully parsed" ),
774 return footprint.release();
785 THROW_IO_ERROR( wxString::Format( wxT(
"Netcode with id %d does not exist. Only %d nets "
797 const auto rules =
m_rules.find( aKind );
802 for(
const ARULE6& rule : rules->second )
804 if( rule.
name == aName )
813 const auto rules =
m_rules.find( aKind );
818 for(
const ARULE6& rule : rules->second )
828 const CFB::COMPOUND_FILE_ENTRY* aEntry )
845 const CFB::COMPOUND_FILE_ENTRY* aEntry )
862 THROW_IO_ERROR( wxT(
"ExtendedPrimitiveInformation stream is not fully parsed" ) );
866 const CFB::COMPOUND_FILE_ENTRY* aEntry )
883 size_t layercount = 0;
884 size_t layerid =
static_cast<size_t>( ALTIUM_LAYER::TOP_LAYER );
886 while( layerid < elem.
stackup.size() && layerid != 0 )
888 layerid = elem.
stackup[ layerid - 1 ].nextId;
892 size_t kicadLayercount = ( layercount % 2 == 0 ) ? layercount : layercount + 1;
902 auto it = stackup.
GetList().begin();
908 auto curLayer =
static_cast<int>(
F_Cu );
910 for(
size_t altiumLayerId =
static_cast<size_t>( ALTIUM_LAYER::TOP_LAYER );
911 altiumLayerId < elem.
stackup.size() && altiumLayerId != 0;
912 altiumLayerId = elem.
stackup[altiumLayerId - 1].nextId )
918 if( layer.
nextId == 0 && layercount != kicadLayercount )
923 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
925 ( *it )->SetThickness( 0 );
930 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
932 ( *it )->SetThickness( 0, 0 );
933 ( *it )->SetThicknessLocked(
true, 0 );
941 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
958 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected id while parsing last stackup layer" ) );
968 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
980 for(
size_t altiumLayerId =
static_cast<size_t>( ALTIUM_LAYER::TOP_OVERLAY );
981 altiumLayerId <= static_cast<size_t>( ALTIUM_LAYER::BOTTOM_SOLDER ); altiumLayerId++ )
992 for(
size_t altiumLayerId =
static_cast<size_t>( ALTIUM_LAYER::MECHANICAL_1 );
993 altiumLayerId <= static_cast<size_t>( ALTIUM_LAYER::MECHANICAL_16 ); altiumLayerId++ )
1013 PLOT_DASH_TYPE::SOLID );
1020 int nextShape = lineChain.
NextShape( i );
1021 bool isLastShape = nextShape < 0;
1046 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1058 if( elem.
kind == ALTIUM_CLASS_KIND::NET_CLASS )
1060 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( elem.
name );
1062 for(
const wxString&
name : elem.
names )
1075 wxLogWarning(
_(
"More than one Altium netclass with name '%s' found. "
1076 "Only the first one will be imported." ), elem.
name );
1092 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1099 uint16_t componentId = 0;
1121 if( reference.find_first_not_of(
"0123456789" ) == wxString::npos )
1122 reference.Prepend( wxT(
"UNK" ) );
1135 THROW_IO_ERROR( wxT(
"Components6 stream is not fully parsed" ) );
1142 while( Angle < aMin )
1145 while( Angle >= aMax )
1153 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1170 THROW_IO_ERROR( wxString::Format( wxT(
"ComponentsBodies6 stream tries to access "
1171 "component id %d of %d existing components" ),
1183 wxLogError( wxT(
"ComponentsBodies6 stream tries to access model id %s which does not "
1194 modelSettings.
m_Filename = modelTuple->second;
1205 orientation = -orientation;
1218 footprint->
Models().push_back( modelSettings );
1222 THROW_IO_ERROR( wxT(
"ComponentsBodies6 stream is not fully parsed" ) );
1229 THROW_IO_ERROR( wxT(
"Incorrect number of reference points for linear dimension object" ) );
1235 wxLogWarning(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1236 "It has been moved to KiCad layer Eco1_User." ),
1249 dimension->
SetStart( referencePoint0 );
1251 if( referencePoint0 != aElem.
xy1 )
1264 SEG segm1( referencePoint0, referencePoint0 + directionNormalVector );
1265 SEG segm2( referencePoint1, referencePoint1 + direction );
1269 THROW_IO_ERROR( wxT(
"Invalid dimension. This should never happen." ) );
1271 dimension->
SetEnd( *intersection );
1273 int height =
static_cast<int>(
EuclideanNorm( direction ) );
1275 if( ( direction.
x > 0 || direction.
y < 0 ) != ( aElem.
angle >= 180.0 ) )
1282 dimension->
SetEnd( referencePoint1 );
1291 wxRegEx units( wxS(
"(mm)|(in)|(mils)|(thou)|(')|(\")" ), wxRE_ADVANCED );
1311 case ALTIUM_UNIT::INCHES:
1312 dimension->
SetUnits( EDA_UNITS::INCHES );
1314 case ALTIUM_UNIT::MILS:
1315 dimension->
SetUnits( EDA_UNITS::MILS );
1317 case ALTIUM_UNIT::MILLIMETERS:
1318 case ALTIUM_UNIT::CENTIMETER:
1319 dimension->
SetUnits( EDA_UNITS::MILLIMETRES );
1330 THROW_IO_ERROR( wxT(
"Not enough reference points for radial dimension object" ) );
1336 wxLogWarning(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1337 "It has been moved to KiCad layer Eco1_User." ),
1351 dimension->
SetStart( referencePoint0 );
1360 : DIM_UNITS_FORMAT::BARE_SUFFIX );
1364 case ALTIUM_UNIT::INCHES:
1365 dimension->
SetUnits( EDA_UNITS::INCHES );
1367 case ALTIUM_UNIT::MILS:
1368 dimension->
SetUnits( EDA_UNITS::MILS );
1370 case ALTIUM_UNIT::MILLIMETERS:
1371 case ALTIUM_UNIT::CENTIMETER:
1372 dimension->
SetUnits( EDA_UNITS::MILLIMETRES );
1380 wxLogError( wxT(
"No text position present for leader dimension object" ) );
1413 wxLogWarning(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1414 "It has been moved to KiCad layer Eco1_User." ),
1441 if( dirVec.
x != 0 || dirVec.
y != 0 )
1452 shape1->
SetStart( referencePoint0 );
1453 shape1->
SetEnd( referencePoint0 + arrVec );
1461 shape2->
SetStart( referencePoint0 );
1462 shape2->
SetEnd( referencePoint0 + arrVec );
1469 wxLogError( wxT(
"No text position present for leader dimension object" ) );
1477 text->SetLayer( klayer );
1491 wxLogWarning(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1492 "It has been moved to KiCad layer Eco1_User." ),
1515 wxLogWarning(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1516 "It has been moved to KiCad layer Eco1_User." ),
1534 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1548 case ALTIUM_DIMENSION_KIND::LINEAR:
1551 case ALTIUM_DIMENSION_KIND::RADIAL:
1554 case ALTIUM_DIMENSION_KIND::LEADER:
1557 case ALTIUM_DIMENSION_KIND::DATUM:
1558 wxLogError(
_(
"Ignored dimension of kind %d (not yet supported)." ), elem.
kind );
1561 case ALTIUM_DIMENSION_KIND::CENTER:
1565 wxLogError(
_(
"Ignored dimension of kind %d (not yet supported)." ), elem.
kind );
1571 THROW_IO_ERROR( wxT(
"Dimensions6 stream is not fully parsed" ) );
1576 const CFB::COMPOUND_FILE_ENTRY* aEntry,
1577 const std::vector<std::string>& aRootDir )
1592 const wxString altiumModelDir = wxT(
"ALTIUM_EMBEDDED_MODELS" );
1594 wxFileName altiumModelsPath = wxFileName::DirName( projectPath );
1595 wxString kicadModelPrefix = wxT(
"${KIPRJMOD}/" ) + altiumModelDir + wxT(
"/" );
1597 if( !altiumModelsPath.AppendDir( altiumModelDir ) )
1598 THROW_IO_ERROR( wxT(
"Cannot construct directory path for step models" ) );
1601 if( !altiumModelsPath.DirExists() )
1603 if( !altiumModelsPath.Mkdir() )
1605 wxLogError(
_(
"Failed to create folder '%s'." ) + wxS(
" " )
1606 +
_(
"No 3D-models will be imported." ),
1607 altiumModelsPath.GetFullPath() );
1613 wxString invalidChars = wxFileName::GetForbiddenChars();
1620 std::vector<std::string> stepPath = aRootDir;
1621 stepPath.emplace_back( std::to_string( idx ) );
1623 bool validName = !elem.
name.IsEmpty() && elem.
name.IsAscii() &&
1624 wxString::npos == elem.
name.find_first_of( invalidChars );
1625 wxString storageName = !validName ? wxString::Format( wxT(
"model_%d" ), idx )
1627 wxFileName storagePath( altiumModelsPath.GetPath(), storageName );
1631 const CFB::COMPOUND_FILE_ENTRY* stepEntry = aAltiumPcbFile.
FindStream( stepPath );
1633 if( stepEntry ==
nullptr )
1635 wxLogError(
_(
"File not found: '%s'. 3D-model not imported." ),
1640 size_t stepSize =
static_cast<size_t>( stepEntry->size );
1641 std::vector<char> stepContent( stepSize );
1647 if( !storagePath.IsDirWritable() )
1649 wxLogError(
_(
"Insufficient permissions to save file '%s'." ),
1650 storagePath.GetFullPath() );
1654 wxMemoryInputStream stepStream( stepContent.data(), stepSize );
1655 wxZlibInputStream zlibInputStream( stepStream );
1657 wxFFileOutputStream outputStream( storagePath.GetFullPath() );
1658 outputStream.Write( zlibInputStream );
1659 outputStream.Close();
1661 m_models.insert( { elem.
id, kicadModelPrefix + storageName } );
1670 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1681 ANET6 elem( reader );
1694 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1743 if( clearanceRule !=
nullptr )
1748 if( polygonConnectRule !=
nullptr )
1752 case ALTIUM_CONNECT_STYLE::DIRECT:
1756 case ALTIUM_CONNECT_STYLE::NONE:
1761 case ALTIUM_CONNECT_STYLE::RELIEF:
1789 if( elem.
hatchstyle != ALTIUM_POLYGON_HATCHSTYLE::SOLID
1790 && elem.
hatchstyle != ALTIUM_POLYGON_HATCHSTYLE::UNKNOWN )
1792 zone->
SetFillMode( ZONE_FILL_MODE::HATCH_PATTERN );
1795 if( elem.
hatchstyle == ALTIUM_POLYGON_HATCHSTYLE::NONE )
1806 if( elem.
hatchstyle == ALTIUM_POLYGON_HATCHSTYLE::DEGREE_45 )
1819 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1837 std::sort( val.second.begin(), val.second.end(),
1840 return lhs.priority < rhs.priority;
1847 if( soldermaskRule )
1858 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1874 THROW_IO_ERROR( wxT(
"BoardRegions stream is not fully parsed" ) );
1878 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1886 for(
int primitiveIndex = 0; reader.
GetRemainingBytes() >= 4; primitiveIndex++ )
1892 || elem.
kind == ALTIUM_REGION_KIND::BOARD_CUTOUT )
1905 THROW_IO_ERROR(
"ShapeBasedRegions6 stream is not fully parsed" );
1911 if( aElem.
kind == ALTIUM_REGION_KIND::BOARD_CUTOUT )
1915 else if( aElem.
kind == ALTIUM_REGION_KIND::POLYGON_CUTOUT || aElem.
is_keepout )
1938 else if( aElem.
kind == ALTIUM_REGION_KIND::POLYGON_CUTOUT )
1955 else if( aElem.
kind == ALTIUM_REGION_KIND::DASHED_OUTLINE )
1962 _(
"Dashed outline found on an Altium layer (%d) with no KiCad equivalent. "
1963 "It has been moved to KiCad layer Eco1_User." ),
1989 else if( aElem.
kind == ALTIUM_REGION_KIND::COPPER )
1997 else if( aElem.
kind == ALTIUM_REGION_KIND::BOARD_CUTOUT )
2003 wxLogError(
_(
"Ignored polygon shape of kind %d (not yet supported)." ), aElem.
kind );
2010 const int aPrimitiveIndex )
2012 if( aElem.
kind == ALTIUM_REGION_KIND::POLYGON_CUTOUT || aElem.
is_keepout )
2026 ZONE* zone =
new ZONE( aFootprint );
2027 aFootprint->
Add( zone, ADD_MODE::APPEND );
2035 else if( aElem.
kind == ALTIUM_REGION_KIND::POLYGON_CUTOUT )
2052 else if( aElem.
kind == ALTIUM_REGION_KIND::COPPER )
2063 else if( aElem.
kind == ALTIUM_REGION_KIND::DASHED_OUTLINE
2064 || aElem.
kind == ALTIUM_REGION_KIND::BOARD_CUTOUT )
2073 _(
"Dashed outline found on an Altium layer (%d) with no KiCad equivalent. "
2074 "It has been moved to KiCad layer Eco1_User." ),
2097 if( aElem.
kind == ALTIUM_REGION_KIND::DASHED_OUTLINE )
2102 aFootprint->
Add( shape, ADD_MODE::APPEND );
2106 wxLogError(
_(
"Ignored polygon shape of kind %d (not yet supported)." ), aElem.
kind );
2129 for(
const std::vector<ALTIUM_VERTICE>& hole : aElem.
holes )
2137 polySet.
AddHole( hole_linechain );
2159 const int aPrimitiveIndex )
2176 for(
const std::vector<ALTIUM_VERTICE>& hole : aElem.
holes )
2184 polySet.
AddHole( hole_linechain );
2187 if( aLayer ==
F_Cu || aLayer ==
B_Cu )
2192 padLayers.set( aLayer );
2194 pad->SetKeepTopBottom(
false );
2195 pad->SetAttribute( PAD_ATTRIB::SMD );
2196 pad->SetShape( PAD_SHAPE::CUSTOM );
2201 pad->SetShape( PAD_SHAPE::CUSTOM );
2202 pad->SetAnchorPadShape( PAD_SHAPE::CIRCLE );
2203 pad->SetSize( { anchorSize, anchorSize } );
2204 pad->SetPosition( anchorPos );
2207 shapePolys.
Move( -anchorPos );
2208 pad->AddPrimitivePoly( shapePolys, 0,
true );
2211 auto it = map.find( aPrimitiveIndex );
2213 if( it != map.end() )
2217 if(
info.pastemaskexpansionmode == ALTIUM_MODE::MANUAL )
2219 pad->SetLocalSolderPasteMargin(
2220 info.pastemaskexpansionmanual ?
info.pastemaskexpansionmanual : 1 );
2223 if(
info.soldermaskexpansionmode == ALTIUM_MODE::MANUAL )
2225 pad->SetLocalSolderMaskMargin(
2226 info.soldermaskexpansionmanual ?
info.soldermaskexpansionmanual : 1 );
2229 if(
info.pastemaskexpansionmode != ALTIUM_MODE::NONE )
2232 if(
info.soldermaskexpansionmode != ALTIUM_MODE::NONE )
2236 pad->SetLayerSet( padLayers );
2238 aFootprint->
Add(
pad, ADD_MODE::APPEND );
2249 aFootprint->
Add( shape, ADD_MODE::APPEND );
2255 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2277 THROW_IO_ERROR( wxString::Format(
"Region stream tries to access polygon id %d "
2278 "of %d existing polygons.",
2285 if( zone ==
nullptr )
2307 for(
const std::vector<ALTIUM_VERTICE>& hole : elem.
holes )
2314 hole_linechain.
Append( hole.at( 0 ).position );
2316 fill.
AddHole( hole_linechain );
2336 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2343 for(
int primitiveIndex = 0; reader.
GetRemainingBytes() >= 4; primitiveIndex++ )
2346 AARC6 elem( reader );
2368 aShape->
SetShape( SHAPE_T::CIRCLE );
2413 for(
const auto& layerExpansionMask :
2416 int width = aElem.
width + ( layerExpansionMask.second * 2 );
2424 arc->
SetLayer( layerExpansionMask.first );
2433 const int aPrimitiveIndex,
const bool aIsBoardImport )
2466 for(
const auto& layerExpansionMask :
2469 int width = aElem.
width + ( layerExpansionMask.second * 2 );
2477 arc->
SetLayer( layerExpansionMask.first );
2479 aFootprint->
Add( arc, ADD_MODE::APPEND );
2490 PCB_SHAPE shape(
nullptr, SHAPE_T::ARC );
2534 aFootprint->
Add( arc, ADD_MODE::APPEND );
2539 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2549 APAD6 elem( reader );
2571 && aElem.
layer != ALTIUM_LAYER::MULTI_LAYER )
2592 && aElem.
layer != ALTIUM_LAYER::MULTI_LAYER )
2607 pad->SetKeepTopBottom(
false );
2618 pad->SetAttribute( PAD_ATTRIB::SMD );
2622 if( aElem.
layer != ALTIUM_LAYER::MULTI_LAYER )
2625 wxLogError(
_(
"Footprint %s pad %s is not marked as multilayer, but is a TH pad." ),
2630 pad->SetAttribute( aElem.
plated ? PAD_ATTRIB::PTH : PAD_ATTRIB::NPTH );
2634 pad->SetDrillShape( PAD_DRILL_SHAPE_T::PAD_DRILL_SHAPE_CIRCLE );
2641 case ALTIUM_PAD_HOLE_SHAPE::ROUND:
2642 wxFAIL_MSG( wxT(
"Round holes are handled before the switch" ) );
2645 case ALTIUM_PAD_HOLE_SHAPE::SQUARE:
2646 wxLogWarning(
_(
"Footprint %s pad %s has a square hole (not yet supported)." ),
2650 pad->SetDrillShape( PAD_DRILL_SHAPE_T::PAD_DRILL_SHAPE_CIRCLE );
2656 case ALTIUM_PAD_HOLE_SHAPE::SLOT:
2658 pad->SetDrillShape( PAD_DRILL_SHAPE_T::PAD_DRILL_SHAPE_OBLONG );
2673 wxLogWarning(
_(
"Footprint %s pad %s has a hole-rotation of %f degrees. "
2674 "KiCad only supports 90 degree rotations." ),
2684 case ALTIUM_PAD_HOLE_SHAPE::UNKNOWN:
2685 wxLogError(
_(
"Footprint %s pad %s uses a hole of unknown kind %d." ),
2690 pad->SetDrillShape( PAD_DRILL_SHAPE_T::PAD_DRILL_SHAPE_CIRCLE );
2700 if( aElem.
padmode != ALTIUM_PAD_MODE::SIMPLE )
2702 wxLogError(
_(
"Footprint %s pad %s uses a complex pad stack (not yet supported.)" ),
2708 case ALTIUM_PAD_SHAPE::RECT:
2709 pad->SetShape( PAD_SHAPE::RECTANGLE );
2712 case ALTIUM_PAD_SHAPE::CIRCLE:
2714 && aElem.
sizeAndShape->alt_shape[0] == ALTIUM_PAD_SHAPE_ALT::ROUNDRECT )
2716 pad->SetShape( PAD_SHAPE::ROUNDRECT );
2717 double ratio = aElem.
sizeAndShape->cornerradius[0] / 200.;
2718 pad->SetRoundRectRadiusRatio( ratio );
2722 pad->SetShape( PAD_SHAPE::CIRCLE );
2726 pad->SetShape( PAD_SHAPE::OVAL );
2731 case ALTIUM_PAD_SHAPE::OCTAGONAL:
2732 pad->SetShape( PAD_SHAPE::CHAMFERED_RECT );
2734 pad->SetChamferRectRatio( 0.25 );
2737 case ALTIUM_PAD_SHAPE::UNKNOWN:
2739 wxLogError(
_(
"Footprint %s pad %s uses an unknown pad-shape." ),
2744 if(
pad->GetAttribute() == PAD_ATTRIB::NPTH &&
pad->HasHole() )
2748 : PAD_SHAPE::OVAL );
2749 pad->SetSize(
pad->GetDrillSize() );
2752 switch( aElem.
layer )
2754 case ALTIUM_LAYER::TOP_LAYER:
2759 case ALTIUM_LAYER::BOTTOM_LAYER:
2764 case ALTIUM_LAYER::MULTI_LAYER:
2770 pad->SetLayer( klayer );
2771 pad->SetLayerSet(
LSET( 1, klayer ) );
2782 pad->SetLayerSet(
pad->GetLayerSet().reset(
F_Mask ) );
2785 pad->SetLayerSet(
pad->GetLayerSet().reset(
B_Mask ) );
2787 aFootprint->
Add(
pad, ADD_MODE::APPEND );
2797 wxLogWarning(
_(
"Non-copper pad %s found on an Altium layer (%d) with no KiCad "
2798 "equivalent. It has been moved to KiCad layer Eco1_User." ),
2818 _(
"Non-copper pad %s found on an Altium layer (%d) with no KiCad equivalent. "
2819 "It has been moved to KiCad layer Eco1_User." ),
2828 aFootprint->
Add(
pad, ADD_MODE::APPEND );
2837 wxLogError(
_(
"Non-copper pad %s is connected to a net, which is not supported." ),
2843 wxLogError(
_(
"Non-copper pad %s has a hole, which is not supported." ), aElem.
name );
2846 if( aElem.
padmode != ALTIUM_PAD_MODE::SIMPLE )
2848 wxLogWarning(
_(
"Non-copper pad %s has a complex pad stack (not yet supported)." ),
2854 case ALTIUM_PAD_SHAPE::RECT:
2873 case ALTIUM_PAD_SHAPE::CIRCLE:
2875 && aElem.
sizeAndShape->alt_shape[0] == ALTIUM_PAD_SHAPE_ALT::ROUNDRECT )
2878 int cornerradius = aElem.
sizeAndShape->cornerradius[0];
2879 int offset = ( std::min( aElem.
topsize.
x, aElem.
topsize.
y ) * cornerradius ) / 200;
2884 if( cornerradius < 100 )
2886 int offsetX = aElem.
topsize.
x / 2 - offset;
2887 int offsetY = aElem.
topsize.
y / 2 - offset;
2901 aShape->
SetShape( SHAPE_T::CIRCLE );
2910 aShape->
SetShape( SHAPE_T::SEGMENT );
2918 aShape->
SetShape( SHAPE_T::SEGMENT );
2930 aShape->
SetShape( SHAPE_T::CIRCLE );
2940 aShape->
SetShape( SHAPE_T::SEGMENT );
2943 PLOT_DASH_TYPE::SOLID ) );
2963 case ALTIUM_PAD_SHAPE::OCTAGONAL:
2980 aShape->
SetPolyPoints( { p11 - chamferX, p11 - chamferY, p12 + chamferY, p12 - chamferX,
2981 p22 + chamferX, p22 + chamferY, p21 - chamferY, p21 + chamferX } );
2988 case ALTIUM_PAD_SHAPE::UNKNOWN:
2990 wxLogError(
_(
"Non-copper pad %s uses an unknown pad-shape." ), aElem.
name );
2997 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3007 AVIA6 elem( reader );
3018 bool start_layer_outside = elem.
layer_start == ALTIUM_LAYER::TOP_LAYER
3019 || elem.
layer_start == ALTIUM_LAYER::BOTTOM_LAYER;
3020 bool end_layer_outside = elem.
layer_end == ALTIUM_LAYER::TOP_LAYER
3021 || elem.
layer_end == ALTIUM_LAYER::BOTTOM_LAYER;
3023 if( start_layer_outside && end_layer_outside )
3025 via->SetViaType( VIATYPE::THROUGH );
3027 else if( ( !start_layer_outside ) && ( !end_layer_outside ) )
3029 via->SetViaType( VIATYPE::BLIND_BURIED );
3033 via->SetViaType( VIATYPE::MICROVIA );
3041 wxLogError(
_(
"Via from layer %d to %d uses a non-copper layer, which is not "
3049 via->SetLayerPair( start_klayer, end_klayer );
3057 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3064 for(
int primitiveIndex = 0; reader.
GetRemainingBytes() >= 4; primitiveIndex++ )
3094 PCB_SHAPE shape(
nullptr, SHAPE_T::SEGMENT );
3108 ALTIUM_RECORD::TRACK, aPrimitiveIndex, aElem.
layer ) )
3110 int width = aElem.
width + ( layerExpansionMask.second * 2 );
3118 seg->
SetLayer( layerExpansionMask.first );
3127 const int aPrimitiveIndex,
3128 const bool aIsBoardImport )
3137 PCB_SHAPE shape(
nullptr, SHAPE_T::SEGMENT );
3162 ALTIUM_RECORD::TRACK, aPrimitiveIndex, aElem.
layer ) )
3164 int width = aElem.
width + ( layerExpansionMask.second * 2 );
3172 seg->
SetLayer( layerExpansionMask.first );
3174 aFootprint->
Add( seg, ADD_MODE::APPEND );
3218 aFootprint->
Add( seg, ADD_MODE::APPEND );
3223 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3233 THROW_IO_ERROR( wxT(
"WideStrings6 stream is not fully parsed" ) );
3237 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3267 if( aElem.
fonttype == ALTIUM_TEXT_TYPE::BARCODE )
3269 wxLogError(
_(
"Ignored barcode on Altium layer %d (not yet supported)." ), aElem.
layer );
3280 if( aElem.
fonttype == ALTIUM_TEXT_TYPE::BARCODE )
3282 wxLogError(
_(
"Ignored barcode on Altium layer %d (not yet supported)." ), aElem.
layer );
3296 wxString trimmedText = aElem.
text;
3299 if( trimmedText.CmpNoCase( wxT(
".Layer_Name" ) ) == 0 )
3300 pcbText->
SetText( wxT(
"${LAYER}" ) );
3325 fpText = &aFootprint->
Value();
3329 fpText =
new PCB_TEXT( aFootprint );
3330 aFootprint->
Add( fpText, ADD_MODE::APPEND );
3334 wxString trimmedText = aElem.
text;
3337 if( !aElem.
isDesignator && trimmedText.CmpNoCase( wxT(
".Designator" ) ) == 0 )
3338 fpText->
SetText( wxT(
"${REFERENCE}" ) );
3339 else if( !aElem.
isComment && trimmedText.CmpNoCase( wxT(
".Comment" ) ) == 0 )
3340 fpText->
SetText( wxT(
"${VALUE}" ) );
3341 else if( trimmedText.CmpNoCase( wxT(
".Layer_Name" ) ) == 0 )
3342 fpText->
SetText( wxT(
"${LAYER}" ) );
3359 if( aElem.
fonttype == ALTIUM_TEXT_TYPE::TRUETYPE )
3367 if( font->
GetName().Contains( wxS(
"Arial" ) ) )
3388 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3421 PCB_SHAPE shape(
nullptr, SHAPE_T::RECTANGLE );
3446 const bool aIsBoardImport )
3449 || aElem.
layer == ALTIUM_LAYER::KEEP_OUT_LAYER )
3452 PCB_SHAPE shape(
nullptr, SHAPE_T::RECTANGLE );
3530 aFootprint->
Add( fill, ADD_MODE::APPEND );
3539 layerSet.set( klayer );
3547 bool keepoutRestrictionVia = ( aKeepoutRestrictions & 0x01 ) != 0;
3548 bool keepoutRestrictionTrack = ( aKeepoutRestrictions & 0x02 ) != 0;
3549 bool keepoutRestrictionCopper = ( aKeepoutRestrictions & 0x04 ) != 0;
3550 bool keepoutRestrictionSMDPad = ( aKeepoutRestrictions & 0x08 ) != 0;
3551 bool keepoutRestrictionTHPad = ( aKeepoutRestrictions & 0x10 ) != 0;
3556 aZone->
SetDoNotAllowPads( keepoutRestrictionSMDPad && keepoutRestrictionTHPad );
3563 const uint8_t aKeepoutRestrictions )
3584 const uint8_t aKeepoutRestrictions )
3586 ZONE* zone =
new ZONE( aFootprint );
3599 aFootprint->
Add( zone, ADD_MODE::APPEND );
3612 if( elems.first == elems.second )
3615 std::vector<std::pair<PCB_LAYER_ID, int>> layerExpansionPairs;
3617 for(
auto it = elems.first; it != elems.second; ++it )
3621 if( pInf.
type == AEXTENDED_PRIMITIVE_INFORMATION_TYPE::MASK )
3627 if( aAltiumLayer == ALTIUM_LAYER::TOP_LAYER
3628 || aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER )
3633 if( aAltiumLayer == ALTIUM_LAYER::BOTTOM_LAYER
3634 || aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER )
3642 if( aAltiumLayer == ALTIUM_LAYER::TOP_LAYER
3643 || aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER )
3648 if( aAltiumLayer == ALTIUM_LAYER::BOTTOM_LAYER
3649 || aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER )
3657 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 int ALTIUM_COMPONENT_NONE
LIB_ID AltiumToKiCadLibID(const wxString &aLibName, const wxString &aLibReference)
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_COMPOUND_FILE &, const CFB::COMPOUND_FILE_ENTRY *)> PARSE_FUNCTION_POINTER_fp
constexpr int ARC_HIGH_DEF
constexpr EDA_IU_SCALE pcbIUScale
@ BS_ITEM_TYPE_DIELECTRIC
const CFB::CompoundFileReader & GetCompoundFileReader() const
std::tuple< wxString, const CFB::COMPOUND_FILE_ENTRY * > FindLibFootprintDirName(const wxString &aFpUnicodeName)
const CFB::COMPOUND_FILE_ENTRY * FindStream(const std::vector< std::string > &aStreamPath) const
size_t GetRemainingBytes() const
static wxString ReadString(const std::map< wxString, wxString > &aProps, const wxString &aKey, const wxString &aDefault)
std::map< uint32_t, wxString > ReadWideStringTable()
std::map< wxString, wxString > ReadProperties(std::function< std::map< wxString, wxString >(const std::string &)> handleBinaryData=[](const std::string &) { return std::map< wxString, wxString >();})
size_t ReadAndSetSubrecordLength()
void ParseFileHeader(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
PROGRESS_REPORTER * m_progressReporter
optional; may be nullptr
void HelperSetZoneLayers(ZONE *aZone, const ALTIUM_LAYER aAltiumLayer)
void ParseShapeBasedRegions6Data(const ALTIUM_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 HelperParseDimensions6Leader(const ADIMENSION6 &aElem)
std::vector< FOOTPRINT * > m_components
const ARULE6 * GetRuleDefault(ALTIUM_RULE_KIND aKind) const
void HelperParsePad6NonCopper(const APAD6 &aElem, PCB_LAYER_ID aLayer, PCB_SHAPE *aShape)
std::vector< PCB_LAYER_ID > GetKicadLayersToIterate(ALTIUM_LAYER aAltiumLayer) const
void ParseRegions6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ParseBoard6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ParseComponentsBodies6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
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 ParseFills6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void Parse(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const std::map< ALTIUM_PCB_DIR, std::string > &aFileMapping)
void ParseBoardRegionsData(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
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
ALTIUM_PCB(BOARD *aBoard, PROGRESS_REPORTER *aProgressReporter)
unsigned m_totalCount
for progress reporting
void HelperPcpShapeAsBoardKeepoutRegion(const PCB_SHAPE &aShape, const ALTIUM_LAYER aAltiumLayer, const uint8_t aKeepoutRestrictions)
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 ConvertFills6ToFootprintItem(FOOTPRINT *aFootprint, const AFILL6 &aElem, const bool aIsBoardImport)
void ConvertShapeBasedRegions6ToBoardItem(const AREGION6 &aElem)
void HelperCreateBoardOutline(const std::vector< ALTIUM_VERTICE > &aVertices)
void ParseVias6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
std::map< ALTIUM_RULE_KIND, std::vector< ARULE6 > > m_rules
void ParseClasses6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void HelperParseDimensions6Linear(const ADIMENSION6 &aElem)
std::map< uint32_t, wxString > m_unicodeStrings
void ConvertTexts6ToBoardItem(const ATEXT6 &aElem)
FOOTPRINT * ParseFootprint(ALTIUM_COMPOUND_FILE &altiumLibFile, const wxString &aFootprintName)
void ParseArcs6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void HelperParseDimensions6Center(const ADIMENSION6 &aElem)
void HelperParseDimensions6Radial(const ADIMENSION6 &aElem)
void HelperSetZoneKeepoutRestrictions(ZONE *aZone, const uint8_t aKeepoutRestrictions)
void ParsePads6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ParseWideStrings6Data(const ALTIUM_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)
void ParseComponents6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
int GetNetCode(uint16_t aId) const
void ConvertPads6ToFootprintItemOnNonCopper(FOOTPRINT *aFootprint, const APAD6 &aElem)
void ConvertTexts6ToFootprintItem(FOOTPRINT *aFootprint, const ATEXT6 &aElem)
unsigned m_lastProgressCount
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)
std::vector< ZONE * > m_polygons
std::map< wxString, wxString > m_models
void ConvertArcs6ToPcbShape(const AARC6 &aElem, PCB_SHAPE *aShape)
void ConvertTracks6ToBoardItemOnLayer(const ATRACK6 &aElem, PCB_LAYER_ID aLayer)
void ConvertFills6ToBoardItem(const AFILL6 &aElem)
void ParseModelsData(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry, const std::vector< std::string > &aRootDir)
void ParseRules6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
FOOTPRINT * HelperGetFootprint(uint16_t aComponent) const
PCB_LAYER_ID GetKicadLayer(ALTIUM_LAYER aAltiumLayer) const
void ConvertTracks6ToFootprintItemOnLayer(FOOTPRINT *aFootprint, const ATRACK6 &aElem, PCB_LAYER_ID aLayer)
void ParseTexts6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ParsePolygons6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ConvertArcs6ToBoardItemOnLayer(const AARC6 &aElem, PCB_LAYER_ID aLayer)
std::map< ALTIUM_RECORD, std::multimap< int, const AEXTENDED_PRIMITIVE_INFORMATION > > m_extendedPrimitiveInformationMaps
void ConvertTexts6ToEdaTextSettings(const ATEXT6 &aElem, EDA_TEXT *aEdaText)
void ParseTracks6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ConvertPads6ToBoardItemOnNonCopper(const APAD6 &aElem)
void ParseNets6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ParseExtendedPrimitiveInformationData(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ParseDimensions6Data(const ALTIUM_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
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
Container for design settings for a BOARD object.
std::shared_ptr< NET_SETTINGS > m_NetSettings
void SetGridOrigin(const VECTOR2I &aOrigin)
const VECTOR2I & GetGridOrigin()
const VECTOR2I & GetAuxOrigin()
void SetAuxOrigin(const VECTOR2I &aOrigin)
int m_SolderMaskExpansion
BOARD_STACKUP & GetStackupDescriptor()
int GetLineThickness(PCB_LAYER_ID aLayer) const
Return the default graphic segment thickness from the layer class for the given layer.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual void SetLocked(bool aLocked)
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Manage layers needed to make a physical board.
void RemoveAll()
Delete all items in list and clear the list.
const std::vector< BOARD_STACKUP_ITEM * > & GetList() const
void BuildDefaultStackupList(const BOARD_DESIGN_SETTINGS *aSettings, int aActiveCopperLayersCount=0)
Create a default stackup, according to the current BOARD_DESIGN_SETTINGS settings.
Information pertinent to a Pcbnew printed circuit board.
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
const BOX2I GetBoardEdgesBoundingBox() const
Return the board bounding box calculated using exclusively the board edges (graphics on Edge....
const PAGE_INFO & GetPageSettings() const
bool IsLayerEnabled(PCB_LAYER_ID aLayer) const
A proxy function that calls the correspondent function in m_BoardSettings tests whether a given layer...
bool SetLayerName(PCB_LAYER_ID aLayer, const wxString &aLayerName)
Changes the name of the layer given by aLayer.
void Move(const VECTOR2I &aMoveVector) override
Move this object.
bool m_LegacyNetclassesLoaded
True if netclasses were loaded from the file.
void SetCopperLayerCount(int aCount)
const wxString & GetFileName() const
bool SetLayerType(PCB_LAYER_ID aLayer, LAYER_T aLayerType)
Change the type of the layer given by aLayer.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
const Vec GetCenter() const
coord_type GetHeight() const
coord_type GetWidth() const
bool Contains(const Vec &aPoint) const
bool IsHorizontal() const
EDA_ANGLE GetArcAngle() const
void SetCenter(const VECTOR2I &aCenter)
void SetFilled(bool aFlag)
void SetPolyShape(const SHAPE_POLY_SET &aShape)
void SetStart(const VECTOR2I &aStart)
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
void SetShape(SHAPE_T aShape)
void SetEnd(const VECTOR2I &aEnd)
void SetArcGeometry(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Set the three controlling points for an arc.
void SetArcAngleAndEnd(const EDA_ANGLE &aAngle, bool aCheckNegativeAngle=false)
Set the end point from the angle center and start.
void SetPolyPoints(const std::vector< VECTOR2I > &aPoints)
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
BOX2I GetTextBox(int aLine=-1, bool aInvertY=false) const
Useful in multiline texts to calculate the full text or a line area (for zones filling,...
const VECTOR2I & GetTextPos() const
void SetTextSize(VECTOR2I aNewSize)
void SetTextPos(const VECTOR2I &aPoint)
void SetMirrored(bool isMirrored)
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
virtual void SetVisible(bool aVisible)
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
void SetKeepUpright(bool aKeepUpright)
virtual void SetText(const wxString &aText)
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
int GetTextThickness() const
void SetItalic(bool aItalic)
void SetFont(KIFONT::FONT *aFont)
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
VECTOR3D m_Offset
3D model offset (mm)
VECTOR3D m_Rotation
3D model rotation (degrees)
wxString m_Filename
The 3D shape filename in 3D library.
FONT is an abstract base class for both outline and stroke fonts.
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false)
const wxString & GetName() const
virtual bool IsOutline() const
A logical library item identifier and consists of various portions much like a URI.
LSET is a set of PCB_LAYER_IDs.
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Handle the data for a net.
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
static LSET PTHMask()
layer set for a through hole pad
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
static LSET SMDMask()
layer set for a SMD pad on Front layer
int GetHeightIU(double aIUScale) const
Gets the page height in IU.
int GetWidthIU(double aIUScale) const
Gets the page width in IU.
virtual VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
void SetUnitsFormat(const DIM_UNITS_FORMAT aFormat)
void SetUnits(EDA_UNITS aUnits)
void SetPrefix(const wxString &aPrefix)
void SetSuffix(const wxString &aSuffix)
void SetLineThickness(int aWidth)
virtual void SetEnd(const VECTOR2I &aPoint)
void SetPrecision(DIM_PRECISION aPrecision)
virtual void SetStart(const VECTOR2I &aPoint)
void SetKeepTextAligned(bool aKeepAligned)
For better understanding of the points that make a dimension:
void SetHeight(int aHeight)
Set the distance from the feature points to the crossbar line.
Mark the center of a circle or arc with a cross shape.
A radial dimension indicates either the radius or diameter of an arc or circle.
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
virtual void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void SetStroke(const STROKE_PARAMS &aStroke) override
VECTOR2I GetPosition() const override
virtual void SetPosition(const VECTOR2I &aPos) override
void SetWidth(int aWidth)
void SetEnd(const VECTOR2I &aEnd)
void SetStart(const VECTOR2I &aStart)
A progress reporter interface for use in multi-threaded environments.
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void Report(const wxString &aMessage)=0
Display aMessage in the progress bar dialog.
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).
OPT_VECTOR2I Intersect(const SEG &aSeg, bool aIgnoreEndpoints=false, bool aLines=false) const
Compute intersection point of segment (this) with segment aSeg.
const VECTOR2I & GetArcMid() const
const VECTOR2I & GetP1() const
const VECTOR2I & GetP0() const
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const SHAPE_ARC & Arc(size_t aArc) const
int NextShape(int aPointIndex, bool aForwards=true) const
Return the vertex index of the next shape in the chain, or -1 if aPointIndex is the last shape.
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
int PointCount() const
Return the number of points (vertices) in this line chain.
ssize_t ArcIndex(size_t aSegment) const
Return the arc index for the given segment index.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
bool IsArcStart(size_t aIndex) const
SEG Segment(int aIndex)
Return a copy of the aIndex-th segment in the line chain.
Represent a set of closed polygons.
void Fracture(POLYGON_MODE aFastMode)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
void BooleanAdd(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset union For aFastMode meaning, see function booleanOp.
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Adds a new hole to the given outline (default: last) and returns its index.
void Move(const VECTOR2I &aVector) override
Simple container to manage line stroke parameters.
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Handle a list of polygons defining a copper zone.
void SetHatchThickness(int aThickness)
void SetNeedRefill(bool aNeedRefill)
void SetDoNotAllowPads(bool aEnable)
void SetPosition(const VECTOR2I &aPos) override
void SetBorderDisplayStyle(ZONE_BORDER_DISPLAY_STYLE aBorderHatchStyle, int aBorderHatchPitch, bool aRebuilBorderdHatch)
Set all hatch parameters for the zone.
const BOX2I GetBoundingBox() const override
void SetMinThickness(int aMinThickness)
void SetHatchOrientation(const EDA_ANGLE &aStep)
void SetDoNotAllowCopperPour(bool aEnable)
void SetThermalReliefSpokeWidth(int aThermalReliefSpokeWidth)
SHAPE_POLY_SET * Outline()
SHAPE_POLY_SET * GetFill(PCB_LAYER_ID aLayer)
void SetIsRuleArea(bool aEnable)
void SetDoNotAllowTracks(bool aEnable)
void SetFilledPolysList(PCB_LAYER_ID aLayer, const SHAPE_POLY_SET &aPolysList)
Set the list of filled polygons.
int GetMinThickness() const
void SetIsFilled(bool isFilled)
void SetFillMode(ZONE_FILL_MODE aFillMode)
bool HasFilledPolysForLayer(PCB_LAYER_ID aLayer) const
void SetDoNotAllowVias(bool aEnable)
void SetLocalClearance(int aClearance)
void SetThermalReliefGap(int aThermalReliefGap)
void SetLayerSet(LSET aLayerSet) override
void SetDoNotAllowFootprints(bool aEnable)
void SetAssignedPriority(unsigned aPriority)
void SetPadConnection(ZONE_CONNECTION aPadConnection)
void SetHatchGap(int aStep)
static int GetDefaultHatchPitch()
static constexpr EDA_ANGLE & ANGLE_45
#define THROW_IO_ERROR(msg)
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
LSET FlipLayerMask(LSET aMask, int aCopperLayersCount)
Calculate the mask layer when flipping a footprint.
#define PROJECT_VAR_NAME
A variable name whose value holds the current project directory.
std::optional< VECTOR2I > OPT_VECTOR2I
wxString NotSpecifiedPrm()
uint8_t keepoutrestrictions
wxString dielectricmaterial
std::vector< ABOARD6_LAYER_STACKUP > stackup
std::vector< ALTIUM_VERTICE > board_vertices
std::vector< wxString > names
wxString sourcefootprintlibrary
wxString sourcedesignator
std::vector< VECTOR2I > textPoint
ALTIUM_DIMENSION_KIND kind
std::vector< VECTOR2I > referencePoint
uint8_t keepoutrestrictions
int32_t soldermaskexpansionmanual
std::unique_ptr< APAD6_SIZE_AND_SHAPE > sizeAndShape
ALTIUM_PAD_SHAPE topshape
ALTIUM_MODE pastemaskexpansionmode
ALTIUM_MODE soldermaskexpansionmode
int32_t pastemaskexpansionmanual
std::vector< ALTIUM_VERTICE > vertices
ALTIUM_POLYGON_HATCHSTYLE hatchstyle
uint8_t keepoutrestrictions
std::vector< ALTIUM_VERTICE > outline
std::vector< std::vector< ALTIUM_VERTICE > > holes
ALTIUM_CONNECT_STYLE polygonconnectStyle
int planeclearanceClearance
int32_t polygonconnectReliefconductorwidth
int32_t polygonconnectAirgapwidth
ALTIUM_TEXT_TYPE fonttype
uint8_t keepoutrestrictions
constexpr double IUTomm(int iu) const
constexpr int mmToIU(double mm) const
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
double DEG2RAD(double deg)
double GetLineLength(const VECTOR2I &aPointA, const VECTOR2I &aPointB)
Return the length of a line segment defined by aPointA and aPointB.
double EuclideanNorm(const VECTOR2I &vector)
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".