48#include <compoundfilereader.h>
55#include <wx/docview.h>
57#include <wx/mstream.h>
58#include <wx/wfstream.h>
59#include <wx/zstream.h>
61#include <magic_enum.hpp>
83 THROW_IO_ERROR( wxString::Format( wxT(
"Component creator tries to access component id %u "
84 "of %u existing components" ),
93 const std::vector<ALTIUM_VERTICE>& aVertices )
102 double startradiant =
DEG2RAD( vertex.startangle );
103 double endradiant =
DEG2RAD( vertex.endangle );
105 -
KiROUND( std::sin( startradiant ) * vertex.radius ) );
108 -
KiROUND( std::sin( endradiant ) * vertex.radius ) );
110 VECTOR2I arcStart = vertex.center + arcStartOffset;
111 VECTOR2I arcEnd = vertex.center + arcEndOffset;
116 if( arcStart.
Distance( vertex.position )
117 < arcEnd.
Distance( vertex.position ) )
144 aLine.
Append( vertex.position );
154 auto override =
m_layermap.find( aAltiumLayer );
158 return override->second;
161 switch( aAltiumLayer )
260 static std::set<ALTIUM_LAYER> altiumLayersWithWarning;
265 std::vector<PCB_LAYER_ID> layers;
266 layers.reserve( layerCount );
271 layers.emplace_back( layer );
282 wxString layerName = it !=
m_layerNames.end() ? it->second : wxString::Format( wxT(
"(%d)" ),
283 (
int) aAltiumLayer );
285 if(
m_reporter && altiumLayersWithWarning.insert( aAltiumLayer ).second )
288 _(
"Altium layer %s has no KiCad equivalent. It has been moved to KiCad "
304 const wxString& aLibrary,
const wxString& aFootprintName )
324 const unsigned PROGRESS_DELTA = 250;
342 const std::map<ALTIUM_PCB_DIR, std::string>& aFileMapping )
345 const std::vector<std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>> parserOrder = {
457 for(
const std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>& cur : parserOrder )
462 std::tie( isRequired,
directory, fp ) = cur;
467 const auto& mappedDirectory = aFileMapping.find(
directory );
469 if( mappedDirectory == aFileMapping.end() )
472 const std::vector<std::string> mappedFile{ mappedDirectory->second,
"Header" };
473 const CFB::COMPOUND_FILE_ENTRY* file = altiumPcbFile.
FindStream( mappedFile );
475 if( file ==
nullptr )
479 uint32_t numOfRecords = reader.
Read<uint32_t>();
485 m_reporter->Report( wxString::Format(
_(
"'%s' was not parsed correctly." ),
499 m_reporter->Report( wxString::Format(
_(
"'%s' was not fully parsed." ),
511 if( boardDirectory != aFileMapping.end() )
513 std::vector<std::string> mappedFile{ boardDirectory->second,
"Data" };
515 const CFB::COMPOUND_FILE_ENTRY* file = altiumPcbFile.
FindStream( mappedFile );
520 "This file does not appear to be in a valid PCB Binary Version 6.0 format. In "
522 "make sure to save as \"PCB Binary Files (*.PcbDoc)\"." ) );
527 for(
const std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>& cur : parserOrder )
532 std::tie( isRequired,
directory, fp ) = cur;
534 const auto& mappedDirectory = aFileMapping.find(
directory );
536 if( mappedDirectory == aFileMapping.end() )
538 wxASSERT_MSG( !isRequired, wxString::Format( wxT(
"Altium Directory of kind %d was "
539 "expected, but no mapping is "
540 "present in the code" ),
545 std::vector<std::string> mappedFile{ mappedDirectory->second };
548 mappedFile.emplace_back(
"Data" );
550 const CFB::COMPOUND_FILE_ENTRY* file = altiumPcbFile.
FindStream( mappedFile );
552 if( file !=
nullptr )
554 fp( altiumPcbFile, file );
556 else if( isRequired )
560 m_reporter->Report( wxString::Format(
_(
"File not found: '%s' for directory '%s'." ),
575 if( zone->GetAssignedPriority() == 1000 )
586 zone->SetAssignedPriority( priority >= 0 ? priority : 0 );
590 for( std::pair<const ALTIUM_LAYER, ZONE*>& zone :
m_outer_plane )
591 zone.second->SetAssignedPriority( 0 );
601 if( !zone->HasFilledPolysForLayer( layer ) )
604 zone->GetFilledPolysList( layer )->Fracture();
642 if( arc->
GetCenter() == dim->GetPosition() )
651 VECTOR2I radialLine = dim->GetEnd() - dim->GetStart();
656 radialLine = radialLine.
Resize( std::max(
radius, 2 ) );
657 dim->SetEnd( dim->GetStart() + (
VECTOR2I) radialLine );
658 dim->SetLeaderLength( totalLength -
radius );
668 int desired_x = ( w - bbbox.
GetWidth() ) / 2;
669 int desired_y = ( h - bbbox.
GetHeight() ) / 2;
671 VECTOR2I movementVector( desired_x - bbbox.
GetX(), desired_y - bbbox.
GetY() );
672 m_board->Move( movementVector );
683 const wxString& aFootprintName )
685 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
703 std::tuple<wxString, const CFB::COMPOUND_FILE_ENTRY*> ret =
706 wxString fpDirName = std::get<0>( ret );
707 const CFB::COMPOUND_FILE_ENTRY* footprintStream = std::get<1>( ret );
709 if( fpDirName.IsEmpty() )
712 wxString::Format(
_(
"Footprint directory not found: '%s'." ), aFootprintName ) );
715 const std::vector<std::string> streamName{ fpDirName.ToStdString(),
"Data" };
716 const CFB::COMPOUND_FILE_ENTRY* footprintData = altiumLibFile.
FindStream( footprintStream, {
"Data" } );
718 if( footprintData ==
nullptr )
731 footprint->SetFPID( fpID );
733 const std::vector<std::string> parametersStreamName{ fpDirName.ToStdString(),
735 const CFB::COMPOUND_FILE_ENTRY* parametersData =
736 altiumLibFile.
FindStream( footprintStream, {
"Parameters" } );
738 if( parametersData !=
nullptr )
741 std::map<wxString, wxString> parameterProperties = parametersReader.
ReadProperties();
743 wxT(
"DESCRIPTION" ), wxT(
"" ) );
744 footprint->SetLibDescription( description );
750 m_reporter->Report( wxString::Format(
_(
"File not found: '%s'." ),
755 footprint->SetLibDescription( wxT(
"" ) );
758 const std::vector<std::string> extendedPrimitiveInformationStreamName{
759 "ExtendedPrimitiveInformation",
"Data"
761 const CFB::COMPOUND_FILE_ENTRY* extendedPrimitiveInformationData =
762 altiumLibFile.
FindStream( footprintStream, extendedPrimitiveInformationStreamName );
764 if( extendedPrimitiveInformationData !=
nullptr )
767 footprint->SetReference( wxT(
"REF**" ) );
768 footprint->SetValue( aFootprintName );
769 footprint->Reference().SetVisible(
true );
770 footprint->Value().SetVisible(
true );
773 const int defaultTextThickness(
pcbIUScale.mmToIU( 0.15 ) );
775 for(
PCB_FIELD* field : footprint->GetFields() )
777 field->SetTextSize( defaultTextSize );
778 field->SetTextThickness( defaultTextThickness );
836 THROW_IO_ERROR( wxString::Format(
_(
"Record of unknown type: '%d'." ), recordtype ) );
842 for(
bool changes =
true; changes; )
847 [&changes](
PAD* aPad1,
PAD* aPad2 )
849 if( !( aPad1->GetNumber().IsEmpty() ^ aPad2->GetNumber().IsEmpty() ) )
852 for( PCB_LAYER_ID layer : aPad1->GetLayerSet() )
854 std::shared_ptr<SHAPE> shape1 = aPad1->GetEffectiveShape( layer );
855 std::shared_ptr<SHAPE> shape2 = aPad2->GetEffectiveShape( layer );
857 if( shape1->Collide( shape2.get() ) )
859 if( aPad1->GetNumber().IsEmpty() )
860 aPad1->SetNumber( aPad2->GetNumber() );
862 aPad2->SetNumber( aPad1->GetNumber() );
871 footprint->AutoPositionFields();
873 if( parser.HasParsingError() )
875 THROW_IO_ERROR( wxString::Format( wxT(
"%s stream was not parsed correctly" ),
879 if( parser.GetRemainingBytes() != 0 )
881 THROW_IO_ERROR( wxString::Format( wxT(
"%s stream is not fully parsed" ),
885 return footprint.release();
896 THROW_IO_ERROR( wxString::Format( wxT(
"Netcode with id %d does not exist. Only %d nets "
908 const auto rules =
m_rules.find( aKind );
913 for(
const ARULE6& rule : rules->second )
915 if( rule.
name == aName )
924 const auto rules =
m_rules.find( aKind );
929 for(
const ARULE6& rule : rules->second )
939 const CFB::COMPOUND_FILE_ENTRY* aEntry )
957 const CFB::COMPOUND_FILE_ENTRY* aEntry )
974 THROW_IO_ERROR( wxT(
"ExtendedPrimitiveInformation stream is not fully parsed" ) );
979 const CFB::COMPOUND_FILE_ENTRY* aEntry )
996 size_t layercount = 0;
999 while( layerid < elem.
stackup.size() && layerid != 0 )
1001 layerid = elem.
stackup[ layerid - 1 ].nextId;
1005 size_t kicadLayercount = ( layercount % 2 == 0 ) ? layercount : layercount + 1;
1006 m_board->SetCopperLayerCount( kicadLayercount );
1015 auto it = stackup.
GetList().begin();
1024 altiumLayerId < elem.
stackup.size() && altiumLayerId != 0;
1025 altiumLayerId = elem.
stackup[altiumLayerId - 1].nextId )
1031 if( layer.
nextId == 0 && layercount != kicadLayercount )
1033 m_board->SetLayerName( ( *it )->GetBrdLayerId(), wxT(
"[unused]" ) );
1036 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
1038 ( *it )->SetThickness( 0 );
1043 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
1045 ( *it )->SetThickness( 0, 0 );
1046 ( *it )->SetThicknessLocked(
true, 0 );
1054 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
1068 if( klayer ==
B_Cu )
1071 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected id while parsing last stackup layer" ) );
1081 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
1130 if( aStackup.size() == 0 )
1133 std::vector<INPUT_LAYER_DESC> inputLayers;
1134 std::map<wxString, ALTIUM_LAYER> altiumLayerNameMap;
1141 [&](
size_t ii ) ->
size_t
1147 return curLayer.
nextId - 1;
1152 for(
size_t ii = 0; ii < aStackup.size(); ii =
next( ii ) )
1154 curLayer = aStackup[ii];
1177 inputLayers.push_back( iLdesc );
1178 altiumLayerNameMap.insert( { curLayer.
name, layer_num } );
1182 if( inputLayers.size() == 0 )
1189 for( std::pair<wxString, PCB_LAYER_ID> layerPair : reMappedLayers )
1193 wxFAIL_MSG( wxT(
"Unexpected Layer ID" ) );
1197 ALTIUM_LAYER altiumID = altiumLayerNameMap.at( layerPair.first );
1198 m_layermap.insert_or_assign( altiumID, layerPair.second );
1199 enabledLayers |=
LSET( { layerPair.second } );
1202 m_board->SetEnabledLayers( enabledLayers );
1203 m_board->SetVisibleLayers( enabledLayers );
1220 int nextShape = lineChain.
NextShape( i );
1221 bool isLastShape = nextShape < 0;
1225 shape->SetStroke( stroke );
1237 shape->SetStroke( stroke );
1239 shape->SetStart( seg.
A );
1240 shape->SetEnd( seg.
B );
1249 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1263 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( elem.
name );
1265 for(
const wxString&
name : elem.
names )
1267 m_board->GetDesignSettings().m_NetSettings->SetNetclassPatternAssignment(
1268 name, nc->GetName() );
1271 if(
m_board->GetDesignSettings().m_NetSettings->HasNetclass( nc->GetName() ) )
1278 msg.Printf(
_(
"More than one Altium netclass with name '%s' found. "
1279 "Only the first one will be imported." ), elem.
name );
1285 m_board->GetDesignSettings().m_NetSettings->SetNetclass( nc->GetName(), nc );
1293 m_board->m_LegacyNetclassesLoaded =
true;
1298 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1305 uint16_t componentId = 0;
1312 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
1322 footprint->SetFPID( fpID );
1324 footprint->SetPosition( elem.
position );
1325 footprint->SetOrientationDegrees( elem.
rotation );
1331 if( reference.find_first_not_of(
"0123456789" ) == wxString::npos )
1332 reference.Prepend( wxT(
"UNK" ) );
1334 footprint->SetReference( reference );
1339 path.push_back( pathid );
1340 path.push_back(
id );
1342 footprint->SetPath(
path );
1346 footprint->SetLocked( elem.
locked );
1347 footprint->Reference().SetVisible( elem.
nameon );
1348 footprint->Value().SetVisible( elem.
commenton );
1358 THROW_IO_ERROR( wxT(
"Components6 stream is not fully parsed" ) );
1365 while( Angle < aMin )
1368 while( Angle >= aMax )
1391 m_reporter->Report( wxString::Format( wxT(
"Model %s not found for footprint %s" ),
1404 if( file->
name.IsEmpty() )
1405 file->
name = model->first.name;
1408 std::vector<char> decompressedData;
1409 wxMemoryInputStream compressedStream( model->second.data(), model->second.size() );
1410 wxZlibInputStream zlibStream( compressedStream );
1414 decompressedData.resize( model->second.size() * 6 );
1417 while( !zlibStream.Eof() )
1419 zlibStream.Read( decompressedData.data() + offset, decompressedData.size() - offset );
1420 size_t bytesRead = zlibStream.LastRead();
1425 offset += bytesRead;
1427 if( offset >= decompressedData.size() )
1428 decompressedData.resize( 2 * decompressedData.size() );
1431 decompressedData.resize( offset );
1452 orientation = -orientation;
1459 modelRotation.
x += 180;
1460 modelRotation.
z = -modelRotation.
z;
1474 aFootprint->
Models().push_back( modelSettings );
1479 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1493 if( skipComponentBodies )
1501 THROW_IO_ERROR( wxString::Format( wxT(
"ComponentsBodies6 stream tries to access "
1502 "component id %d of %zu existing components" ),
1517 msg.Printf( wxT(
"ComponentsBodies6 stream tries to access model id %s which does "
1518 "not exist" ), elem.
modelId );
1531 wxMemoryInputStream compressedStream( modelData.
m_data.data(), modelData.
m_data.size() );
1532 wxZlibInputStream zlibStream( compressedStream );
1533 wxMemoryOutputStream decompressedStream;
1535 zlibStream.Read( decompressedStream );
1558 orientation = -orientation;
1581 footprint->
Models().push_back( modelSettings );
1585 THROW_IO_ERROR( wxT(
"ComponentsBodies6 stream is not fully parsed" ) );
1592 THROW_IO_ERROR( wxT(
"Incorrect number of reference points for linear dimension object" ) );
1601 _(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1602 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer ),
1615 dimension->SetLayer( klayer );
1616 dimension->SetStart( referencePoint0 );
1618 if( referencePoint0 != aElem.
xy1 )
1630 VECTOR2I referenceDiff = referencePoint1 - referencePoint0;
1632 SEG segm1( referencePoint0, referencePoint0 + directionNormalVector );
1633 SEG segm2( referencePoint1, referencePoint1 + direction );
1637 THROW_IO_ERROR( wxT(
"Invalid dimension. This should never happen." ) );
1639 dimension->SetEnd( *intersection );
1643 if( direction.
Cross( referenceDiff ) > 0 )
1646 dimension->SetHeight( height );
1650 dimension->SetEnd( referencePoint1 );
1653 dimension->SetLineThickness( aElem.
linewidth );
1659 int dist = ( dimension->GetEnd() - dimension->GetStart() ).EuclideanNorm();
1661 if( dist < 3 * dimension->GetArrowLength() )
1665 wxRegEx units( wxS(
"(mm)|(in)|(mils)|(thou)|(')|(\")" ), wxRE_ADVANCED );
1677 dimension->Text().SetBold( aElem.
textbold );
1680 dimension->SetTextThickness( dimension->GetTextThickness() *
BOLD_FACTOR );
1699 THROW_IO_ERROR( wxT(
"Not enough reference points for radial dimension object" ) );
1708 _(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1709 "It has been moved to KiCad layer Eco1_User." ),
1719 std::unique_ptr<PCB_DIM_RADIAL> dimension = std::make_unique<PCB_DIM_RADIAL>(
m_board );
1722 dimension->SetLayer( klayer );
1723 dimension->SetStart( referencePoint0 );
1724 dimension->SetEnd( aElem.
xy1 );
1725 dimension->SetLineThickness( aElem.
linewidth );
1726 dimension->SetKeepTextAligned(
false );
1747 m_reporter->Report( wxT(
"No text position present for leader dimension object" ),
1754 dimension->SetTextPos( aElem.
textPoint.at( 0 ) );
1760 dimension->SetBold( aElem.
textbold );
1763 dimension->SetTextThickness( dimension->GetTextThickness() *
BOLD_FACTOR );
1771 int yAdjust = dimension->GetTextBox(
nullptr ).GetCenter().y - dimension->GetTextPos().y;
1772 dimension->SetTextPos( dimension->GetTextPos() +
VECTOR2I( 0, yAdjust + aElem.
textgap ) );
1789 msg.Printf(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1790 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer );
1807 shape->SetLayer( klayer );
1809 shape->SetStart( last );
1821 if( dirVec.
x != 0 || dirVec.
y != 0 )
1830 shape1->SetLayer( klayer );
1832 shape1->SetStart( referencePoint0 );
1833 shape1->SetEnd( referencePoint0 + arrVec );
1843 shape2->SetLayer( klayer );
1845 shape2->SetStart( referencePoint0 );
1846 shape2->SetEnd( referencePoint0 + arrVec );
1858 m_reporter->Report( wxT(
"No text position present for leader dimension object" ),
1865 std::unique_ptr<PCB_TEXT>
text = std::make_unique<PCB_TEXT>(
m_board );
1869 text->SetLayer( klayer );
1888 msg.Printf(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1889 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer );
1900 shape->SetLayer( klayer );
1919 msg.Printf(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1920 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer );
1930 std::unique_ptr<PCB_DIM_CENTER> dimension = std::make_unique<PCB_DIM_CENTER>(
m_board );
1932 dimension->SetLayer( klayer );
1933 dimension->SetLineThickness( aElem.
linewidth );
1934 dimension->SetStart( aElem.
xy1 );
1935 dimension->SetEnd( aElem.
xy1 + vec );
1942 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1962 m_reporter->Report( wxString::Format(
_(
"Ignored Angular dimension (not yet supported)." ) ),
1975 m_reporter->Report( wxString::Format(
_(
"Ignored Datum dimension (not yet supported)." ) ),
1983 m_reporter->Report( wxString::Format(
_(
"Ignored Baseline dimension (not yet supported)." ) ),
1993 m_reporter->Report( wxString::Format(
_(
"Ignored Linear dimension (not yet supported)." ) ),
2000 m_reporter->Report( wxString::Format(
_(
"Ignored Radial dimension (not yet supported)." ) ),
2008 msg.Printf(
_(
"Ignored dimension of kind %d (not yet supported)." ), elem.
kind );
2016 THROW_IO_ERROR( wxT(
"Dimensions6 stream is not fully parsed" ) );
2021 const CFB::COMPOUND_FILE_ENTRY* aEntry,
2022 const std::vector<std::string>& aRootDir )
2033 wxString invalidChars = wxFileName::GetForbiddenChars();
2040 std::vector<std::string> stepPath = aRootDir;
2041 stepPath.emplace_back( std::to_string( idx ) );
2043 bool validName = !elem.
name.IsEmpty() && elem.
name.IsAscii()
2044 && wxString::npos == elem.
name.find_first_of( invalidChars );
2045 wxString storageName = validName ? elem.
name : wxString::Format( wxT(
"model_%d" ), idx );
2049 const CFB::COMPOUND_FILE_ENTRY* stepEntry = aAltiumPcbFile.
FindStream( stepPath );
2051 if( stepEntry ==
nullptr )
2056 msg.Printf(
_(
"File not found: '%s'. 3D-model not imported." ),
FormatPath( stepPath ) );
2063 size_t stepSize =
static_cast<size_t>( stepEntry->size );
2064 std::vector<char> stepContent( stepSize );
2072 std::move( stepContent ) ) ) );
2076 std::map<wxString, std::vector<wxString>> nameIdMap;
2079 nameIdMap[data.m_modelname].push_back(
id );
2081 for(
auto& [
name, ids] : nameIdMap )
2083 for(
size_t i = 1; i < ids.size(); i++ )
2085 const wxString&
id = ids[i];
2092 wxString modelName = modelTuple->second.m_modelname;
2094 if( modelName.Contains(
"." ) )
2097 wxString baseName = modelName.BeforeLast(
'.', &ext );
2099 modelTuple->second.m_modelname = baseName +
'_' + std::to_string( i ) +
'.' + ext;
2103 modelTuple->second.m_modelname = modelName +
'_' + std::to_string( i );
2114 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2126 ANET6 elem( reader );
2140 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2183 msg.Printf(
_(
"Polygon outline count is %d, expected 1." ), outline.
OutlineCount() );
2191 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board);
2197 zone->SetPosition( elem.
vertices.at( 0 ).position );
2198 zone->SetLocked( elem.
locked );
2200 zone->Outline()->AddOutline( outline.
Outline( 0 ) );
2207 int planeLayers = 0;
2208 int signalLayers = 0;
2222 if( planeLayers > 0 && planeClearanceRule )
2225 if( signalLayers > 0 && zoneClearanceRule )
2233 if( polygonConnectRule !=
nullptr )
2252 zone->SetThermalReliefSpokeWidth(
2263 zone->SetAssignedPriority( 1 );
2268 || zone->GetBoundingBox().Contains( outer_plane->second->GetBoundingBox() ) )
2283 const BOX2I& bbox = zone->GetBoundingBox();
2292 zone->SetHatchOrientation(
ANGLE_45 );
2307 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2325 std::sort( val.second.begin(), val.second.end(),
2328 return lhs.priority < rhs.priority;
2341 if( trackWidthRule )
2343 m_board->GetDesignSettings().m_TrackMinWidth = trackWidthRule->
minLimit;
2347 if( routingViasRule )
2349 m_board->GetDesignSettings().m_ViasMinSize = routingViasRule->
minWidth;
2358 if( holeToHoleRule )
2364 if( soldermaskRule )
2375 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2391 THROW_IO_ERROR( wxT(
"BoardRegions stream is not fully parsed" ) );
2395 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2403 for(
int primitiveIndex = 0; reader.
GetRemainingBytes() >= 4; primitiveIndex++ )
2422 THROW_IO_ERROR(
"ShapeBasedRegions6 stream is not fully parsed" );
2446 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board );
2448 zone->SetIsRuleArea(
true );
2456 zone->SetDoNotAllowZoneFills(
true );
2457 zone->SetDoNotAllowVias(
false );
2458 zone->SetDoNotAllowTracks(
false );
2459 zone->SetDoNotAllowPads(
false );
2460 zone->SetDoNotAllowFootprints(
false );
2463 zone->SetPosition( aElem.
outline.at( 0 ).position );
2464 zone->Outline()->AddOutline( linechain );
2482 msg.Printf(
_(
"Dashed outline found on an Altium layer (%d) with no KiCad equivalent. "
2483 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer );
2504 shape->SetPolyShape( linechain );
2505 shape->SetFilled(
false );
2506 shape->SetLayer( klayer );
2528 msg.Printf(
_(
"Ignored polygon shape of kind %d (not yet supported)." ), aElem.
kind );
2537 const int aPrimitiveIndex )
2553 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aFootprint );
2555 zone->SetIsRuleArea(
true );
2563 zone->SetDoNotAllowZoneFills(
true );
2564 zone->SetDoNotAllowVias(
false );
2565 zone->SetDoNotAllowTracks(
false );
2566 zone->SetDoNotAllowPads(
false );
2567 zone->SetDoNotAllowFootprints(
false );
2570 zone->SetPosition( aElem.
outline.at( 0 ).position );
2571 zone->Outline()->AddOutline( linechain );
2605 msg.Printf(
_(
"Loading library '%s':\n"
2606 "Footprint %s contains a dashed outline on Altium layer (%d) with "
2607 "no KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
2619 msg.Printf(
_(
"Footprint %s contains a dashed outline on Altium layer (%d) with "
2620 "no KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
2642 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aFootprint,
SHAPE_T::POLY );
2644 shape->SetPolyShape( linechain );
2645 shape->SetFilled(
false );
2646 shape->SetLayer( klayer );
2662 msg.Printf(
_(
"Error loading library '%s':\n"
2663 "Footprint %s contains polygon shape of kind %d (not yet supported)." ),
2675 msg.Printf(
_(
"Footprint %s contains polygon shape of kind %d (not yet supported)." ),
2703 for(
const std::vector<ALTIUM_VERTICE>& hole : aElem.
holes )
2711 polySet.
AddHole( hole_linechain );
2716 shape->SetPolyShape( polySet );
2717 shape->SetFilled(
true );
2718 shape->SetLayer( aLayer );
2733 const int aPrimitiveIndex )
2750 for(
const std::vector<ALTIUM_VERTICE>& hole : aElem.
holes )
2758 polySet.
AddHole( hole_linechain );
2761 if( aLayer ==
F_Cu || aLayer ==
B_Cu )
2764 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
2767 padLayers.
set( aLayer );
2778 pad->SetPosition( anchorPos );
2781 shapePolys.
Move( -anchorPos );
2785 auto it = map.find( aPrimitiveIndex );
2787 if( it != map.end() )
2793 pad->SetLocalSolderPasteMargin(
info.pastemaskexpansionmanual );
2798 pad->SetLocalSolderMaskMargin(
info.soldermaskexpansionmanual );
2808 pad->SetLayerSet( padLayers );
2814 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aFootprint,
SHAPE_T::POLY );
2816 shape->SetPolyShape( polySet );
2817 shape->SetFilled(
true );
2818 shape->SetLayer( aLayer );
2827 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2843 THROW_IO_ERROR( wxString::Format(
"Region stream tries to access polygon id %d "
2844 "of %d existing polygons.",
2851 if( zone ==
nullptr )
2873 for(
const std::vector<ALTIUM_VERTICE>& hole : elem.
holes )
2880 hole_linechain.
Append( hole.at( 0 ).position );
2882 fill.
AddHole( hole_linechain );
2902 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2909 for(
int primitiveIndex = 0; reader.
GetRemainingBytes() >= 4; primitiveIndex++ )
2912 AARC6 elem( reader );
2963 THROW_IO_ERROR( wxString::Format(
"Tracks stream tries to access polygon id %u "
2964 "of %zu existing polygons.",
2970 if( zone ==
nullptr )
3018 for(
const auto& layerExpansionMask :
3021 int width = aElem.
width + ( layerExpansionMask.second * 2 );
3025 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>(
m_board );
3029 arc->SetLayer( layerExpansionMask.first );
3038 const int aPrimitiveIndex,
const bool aIsBoardImport )
3042 wxFAIL_MSG( wxString::Format(
"Altium: Unexpected footprint Arc with polygon id %d",
3075 for(
const auto& layerExpansionMask :
3078 int width = aElem.
width + ( layerExpansionMask.second * 2 );
3082 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>( aFootprint );
3086 arc->SetLayer( layerExpansionMask.first );
3118 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board, &shapeArc );
3120 arc->SetWidth( aElem.
width );
3121 arc->SetLayer( aLayer );
3129 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>(
m_board);
3133 arc->SetLayer( aLayer );
3143 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>( aFootprint );
3147 arc->SetLayer( aLayer );
3154 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3164 APAD6 elem( reader );
3193 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
3194 footprint->SetPosition( aElem.
position );
3205 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
3207 pad->SetNumber(
"" );
3218 pad->SetLayerSet(
LSET().AllCuMask() );
3245 pad->Padstack().FrontOuterLayers().has_solder_mask =
true;
3249 pad->Padstack().FrontOuterLayers().has_solder_mask =
false;
3255 pad->Padstack().BackOuterLayers().has_solder_mask =
true;
3259 pad->Padstack().BackOuterLayers().has_solder_mask =
false;
3264 pad->SetLocked(
true );
3294 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
3317 msg.Printf(
_(
"Error loading library '%s':\n"
3318 "Footprint %s pad %s is not marked as multilayer, but is a TH pad." ),
3330 msg.Printf(
_(
"Footprint %s pad %s is not marked as multilayer, but is a TH pad." ),
3350 wxFAIL_MSG( wxT(
"Round holes are handled before the switch" ) );
3359 msg.Printf(
_(
"Loading library '%s':\n"
3360 "Footprint %s pad %s has a square hole (not yet supported)." ),
3372 msg.Printf(
_(
"Footprint %s pad %s has a square hole (not yet supported)." ),
3407 msg.Printf(
_(
"Loading library '%s':\n"
3408 "Footprint %s pad %s has a hole-rotation of %d degrees. "
3409 "KiCad only supports 90 degree rotations." ),
3422 msg.Printf(
_(
"Footprint %s pad %s has a hole-rotation of %d degrees. "
3423 "KiCad only supports 90 degree rotations." ),
3442 msg.Printf(
_(
"Error loading library '%s':\n"
3443 "Footprint %s pad %s uses a hole of unknown kind %d." ),
3456 msg.Printf(
_(
"Footprint %s pad %s uses a hole of unknown kind %d." ),
3476 auto setCopperGeometry =
3521 msg.Printf(
_(
"Error loading library '%s':\n"
3522 "Footprint %s pad %s uses an unknown pad shape." ),
3534 msg.Printf(
_(
"Footprint %s pad %s uses an unknown pad shape." ),
3585 switch( aElem.
layer )
3603 pad->SetLayer( klayer );
3604 pad->SetLayerSet(
LSET( { klayer } ) );
3615 pad->SetLayerSet(
pad->GetLayerSet().reset(
F_Mask ) );
3618 pad->SetLayerSet(
pad->GetLayerSet().reset(
B_Mask ) );
3633 msg.Printf(
_(
"Non-copper pad %s found on an Altium layer (%d) with no KiCad "
3634 "equivalent. It has been moved to KiCad layer Eco1_User." ),
3642 std::unique_ptr<PCB_SHAPE>
pad = std::make_unique<PCB_SHAPE>(
m_board );
3661 msg.Printf(
_(
"Loading library '%s':\n"
3662 "Footprint %s non-copper pad %s found on an Altium layer (%d) with no "
3663 "KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
3676 msg.Printf(
_(
"Footprint %s non-copper pad %s found on an Altium layer (%d) with no "
3677 "KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
3688 std::unique_ptr<PCB_SHAPE>
pad = std::make_unique<PCB_SHAPE>( aFootprint );
3704 msg.Printf(
_(
"Non-copper pad %s is connected to a net, which is not supported." ),
3715 msg.Printf(
_(
"Non-copper pad %s has a hole, which is not supported." ), aElem.
name );
3725 msg.Printf(
_(
"Non-copper pad %s has a complex pad stack (not yet supported)." ),
3758 int offset = ( std::min( aElem.
topsize.
x, aElem.
topsize.
y ) * cornerradius ) / 200;
3763 if( cornerradius < 100 )
3765 int offsetX = aElem.
topsize.
x / 2 - offset;
3766 int offsetY = aElem.
topsize.
y / 2 - offset;
3859 aShape->
SetPolyPoints( { p11 - chamferX, p11 - chamferY, p12 + chamferY, p12 - chamferX,
3860 p22 + chamferX, p22 + chamferY, p21 - chamferY, p21 + chamferX } );
3872 msg.Printf(
_(
"Non-copper pad %s uses an unknown pad shape." ), aElem.
name );
3882 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3892 AVIA6 elem( reader );
3894 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
3906 if( start_layer_outside && end_layer_outside )
3910 else if( ( !start_layer_outside ) || ( !end_layer_outside ) )
3929 msg.Printf(
_(
"Via from layer %d to %d uses a non-copper layer, which is not "
3940 via->SetLayerPair( start_klayer, end_klayer );
3963 wxCHECK2_MSG( altiumLayer < 32,
break,
3964 "Altium importer expects 32 or fewer copper layers" );
3989 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3996 for(
int primitiveIndex = 0; reader.
GetRemainingBytes() >= 4; primitiveIndex++ )
4027 msg.Printf( wxT(
"ATRACK6 stream tries to access polygon id %u "
4028 "of %u existing polygons; skipping it" ),
4029 static_cast<unsigned>( aElem.
polygon ),
4030 static_cast<unsigned>(
m_polygons.size() ) );
4039 if( zone ==
nullptr )
4089 int width = aElem.
width + ( layerExpansionMask.second * 2 );
4094 seg->SetStart( aElem.
start );
4095 seg->SetEnd( aElem.
end );
4097 seg->SetLayer( layerExpansionMask.first );
4106 const int aPrimitiveIndex,
4107 const bool aIsBoardImport )
4111 wxFAIL_MSG( wxString::Format(
"Altium: Unexpected footprint Track with polygon id %u",
4147 int width = aElem.
width + ( layerExpansionMask.second * 2 );
4150 std::unique_ptr<PCB_SHAPE> seg = std::make_unique<PCB_SHAPE>( aFootprint,
SHAPE_T::SEGMENT );
4152 seg->SetStart( aElem.
start );
4153 seg->SetEnd( aElem.
end );
4155 seg->SetLayer( layerExpansionMask.first );
4167 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
4169 track->SetStart( aElem.
start );
4170 track->SetEnd( aElem.
end );
4171 track->SetWidth( aElem.
width );
4172 track->SetLayer( aLayer );
4181 seg->SetStart( aElem.
start );
4182 seg->SetEnd( aElem.
end );
4184 seg->SetLayer( aLayer );
4194 std::unique_ptr<PCB_SHAPE> seg = std::make_unique<PCB_SHAPE>( aFootprint,
SHAPE_T::SEGMENT );
4196 seg->SetStart( aElem.
start );
4197 seg->SetEnd( aElem.
end );
4199 seg->SetLayer( aLayer );
4206 const CFB::COMPOUND_FILE_ENTRY* aEntry )
4216 THROW_IO_ERROR( wxT(
"WideStrings6 stream is not fully parsed" ) );
4220 const CFB::COMPOUND_FILE_ENTRY* aEntry )
4255 msg.Printf(
_(
"Ignored barcode on Altium layer %d (not yet supported)." ),
4277 msg.Printf(
_(
"Error loading library '%s':\n"
4278 "Footprint %s contains barcode on Altium layer %d (not yet supported)." ),
4290 msg.Printf(
_(
"Footprint %s contains barcode on Altium layer %d (not yet supported)." ),
4307 std::unique_ptr<PCB_TEXTBOX> pcbTextbox = std::make_unique<PCB_TEXTBOX>(
m_board );
4308 std::unique_ptr<PCB_TEXT> pcbText = std::make_unique<PCB_TEXT>(
m_board );
4312 static const std::map<wxString, wxString> variableMap = {
4313 {
"LAYER_NAME",
"LAYER" },
4314 {
"PRINT_DATE",
"CURRENT_DATE"},
4324 item = pcbTextbox.get();
4325 text = pcbTextbox.get();
4336 text->SetText( kicadText );
4350 std::unique_ptr<PCB_TEXTBOX> fpTextbox = std::make_unique<PCB_TEXTBOX>( aFootprint );
4351 std::unique_ptr<PCB_TEXT> fpText = std::make_unique<PCB_TEXT>( aFootprint );
4368 item = &aFootprint->
Value();
4370 field = &aFootprint->
Value();
4374 item = fpText.get();
4375 text = fpText.get();
4379 static const std::map<wxString, wxString> variableMap = {
4380 {
"DESIGNATOR",
"REFERENCE" },
4381 {
"COMMENT",
"VALUE" },
4382 {
"VALUE",
"ALTIUM_VALUE" },
4383 {
"LAYER_NAME",
"LAYER" },
4384 {
"PRINT_DATE",
"CURRENT_DATE"},
4389 item = fpTextbox.get();
4390 text = fpTextbox.get();
4403 text->SetText( kicadText );
4404 text->SetKeepUpright(
false );
4441 kicadMargin =
VECTOR2I( charWidth * 0.933, charHeight * 0.67 );
4443 kicadMargin =
VECTOR2I( charWidth * 0.808, charHeight * 0.844 );
4446 + kicadMargin * 2 - margin * 2 );
4448 kposition = kposition - kicadMargin + margin;
4466 switch( justification )
4490 msg.Printf(
_(
"Unknown textbox justification %d, aText %s" ), justification,
4510 int rectHeight = aElem.
height;
4513 rectWidth = -rectWidth;
4519 switch( justification )
4525 kposition.
y -= rectHeight;
4531 kposition.
y -= rectHeight / 2;
4541 kposition.
x += rectWidth / 2;
4542 kposition.
y -= rectHeight;
4548 kposition.
x += rectWidth / 2;
4549 kposition.
y -= rectHeight / 2;
4555 kposition.
x += rectWidth / 2;
4561 kposition.
x += rectWidth;
4562 kposition.
y -= rectHeight;
4568 kposition.
x += rectWidth;
4569 kposition.
y -= rectHeight / 2;
4575 kposition.
x += rectWidth;
4628 if( font->
GetName().Contains( wxS(
"Arial" ) ) )
4643 const CFB::COMPOUND_FILE_ENTRY* aEntry )
4701 const bool aIsBoardImport )
4743 fill->SetFilled(
true );
4744 fill->SetLayer( aLayer );
4747 fill->SetStart( aElem.
pos1 );
4748 fill->SetEnd( aElem.
pos2 );
4770 if( aLayer ==
F_Cu || aLayer ==
B_Cu )
4772 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
4775 padLayers.
set( aLayer );
4790 std::swap( width, height );
4793 pad->SetPosition( aElem.
pos1 / 2 + aElem.
pos2 / 2 );
4805 pad->SetPosition( anchorPos );
4816 aElem.
pos1.
y / 2 + aElem.
pos2.
y / 2 - anchorPos.
y );
4818 pad->AddPrimitivePoly(
F_Cu, shapePolys, 0,
true );
4822 pad->SetLayerSet( padLayers );
4828 std::unique_ptr<PCB_SHAPE> fill =
4831 fill->SetFilled(
true );
4832 fill->SetLayer( aLayer );
4835 fill->SetStart( aElem.
pos1 );
4836 fill->SetEnd( aElem.
pos2 );
4855 layerSet.
set( klayer );
4863 bool keepoutRestrictionVia = ( aKeepoutRestrictions & 0x01 ) != 0;
4864 bool keepoutRestrictionTrack = ( aKeepoutRestrictions & 0x02 ) != 0;
4865 bool keepoutRestrictionCopper = ( aKeepoutRestrictions & 0x04 ) != 0;
4866 bool keepoutRestrictionSMDPad = ( aKeepoutRestrictions & 0x08 ) != 0;
4867 bool keepoutRestrictionTHPad = ( aKeepoutRestrictions & 0x10 ) != 0;
4879 const uint8_t aKeepoutRestrictions )
4881 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board );
4883 zone->SetIsRuleArea(
true );
4900 const uint8_t aKeepoutRestrictions )
4902 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aFootprint );
4904 zone->SetIsRuleArea(
true );
4928 if( elems.first == elems.second )
4931 std::vector<std::pair<PCB_LAYER_ID, int>> layerExpansionPairs;
4933 for(
auto it = elems.first; it != elems.second; ++it )
4973 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)
@ EXTENDPRIMITIVEINFORMATION
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.
#define DEFAULT_BOARD_THICKNESS_MM
@ BS_ITEM_TYPE_DIELECTRIC
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
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.
void SetGridOrigin(const VECTOR2I &aOrigin)
const VECTOR2I & GetGridOrigin() const
void SetAuxOrigin(const VECTOR2I &aOrigin)
const VECTOR2I & GetAuxOrigin() const
BOARD_STACKUP & GetStackupDescriptor()
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual void SetIsKnockout(bool aKnockout)
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
virtual LSET BoardLayerSet() const
Return the LSET for the board that this item resides 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
int BuildBoardThicknessFromStackup() 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.
constexpr coord_type GetY() const
constexpr size_type GetWidth() const
constexpr coord_type GetX() const
constexpr size_type GetHeight() const
bool IsHorizontal() const
bool IsCardinal90() const
EDA_ANGLE GetArcAngle() const
void SetCenter(const VECTOR2I &aCenter)
virtual void SetFilled(bool aFlag)
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 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,...
int GetTextHeight() const
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
void SetTextPos(const VECTOR2I &aPoint)
KIFONT::FONT * GetFont() const
void SetMirrored(bool isMirrored)
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
void SetBoldFlag(bool aBold)
Set only the bold flag, without changing the font.
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
GR_TEXT_V_ALIGN_T GetVertJustify() const
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
void SetItalic(bool aItalic)
Set the text to be italic - this will also update the font if needed.
void SetFont(KIFONT::FONT *aFont)
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
wxString GetEmbeddedFileLink(const EMBEDDED_FILE &aFile) const
Return the link for an embedded file.
EMBEDDED_FILE * AddFile(const wxFileName &aName, bool aOverwrite)
Load a file from disk and adds it to the collection.
static RETURN_CODE CompressAndEncode(EMBEDDED_FILE &aFile)
Take data from the #decompressedData buffer and compresses it using ZSTD into the #compressedEncodedD...
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 std::vector< wxString > *aEmbeddedFiles=nullptr, bool aForDrawingSheet=false)
virtual bool IsStroke() const
const wxString & GetName() const
virtual bool IsOutline() const
LAYER_RANGE_ITERATOR begin() const
A logical library item identifier and consists of various portions much like a URI.
LSET is a set of PCB_LAYER_IDs.
static const LSET & AllBoardTechMask()
Return a mask holding board technical layers (no CU layer) on both side.
static const LSET & UserMask()
static LSET UserDefinedLayersMask(int aUserDefinedLayerCount=MAX_USER_DEFINED_LAYERS)
Return a mask with the requested number of user defined layers.
static const LSET & InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
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 ...
A PADSTACK defines the characteristics of a single or multi-layer pad, in the IPC sense of the word.
void SetRoundRectRadiusRatio(double aRatio, PCB_LAYER_ID aLayer)
void SetChamferRatio(double aRatio, PCB_LAYER_ID aLayer)
void SetShape(PAD_SHAPE aShape, PCB_LAYER_ID aLayer)
void SetChamferPositions(int aPositions, PCB_LAYER_ID aLayer)
@ NORMAL
Shape is the same on all layers.
@ CUSTOM
Shapes can be defined on arbitrary layers.
@ FRONT_INNER_BACK
Up to three shapes can be defined (F_Cu, inner copper layers, B_Cu)
void SetSize(const VECTOR2I &aSize, PCB_LAYER_ID aLayer)
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
static constexpr PCB_LAYER_ID INNER_LAYERS
! The layer identifier to use for "inner layers" on top/inner/bottom padstacks
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
virtual VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
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.
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
void SetPosition(const VECTOR2I &aPos) override
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
void SetBorderEnabled(bool enabled)
void SetMarginTop(int aTop)
void SetMarginLeft(int aLeft)
void SetMarginBottom(int aBottom)
void SetTextAngle(const EDA_ANGLE &aAngle) override
void SetMarginRight(int aRight)
A progress reporter interface for use in multi-threaded environments.
A pure virtual class used to derive REPORTER objects from.
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
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.
SEG Segment(int aIndex) const
Return a copy of the aIndex-th segment in the line chain.
int NextShape(int aPointIndex) const
Return the vertex index of the next shape in the chain, or -1 if aPointIndex is the last shape.
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
Represent a set of closed polygons.
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
void BooleanAdd(const SHAPE_POLY_SET &b)
Perform boolean polyset union.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
void Fracture()
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
void Inflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify=false)
Perform outline inflation/deflation.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Adds a new hole to the given outline (default: last) and returns its index.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
int OutlineCount() const
Return the number of outlines in the set.
void Move(const VECTOR2I &aVector) override
Simple container to manage line stroke parameters.
constexpr extended_type Cross(const VECTOR2< T > &aVector) const
Compute cross product of self with aVector.
double Distance(const VECTOR2< extended_type > &aVector) const
Compute the distance between two vectors.
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
constexpr VECTOR2< T > Perpendicular() const
Compute the perpendicular vector.
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 SetNeedRefill(bool aNeedRefill)
void SetDoNotAllowPads(bool aEnable)
SHAPE_POLY_SET * GetFill(PCB_LAYER_ID aLayer)
void SetDoNotAllowTracks(bool aEnable)
void SetFilledPolysList(PCB_LAYER_ID aLayer, const SHAPE_POLY_SET &aPolysList)
Set the list of filled polygons.
void SetIsFilled(bool isFilled)
bool HasFilledPolysForLayer(PCB_LAYER_ID aLayer) const
void SetLayerSet(const LSET &aLayerSet) override
void SetDoNotAllowVias(bool aEnable)
void SetDoNotAllowFootprints(bool aEnable)
void SetDoNotAllowZoneFills(bool aEnable)
static int GetDefaultHatchPitch()
@ CHAMFER_ACUTE_CORNERS
Acute angles are chamfered.
static constexpr EDA_ANGLE ANGLE_90
static constexpr EDA_ANGLE ANGLE_45
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
bool m_ImportSkipComponentBodies
Skip importing component bodies when importing some format files, such as Altium.
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
size_t CopperLayerToOrdinal(PCB_LAYER_ID aLayer)
Converts KiCad copper layer enum to an ordinal between the front and back layers.
PCB_LAYER_ID
A quick note on layer IDs:
void for_all_pairs(_InputIterator __first, _InputIterator __last, _Function __f)
Apply a function to every possible pair of elements of a sequence.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
@ SMD
Smd pad, appears on the solder paste layer (default)
@ PTH
Plated through hole pad.
std::function< std::map< wxString, PCB_LAYER_ID >(const std::vector< INPUT_LAYER_DESC > &)> LAYER_MAPPING_HANDLER
Pointer to a function that takes a map of source and KiCad layers and returns a re-mapped version.
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 sourceHierachicalPath
wxString sourcefootprintlibrary
wxString sourcedesignator
std::vector< VECTOR2I > textPoint
ALTIUM_DIMENSION_KIND kind
std::vector< VECTOR2I > referencePoint
uint8_t keepoutrestrictions
std::vector< char > m_data
ALTIUM_PAD_SHAPE inner_shape[29]
ALTIUM_PAD_HOLE_SHAPE holeshape
ALTIUM_PAD_SHAPE_ALT alt_shape[32]
int32_t soldermaskexpansionmanual
std::unique_ptr< APAD6_SIZE_AND_SHAPE > sizeAndShape
ALTIUM_PAD_SHAPE topshape
ALTIUM_MODE pastemaskexpansionmode
ALTIUM_MODE soldermaskexpansionmode
ALTIUM_PAD_SHAPE botshape
ALTIUM_PAD_SHAPE midshape
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
uint32_t text_offset_width
uint32_t textbox_rect_height
ALTIUM_TEXT_POSITION textbox_rect_justification
uint32_t textbox_rect_width
uint32_t margin_border_width
bool isJustificationValid
ALTIUM_TEXT_TYPE fonttype
uint8_t keepoutrestrictions
int32_t soldermask_expansion_front
bool soldermask_expansion_manual
int32_t soldermask_expansion_back
uint32_t diameter_by_layer[32]
std::vector< char > decompressedData
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
double DEG2RAD(double deg)
@ 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
VECTOR2< int32_t > VECTOR2I
VECTOR3< double > VECTOR3D
@ THERMAL
Use thermal relief for pads.
@ NONE
Pads are not covered.
@ FULL
pads are covered by copper