59#include <compoundfilereader.h>
66#include <wx/docview.h>
68#include <wx/mstream.h>
69#include <wx/wfstream.h>
70#include <wx/zstream.h>
72#include <magic_enum.hpp>
76#include <unordered_set>
108 name = wxString::Format( wxT(
"__ALTIUM_UNNAMED_NET_%d" ), ++aCounter );
118 return aExpr.IsSameAs( wxS(
"All" ),
false );
124 static const wxString prefix = wxT(
"InNetClass('" );
127 || !aRule.
scope1expr.EndsWith( wxT(
"')" ) ) )
132 *aNetclassName = aRule.
scope1expr.Mid( prefix.Length(),
133 aRule.
scope1expr.Length() - prefix.Length() - 2 );
135 return !aNetclassName->IsEmpty();
140 NET_SETTINGS& aNetSettings, std::vector<const ARULE6*>* aUnresolved )
142 const std::map<wxString, std::shared_ptr<NETCLASS>>& netclasses = aNetSettings.
GetNetclasses();
144 for(
const auto& [kind, rules] : aRulesByKind )
152 std::set<wxString> applied;
154 for(
const ARULE6& rule : rules )
156 wxString netclassName;
161 auto it = netclasses.find( netclassName );
163 if( it == netclasses.end() )
166 aUnresolved->push_back( &rule );
172 if( !applied.insert( netclassName ).second )
175 const std::shared_ptr<NETCLASS>& netclass = it->second;
184 netclass->SetViaDiameter( rule.width );
185 netclass->SetViaDrill( rule.holeWidth );
199 THROW_IO_ERRORF( wxT(
"Component creator tries to access component id %u of %u existing components" ),
207std::shared_ptr<EMBEDDED_FILES::EMBEDDED_FILE>
209 const std::vector<char>& aCompressedData,
bool& aIsNew )
213 auto it = files.find( aModelName );
215 aIsNew = it == files.end();
222 auto file = std::make_shared<EMBEDDED_FILES::EMBEDDED_FILE>();
223 file->name = aModelName;
226 wxMemoryInputStream compressedStream( aCompressedData.data(), aCompressedData.size() );
227 wxZlibInputStream zlibStream( compressedStream );
231 file->decompressedData.resize( aCompressedData.size() * 6 );
234 while( !zlibStream.Eof() )
236 zlibStream.Read( file->decompressedData.data() + offset,
237 file->decompressedData.size() - offset );
239 size_t bytesRead = zlibStream.LastRead();
246 if( offset >= file->decompressedData.size() )
247 file->decompressedData.resize( 2 * file->decompressedData.size() );
250 file->decompressedData.resize( offset );
254 file->decompressedData.shrink_to_fit();
256 embeddedFiles->
AddFile( file );
263 const std::vector<ALTIUM_VERTICE>& aVertices )
272 double startradiant =
DEG2RAD( vertex.startangle );
273 double endradiant =
DEG2RAD( vertex.endangle );
274 VECTOR2I arcStartOffset =
KiROUND( std::cos( startradiant ) * vertex.radius,
275 -std::sin( startradiant ) * vertex.radius );
277 VECTOR2I arcEndOffset =
KiROUND( std::cos( endradiant ) * vertex.radius,
278 -std::sin( endradiant ) * vertex.radius );
280 VECTOR2I arcStart = vertex.center + arcStartOffset;
281 VECTOR2I arcEnd = vertex.center + arcEndOffset;
286 if( arcStart.
Distance( vertex.position )
287 < arcEnd.
Distance( vertex.position ) )
314 aLine.
Append( vertex.position );
324 auto override =
m_layermap.find( aAltiumLayer );
328 return override->second;
343 switch( aAltiumLayer )
445 std::vector<PCB_LAYER_ID> layers;
446 layers.reserve( layerCount );
451 layers.emplace_back( layer );
468 const wxString& aLibrary,
const wxString& aFootprintName )
488 const unsigned PROGRESS_DELTA = 250;
505 const std::map<ALTIUM_PCB_DIR, std::string>& aFileMapping,
506 const std::map<std::string, UTF8>* aProperties )
512 const std::vector<std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>> parserOrder = {
634 for(
const std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>& cur : parserOrder )
639 std::tie( isRequired,
directory, fp ) = cur;
644 const auto& mappedDirectory = aFileMapping.find(
directory );
646 if( mappedDirectory == aFileMapping.end() )
649 const std::vector<std::string> mappedFile{ mappedDirectory->second,
"Header" };
650 const CFB::COMPOUND_FILE_ENTRY* file = altiumPcbFile.
FindStream( mappedFile );
652 if( file ==
nullptr )
656 uint32_t numOfRecords = reader.
Read<uint32_t>();
662 m_reporter->Report( wxString::Format(
_(
"'%s' was not parsed correctly." ),
676 m_reporter->Report( wxString::Format(
_(
"'%s' was not fully parsed." ),
688 if( boardDirectory != aFileMapping.end() )
690 std::vector<std::string> mappedFile{ boardDirectory->second,
"Data" };
692 const CFB::COMPOUND_FILE_ENTRY* file = altiumPcbFile.
FindStream( mappedFile );
696 THROW_IO_ERROR(
_(
"This file does not appear to be in a valid PCB Binary Version 6.0 format. In "
697 "Altium Designer, make sure to save as \"PCB Binary Files (*.PcbDoc)\"." ) );
702 for(
const std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>& cur : parserOrder )
707 std::tie( isRequired,
directory, fp ) = cur;
709 const auto& mappedDirectory = aFileMapping.find(
directory );
711 if( mappedDirectory == aFileMapping.end() )
713 wxASSERT_MSG( !isRequired, wxString::Format( wxT(
"Altium Directory of kind %d was "
714 "expected, but no mapping is "
715 "present in the code" ),
720 std::vector<std::string> mappedFile{ mappedDirectory->second };
723 mappedFile.emplace_back(
"Data" );
725 const CFB::COMPOUND_FILE_ENTRY* file = altiumPcbFile.
FindStream( mappedFile );
727 if( file !=
nullptr )
729 fp( altiumPcbFile, file );
731 else if( isRequired )
735 m_reporter->Report( wxString::Format(
_(
"File not found: '%s' for directory '%s'." ),
758 if( zone->GetAssignedPriority() == 1000 )
769 zone->SetAssignedPriority( priority >= 0 ? priority : 0 );
773 for( std::pair<const ALTIUM_LAYER, ZONE*>& zone :
m_outer_plane )
774 zone.second->SetAssignedPriority( 0 );
778 BS::multi_future<void> fractureFutures;
787 if( !zone->HasFilledPolysForLayer( layer ) )
791 fractureFutures.push_back(
tp.submit_task(
792 [fill = zone->GetFilledPolysList( layer )]()
800 fractureFutures.wait();
801 fractureFutures.get();
837 if( arc->
GetCenter() == dim->GetPosition() )
846 VECTOR2I radialLine = dim->GetEnd() - dim->GetStart();
851 radialLine = radialLine.
Resize( std::max(
radius, 2 ) );
852 dim->SetEnd( dim->GetStart() + (
VECTOR2I) radialLine );
853 dim->SetLeaderLength( totalLength -
radius );
863 int desired_x = ( w - bbbox.
GetWidth() ) / 2;
864 int desired_y = ( h - bbbox.
GetHeight() ) / 2;
866 VECTOR2I movementVector( desired_x - bbbox.
GetX(), desired_y - bbbox.
GetY() );
867 m_board->Move( movementVector );
873 m_board->m_LegacyDesignSettingsLoaded =
true;
879 const wxString& aFootprintName )
881 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
886 const std::vector<std::string> libStreamName{
"Library",
"Data" };
887 const CFB::COMPOUND_FILE_ENTRY* libStream = altiumLibFile.
FindStream( libStreamName );
889 if( libStream ==
nullptr )
905 std::tuple<wxString, const CFB::COMPOUND_FILE_ENTRY*> ret =
908 wxString fpDirName = std::get<0>( ret );
909 const CFB::COMPOUND_FILE_ENTRY* footprintStream = std::get<1>( ret );
911 if( fpDirName.IsEmpty() )
912 THROW_IO_ERRORF(
_(
"Footprint directory not found: '%s'." ), aFootprintName );
914 const std::vector<std::string> streamName{ fpDirName.ToStdString(),
"Data" };
915 const CFB::COMPOUND_FILE_ENTRY* footprintData = altiumLibFile.
FindStream( footprintStream, {
"Data" } );
927 footprint->SetFPID( fpID );
929 const std::vector<std::string> parametersStreamName{ fpDirName.ToStdString(),
"Parameters" };
930 const CFB::COMPOUND_FILE_ENTRY* parametersData = altiumLibFile.
FindStream( footprintStream, {
"Parameters" } );
932 if( parametersData !=
nullptr )
935 std::map<wxString, wxString> parameterProperties = parametersReader.
ReadProperties();
937 footprint->SetLibDescription( description );
943 m_reporter->Report( wxString::Format(
_(
"File not found: '%s'." ),
FormatPath( parametersStreamName ) ),
947 footprint->SetLibDescription( wxT(
"" ) );
950 const std::vector<std::string> extendedPrimitiveInformationStreamName{
951 "ExtendedPrimitiveInformation",
"Data"
953 const CFB::COMPOUND_FILE_ENTRY* extendedPrimitiveInformationData =
954 altiumLibFile.
FindStream( footprintStream, extendedPrimitiveInformationStreamName );
956 if( extendedPrimitiveInformationData !=
nullptr )
959 footprint->SetReference( wxT(
"REF**" ) );
960 footprint->SetValue( aFootprintName );
961 footprint->Reference().SetVisible(
true );
962 footprint->Value().SetVisible(
true );
965 const int defaultTextThickness(
pcbIUScale.mmToIU( 0.15 ) );
967 for(
PCB_FIELD* field : footprint->GetFields() )
969 field->SetTextSize( defaultTextSize );
970 field->SetTextThickness( defaultTextThickness );
1038 if( !aPad->GetNumber().IsEmpty() )
1044 && !aPad->GetPrimitives( layer ).empty() )
1053 auto commonCopperLayer =
1065 auto mergeRegionPadInto =
1066 [&](
PAD* aNamedPad,
PAD* aRegionPad )
1068 PCB_LAYER_ID layer = commonCopperLayer( aRegionPad, aNamedPad );
1086 int minExtent = std::min( aNamedPad->
GetSize( layer ).
x,
1110 const std::vector<std::shared_ptr<PCB_SHAPE>>& prims =
1113 for(
const std::shared_ptr<PCB_SHAPE>& src : prims )
1118 copy->Move( anchorShift );
1142 std::vector<PAD*> regionPads;
1143 std::vector<PAD*> namedPads;
1145 for(
PAD*
pad : footprint->Pads() )
1147 if( isRegionPad(
pad ) )
1148 regionPads.push_back(
pad );
1149 else if( !
pad->GetNumber().IsEmpty() )
1150 namedPads.push_back(
pad );
1155 std::unordered_set<PAD*> consumedNamed;
1157 for(
PAD* regionPad : regionPads )
1160 : regionPad->IsOnLayer(
B_Cu ) ?
B_Cu
1163 std::shared_ptr<SHAPE_POLY_SET> outline =
1164 regionPad->GetEffectivePolygon( regionCu,
ERROR_INSIDE );
1166 if( !outline || outline->OutlineCount() == 0 )
1171 PAD* bestNamed =
nullptr;
1172 int64_t bestDistSq = std::numeric_limits<int64_t>::max();
1174 for(
PAD* namedPad : namedPads )
1176 if( consumedNamed.count( namedPad ) )
1180 && !( namedPad->GetLayerSet() & regionPad->GetLayerSet() &
LSET::AllCuMask() ).any() )
1185 if( !outline->Contains( namedPad->GetPosition(), -1, 0 ) )
1188 VECTOR2I delta = namedPad->GetPosition() - regionPad->GetPosition();
1191 if( distSq < bestDistSq )
1193 bestDistSq = distSq;
1194 bestNamed = namedPad;
1200 mergeRegionPadInto( bestNamed, regionPad );
1201 consumedNamed.insert( bestNamed );
1202 footprint->Remove( regionPad );
1208 for(
bool changes =
true; changes; )
1213 [&changes](
PAD* aPad1,
PAD* aPad2 )
1215 if( !( aPad1->GetNumber().IsEmpty() ^ aPad2->GetNumber().IsEmpty() ) )
1218 for( PCB_LAYER_ID layer : aPad1->GetLayerSet() )
1220 std::shared_ptr<SHAPE> shape1 = aPad1->GetEffectiveShape( layer );
1221 std::shared_ptr<SHAPE> shape2 = aPad2->GetEffectiveShape( layer );
1223 if( shape1->Collide( shape2.get() ) )
1225 if( aPad1->GetNumber().IsEmpty() )
1226 aPad1->SetNumber( aPad2->GetNumber() );
1228 aPad2->SetNumber( aPad1->GetNumber() );
1237 footprint->AutoPositionFields();
1242 footprint->SetAttributes( footprint->GetAttributes() | footprint->GetLikelyAttribute() );
1244 if( parser.HasParsingError() )
1247 if( parser.GetRemainingBytes() != 0 )
1261 THROW_IO_ERRORF( wxT(
"Netcode with id %d does not exist. Only %zu nets are known" ),
1272 const auto rules =
m_rules.find( aKind );
1277 for(
const ARULE6& rule : rules->second )
1288 const auto rules =
m_rules.find( aKind );
1293 for(
const ARULE6& rule : rules->second )
1305 const auto rules =
m_rules.find( aKind );
1319 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1337 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1350 std::move( elem ) );
1354 THROW_IO_ERROR( wxT(
"ExtendedPrimitiveInformation stream is not fully parsed" ) );
1359 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1376 size_t layercount = 0;
1379 while( layerid < elem.
stackup.size() && layerid != 0 )
1381 layerid = elem.
stackup[ layerid - 1 ].nextId;
1385 size_t kicadLayercount = ( layercount % 2 == 0 ) ? layercount : layercount + 1;
1386 m_board->SetCopperLayerCount( kicadLayercount );
1395 auto it = stackup.
GetList().begin();
1404 altiumLayerId < elem.
stackup.size() && altiumLayerId != 0;
1405 altiumLayerId = elem.
stackup[altiumLayerId - 1].nextId )
1411 if( layer.
nextId == 0 && layercount != kicadLayercount )
1413 m_board->SetLayerName( ( *it )->GetBrdLayerId(), wxT(
"[unused]" ) );
1416 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
1418 ( *it )->SetThickness( 0 );
1423 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
1425 ( *it )->SetThickness( 0, 0 );
1426 ( *it )->SetThicknessLocked(
true, 0 );
1434 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
1448 if( klayer ==
B_Cu )
1451 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected id while parsing last stackup layer" ) );
1461 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
1493 m_reporter->Report( wxString::Format(
_(
"Board outline has %d vertices outside the "
1494 "coordinate range; they were dropped." ),
1510 for(
const auto& [altiumLayer, kicadLayer] :
m_layermap )
1531 return ordinal < ALTIUM_PADSTACK_IDX_COUNT ? static_cast<int>( ordinal ) : -1;
1543 wxString nameLower = aName.Lower();
1544 return nameLower.Contains( wxT(
"courtyard" ) ) || nameLower.Contains( wxT(
"court yard" ) )
1545 || nameLower.Contains( wxT(
"crtyd" ) );
1552 wxString nameLower = aName.Lower();
1553 return nameLower.Contains( wxT(
"assembly" ) ) || nameLower.Contains( wxT(
"assy" ) );
1562 auto check = [&isTop](
bool aTopCond,
bool aBotCond )
1564 if( aTopCond && aBotCond )
1567 if( !aTopCond && !aBotCond )
1574 wxString lower = aName.Lower();
1576 if( check( lower.StartsWith(
"top" ), lower.StartsWith(
"bot" ) ) )
1579 if( check( lower.EndsWith(
"_t" ), lower.EndsWith(
"_b" ) ) )
1582 if( check( lower.EndsWith(
".t" ), lower.EndsWith(
".b" ) ) )
1585 if( check( lower.Contains(
"top" ), lower.Contains(
"bot" ) ) )
1598 if( aStackup.size() == 0 )
1601 std::vector<INPUT_LAYER_DESC> inputLayers;
1602 std::map<wxString, ALTIUM_LAYER> altiumLayerNameMap;
1609 bool frontCourtyardMapped =
false;
1610 bool backCourtyardMapped =
false;
1612 for(
size_t ii = 0; ii < aStackup.size(); ii++ )
1614 curLayer = aStackup[ii];
1633 auto existingMapping =
m_layermap.find( layer_num );
1661 if( isTopSide && !frontCourtyardMapped )
1664 frontCourtyardMapped =
true;
1666 else if( !isTopSide && !backCourtyardMapped )
1669 backCourtyardMapped =
true;
1671 else if( !frontCourtyardMapped )
1674 frontCourtyardMapped =
true;
1676 else if( !backCourtyardMapped )
1679 backCourtyardMapped =
true;
1702 inputLayers.push_back( iLdesc );
1703 altiumLayerNameMap.insert( { curLayer.
name, layer_num } );
1707 if( inputLayers.size() == 0 )
1713 for( std::pair<wxString, PCB_LAYER_ID> layerPair : reMappedLayers )
1721 m_reporter->Report( wxString::Format(
_(
"Layer '%s' could not be mapped and "
1722 "will be skipped." ),
1730 ALTIUM_LAYER altiumID = altiumLayerNameMap.at( layerPair.first );
1731 m_layermap.insert_or_assign( altiumID, layerPair.second );
1732 enabledLayers |=
LSET( { layerPair.second } );
1737 for(
const auto& [
name, altLayer] : altiumLayerNameMap )
1739 if( reMappedLayers.find(
name ) == reMappedLayers.end()
1746 m_board->SetEnabledLayers( enabledLayers );
1747 m_board->SetVisibleLayers( enabledLayers );
1760 if( !layer.mechenabled )
1768 switch( layer.mechkind )
1829 shape->SetStroke( stroke );
1841 shape->SetStroke( stroke );
1843 shape->SetStart( seg.
A );
1844 shape->SetEnd( seg.
B );
1853 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1867 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( elem.
name,
false );
1869 for(
const wxString&
name : elem.
names )
1875 if(
m_board->GetDesignSettings().m_NetSettings->HasNetclass( nc->GetName() ) )
1882 msg.Printf(
_(
"More than one Altium netclass with name '%s' found. "
1883 "Only the first one will be imported." ), elem.
name );
1889 m_board->GetDesignSettings().m_NetSettings->SetNetclass( nc->GetName(), nc );
1901 m_board->m_LegacyNetclassesLoaded =
true;
1907 std::shared_ptr<NET_SETTINGS> netSettings =
m_board->GetDesignSettings().m_NetSettings;
1909 netSettings->RecomputeEffectiveNetclasses();
1913 if( net->GetNetCode() <= 0 )
1916 if( std::shared_ptr<NETCLASS> netclass = netSettings->GetEffectiveNetClass( net->GetNetname() ) )
1917 net->SetNetClass( netclass );
1923 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1935 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
1946 wxString fpName = elem.
pattern;
1948 if( fpName.Contains( wxT(
"\\" ) ) || fpName.Contains( wxT(
"/" ) ) )
1950 wxFileName fpPath( fpName, wxPATH_WIN );
1951 fpName = fpPath.GetFullName();
1956 footprint->SetFPID( fpID );
1958 footprint->SetPosition( elem.
position );
1959 footprint->SetOrientationDegrees( elem.
rotation );
1965 if( reference.find_first_not_of(
"0123456789" ) == wxString::npos )
1966 reference.Prepend( wxT(
"UNK" ) );
1968 footprint->SetReference( reference );
1973 path.push_back( pathid );
1974 path.push_back(
id );
1976 footprint->SetPath(
path );
1980 footprint->SetLocked( elem.
locked );
1981 footprint->Reference().SetVisible( elem.
nameon );
1982 footprint->Value().SetVisible( elem.
commenton );
1990 THROW_IO_ERROR( wxT(
"Components6 stream is not fully parsed" ) );
1997 while( Angle < aMin )
2000 while( Angle >= aMax )
2023 m_reporter->Report( wxString::Format( wxT(
"Model %s not found for footprint %s" ),
2034 std::shared_ptr<EMBEDDED_FILES::EMBEDDED_FILE> file =
2053 orientation = -orientation;
2060 modelRotation.
x += 180;
2061 modelRotation.
z = -modelRotation.
z;
2075 aFootprint->
Models().push_back( modelSettings );
2080 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2086 BS::multi_future<void> embeddedFutures;
2097 if( skipComponentBodies )
2105 THROW_IO_ERRORF( wxT(
"ComponentsBodies6 stream tries to access component id %d of %zu existing "
2121 msg.Printf( wxT(
"ComponentsBodies6 stream tries to access model id %s which does "
2122 "not exist" ), elem.
modelId );
2133 std::shared_ptr<EMBEDDED_FILES::EMBEDDED_FILE> file =
2140 embeddedFutures.push_back(
tp.submit_task(
2143 EMBEDDED_FILES::CompressAndEncode( *file );
2163 orientation = -orientation;
2186 footprint->
Models().push_back( modelSettings );
2189 embeddedFutures.wait();
2192 THROW_IO_ERROR( wxT(
"ComponentsBodies6 stream is not fully parsed" ) );
2199 THROW_IO_ERROR( wxT(
"Incorrect number of reference points for linear dimension object" ) );
2208 _(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
2209 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer ),
2222 dimension->SetLayer( klayer );
2223 dimension->SetStart( referencePoint0 );
2225 if( referencePoint0 != aElem.
xy1 )
2237 VECTOR2I referenceDiff = referencePoint1 - referencePoint0;
2239 SEG segm1( referencePoint0, referencePoint0 + directionNormalVector );
2240 SEG segm2( referencePoint1, referencePoint1 + direction );
2244 THROW_IO_ERROR( wxT(
"Invalid dimension. This should never happen." ) );
2246 dimension->SetEnd( *intersection );
2250 if( direction.
Cross( referenceDiff ) > 0 )
2253 dimension->SetHeight( height );
2257 dimension->SetEnd( referencePoint1 );
2260 dimension->SetLineThickness( aElem.
linewidth );
2266 int dist = ( dimension->GetEnd() - dimension->GetStart() ).EuclideanNorm();
2268 if( dist < 3 * dimension->GetArrowLength() )
2272 wxRegEx units( wxS(
"(mm)|(in)|(mils)|(thou)|(')|(\")" ), wxRE_ADVANCED );
2284 dimension->Text().SetBold( aElem.
textbold );
2287 dimension->SetTextThickness( dimension->GetTextThickness() *
BOLD_FACTOR );
2306 THROW_IO_ERROR( wxT(
"Not enough reference points for radial dimension object" ) );
2315 _(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
2316 "It has been moved to KiCad layer Eco1_User." ),
2325 std::unique_ptr<PCB_DIM_RADIAL> dimension = std::make_unique<PCB_DIM_RADIAL>(
m_board );
2328 dimension->SetLayer( klayer );
2329 dimension->SetStart( referencePoint0 );
2330 dimension->SetEnd( aElem.
xy1 );
2331 dimension->SetLineThickness( aElem.
linewidth );
2332 dimension->SetKeepTextAligned(
false );
2353 m_reporter->Report( wxT(
"No text position present for leader dimension object" ),
2360 dimension->SetTextPos( aElem.
textPoint.at( 0 ) );
2366 dimension->SetBold( aElem.
textbold );
2369 dimension->SetTextThickness( dimension->GetTextThickness() *
BOLD_FACTOR );
2377 int yAdjust = dimension->GetTextBox(
nullptr ).GetCenter().y - dimension->GetTextPos().y;
2378 dimension->SetTextPos( dimension->GetTextPos() +
VECTOR2I( 0, yAdjust + aElem.
textgap ) );
2395 msg.Printf(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
2396 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer );
2413 shape->SetLayer( klayer );
2415 shape->SetStart( last );
2427 if( dirVec.
x != 0 || dirVec.
y != 0 )
2436 shape1->SetLayer( klayer );
2438 shape1->SetStart( referencePoint0 );
2439 shape1->SetEnd( referencePoint0 + arrVec );
2449 shape2->SetLayer( klayer );
2451 shape2->SetStart( referencePoint0 );
2452 shape2->SetEnd( referencePoint0 + arrVec );
2464 m_reporter->Report( wxT(
"No text position present for leader dimension object" ),
2471 std::unique_ptr<PCB_TEXT>
text = std::make_unique<PCB_TEXT>(
m_board );
2475 text->SetLayer( klayer );
2494 msg.Printf(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
2495 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer );
2506 shape->SetLayer( klayer );
2525 msg.Printf(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
2526 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer );
2536 std::unique_ptr<PCB_DIM_CENTER> dimension = std::make_unique<PCB_DIM_CENTER>(
m_board );
2538 dimension->SetLayer( klayer );
2539 dimension->SetLineThickness( aElem.
linewidth );
2540 dimension->SetStart( aElem.
xy1 );
2541 dimension->SetEnd( aElem.
xy1 + vec );
2548 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2568 m_reporter->Report( wxString::Format(
_(
"Ignored Angular dimension (not yet supported)." ) ),
2581 m_reporter->Report( wxString::Format(
_(
"Ignored Datum dimension (not yet supported)." ) ),
2589 m_reporter->Report( wxString::Format(
_(
"Ignored Baseline dimension (not yet supported)." ) ),
2599 m_reporter->Report( wxString::Format(
_(
"Ignored Linear dimension (not yet supported)." ) ),
2606 m_reporter->Report( wxString::Format(
_(
"Ignored Radial dimension (not yet supported)." ) ),
2614 msg.Printf(
_(
"Ignored dimension of kind %d (not yet supported)." ), elem.
kind );
2622 THROW_IO_ERROR( wxT(
"Dimensions6 stream is not fully parsed" ) );
2627 const CFB::COMPOUND_FILE_ENTRY* aEntry,
2628 const std::vector<std::string>& aRootDir )
2639 wxString invalidChars = wxFileName::GetForbiddenChars();
2646 std::vector<std::string> stepPath = aRootDir;
2647 stepPath.emplace_back( std::to_string( idx ) );
2649 bool validName = !elem.
name.IsEmpty() && elem.
name.IsAscii()
2650 && wxString::npos == elem.
name.find_first_of( invalidChars );
2651 wxString storageName = validName ? elem.
name : wxString::Format( wxT(
"model_%d" ), idx );
2655 const CFB::COMPOUND_FILE_ENTRY* stepEntry = aAltiumPcbFile.
FindStream( stepPath );
2657 if( stepEntry ==
nullptr )
2662 msg.Printf(
_(
"File not found: '%s'. 3D-model not imported." ),
FormatPath( stepPath ) );
2669 size_t stepSize =
static_cast<size_t>( stepEntry->size );
2670 std::vector<char> stepContent( stepSize );
2678 std::move( stepContent ) ) ) );
2682 std::map<wxString, std::vector<wxString>> nameIdMap;
2685 nameIdMap[data.m_modelname].push_back(
id );
2687 for(
auto& [
name, ids] : nameIdMap )
2689 for(
size_t i = 1; i < ids.size(); i++ )
2691 const wxString&
id = ids[i];
2698 wxString modelName = modelTuple->second.m_modelname;
2700 if( modelName.Contains(
"." ) )
2703 wxString baseName = modelName.BeforeLast(
'.', &ext );
2705 modelTuple->second.m_modelname = baseName +
'_' + std::to_string( i ) +
'.' + ext;
2709 modelTuple->second.m_modelname = modelName +
'_' + std::to_string( i );
2720 std::set<wxString>& aAmbiguous )
2722 auto collect = [&](
const std::map<wxString, wxString>& aProps )
2742 if(
name.IsEmpty() )
2745 wxString key =
name.Upper();
2746 auto it = aNames.find( key );
2748 if( it == aNames.end() )
2749 aNames.emplace( key,
name );
2750 else if( it->second !=
name )
2751 aAmbiguous.insert( key );
2757 const CFB::COMPOUND_FILE_ENTRY* header = schFile.
FindStream( {
"FileHeader" } );
2779 std::set<wxString> ambiguous;
2781 for(
int i = 0;; i++ )
2783 auto it = aProperties.find(
"sch" + std::to_string( i ) );
2785 if( it == aProperties.end() )
2798 for(
const wxString& key : ambiguous )
2815 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2824 int unnamedNetCount = 0;
2829 ANET6 elem( reader );
2833 if( netName.IsEmpty() )
2839 m_reporter->Report( wxString::Format(
_(
"Altium net %zu has no name; imported as '%s'." ),
2857 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2871 m_reporter->Report( wxString::Format(
_(
"Polygon on layer '%s' has %d vertices "
2872 "outside the coordinate range; they were "
2910 msg.Printf(
_(
"Polygon outline count is %d, expected 1." ), outline.
OutlineCount() );
2918 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board);
2924 zone->SetPosition( elem.
vertices.at( 0 ).position );
2925 zone->SetLocked( elem.
locked );
2927 zone->Outline()->AddOutline( outline.
Outline( 0 ) );
2934 int planeLayers = 0;
2935 int signalLayers = 0;
2949 if( planeLayers > 0 && planeClearanceRule )
2952 if( signalLayers > 0 && zoneClearanceRule )
2960 if( polygonConnectRule !=
nullptr )
2979 zone->SetThermalReliefSpokeWidth(
2990 zone->SetAssignedPriority( 1 );
2995 || zone->GetBoundingBox().Contains( outer_plane->second->GetBoundingBox() ) )
3010 const BOX2I& bbox = zone->GetBoundingBox();
3019 zone->SetHatchOrientation(
ANGLE_45 );
3034 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3053 std::sort( val.second.begin(), val.second.end(),
3056 return lhs.priority < rhs.priority;
3070 if( trackWidthRule )
3072 m_board->GetDesignSettings().m_TrackMinWidth = trackWidthRule->
minLimit;
3076 if( routingViasRule )
3078 m_board->GetDesignSettings().m_ViasMinSize = routingViasRule->
minWidth;
3087 if( holeToHoleRule )
3090 if( boardOutlineRule )
3096 if( soldermaskRule )
3102 std::shared_ptr<NET_SETTINGS> netSettings =
m_board->GetDesignSettings().m_NetSettings;
3103 std::shared_ptr<NETCLASS> defaultNetclass = netSettings->GetDefaultNetclass();
3106 defaultNetclass->SetClearance( clearanceRule->
clearanceGap );
3108 if( trackWidthRule )
3109 defaultNetclass->SetTrackWidth( trackWidthRule->
preferredWidth );
3111 if( routingViasRule )
3113 defaultNetclass->SetViaDiameter( routingViasRule->
width );
3114 defaultNetclass->SetViaDrill( routingViasRule->
holeWidth );
3117 std::vector<const ARULE6*> unresolvedNetclassRules;
3123 for(
const ARULE6* rule : unresolvedNetclassRules )
3125 wxString netclassName;
3128 m_reporter->Report( wxString::Format(
_(
"Altium rule '%s' applies to netclass '%s', which this "
3129 "board does not define. Its constraint is not imported." ),
3130 rule->name, netclassName ),
3143 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3159 THROW_IO_ERROR( wxT(
"BoardRegions stream is not fully parsed" ) );
3163 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3171 for(
int primitiveIndex = 0; reader.
GetRemainingBytes() >= 4; primitiveIndex++ )
3190 THROW_IO_ERROR( wxT(
"ShapeBasedRegions6 stream is not fully parsed" ) );
3218 if( restrictions == 0 )
3221 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board );
3223 zone->SetIsRuleArea(
true );
3227 zone->SetPosition( aElem.
outline.at( 0 ).position );
3228 zone->Outline()->AddOutline( linechain );
3248 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board );
3250 zone->SetPosition( aElem.
outline.at( 0 ).position );
3251 zone->Outline()->AddOutline( linechain );
3259 fill.
Append( linechain );
3263 zone->SetFilledPolysList( klayer, fill );
3265 zone->SetIsFilled(
true );
3266 zone->SetNeedRefill(
false );
3279 msg.Printf(
_(
"Dashed outline found on an Altium layer (%d) with no KiCad equivalent. "
3280 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer );
3301 shape->SetPolyShape( linechain );
3302 shape->SetFilled(
false );
3303 shape->SetLayer( klayer );
3321 msg.Printf(
_(
"Ignored polygon shape of kind %d (not yet supported)." ), aElem.
kind );
3330 const int aPrimitiveIndex )
3350 if( restrictions == 0 )
3353 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aFootprint );
3355 zone->SetIsRuleArea(
true );
3359 zone->SetPosition( aElem.
outline.at( 0 ).position );
3360 zone->Outline()->AddOutline( linechain );
3396 msg.Printf(
_(
"Loading library '%s':\n"
3397 "Footprint %s contains a dashed outline on Altium layer (%d) with "
3398 "no KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
3410 msg.Printf(
_(
"Footprint %s contains a dashed outline on Altium layer (%d) with "
3411 "no KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
3433 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aFootprint,
SHAPE_T::POLY );
3435 shape->SetPolyShape( linechain );
3436 shape->SetFilled(
false );
3437 shape->SetLayer( klayer );
3453 msg.Printf(
_(
"Error loading library '%s':\n"
3454 "Footprint %s contains polygon shape of kind %d (not yet supported)." ),
3466 msg.Printf(
_(
"Footprint %s contains polygon shape of kind %d (not yet supported)." ),
3477 const int aPrimitiveIndex )
3494 for(
const std::vector<ALTIUM_VERTICE>& hole : aElem.
holes )
3502 polySet.
AddHole( hole_linechain );
3507 shape->SetPolyShape( polySet );
3508 shape->SetFilled(
true );
3509 shape->SetLayer( aLayer );
3520 if( aLayer ==
F_Cu || aLayer ==
B_Cu )
3522 for(
const auto& layerExpansionMask :
3525 const PCB_LAYER_ID maskLayer = layerExpansionMask.first;
3533 int expansion = layerExpansionMask.second;
3540 maskShape->SetPolyShape( expandedPolySet );
3541 maskShape->SetFilled(
true );
3542 maskShape->SetLayer( maskLayer );
3554 const int aPrimitiveIndex )
3571 for(
const std::vector<ALTIUM_VERTICE>& hole : aElem.
holes )
3579 polySet.
AddHole( hole_linechain );
3582 if( aLayer ==
F_Cu || aLayer ==
B_Cu )
3584 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
3587 padLayers.
set( aLayer );
3599 pad->SetPosition( anchorPos );
3606 shapePolys.
Move( -anchorPos );
3610 auto it = map.find( aPrimitiveIndex );
3612 if( it != map.end() )
3618 pad->SetLocalSolderPasteMargin(
info.pastemaskexpansionmanual );
3623 pad->SetLocalSolderMaskMargin(
info.soldermaskexpansionmanual );
3633 pad->SetLayerSet( padLayers );
3639 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aFootprint,
SHAPE_T::POLY );
3641 shape->SetPolyShape( polySet );
3642 shape->SetFilled(
true );
3643 shape->SetLayer( aLayer );
3652 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3668 THROW_IO_ERRORF( wxT(
"Region stream tries to access polygon id %d of %d existing polygons." ),
3674 if( zone ==
nullptr )
3693 for(
const std::vector<ALTIUM_VERTICE>& hole : elem.
holes )
3700 hole_linechain.
Append( hole.at( 0 ).position );
3702 fill.
AddHole( hole_linechain );
3722 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3729 for(
int primitiveIndex = 0; reader.
GetRemainingBytes() >= 4; primitiveIndex++ )
3732 AARC6 elem( reader );
3783 THROW_IO_ERRORF( wxT(
"Tracks stream tries to access polygon id %u of %zu existing polygons." ),
3789 if( zone ==
nullptr )
3837 for(
const auto& layerExpansionMask :
3840 int width = aElem.
width + ( layerExpansionMask.second * 2 );
3844 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>(
m_board );
3848 arc->SetLayer( layerExpansionMask.first );
3857 const int aPrimitiveIndex,
const bool aIsBoardImport )
3861 wxFAIL_MSG( wxString::Format(
"Altium: Unexpected footprint Arc with polygon id %d",
3894 for(
const auto& layerExpansionMask :
3897 int width = aElem.
width + ( layerExpansionMask.second * 2 );
3901 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>( aFootprint );
3905 arc->SetLayer( layerExpansionMask.first );
3927 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board, &shapeArc );
3929 arc->SetWidth( aElem.
width );
3930 arc->SetLayer( aLayer );
3933 PCB_ARC* added = arc.release();
3941 if(
std::abs( sweepDegrees ) >= 359.999 )
3945 addArc( aElem.
center + startOffset, halfSweep );
3946 addArc( aElem.
center - startOffset, halfSweep );
3953 addArc( aElem.
center + startOffset, includedAngle );
3957 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>(
m_board);
3961 arc->SetLayer( aLayer );
3971 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>( aFootprint );
3975 arc->SetLayer( aLayer );
3982 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3992 APAD6 elem( reader );
4021 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
4022 footprint->SetPosition( aElem.
position );
4037 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
4039 pad->SetNumber(
"" );
4048 pad->SetLayerSet(
LSET().AllCuMask() );
4080 cuLayers &=
m_board->GetEnabledLayers();
4089 pad->SetSize( layer,
VECTOR2I( diameter, diameter ) );
4096 pad->Padstack().FrontOuterLayers().has_solder_mask =
true;
4100 pad->Padstack().FrontOuterLayers().has_solder_mask =
false;
4106 pad->Padstack().BackOuterLayers().has_solder_mask =
true;
4110 pad->Padstack().BackOuterLayers().has_solder_mask =
false;
4115 pad->SetLocked(
true );
4145 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
4168 msg.Printf(
_(
"Error loading library '%s':\n"
4169 "Footprint %s pad %s is not marked as multilayer, but is a TH pad." ),
4181 msg.Printf(
_(
"Footprint %s pad %s is not marked as multilayer, but is a TH pad." ),
4201 wxFAIL_MSG( wxT(
"Round holes are handled before the switch" ) );
4210 msg.Printf(
_(
"Loading library '%s':\n"
4211 "Footprint %s pad %s has a square hole (not yet supported)." ),
4223 msg.Printf(
_(
"Footprint %s pad %s has a square hole (not yet supported)." ),
4239 bool slotRotationSupported;
4243 if( !slotRotationSupported )
4253 msg.Printf(
_(
"Loading library '%s':\n"
4254 "Footprint %s pad %s has a hole-rotation of %d degrees. "
4255 "KiCad only supports 90 degree rotations." ),
4268 msg.Printf(
_(
"Footprint %s pad %s has a hole-rotation of %d degrees. "
4269 "KiCad only supports 90 degree rotations." ),
4288 msg.Printf(
_(
"Error loading library '%s':\n"
4289 "Footprint %s pad %s uses a hole of unknown kind %d." ),
4302 msg.Printf(
_(
"Footprint %s pad %s uses a hole of unknown kind %d." ),
4319 auto setCopperGeometry =
4323 bool hasAltiumEntry = aElem.
sizeAndShape && aAltiumIdx >= 0
4328 if( aElem.
holesize != 0 && hasAltiumEntry )
4345 else if( aSize.x == aSize.y )
4369 msg.Printf(
_(
"Error loading library '%s':\n"
4370 "Footprint %s pad %s uses an unknown pad shape." ),
4382 msg.Printf(
_(
"Footprint %s pad %s uses an unknown pad shape." ),
4435 setCopperGeometry( layer, idx, shape.
inner_shape[inner],
4445 switch( aElem.
layer )
4463 pad->SetLayer( klayer );
4464 pad->SetLayerSet(
LSET( { klayer } ) );
4475 pad->SetLayerSet(
pad->GetLayerSet().reset(
F_Mask ) );
4478 pad->SetLayerSet(
pad->GetLayerSet().reset(
B_Mask ) );
4496 msg.Printf(
_(
"Non-copper pad %s found on an Altium layer (%d) with no KiCad "
4497 "equivalent. It has been moved to KiCad layer Eco1_User." ),
4505 std::unique_ptr<PCB_SHAPE>
pad = std::make_unique<PCB_SHAPE>(
m_board );
4524 msg.Printf(
_(
"Loading library '%s':\n"
4525 "Footprint %s non-copper pad %s found on an Altium layer (%d) with no "
4526 "KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
4539 msg.Printf(
_(
"Footprint %s non-copper pad %s found on an Altium layer (%d) with no "
4540 "KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
4551 std::unique_ptr<PCB_SHAPE>
pad = std::make_unique<PCB_SHAPE>( aFootprint );
4567 msg.Printf(
_(
"Non-copper pad %s is connected to a net, which is not supported." ),
4578 msg.Printf(
_(
"Non-copper pad %s has a hole, which is not supported." ), aElem.
name );
4588 msg.Printf(
_(
"Non-copper pad %s has a complex pad stack (not yet supported)." ),
4620 int offset = ( std::min( aElem.
topsize.
x, aElem.
topsize.
y ) * cornerradius ) / 200;
4625 if( cornerradius < 100 )
4627 int offsetX = aElem.
topsize.
x / 2 - offset;
4628 int offsetY = aElem.
topsize.
y / 2 - offset;
4721 aShape->
SetPolyPoints( { p11 - chamferX, p11 - chamferY, p12 + chamferY, p12 - chamferX,
4722 p22 + chamferX, p22 + chamferY, p21 - chamferY, p21 + chamferX } );
4734 msg.Printf(
_(
"Non-copper pad %s uses an unknown pad shape." ), aElem.
name );
4744 const CFB::COMPOUND_FILE_ENTRY* aEntry )
4754 AVIA6 elem( reader );
4756 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
4768 if( start_layer_outside && end_layer_outside )
4772 else if( ( !start_layer_outside ) && ( !end_layer_outside ) )
4795 msg.Printf(
_(
"Via from layer %d to %d uses a non-copper layer, which is not "
4806 via->SetLayerPair( start_klayer, end_klayer );
4833 via->SetWidth( layer, altiumLayer < 0 ? elem.
diameter
4866 const CFB::COMPOUND_FILE_ENTRY* aEntry )
4873 for(
int primitiveIndex = 0; reader.
GetRemainingBytes() >= 4; primitiveIndex++ )
4904 msg.Printf( wxT(
"ATRACK6 stream tries to access polygon id %u "
4905 "of %u existing polygons; skipping it" ),
4906 static_cast<unsigned>( aElem.
polygon ),
4907 static_cast<unsigned>(
m_polygons.size() ) );
4916 if( zone ==
nullptr )
4964 aPrimitiveIndex, aElem.
layer ) )
4966 int width = aElem.
width + ( layerExpansionMask.second * 2 );
4971 seg->SetStart( aElem.
start );
4972 seg->SetEnd( aElem.
end );
4974 seg->SetLayer( layerExpansionMask.first );
4983 const int aPrimitiveIndex,
4984 const bool aIsBoardImport )
4988 wxFAIL_MSG( wxString::Format( wxT(
"Altium: Unexpected footprint Track with polygon id %u" ),
5022 aPrimitiveIndex, aElem.
layer ) )
5024 int width = aElem.
width + ( layerExpansionMask.second * 2 );
5027 std::unique_ptr<PCB_SHAPE> seg = std::make_unique<PCB_SHAPE>( aFootprint,
SHAPE_T::SEGMENT );
5029 seg->SetStart( aElem.
start );
5030 seg->SetEnd( aElem.
end );
5032 seg->SetLayer( layerExpansionMask.first );
5044 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
5046 track->SetStart( aElem.
start );
5047 track->SetEnd( aElem.
end );
5048 track->SetWidth( aElem.
width );
5049 track->SetLayer( aLayer );
5062 seg->SetStart( aElem.
start );
5063 seg->SetEnd( aElem.
end );
5065 seg->SetLayer( aLayer );
5075 std::unique_ptr<PCB_SHAPE> seg = std::make_unique<PCB_SHAPE>( aFootprint,
SHAPE_T::SEGMENT );
5077 seg->SetStart( aElem.
start );
5078 seg->SetEnd( aElem.
end );
5080 seg->SetLayer( aLayer );
5087 const CFB::COMPOUND_FILE_ENTRY* aEntry )
5097 THROW_IO_ERROR( wxT(
"WideStrings6 stream is not fully parsed" ) );
5101 const CFB::COMPOUND_FILE_ENTRY* aEntry )
5115 THROW_IO_ERROR( wxT(
"SmartUnions6 stream is not fully parsed" ) );
5120 const CFB::COMPOUND_FILE_ENTRY* aEntry )
5125 reader.
Read<uint32_t>();
5129 THROW_IO_ERROR( wxT(
"UnionNames stream is not fully parsed" ) );
5148 if( tuning.baseline.size() < 2
5149 || ( tuning.is_diffpair && tuning.baselinecoupled.size() < 2 ) )
5154 const std::vector<BOARD_ITEM*>& items = itemsIt->second;
5168 std::unique_ptr<PCB_TUNING_PATTERN> pattern(
static_cast<PCB_TUNING_PATTERN*
>( generator ) );
5169 pattern->SetParent(
m_board );
5170 pattern->SetLayer( layer );
5171 pattern->SetTuningMode( mode );
5174 if(
auto nameIt =
m_unionNames.find( tuning.unionindex );
5175 nameIt !=
m_unionNames.end() && !nameIt->second.IsEmpty() )
5177 pattern->SetName( nameIt->second );
5180 pattern->SetMaxAmplitude( tuning.amplitude );
5181 pattern->SetMinAmplitude( tuning.minamplitude );
5182 pattern->SetSpacing( tuning.gap );
5183 pattern->SetSingleSided( tuning.singleside );
5187 pattern->SetRounded( tuning.style != 0 );
5189 if( tuning.mitterradiusratio > 0.0 )
5191 int percent =
KiROUND( tuning.mitterradiusratio * 100.0 );
5192 pattern->SetCornerRadiusPercentage( std::clamp( percent, 0, 100 ) );
5196 bool singleNet =
true;
5200 pattern->AddItem( item );
5205 netCode = bci->GetNetCode();
5206 else if( netCode != bci->GetNetCode() )
5213 if( netCode >= 0 && singleNet )
5215 pattern->SetNetCode( netCode );
5221 SEG::ecoord bestDist = std::numeric_limits<SEG::ecoord>::max();
5233 if( dist < bestDist )
5240 pattern->SetLastNetName( bestNet );
5244 pattern->SetWidth( track->GetWidth() );
5246 pattern->SetBaseLine( baseLine );
5247 pattern->SetPosition( baseLine.
CPoint( 0 ) );
5254 pattern->SetBaseLineCoupled( baseLineCoupled );
5256 int centreToCentre = baseLine.
Distance( baseLineCoupled.
CPoint( 0 ),
false );
5258 pattern->SetDiffPairGap( std::max( centreToCentre - pattern->GetWidth(), 0 ) );
5267 m_reporter->Report( wxString::Format(
_(
"Imported %d length-tuning pattern(s)." ),
5291 footprint->SetAttributes( footprint->GetAttributes() | footprint->GetLikelyAttribute() );
5297 const CFB::COMPOUND_FILE_ENTRY* aEntry )
5356 std::unique_ptr<PCB_TEXTBOX> pcbTextbox = std::make_unique<PCB_TEXTBOX>(
m_board );
5357 std::unique_ptr<PCB_TEXT> pcbText = std::make_unique<PCB_TEXT>(
m_board );
5361 static const std::map<wxString, wxString> variableMap = {
5362 {
"LAYER_NAME",
"LAYER" },
5363 {
"PRINT_DATE",
"CURRENT_DATE"},
5372 item = pcbTextbox.get();
5373 text = pcbTextbox.get();
5376 text->SetText( kicadText );
5401 std::unique_ptr<PCB_TEXTBOX> fpTextbox = std::make_unique<PCB_TEXTBOX>( aFootprint );
5402 std::unique_ptr<PCB_TEXT> fpText = std::make_unique<PCB_TEXT>( aFootprint );
5417 item = &aFootprint->
Value();
5422 item = fpText.get();
5423 text = fpText.get();
5427 static const std::map<wxString, wxString> variableMap = {
5428 {
"DESIGNATOR",
"REFERENCE" },
5429 {
"COMMENT",
"VALUE" },
5430 {
"VALUE",
"ALTIUM_VALUE" },
5431 {
"LAYER_NAME",
"LAYER" },
5432 {
"PRINT_DATE",
"CURRENT_DATE"},
5437 item = fpTextbox.get();
5438 text = fpTextbox.get();
5443 text->SetText( kicadText );
5456 text->SetKeepUpright(
false );
5471 std::unique_ptr<PCB_BARCODE> pcbBarcode = std::make_unique<PCB_BARCODE>(
m_board );
5473 pcbBarcode->SetLayer( aLayer );
5474 pcbBarcode->SetPosition( aElem.
position );
5478 pcbBarcode->SetText( aElem.
text );
5488 pcbBarcode->AssembleBarcode();
5497 std::unique_ptr<PCB_BARCODE> fpBarcode = std::make_unique<PCB_BARCODE>( aFootprint );
5499 fpBarcode->SetLayer( aLayer );
5500 fpBarcode->SetPosition( aElem.
position );
5504 fpBarcode->SetText( aElem.
text );
5514 fpBarcode->AssembleBarcode();
5543 kicadMargin =
VECTOR2I( charWidth * 0.933, charHeight * 0.67 );
5545 kicadMargin =
VECTOR2I( charWidth * 0.808, charHeight * 0.844 );
5548 + kicadMargin * 2 - margin * 2 );
5550 kposition = kposition - kicadMargin + margin;
5567 switch( justification )
5591 msg.Printf(
_(
"Unknown textbox justification %d, aText %s" ), justification,
5611 int rectHeight = aElem.
height;
5629 rectWidth = -rectWidth;
5634 switch( justification )
5640 kposition.
y -= rectHeight;
5646 kposition.
y -= rectHeight / 2;
5656 kposition.
x += rectWidth / 2;
5657 kposition.
y -= rectHeight;
5663 kposition.
x += rectWidth / 2;
5664 kposition.
y -= rectHeight / 2;
5670 kposition.
x += rectWidth / 2;
5676 kposition.
x += rectWidth;
5677 kposition.
y -= rectHeight;
5683 kposition.
x += rectWidth;
5684 kposition.
y -= rectHeight / 2;
5690 kposition.
x += rectWidth;
5743 if( font->
GetName().Contains( wxS(
"Arial" ) ) )
5762 const CFB::COMPOUND_FILE_ENTRY* aEntry )
5820 const bool aIsBoardImport )
5862 fill->SetFilled(
true );
5863 fill->SetLayer( aLayer );
5866 fill->SetStart( aElem.
pos1 );
5867 fill->SetEnd( aElem.
pos2 );
5889 if( aLayer ==
F_Cu || aLayer ==
B_Cu )
5891 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
5894 padLayers.
set( aLayer );
5910 std::swap( width, height );
5913 pad->SetPosition( aElem.
pos1 / 2 + aElem.
pos2 / 2 );
5926 pad->SetPosition( anchorPos );
5937 aElem.
pos1.
y / 2 + aElem.
pos2.
y / 2 - anchorPos.
y );
5939 pad->AddPrimitivePoly(
F_Cu, shapePolys, 0,
true );
5943 pad->SetLayerSet( padLayers );
5949 std::unique_ptr<PCB_SHAPE> fill = std::make_unique<PCB_SHAPE>( aFootprint,
SHAPE_T::RECTANGLE );
5951 fill->SetFilled(
true );
5952 fill->SetLayer( aLayer );
5955 fill->SetStart( aElem.
pos1 );
5956 fill->SetEnd( aElem.
pos2 );
5975 layerSet.
set( klayer );
6004 if( aKeepoutRestrictions != 0 )
6005 return aKeepoutRestrictions;
6037 const uint8_t aKeepoutRestrictions )
6041 if( restrictions == 0 )
6044 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board );
6046 zone->SetIsRuleArea(
true );
6063 const uint8_t aKeepoutRestrictions )
6067 if( restrictions == 0 )
6070 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aFootprint );
6072 zone->SetIsRuleArea(
true );
6096 if( elems.first == elems.second )
6099 std::vector<std::pair<PCB_LAYER_ID, int>> layerExpansionPairs;
6101 for(
auto it = elems.first; it != elems.second; ++it )
6141 return layerExpansionPairs;
std::string FormatPath(const std::vector< std::string > &aVectorPath)
Helper for debug logging (vector -> string)
VECTOR2I altiumSlotDrillSize(uint32_t aHoleSize, uint32_t aSlotSize, double aSlotRotation, bool &aRotationSupported)
Convert an Altium slot's independent rotation and dimensions to KiCad's cardinal drill shape.
const ARULE6 * selectAltiumPolygonRule(const std::vector< ARULE6 > &aRulesByPriorityAsc)
Select the highest Altium-priority rule whose scope references polygons.
bool altiumViaSideIsTented(bool aTentFlag, bool aManual, bool aFromHole, uint32_t aHoleSize, int32_t aMaskExpansion, int aLandDiameter)
Decide whether one side of an Altium via should be tented when imported into KiCad.
const uint8_t ALTIUM_KEEPOUT_VIA
const uint8_t ALTIUM_KEEPOUT_COPPER
const uint8_t ALTIUM_KEEPOUT_SMD_PAD
@ BOARD_OUTLINE_CLEARANCE
const uint8_t ALTIUM_KEEPOUT_TH_PAD
const uint8_t ALTIUM_KEEPOUT_TRACK
const uint8_t ALTIUM_KEEPOUT_ALL
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)
constexpr int ALTIUM_PADSTACK_IDX_COUNT
constexpr int ALTIUM_BOTTOM_PADSTACK_IDX
static bool IsLayerNameAssembly(const wxString &aName)
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
constexpr int ALTIUM_TOP_PADSTACK_IDX
static void altiumCollectSchematicNetNames(const wxString &aFileName, std::map< wxString, wxString > &aNames, std::set< wxString > &aAmbiguous)
static bool GetAltiumNetclassScopeName(const ARULE6 &aRule, wxString *aNetclassName)
wxString AltiumUnnamedNetName(const BOARD &aBoard, int &aCounter)
Invent a placeholder name for an Altium net that has none.
constexpr int ALTIUM_MID2_PADSTACK_IDX
static bool IsAltiumScopeAll(const wxString &aExpr)
static bool IsLayerNameCourtyard(const wxString &aName)
bool IsAltiumLayerCopper(ALTIUM_LAYER aLayer)
void ApplyAltiumNetclassRules(const std::map< ALTIUM_RULE_KIND, std::vector< ARULE6 > > &aRulesByKind, NET_SETTINGS &aNetSettings, std::vector< const ARULE6 * > *aUnresolved)
Copy the values of Altium rules scoped to a single netclass onto that netclass.
bool IsAltiumLayerAPlane(ALTIUM_LAYER aLayer)
static bool IsLayerNameTopSide(const wxString &aName)
constexpr int ALTIUM_MID1_PADSTACK_IDX
void ApplyAltiumNetclassRules(const std::map< ALTIUM_RULE_KIND, std::vector< ARULE6 > > &aRulesByKind, NET_SETTINGS &aNetSettings, std::vector< const ARULE6 * > *aUnresolved=nullptr)
Copy the values of Altium rules scoped to a single netclass onto that netclass.
wxString AltiumUnnamedNetName(const BOARD &aBoard, int &aCounter)
Invent a placeholder name for an Altium net that has none.
@ EXTENDPRIMITIVEINFORMATION
std::function< void(const ALTIUM_PCB_COMPOUND_FILE &, const CFB::COMPOUND_FILE_ENTRY *)> PARSE_FUNCTION_POINTER_fp
KIID AltiumUniqueIdToKiid(const wxString &aUniqueId)
Derive a stable KIID from an Altium component unique id.
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.
std::map< wxString, wxString > ReadProperties()
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
std::shared_ptr< EMBEDDED_FILES::EMBEDDED_FILE > HelperEmbedModel(FOOTPRINT *aFootprint, const wxString &aModelName, const std::vector< char > &aCompressedData, bool &aIsNew)
Return the 3D model aModelName embedded in aFootprint, inflating and embedding aCompressedData first ...
void ParseClasses6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
std::vector< PCB_DIM_RADIAL * > m_radialDimensions
const ARULE6 * GetRuleForPolygon(ALTIUM_RULE_KIND aKind) const
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 HelperCreateTuningPatterns()
void ConvertTexts6ToFootprintItemOnLayer(FOOTPRINT *aFootprint, const ATEXT6 &aElem, PCB_LAYER_ID aLayer)
std::map< ALTIUM_LAYER, PCB_LAYER_ID > m_layermap
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 HelperFillMechanicalLayerAssignments(const std::vector< ABOARD6_LAYER_STACKUP > &aStackup)
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
std::map< uint32_t, wxString > m_unionNames
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 ConvertBarcodes6ToBoardItemOnLayer(const ATEXT6 &aElem, PCB_LAYER_ID aLayer)
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 HelperCreateBoardOutline(const std::vector< ALTIUM_VERTICE > &aVertices)
std::map< int, std::vector< BOARD_ITEM * > > m_unionToBoardItems
void HelperAssignNetclassesToNets()
Rebuild the composite netclasses and point every net at its effective netclass.
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 MapSchematicNetNames(const std::map< std::string, UTF8 > &aProperties)
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 ParseUnionNamesData(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
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)
std::unique_ptr< 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)
void HelperBuildPadstackLayerIndex()
wxString m_library
for footprint library loading error reporting
void ConvertPads6ToFootprintItemOnNonCopper(FOOTPRINT *aFootprint, const APAD6 &aElem)
std::map< wxString, wxString > m_schematicNetNames
void ConvertShapeBasedRegions6ToBoardItemOnLayer(const AREGION6 &aElem, PCB_LAYER_ID aLayer, const int aPrimitiveIndex)
void ConvertTexts6ToFootprintItem(FOOTPRINT *aFootprint, const ATEXT6 &aElem)
unsigned m_lastProgressCount
void ParseFills6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
uint8_t HelperGetKeepoutRestrictions(const uint8_t aKeepoutRestrictions, const ALTIUM_LAYER aAltiumLayer)
Resolve an Altium keepout restriction mask, substituting the restrictions implied by the layer when t...
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< ASMARTUNION6 > m_tuningUnions
void HelperSetFootprintMountingStyles()
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)
std::map< PCB_LAYER_ID, int > m_padstackLayerIndex
void Parse(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const std::map< ALTIUM_PCB_DIR, std::string > &aFileMapping, const std::map< std::string, UTF8 > *aProperties=nullptr)
FOOTPRINT * HelperGetFootprint(uint16_t aComponent) const
void HelperFootprintZoneToLibFrame(ZONE &aZone, const FOOTPRINT &aFootprint)
LAYER_MAPPING_HANDLER m_layerMappingHandler
void ConvertShapeBasedRegions6ToBoardItem(const AREGION6 &aElem, const int aPrimitiveIndex)
void ParsePolygons6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
PCB_LAYER_ID GetKicadLayer(ALTIUM_LAYER aAltiumLayer) const
int HelperGetPadstackLayerIndex(PCB_LAYER_ID aLayer) const
Return the slot aLayer occupies in an Altium padstack's per-layer arrays.
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 ParseSmartUnions6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
wxString SchematicCasedNetName(const wxString &aNetName) const
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 ConvertBarcodes6ToFootprintItemOnLayer(FOOTPRINT *aFootprint, const ATEXT6 &aElem, PCB_LAYER_ID aLayer)
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 int ReadInt(const std::map< wxString, wxString > &aProps, const wxString &aKey, int aDefault)
static wxString ReadString(const std::map< wxString, wxString > &aProps, const wxString &aKey, const wxString &aDefault)
BASE_SET & set(size_t pos)
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
wxString GetNetname() const
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.
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
constexpr coord_type GetY() const
constexpr size_type GetWidth() const
constexpr coord_type GetX() const
constexpr size_type GetHeight() const
bool IsCardinal90() const
void SetCenter(const VECTOR2I &aCenter)
virtual void SetFilled(bool aFlag)
void SetPolyPoints(const std::vector< VECTOR2I > &aPoints)
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
virtual void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
virtual void SetTextPos(const VECTOR2I &aPoint)
virtual int GetTextHeight() const
KIFONT::FONT * GetFont() const
void SetMirrored(bool isMirrored)
BOX2I GetTextBox(const RENDER_SETTINGS *aSettings, int aLine=-1) const
Useful in multiline texts to calculate the full text or a line area (for zones filling,...
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
virtual int GetTextWidth() const
void SetBoldFlag(bool aBold)
Set only the bold flag, without changing the font.
void MigrateLegacyBoldStrokeWidth()
Migrate a pre-v11 bold stroke text so its stored thickness holds the base (non-bold) width.
virtual void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
int GetEffectiveTextPenWidth(int aDefaultPenWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
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)
EMBEDDED_FILE * AddFile(const wxFileName &aName, bool aOverwrite)
Load a file from disk and adds it to the collection.
const std::map< wxString, std::shared_ptr< EMBEDDED_FILE > > & EmbeddedFileMap() const
Provide an iterable view of the file collection.
static RETURN_CODE CompressAndEncode(EMBEDDED_FILE &aFile)
Take data from the decompressedData buffer and compresses it using ZSTD into the compressedEncodedDat...
VECTOR3D m_Offset
3D model offset (mm)
VECTOR3D m_Rotation
3D model rotation (degrees)
wxString m_Filename
The 3D shape filename in 3D library.
PCB_GENERATOR * CreateFromType(const wxString &aTypeStr)
static GENERATORS_MGR & Instance()
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 & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
static const LSET & UserMask()
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
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 ...
NET_SETTINGS stores various net-related settings in a project context.
const std::map< wxString, std::shared_ptr< NETCLASS > > & GetNetclasses() const
Gets all netclasses.
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 SetOffset(const VECTOR2I &aOffset, 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
! The layer identifier to use for the single defintion on normal padstacks
static constexpr PCB_LAYER_ID INNER_LAYERS
! The layer identifier to use for "inner layers" on top/inner/bottom padstacks
void SetAnchorPadShape(PCB_LAYER_ID aLayer, PAD_SHAPE aShape)
Set the shape of the anchor pad for custom shaped pads.
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
const std::vector< std::shared_ptr< PCB_SHAPE > > & GetPrimitives(PCB_LAYER_ID aLayer) const
Accessor to the basic shape list for custom-shaped pads.
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Test to see if this object is on the given layer.
static LSET PTHMask()
layer set for a through hole pad
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc=ERROR_INSIDE, bool aIgnoreLineWidth=false) const override
Convert the pad shape to a closed polygon.
void SetShape(PCB_LAYER_ID aLayer, PAD_SHAPE aShape)
Set the new shape of this pad.
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
PAD_SHAPE GetShape(PCB_LAYER_ID aLayer) const
void AddPrimitive(PCB_LAYER_ID aLayer, PCB_SHAPE *aPrimitive)
Add item to the custom shape primitives list.
void SetLocalSolderMaskMargin(std::optional< int > aMargin)
VECTOR2I GetSize(PCB_LAYER_ID aLayer) const
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
void SetSize(PCB_LAYER_ID aLayer, const VECTOR2I &aSize)
static LSET SMDMask()
layer set for a SMD pad on Front layer
std::optional< int > GetLocalSolderPasteMargin() const
std::optional< int > GetLocalSolderMaskMargin() const
void SetLocalSolderPasteMargin(std::optional< int > aMargin)
VECTOR2I ShapePos(PCB_LAYER_ID aLayer) const
void SetLayerSet(const LSET &aLayers) override
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.
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
void SetArcAngleAndEnd(const EDA_ANGLE &aAngle, bool aCheckNegativeAngle=false)
void SetShape(SHAPE_T aShape) override
void SetPosition(const VECTOR2I &aPos) override
void SetEnd(const VECTOR2I &aEnd) override
void SetPolyShape(const SHAPE_POLY_SET &aShape) override
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void Move(const VECTOR2I &aMoveVector) override
Move this object.
void SetStart(const VECTOR2I &aStart) override
void SetStroke(const STROKE_PARAMS &aStroke) override
VECTOR2I GetPosition() const override
void SetBorderEnabled(bool enabled)
Disables the border, this is done by changing the stroke internally.
void SetMarginTop(int aTop)
void SetMarginLeft(int aLeft)
void SetMarginBottom(int aBottom)
void SetTextAngle(const EDA_ANGLE &aAngle) override
void SetMarginRight(int aRight)
const VECTOR2I & GetStart() const
const VECTOR2I & GetEnd() const
A progress reporter interface for use in multi-threaded environments.
A pure virtual class used to derive REPORTER objects from.
ecoord SquaredDistance(const SEG &aSeg) const
VECTOR2I::extended_type ecoord
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 Distance(const VECTOR2I &aP, bool aOutlineOnly) 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.
const VECTOR2I & CLastPoint() const
Return the last 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.
ITERATOR IterateWithHoles(int aOutline)
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
void SetVertex(const VERTEX_INDEX &aIndex, const VECTOR2I &aPos)
Accessor function to set the position of a specific point.
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
void Fracture(bool aSimplify=true)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
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 * Outline()
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.
@ ROUND_ALL_CORNERS
All angles are rounded.
static constexpr EDA_ANGLE ANGLE_0
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
#define THROW_IO_ERRORF(msg,...)
#define THROW_IO_CANCELLED()
wxString LayerName(int aLayer)
Returns the default display name for a given layer.
#define MAX_USER_DEFINED_LAYERS
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:
const std::vector< uint8_t > COMPOUND_FILE_HEADER
bool fileHasBinaryHeader(const wxString &aFilePath, const std::vector< uint8_t > &aHeader, size_t aOffset)
Check if a file starts with a defined binary header.
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.
PAD_SHAPE
The set of pad shapes, used with PAD::{Set,Get}Shape()
BARCODE class definition.
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
double dielectriclosstangent
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< ABOARD6_LAYER_STACKUP > stackup
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
int32_t pad_to_die_length
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_BARCODE_TYPE barcode_type
ALTIUM_TEXT_TYPE fonttype
uint8_t keepoutrestrictions
bool soldermask_expansion_from_hole
int32_t soldermask_expansion_front
bool soldermask_expansion_manual
int32_t soldermask_expansion_back
uint32_t diameter_by_layer[32]
KIBIS top(path, &reporter)
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
BS::priority_thread_pool thread_pool
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