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>
105 name = wxString::Format( wxT(
"__ALTIUM_UNNAMED_NET_%d" ), ++aCounter );
115 return aExpr.IsSameAs( wxS(
"All" ),
false );
121 static const wxString prefix = wxT(
"InNetClass('" );
124 || !aRule.
scope1expr.EndsWith( wxT(
"')" ) ) )
129 *aNetclassName = aRule.
scope1expr.Mid( prefix.Length(),
130 aRule.
scope1expr.Length() - prefix.Length() - 2 );
132 return !aNetclassName->IsEmpty();
137 NET_SETTINGS& aNetSettings, std::vector<const ARULE6*>* aUnresolved )
139 const std::map<wxString, std::shared_ptr<NETCLASS>>& netclasses = aNetSettings.
GetNetclasses();
141 for(
const auto& [kind, rules] : aRulesByKind )
149 std::set<wxString> applied;
151 for(
const ARULE6& rule : rules )
153 wxString netclassName;
158 auto it = netclasses.find( netclassName );
160 if( it == netclasses.end() )
163 aUnresolved->push_back( &rule );
169 if( !applied.insert( netclassName ).second )
172 const std::shared_ptr<NETCLASS>& netclass = it->second;
181 netclass->SetViaDiameter( rule.width );
182 netclass->SetViaDrill( rule.holeWidth );
196 THROW_IO_ERRORF( wxT(
"Component creator tries to access component id %u of %u existing components" ),
204std::shared_ptr<EMBEDDED_FILES::EMBEDDED_FILE>
206 const std::vector<char>& aCompressedData,
bool& aIsNew )
210 auto it = files.find( aModelName );
212 aIsNew = it == files.end();
219 auto file = std::make_shared<EMBEDDED_FILES::EMBEDDED_FILE>();
220 file->name = aModelName;
223 wxMemoryInputStream compressedStream( aCompressedData.data(), aCompressedData.size() );
224 wxZlibInputStream zlibStream( compressedStream );
228 file->decompressedData.resize( aCompressedData.size() * 6 );
231 while( !zlibStream.Eof() )
233 zlibStream.Read( file->decompressedData.data() + offset,
234 file->decompressedData.size() - offset );
236 size_t bytesRead = zlibStream.LastRead();
243 if( offset >= file->decompressedData.size() )
244 file->decompressedData.resize( 2 * file->decompressedData.size() );
247 file->decompressedData.resize( offset );
251 file->decompressedData.shrink_to_fit();
253 embeddedFiles->
AddFile( file );
260 const std::vector<ALTIUM_VERTICE>& aVertices )
269 double startradiant =
DEG2RAD( vertex.startangle );
270 double endradiant =
DEG2RAD( vertex.endangle );
271 VECTOR2I arcStartOffset =
KiROUND( std::cos( startradiant ) * vertex.radius,
272 -std::sin( startradiant ) * vertex.radius );
274 VECTOR2I arcEndOffset =
KiROUND( std::cos( endradiant ) * vertex.radius,
275 -std::sin( endradiant ) * vertex.radius );
277 VECTOR2I arcStart = vertex.center + arcStartOffset;
278 VECTOR2I arcEnd = vertex.center + arcEndOffset;
283 if( arcStart.
Distance( vertex.position )
284 < arcEnd.
Distance( vertex.position ) )
311 aLine.
Append( vertex.position );
321 auto override =
m_layermap.find( aAltiumLayer );
325 return override->second;
340 switch( aAltiumLayer )
442 std::vector<PCB_LAYER_ID> layers;
443 layers.reserve( layerCount );
448 layers.emplace_back( layer );
465 const wxString& aLibrary,
const wxString& aFootprintName )
485 const unsigned PROGRESS_DELTA = 250;
502 const std::map<ALTIUM_PCB_DIR, std::string>& aFileMapping,
503 const std::map<std::string, UTF8>* aProperties )
509 const std::vector<std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>> parserOrder = {
631 for(
const std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>& cur : parserOrder )
636 std::tie( isRequired,
directory, fp ) = cur;
641 const auto& mappedDirectory = aFileMapping.find(
directory );
643 if( mappedDirectory == aFileMapping.end() )
646 const std::vector<std::string> mappedFile{ mappedDirectory->second,
"Header" };
647 const CFB::COMPOUND_FILE_ENTRY* file = altiumPcbFile.
FindStream( mappedFile );
649 if( file ==
nullptr )
653 uint32_t numOfRecords = reader.
Read<uint32_t>();
659 m_reporter->Report( wxString::Format(
_(
"'%s' was not parsed correctly." ),
673 m_reporter->Report( wxString::Format(
_(
"'%s' was not fully parsed." ),
685 if( boardDirectory != aFileMapping.end() )
687 std::vector<std::string> mappedFile{ boardDirectory->second,
"Data" };
689 const CFB::COMPOUND_FILE_ENTRY* file = altiumPcbFile.
FindStream( mappedFile );
693 THROW_IO_ERROR(
_(
"This file does not appear to be in a valid PCB Binary Version 6.0 format. In "
694 "Altium Designer, make sure to save as \"PCB Binary Files (*.PcbDoc)\"." ) );
699 for(
const std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>& cur : parserOrder )
704 std::tie( isRequired,
directory, fp ) = cur;
706 const auto& mappedDirectory = aFileMapping.find(
directory );
708 if( mappedDirectory == aFileMapping.end() )
710 wxASSERT_MSG( !isRequired, wxString::Format( wxT(
"Altium Directory of kind %d was "
711 "expected, but no mapping is "
712 "present in the code" ),
717 std::vector<std::string> mappedFile{ mappedDirectory->second };
720 mappedFile.emplace_back(
"Data" );
722 const CFB::COMPOUND_FILE_ENTRY* file = altiumPcbFile.
FindStream( mappedFile );
724 if( file !=
nullptr )
726 fp( altiumPcbFile, file );
728 else if( isRequired )
732 m_reporter->Report( wxString::Format(
_(
"File not found: '%s' for directory '%s'." ),
755 if( zone->GetAssignedPriority() == 1000 )
766 zone->SetAssignedPriority( priority >= 0 ? priority : 0 );
770 for( std::pair<const ALTIUM_LAYER, ZONE*>& zone :
m_outer_plane )
771 zone.second->SetAssignedPriority( 0 );
781 if( !zone->HasFilledPolysForLayer( layer ) )
784 zone->GetFilledPolysList( layer )->Fracture();
822 if( arc->
GetCenter() == dim->GetPosition() )
831 VECTOR2I radialLine = dim->GetEnd() - dim->GetStart();
836 radialLine = radialLine.
Resize( std::max(
radius, 2 ) );
837 dim->SetEnd( dim->GetStart() + (
VECTOR2I) radialLine );
838 dim->SetLeaderLength( totalLength -
radius );
848 int desired_x = ( w - bbbox.
GetWidth() ) / 2;
849 int desired_y = ( h - bbbox.
GetHeight() ) / 2;
851 VECTOR2I movementVector( desired_x - bbbox.
GetX(), desired_y - bbbox.
GetY() );
852 m_board->Move( movementVector );
858 m_board->m_LegacyDesignSettingsLoaded =
true;
864 const wxString& aFootprintName )
866 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
871 const std::vector<std::string> libStreamName{
"Library",
"Data" };
872 const CFB::COMPOUND_FILE_ENTRY* libStream = altiumLibFile.
FindStream( libStreamName );
874 if( libStream ==
nullptr )
890 std::tuple<wxString, const CFB::COMPOUND_FILE_ENTRY*> ret =
893 wxString fpDirName = std::get<0>( ret );
894 const CFB::COMPOUND_FILE_ENTRY* footprintStream = std::get<1>( ret );
896 if( fpDirName.IsEmpty() )
897 THROW_IO_ERRORF(
_(
"Footprint directory not found: '%s'." ), aFootprintName );
899 const std::vector<std::string> streamName{ fpDirName.ToStdString(),
"Data" };
900 const CFB::COMPOUND_FILE_ENTRY* footprintData = altiumLibFile.
FindStream( footprintStream, {
"Data" } );
912 footprint->SetFPID( fpID );
914 const std::vector<std::string> parametersStreamName{ fpDirName.ToStdString(),
"Parameters" };
915 const CFB::COMPOUND_FILE_ENTRY* parametersData = altiumLibFile.
FindStream( footprintStream, {
"Parameters" } );
917 if( parametersData !=
nullptr )
920 std::map<wxString, wxString> parameterProperties = parametersReader.
ReadProperties();
922 footprint->SetLibDescription( description );
928 m_reporter->Report( wxString::Format(
_(
"File not found: '%s'." ),
FormatPath( parametersStreamName ) ),
932 footprint->SetLibDescription( wxT(
"" ) );
935 const std::vector<std::string> extendedPrimitiveInformationStreamName{
936 "ExtendedPrimitiveInformation",
"Data"
938 const CFB::COMPOUND_FILE_ENTRY* extendedPrimitiveInformationData =
939 altiumLibFile.
FindStream( footprintStream, extendedPrimitiveInformationStreamName );
941 if( extendedPrimitiveInformationData !=
nullptr )
944 footprint->SetReference( wxT(
"REF**" ) );
945 footprint->SetValue( aFootprintName );
946 footprint->Reference().SetVisible(
true );
947 footprint->Value().SetVisible(
true );
950 const int defaultTextThickness(
pcbIUScale.mmToIU( 0.15 ) );
952 for(
PCB_FIELD* field : footprint->GetFields() )
954 field->SetTextSize( defaultTextSize );
955 field->SetTextThickness( defaultTextThickness );
1019 for(
bool changes =
true; changes; )
1024 [&changes](
PAD* aPad1,
PAD* aPad2 )
1026 if( !( aPad1->GetNumber().IsEmpty() ^ aPad2->GetNumber().IsEmpty() ) )
1029 for( PCB_LAYER_ID layer : aPad1->GetLayerSet() )
1031 std::shared_ptr<SHAPE> shape1 = aPad1->GetEffectiveShape( layer );
1032 std::shared_ptr<SHAPE> shape2 = aPad2->GetEffectiveShape( layer );
1034 if( shape1->Collide( shape2.get() ) )
1036 if( aPad1->GetNumber().IsEmpty() )
1037 aPad1->SetNumber( aPad2->GetNumber() );
1039 aPad2->SetNumber( aPad1->GetNumber() );
1048 footprint->AutoPositionFields();
1053 footprint->SetAttributes( footprint->GetAttributes() | footprint->GetLikelyAttribute() );
1055 if( parser.HasParsingError() )
1058 if( parser.GetRemainingBytes() != 0 )
1072 THROW_IO_ERRORF( wxT(
"Netcode with id %d does not exist. Only %zu nets are known" ),
1083 const auto rules =
m_rules.find( aKind );
1088 for(
const ARULE6& rule : rules->second )
1099 const auto rules =
m_rules.find( aKind );
1104 for(
const ARULE6& rule : rules->second )
1116 const auto rules =
m_rules.find( aKind );
1130 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1148 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1161 std::move( elem ) );
1165 THROW_IO_ERROR( wxT(
"ExtendedPrimitiveInformation stream is not fully parsed" ) );
1170 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1187 size_t layercount = 0;
1190 while( layerid < elem.
stackup.size() && layerid != 0 )
1192 layerid = elem.
stackup[ layerid - 1 ].nextId;
1196 size_t kicadLayercount = ( layercount % 2 == 0 ) ? layercount : layercount + 1;
1197 m_board->SetCopperLayerCount( kicadLayercount );
1206 auto it = stackup.
GetList().begin();
1215 altiumLayerId < elem.
stackup.size() && altiumLayerId != 0;
1216 altiumLayerId = elem.
stackup[altiumLayerId - 1].nextId )
1222 if( layer.
nextId == 0 && layercount != kicadLayercount )
1224 m_board->SetLayerName( ( *it )->GetBrdLayerId(), wxT(
"[unused]" ) );
1227 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
1229 ( *it )->SetThickness( 0 );
1234 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
1236 ( *it )->SetThickness( 0, 0 );
1237 ( *it )->SetThicknessLocked(
true, 0 );
1245 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
1259 if( klayer ==
B_Cu )
1262 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected id while parsing last stackup layer" ) );
1272 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
1304 m_reporter->Report( wxString::Format(
_(
"Board outline has %d vertices outside the "
1305 "coordinate range; they were dropped." ),
1321 for(
const auto& [altiumLayer, kicadLayer] :
m_layermap )
1342 return ordinal < ALTIUM_PADSTACK_IDX_COUNT ? static_cast<int>( ordinal ) : -1;
1354 wxString nameLower = aName.Lower();
1355 return nameLower.Contains( wxT(
"courtyard" ) ) || nameLower.Contains( wxT(
"court yard" ) )
1356 || nameLower.Contains( wxT(
"crtyd" ) );
1363 wxString nameLower = aName.Lower();
1364 return nameLower.Contains( wxT(
"assembly" ) ) || nameLower.Contains( wxT(
"assy" ) );
1373 auto check = [&isTop](
bool aTopCond,
bool aBotCond )
1375 if( aTopCond && aBotCond )
1378 if( !aTopCond && !aBotCond )
1385 wxString lower = aName.Lower();
1387 if( check( lower.StartsWith(
"top" ), lower.StartsWith(
"bot" ) ) )
1390 if( check( lower.EndsWith(
"_t" ), lower.EndsWith(
"_b" ) ) )
1393 if( check( lower.EndsWith(
".t" ), lower.EndsWith(
".b" ) ) )
1396 if( check( lower.Contains(
"top" ), lower.Contains(
"bot" ) ) )
1409 if( aStackup.size() == 0 )
1412 std::vector<INPUT_LAYER_DESC> inputLayers;
1413 std::map<wxString, ALTIUM_LAYER> altiumLayerNameMap;
1420 bool frontCourtyardMapped =
false;
1421 bool backCourtyardMapped =
false;
1423 for(
size_t ii = 0; ii < aStackup.size(); ii++ )
1425 curLayer = aStackup[ii];
1444 auto existingMapping =
m_layermap.find( layer_num );
1472 if( isTopSide && !frontCourtyardMapped )
1475 frontCourtyardMapped =
true;
1477 else if( !isTopSide && !backCourtyardMapped )
1480 backCourtyardMapped =
true;
1482 else if( !frontCourtyardMapped )
1485 frontCourtyardMapped =
true;
1487 else if( !backCourtyardMapped )
1490 backCourtyardMapped =
true;
1513 inputLayers.push_back( iLdesc );
1514 altiumLayerNameMap.insert( { curLayer.
name, layer_num } );
1518 if( inputLayers.size() == 0 )
1524 for( std::pair<wxString, PCB_LAYER_ID> layerPair : reMappedLayers )
1532 m_reporter->Report( wxString::Format(
_(
"Layer '%s' could not be mapped and "
1533 "will be skipped." ),
1541 ALTIUM_LAYER altiumID = altiumLayerNameMap.at( layerPair.first );
1542 m_layermap.insert_or_assign( altiumID, layerPair.second );
1543 enabledLayers |=
LSET( { layerPair.second } );
1548 for(
const auto& [
name, altLayer] : altiumLayerNameMap )
1550 if( reMappedLayers.find(
name ) == reMappedLayers.end()
1557 m_board->SetEnabledLayers( enabledLayers );
1558 m_board->SetVisibleLayers( enabledLayers );
1571 if( !layer.mechenabled )
1579 switch( layer.mechkind )
1640 shape->SetStroke( stroke );
1652 shape->SetStroke( stroke );
1654 shape->SetStart( seg.
A );
1655 shape->SetEnd( seg.
B );
1664 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1678 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( elem.
name,
false );
1680 for(
const wxString&
name : elem.
names )
1686 if(
m_board->GetDesignSettings().m_NetSettings->HasNetclass( nc->GetName() ) )
1693 msg.Printf(
_(
"More than one Altium netclass with name '%s' found. "
1694 "Only the first one will be imported." ), elem.
name );
1700 m_board->GetDesignSettings().m_NetSettings->SetNetclass( nc->GetName(), nc );
1712 m_board->m_LegacyNetclassesLoaded =
true;
1718 std::shared_ptr<NET_SETTINGS> netSettings =
m_board->GetDesignSettings().m_NetSettings;
1720 netSettings->RecomputeEffectiveNetclasses();
1724 if( net->GetNetCode() <= 0 )
1727 if( std::shared_ptr<NETCLASS> netclass = netSettings->GetEffectiveNetClass( net->GetNetname() ) )
1728 net->SetNetClass( netclass );
1734 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1746 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
1757 wxString fpName = elem.
pattern;
1759 if( fpName.Contains( wxT(
"\\" ) ) || fpName.Contains( wxT(
"/" ) ) )
1761 wxFileName fpPath( fpName, wxPATH_WIN );
1762 fpName = fpPath.GetFullName();
1767 footprint->SetFPID( fpID );
1769 footprint->SetPosition( elem.
position );
1770 footprint->SetOrientationDegrees( elem.
rotation );
1776 if( reference.find_first_not_of(
"0123456789" ) == wxString::npos )
1777 reference.Prepend( wxT(
"UNK" ) );
1779 footprint->SetReference( reference );
1784 path.push_back( pathid );
1785 path.push_back(
id );
1787 footprint->SetPath(
path );
1791 footprint->SetLocked( elem.
locked );
1792 footprint->Reference().SetVisible( elem.
nameon );
1793 footprint->Value().SetVisible( elem.
commenton );
1801 THROW_IO_ERROR( wxT(
"Components6 stream is not fully parsed" ) );
1808 while( Angle < aMin )
1811 while( Angle >= aMax )
1834 m_reporter->Report( wxString::Format( wxT(
"Model %s not found for footprint %s" ),
1845 std::shared_ptr<EMBEDDED_FILES::EMBEDDED_FILE> file =
1864 orientation = -orientation;
1871 modelRotation.
x += 180;
1872 modelRotation.
z = -modelRotation.
z;
1886 aFootprint->
Models().push_back( modelSettings );
1891 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1897 BS::multi_future<void> embeddedFutures;
1908 if( skipComponentBodies )
1916 THROW_IO_ERRORF( wxT(
"ComponentsBodies6 stream tries to access component id %d of %zu existing "
1932 msg.Printf( wxT(
"ComponentsBodies6 stream tries to access model id %s which does "
1933 "not exist" ), elem.
modelId );
1944 std::shared_ptr<EMBEDDED_FILES::EMBEDDED_FILE> file =
1951 embeddedFutures.push_back(
tp.submit_task(
1954 EMBEDDED_FILES::CompressAndEncode( *file );
1974 orientation = -orientation;
1997 footprint->
Models().push_back( modelSettings );
2000 embeddedFutures.wait();
2003 THROW_IO_ERROR( wxT(
"ComponentsBodies6 stream is not fully parsed" ) );
2010 THROW_IO_ERROR( wxT(
"Incorrect number of reference points for linear dimension object" ) );
2019 _(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
2020 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer ),
2033 dimension->SetLayer( klayer );
2034 dimension->SetStart( referencePoint0 );
2036 if( referencePoint0 != aElem.
xy1 )
2048 VECTOR2I referenceDiff = referencePoint1 - referencePoint0;
2050 SEG segm1( referencePoint0, referencePoint0 + directionNormalVector );
2051 SEG segm2( referencePoint1, referencePoint1 + direction );
2055 THROW_IO_ERROR( wxT(
"Invalid dimension. This should never happen." ) );
2057 dimension->SetEnd( *intersection );
2061 if( direction.
Cross( referenceDiff ) > 0 )
2064 dimension->SetHeight( height );
2068 dimension->SetEnd( referencePoint1 );
2071 dimension->SetLineThickness( aElem.
linewidth );
2077 int dist = ( dimension->GetEnd() - dimension->GetStart() ).EuclideanNorm();
2079 if( dist < 3 * dimension->GetArrowLength() )
2083 wxRegEx units( wxS(
"(mm)|(in)|(mils)|(thou)|(')|(\")" ), wxRE_ADVANCED );
2095 dimension->Text().SetBold( aElem.
textbold );
2098 dimension->SetTextThickness( dimension->GetTextThickness() *
BOLD_FACTOR );
2117 THROW_IO_ERROR( wxT(
"Not enough reference points for radial dimension object" ) );
2126 _(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
2127 "It has been moved to KiCad layer Eco1_User." ),
2136 std::unique_ptr<PCB_DIM_RADIAL> dimension = std::make_unique<PCB_DIM_RADIAL>(
m_board );
2139 dimension->SetLayer( klayer );
2140 dimension->SetStart( referencePoint0 );
2141 dimension->SetEnd( aElem.
xy1 );
2142 dimension->SetLineThickness( aElem.
linewidth );
2143 dimension->SetKeepTextAligned(
false );
2164 m_reporter->Report( wxT(
"No text position present for leader dimension object" ),
2171 dimension->SetTextPos( aElem.
textPoint.at( 0 ) );
2177 dimension->SetBold( aElem.
textbold );
2180 dimension->SetTextThickness( dimension->GetTextThickness() *
BOLD_FACTOR );
2188 int yAdjust = dimension->GetTextBox(
nullptr ).GetCenter().y - dimension->GetTextPos().y;
2189 dimension->SetTextPos( dimension->GetTextPos() +
VECTOR2I( 0, yAdjust + aElem.
textgap ) );
2206 msg.Printf(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
2207 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer );
2224 shape->SetLayer( klayer );
2226 shape->SetStart( last );
2238 if( dirVec.
x != 0 || dirVec.
y != 0 )
2247 shape1->SetLayer( klayer );
2249 shape1->SetStart( referencePoint0 );
2250 shape1->SetEnd( referencePoint0 + arrVec );
2260 shape2->SetLayer( klayer );
2262 shape2->SetStart( referencePoint0 );
2263 shape2->SetEnd( referencePoint0 + arrVec );
2275 m_reporter->Report( wxT(
"No text position present for leader dimension object" ),
2282 std::unique_ptr<PCB_TEXT>
text = std::make_unique<PCB_TEXT>(
m_board );
2286 text->SetLayer( klayer );
2305 msg.Printf(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
2306 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer );
2317 shape->SetLayer( klayer );
2336 msg.Printf(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
2337 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer );
2347 std::unique_ptr<PCB_DIM_CENTER> dimension = std::make_unique<PCB_DIM_CENTER>(
m_board );
2349 dimension->SetLayer( klayer );
2350 dimension->SetLineThickness( aElem.
linewidth );
2351 dimension->SetStart( aElem.
xy1 );
2352 dimension->SetEnd( aElem.
xy1 + vec );
2359 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2379 m_reporter->Report( wxString::Format(
_(
"Ignored Angular dimension (not yet supported)." ) ),
2392 m_reporter->Report( wxString::Format(
_(
"Ignored Datum dimension (not yet supported)." ) ),
2400 m_reporter->Report( wxString::Format(
_(
"Ignored Baseline dimension (not yet supported)." ) ),
2410 m_reporter->Report( wxString::Format(
_(
"Ignored Linear dimension (not yet supported)." ) ),
2417 m_reporter->Report( wxString::Format(
_(
"Ignored Radial dimension (not yet supported)." ) ),
2425 msg.Printf(
_(
"Ignored dimension of kind %d (not yet supported)." ), elem.
kind );
2433 THROW_IO_ERROR( wxT(
"Dimensions6 stream is not fully parsed" ) );
2438 const CFB::COMPOUND_FILE_ENTRY* aEntry,
2439 const std::vector<std::string>& aRootDir )
2450 wxString invalidChars = wxFileName::GetForbiddenChars();
2457 std::vector<std::string> stepPath = aRootDir;
2458 stepPath.emplace_back( std::to_string( idx ) );
2460 bool validName = !elem.
name.IsEmpty() && elem.
name.IsAscii()
2461 && wxString::npos == elem.
name.find_first_of( invalidChars );
2462 wxString storageName = validName ? elem.
name : wxString::Format( wxT(
"model_%d" ), idx );
2466 const CFB::COMPOUND_FILE_ENTRY* stepEntry = aAltiumPcbFile.
FindStream( stepPath );
2468 if( stepEntry ==
nullptr )
2473 msg.Printf(
_(
"File not found: '%s'. 3D-model not imported." ),
FormatPath( stepPath ) );
2480 size_t stepSize =
static_cast<size_t>( stepEntry->size );
2481 std::vector<char> stepContent( stepSize );
2489 std::move( stepContent ) ) ) );
2493 std::map<wxString, std::vector<wxString>> nameIdMap;
2496 nameIdMap[data.m_modelname].push_back(
id );
2498 for(
auto& [
name, ids] : nameIdMap )
2500 for(
size_t i = 1; i < ids.size(); i++ )
2502 const wxString&
id = ids[i];
2509 wxString modelName = modelTuple->second.m_modelname;
2511 if( modelName.Contains(
"." ) )
2514 wxString baseName = modelName.BeforeLast(
'.', &ext );
2516 modelTuple->second.m_modelname = baseName +
'_' + std::to_string( i ) +
'.' + ext;
2520 modelTuple->second.m_modelname = modelName +
'_' + std::to_string( i );
2531 std::set<wxString>& aAmbiguous )
2533 auto collect = [&](
const std::map<wxString, wxString>& aProps )
2553 if(
name.IsEmpty() )
2556 wxString key =
name.Upper();
2557 auto it = aNames.find( key );
2559 if( it == aNames.end() )
2560 aNames.emplace( key,
name );
2561 else if( it->second !=
name )
2562 aAmbiguous.insert( key );
2568 const CFB::COMPOUND_FILE_ENTRY* header = schFile.
FindStream( {
"FileHeader" } );
2590 std::set<wxString> ambiguous;
2592 for(
int i = 0;; i++ )
2594 auto it = aProperties.find(
"sch" + std::to_string( i ) );
2596 if( it == aProperties.end() )
2609 for(
const wxString& key : ambiguous )
2626 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2635 int unnamedNetCount = 0;
2640 ANET6 elem( reader );
2644 if( netName.IsEmpty() )
2650 m_reporter->Report( wxString::Format(
_(
"Altium net %zu has no name; imported as '%s'." ),
2668 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2682 m_reporter->Report( wxString::Format(
_(
"Polygon on layer '%s' has %d vertices "
2683 "outside the coordinate range; they were "
2721 msg.Printf(
_(
"Polygon outline count is %d, expected 1." ), outline.
OutlineCount() );
2729 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board);
2735 zone->SetPosition( elem.
vertices.at( 0 ).position );
2736 zone->SetLocked( elem.
locked );
2738 zone->Outline()->AddOutline( outline.
Outline( 0 ) );
2745 int planeLayers = 0;
2746 int signalLayers = 0;
2760 if( planeLayers > 0 && planeClearanceRule )
2763 if( signalLayers > 0 && zoneClearanceRule )
2771 if( polygonConnectRule !=
nullptr )
2790 zone->SetThermalReliefSpokeWidth(
2801 zone->SetAssignedPriority( 1 );
2806 || zone->GetBoundingBox().Contains( outer_plane->second->GetBoundingBox() ) )
2821 const BOX2I& bbox = zone->GetBoundingBox();
2830 zone->SetHatchOrientation(
ANGLE_45 );
2845 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2864 std::sort( val.second.begin(), val.second.end(),
2867 return lhs.priority < rhs.priority;
2881 if( trackWidthRule )
2883 m_board->GetDesignSettings().m_TrackMinWidth = trackWidthRule->
minLimit;
2887 if( routingViasRule )
2889 m_board->GetDesignSettings().m_ViasMinSize = routingViasRule->
minWidth;
2898 if( holeToHoleRule )
2901 if( boardOutlineRule )
2907 if( soldermaskRule )
2913 std::shared_ptr<NET_SETTINGS> netSettings =
m_board->GetDesignSettings().m_NetSettings;
2914 std::shared_ptr<NETCLASS> defaultNetclass = netSettings->GetDefaultNetclass();
2917 defaultNetclass->SetClearance( clearanceRule->
clearanceGap );
2919 if( trackWidthRule )
2920 defaultNetclass->SetTrackWidth( trackWidthRule->
preferredWidth );
2922 if( routingViasRule )
2924 defaultNetclass->SetViaDiameter( routingViasRule->
width );
2925 defaultNetclass->SetViaDrill( routingViasRule->
holeWidth );
2928 std::vector<const ARULE6*> unresolvedNetclassRules;
2934 for(
const ARULE6* rule : unresolvedNetclassRules )
2936 wxString netclassName;
2939 m_reporter->Report( wxString::Format(
_(
"Altium rule '%s' applies to netclass '%s', which this "
2940 "board does not define. Its constraint is not imported." ),
2941 rule->name, netclassName ),
2954 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2970 THROW_IO_ERROR( wxT(
"BoardRegions stream is not fully parsed" ) );
2974 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2982 for(
int primitiveIndex = 0; reader.
GetRemainingBytes() >= 4; primitiveIndex++ )
3001 THROW_IO_ERROR( wxT(
"ShapeBasedRegions6 stream is not fully parsed" ) );
3029 if( restrictions == 0 )
3032 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board );
3034 zone->SetIsRuleArea(
true );
3038 zone->SetPosition( aElem.
outline.at( 0 ).position );
3039 zone->Outline()->AddOutline( linechain );
3059 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board );
3061 zone->SetPosition( aElem.
outline.at( 0 ).position );
3062 zone->Outline()->AddOutline( linechain );
3070 fill.
Append( linechain );
3074 zone->SetFilledPolysList( klayer, fill );
3076 zone->SetIsFilled(
true );
3077 zone->SetNeedRefill(
false );
3090 msg.Printf(
_(
"Dashed outline found on an Altium layer (%d) with no KiCad equivalent. "
3091 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer );
3112 shape->SetPolyShape( linechain );
3113 shape->SetFilled(
false );
3114 shape->SetLayer( klayer );
3132 msg.Printf(
_(
"Ignored polygon shape of kind %d (not yet supported)." ), aElem.
kind );
3141 const int aPrimitiveIndex )
3161 if( restrictions == 0 )
3164 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aFootprint );
3166 zone->SetIsRuleArea(
true );
3170 zone->SetPosition( aElem.
outline.at( 0 ).position );
3171 zone->Outline()->AddOutline( linechain );
3207 msg.Printf(
_(
"Loading library '%s':\n"
3208 "Footprint %s contains a dashed outline on Altium layer (%d) with "
3209 "no KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
3221 msg.Printf(
_(
"Footprint %s contains a dashed outline on Altium layer (%d) with "
3222 "no KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
3244 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aFootprint,
SHAPE_T::POLY );
3246 shape->SetPolyShape( linechain );
3247 shape->SetFilled(
false );
3248 shape->SetLayer( klayer );
3264 msg.Printf(
_(
"Error loading library '%s':\n"
3265 "Footprint %s contains polygon shape of kind %d (not yet supported)." ),
3277 msg.Printf(
_(
"Footprint %s contains polygon shape of kind %d (not yet supported)." ),
3288 const int aPrimitiveIndex )
3305 for(
const std::vector<ALTIUM_VERTICE>& hole : aElem.
holes )
3313 polySet.
AddHole( hole_linechain );
3318 shape->SetPolyShape( polySet );
3319 shape->SetFilled(
true );
3320 shape->SetLayer( aLayer );
3331 if( aLayer ==
F_Cu || aLayer ==
B_Cu )
3333 for(
const auto& layerExpansionMask :
3336 const PCB_LAYER_ID maskLayer = layerExpansionMask.first;
3344 int expansion = layerExpansionMask.second;
3351 maskShape->SetPolyShape( expandedPolySet );
3352 maskShape->SetFilled(
true );
3353 maskShape->SetLayer( maskLayer );
3365 const int aPrimitiveIndex )
3382 for(
const std::vector<ALTIUM_VERTICE>& hole : aElem.
holes )
3390 polySet.
AddHole( hole_linechain );
3393 if( aLayer ==
F_Cu || aLayer ==
B_Cu )
3395 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
3398 padLayers.
set( aLayer );
3410 pad->SetPosition( anchorPos );
3417 shapePolys.
Move( -anchorPos );
3421 auto it = map.find( aPrimitiveIndex );
3423 if( it != map.end() )
3429 pad->SetLocalSolderPasteMargin(
info.pastemaskexpansionmanual );
3434 pad->SetLocalSolderMaskMargin(
info.soldermaskexpansionmanual );
3444 pad->SetLayerSet( padLayers );
3450 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aFootprint,
SHAPE_T::POLY );
3452 shape->SetPolyShape( polySet );
3453 shape->SetFilled(
true );
3454 shape->SetLayer( aLayer );
3463 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3479 THROW_IO_ERRORF( wxT(
"Region stream tries to access polygon id %d of %d existing polygons." ),
3485 if( zone ==
nullptr )
3504 for(
const std::vector<ALTIUM_VERTICE>& hole : elem.
holes )
3511 hole_linechain.
Append( hole.at( 0 ).position );
3513 fill.
AddHole( hole_linechain );
3533 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3540 for(
int primitiveIndex = 0; reader.
GetRemainingBytes() >= 4; primitiveIndex++ )
3543 AARC6 elem( reader );
3594 THROW_IO_ERRORF( wxT(
"Tracks stream tries to access polygon id %u of %zu existing polygons." ),
3600 if( zone ==
nullptr )
3648 for(
const auto& layerExpansionMask :
3651 int width = aElem.
width + ( layerExpansionMask.second * 2 );
3655 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>(
m_board );
3659 arc->SetLayer( layerExpansionMask.first );
3668 const int aPrimitiveIndex,
const bool aIsBoardImport )
3672 wxFAIL_MSG( wxString::Format(
"Altium: Unexpected footprint Arc with polygon id %d",
3705 for(
const auto& layerExpansionMask :
3708 int width = aElem.
width + ( layerExpansionMask.second * 2 );
3712 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>( aFootprint );
3716 arc->SetLayer( layerExpansionMask.first );
3738 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board, &shapeArc );
3740 arc->SetWidth( aElem.
width );
3741 arc->SetLayer( aLayer );
3744 PCB_ARC* added = arc.release();
3752 if(
std::abs( sweepDegrees ) >= 359.999 )
3756 addArc( aElem.
center + startOffset, halfSweep );
3757 addArc( aElem.
center - startOffset, halfSweep );
3764 addArc( aElem.
center + startOffset, includedAngle );
3768 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>(
m_board);
3772 arc->SetLayer( aLayer );
3782 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>( aFootprint );
3786 arc->SetLayer( aLayer );
3793 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3803 APAD6 elem( reader );
3832 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
3833 footprint->SetPosition( aElem.
position );
3848 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
3850 pad->SetNumber(
"" );
3859 pad->SetLayerSet(
LSET().AllCuMask() );
3891 cuLayers &=
m_board->GetEnabledLayers();
3900 pad->SetSize( layer,
VECTOR2I( diameter, diameter ) );
3907 pad->Padstack().FrontOuterLayers().has_solder_mask =
true;
3911 pad->Padstack().FrontOuterLayers().has_solder_mask =
false;
3917 pad->Padstack().BackOuterLayers().has_solder_mask =
true;
3921 pad->Padstack().BackOuterLayers().has_solder_mask =
false;
3926 pad->SetLocked(
true );
3956 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
3979 msg.Printf(
_(
"Error loading library '%s':\n"
3980 "Footprint %s pad %s is not marked as multilayer, but is a TH pad." ),
3992 msg.Printf(
_(
"Footprint %s pad %s is not marked as multilayer, but is a TH pad." ),
4012 wxFAIL_MSG( wxT(
"Round holes are handled before the switch" ) );
4021 msg.Printf(
_(
"Loading library '%s':\n"
4022 "Footprint %s pad %s has a square hole (not yet supported)." ),
4034 msg.Printf(
_(
"Footprint %s pad %s has a square hole (not yet supported)." ),
4050 bool slotRotationSupported;
4054 if( !slotRotationSupported )
4064 msg.Printf(
_(
"Loading library '%s':\n"
4065 "Footprint %s pad %s has a hole-rotation of %d degrees. "
4066 "KiCad only supports 90 degree rotations." ),
4079 msg.Printf(
_(
"Footprint %s pad %s has a hole-rotation of %d degrees. "
4080 "KiCad only supports 90 degree rotations." ),
4099 msg.Printf(
_(
"Error loading library '%s':\n"
4100 "Footprint %s pad %s uses a hole of unknown kind %d." ),
4113 msg.Printf(
_(
"Footprint %s pad %s uses a hole of unknown kind %d." ),
4130 auto setCopperGeometry =
4134 bool hasAltiumEntry = aElem.
sizeAndShape && aAltiumIdx >= 0
4139 if( aElem.
holesize != 0 && hasAltiumEntry )
4156 else if( aSize.x == aSize.y )
4180 msg.Printf(
_(
"Error loading library '%s':\n"
4181 "Footprint %s pad %s uses an unknown pad shape." ),
4193 msg.Printf(
_(
"Footprint %s pad %s uses an unknown pad shape." ),
4246 setCopperGeometry( layer, idx, shape.
inner_shape[inner],
4256 switch( aElem.
layer )
4274 pad->SetLayer( klayer );
4275 pad->SetLayerSet(
LSET( { klayer } ) );
4286 pad->SetLayerSet(
pad->GetLayerSet().reset(
F_Mask ) );
4289 pad->SetLayerSet(
pad->GetLayerSet().reset(
B_Mask ) );
4307 msg.Printf(
_(
"Non-copper pad %s found on an Altium layer (%d) with no KiCad "
4308 "equivalent. It has been moved to KiCad layer Eco1_User." ),
4316 std::unique_ptr<PCB_SHAPE>
pad = std::make_unique<PCB_SHAPE>(
m_board );
4335 msg.Printf(
_(
"Loading library '%s':\n"
4336 "Footprint %s non-copper pad %s found on an Altium layer (%d) with no "
4337 "KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
4350 msg.Printf(
_(
"Footprint %s non-copper pad %s found on an Altium layer (%d) with no "
4351 "KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
4362 std::unique_ptr<PCB_SHAPE>
pad = std::make_unique<PCB_SHAPE>( aFootprint );
4378 msg.Printf(
_(
"Non-copper pad %s is connected to a net, which is not supported." ),
4389 msg.Printf(
_(
"Non-copper pad %s has a hole, which is not supported." ), aElem.
name );
4399 msg.Printf(
_(
"Non-copper pad %s has a complex pad stack (not yet supported)." ),
4431 int offset = ( std::min( aElem.
topsize.
x, aElem.
topsize.
y ) * cornerradius ) / 200;
4436 if( cornerradius < 100 )
4438 int offsetX = aElem.
topsize.
x / 2 - offset;
4439 int offsetY = aElem.
topsize.
y / 2 - offset;
4532 aShape->
SetPolyPoints( { p11 - chamferX, p11 - chamferY, p12 + chamferY, p12 - chamferX,
4533 p22 + chamferX, p22 + chamferY, p21 - chamferY, p21 + chamferX } );
4545 msg.Printf(
_(
"Non-copper pad %s uses an unknown pad shape." ), aElem.
name );
4555 const CFB::COMPOUND_FILE_ENTRY* aEntry )
4565 AVIA6 elem( reader );
4567 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
4579 if( start_layer_outside && end_layer_outside )
4583 else if( ( !start_layer_outside ) && ( !end_layer_outside ) )
4606 msg.Printf(
_(
"Via from layer %d to %d uses a non-copper layer, which is not "
4617 via->SetLayerPair( start_klayer, end_klayer );
4644 via->SetWidth( layer, altiumLayer < 0 ? elem.
diameter
4677 const CFB::COMPOUND_FILE_ENTRY* aEntry )
4684 for(
int primitiveIndex = 0; reader.
GetRemainingBytes() >= 4; primitiveIndex++ )
4715 msg.Printf( wxT(
"ATRACK6 stream tries to access polygon id %u "
4716 "of %u existing polygons; skipping it" ),
4717 static_cast<unsigned>( aElem.
polygon ),
4718 static_cast<unsigned>(
m_polygons.size() ) );
4727 if( zone ==
nullptr )
4775 aPrimitiveIndex, aElem.
layer ) )
4777 int width = aElem.
width + ( layerExpansionMask.second * 2 );
4782 seg->SetStart( aElem.
start );
4783 seg->SetEnd( aElem.
end );
4785 seg->SetLayer( layerExpansionMask.first );
4794 const int aPrimitiveIndex,
4795 const bool aIsBoardImport )
4799 wxFAIL_MSG( wxString::Format( wxT(
"Altium: Unexpected footprint Track with polygon id %u" ),
4833 aPrimitiveIndex, aElem.
layer ) )
4835 int width = aElem.
width + ( layerExpansionMask.second * 2 );
4838 std::unique_ptr<PCB_SHAPE> seg = std::make_unique<PCB_SHAPE>( aFootprint,
SHAPE_T::SEGMENT );
4840 seg->SetStart( aElem.
start );
4841 seg->SetEnd( aElem.
end );
4843 seg->SetLayer( layerExpansionMask.first );
4855 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
4857 track->SetStart( aElem.
start );
4858 track->SetEnd( aElem.
end );
4859 track->SetWidth( aElem.
width );
4860 track->SetLayer( aLayer );
4873 seg->SetStart( aElem.
start );
4874 seg->SetEnd( aElem.
end );
4876 seg->SetLayer( aLayer );
4886 std::unique_ptr<PCB_SHAPE> seg = std::make_unique<PCB_SHAPE>( aFootprint,
SHAPE_T::SEGMENT );
4888 seg->SetStart( aElem.
start );
4889 seg->SetEnd( aElem.
end );
4891 seg->SetLayer( aLayer );
4898 const CFB::COMPOUND_FILE_ENTRY* aEntry )
4908 THROW_IO_ERROR( wxT(
"WideStrings6 stream is not fully parsed" ) );
4912 const CFB::COMPOUND_FILE_ENTRY* aEntry )
4926 THROW_IO_ERROR( wxT(
"SmartUnions6 stream is not fully parsed" ) );
4931 const CFB::COMPOUND_FILE_ENTRY* aEntry )
4936 reader.
Read<uint32_t>();
4940 THROW_IO_ERROR( wxT(
"UnionNames stream is not fully parsed" ) );
4959 if( tuning.baseline.size() < 2
4960 || ( tuning.is_diffpair && tuning.baselinecoupled.size() < 2 ) )
4965 const std::vector<BOARD_ITEM*>& items = itemsIt->second;
4979 std::unique_ptr<PCB_TUNING_PATTERN> pattern(
static_cast<PCB_TUNING_PATTERN*
>( generator ) );
4980 pattern->SetParent(
m_board );
4981 pattern->SetLayer( layer );
4982 pattern->SetTuningMode( mode );
4985 if(
auto nameIt =
m_unionNames.find( tuning.unionindex );
4986 nameIt !=
m_unionNames.end() && !nameIt->second.IsEmpty() )
4988 pattern->SetName( nameIt->second );
4991 pattern->SetMaxAmplitude( tuning.amplitude );
4992 pattern->SetMinAmplitude( tuning.minamplitude );
4993 pattern->SetSpacing( tuning.gap );
4994 pattern->SetSingleSided( tuning.singleside );
4998 pattern->SetRounded( tuning.style != 0 );
5000 if( tuning.mitterradiusratio > 0.0 )
5002 int percent =
KiROUND( tuning.mitterradiusratio * 100.0 );
5003 pattern->SetCornerRadiusPercentage( std::clamp( percent, 0, 100 ) );
5007 bool singleNet =
true;
5011 pattern->AddItem( item );
5016 netCode = bci->GetNetCode();
5017 else if( netCode != bci->GetNetCode() )
5024 if( netCode >= 0 && singleNet )
5026 pattern->SetNetCode( netCode );
5032 SEG::ecoord bestDist = std::numeric_limits<SEG::ecoord>::max();
5044 if( dist < bestDist )
5051 pattern->SetLastNetName( bestNet );
5055 pattern->SetWidth( track->GetWidth() );
5057 pattern->SetBaseLine( baseLine );
5058 pattern->SetPosition( baseLine.
CPoint( 0 ) );
5065 pattern->SetBaseLineCoupled( baseLineCoupled );
5067 int centreToCentre = baseLine.
Distance( baseLineCoupled.
CPoint( 0 ),
false );
5069 pattern->SetDiffPairGap( std::max( centreToCentre - pattern->GetWidth(), 0 ) );
5078 m_reporter->Report( wxString::Format(
_(
"Imported %d length-tuning pattern(s)." ),
5102 footprint->SetAttributes( footprint->GetAttributes() | footprint->GetLikelyAttribute() );
5108 const CFB::COMPOUND_FILE_ENTRY* aEntry )
5167 std::unique_ptr<PCB_TEXTBOX> pcbTextbox = std::make_unique<PCB_TEXTBOX>(
m_board );
5168 std::unique_ptr<PCB_TEXT> pcbText = std::make_unique<PCB_TEXT>(
m_board );
5172 static const std::map<wxString, wxString> variableMap = {
5173 {
"LAYER_NAME",
"LAYER" },
5174 {
"PRINT_DATE",
"CURRENT_DATE"},
5183 item = pcbTextbox.get();
5184 text = pcbTextbox.get();
5187 text->SetText( kicadText );
5212 std::unique_ptr<PCB_TEXTBOX> fpTextbox = std::make_unique<PCB_TEXTBOX>( aFootprint );
5213 std::unique_ptr<PCB_TEXT> fpText = std::make_unique<PCB_TEXT>( aFootprint );
5228 item = &aFootprint->
Value();
5233 item = fpText.get();
5234 text = fpText.get();
5238 static const std::map<wxString, wxString> variableMap = {
5239 {
"DESIGNATOR",
"REFERENCE" },
5240 {
"COMMENT",
"VALUE" },
5241 {
"VALUE",
"ALTIUM_VALUE" },
5242 {
"LAYER_NAME",
"LAYER" },
5243 {
"PRINT_DATE",
"CURRENT_DATE"},
5248 item = fpTextbox.get();
5249 text = fpTextbox.get();
5254 text->SetText( kicadText );
5267 text->SetKeepUpright(
false );
5282 std::unique_ptr<PCB_BARCODE> pcbBarcode = std::make_unique<PCB_BARCODE>(
m_board );
5284 pcbBarcode->SetLayer( aLayer );
5285 pcbBarcode->SetPosition( aElem.
position );
5289 pcbBarcode->SetText( aElem.
text );
5299 pcbBarcode->AssembleBarcode();
5308 std::unique_ptr<PCB_BARCODE> fpBarcode = std::make_unique<PCB_BARCODE>( aFootprint );
5310 fpBarcode->SetLayer( aLayer );
5311 fpBarcode->SetPosition( aElem.
position );
5315 fpBarcode->SetText( aElem.
text );
5325 fpBarcode->AssembleBarcode();
5354 kicadMargin =
VECTOR2I( charWidth * 0.933, charHeight * 0.67 );
5356 kicadMargin =
VECTOR2I( charWidth * 0.808, charHeight * 0.844 );
5359 + kicadMargin * 2 - margin * 2 );
5361 kposition = kposition - kicadMargin + margin;
5378 switch( justification )
5402 msg.Printf(
_(
"Unknown textbox justification %d, aText %s" ), justification,
5422 int rectHeight = aElem.
height;
5440 rectWidth = -rectWidth;
5445 switch( justification )
5451 kposition.
y -= rectHeight;
5457 kposition.
y -= rectHeight / 2;
5467 kposition.
x += rectWidth / 2;
5468 kposition.
y -= rectHeight;
5474 kposition.
x += rectWidth / 2;
5475 kposition.
y -= rectHeight / 2;
5481 kposition.
x += rectWidth / 2;
5487 kposition.
x += rectWidth;
5488 kposition.
y -= rectHeight;
5494 kposition.
x += rectWidth;
5495 kposition.
y -= rectHeight / 2;
5501 kposition.
x += rectWidth;
5554 if( font->
GetName().Contains( wxS(
"Arial" ) ) )
5573 const CFB::COMPOUND_FILE_ENTRY* aEntry )
5631 const bool aIsBoardImport )
5673 fill->SetFilled(
true );
5674 fill->SetLayer( aLayer );
5677 fill->SetStart( aElem.
pos1 );
5678 fill->SetEnd( aElem.
pos2 );
5700 if( aLayer ==
F_Cu || aLayer ==
B_Cu )
5702 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
5705 padLayers.
set( aLayer );
5721 std::swap( width, height );
5724 pad->SetPosition( aElem.
pos1 / 2 + aElem.
pos2 / 2 );
5737 pad->SetPosition( anchorPos );
5748 aElem.
pos1.
y / 2 + aElem.
pos2.
y / 2 - anchorPos.
y );
5750 pad->AddPrimitivePoly(
F_Cu, shapePolys, 0,
true );
5754 pad->SetLayerSet( padLayers );
5760 std::unique_ptr<PCB_SHAPE> fill = std::make_unique<PCB_SHAPE>( aFootprint,
SHAPE_T::RECTANGLE );
5762 fill->SetFilled(
true );
5763 fill->SetLayer( aLayer );
5766 fill->SetStart( aElem.
pos1 );
5767 fill->SetEnd( aElem.
pos2 );
5786 layerSet.
set( klayer );
5815 if( aKeepoutRestrictions != 0 )
5816 return aKeepoutRestrictions;
5848 const uint8_t aKeepoutRestrictions )
5852 if( restrictions == 0 )
5855 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board );
5857 zone->SetIsRuleArea(
true );
5874 const uint8_t aKeepoutRestrictions )
5878 if( restrictions == 0 )
5881 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aFootprint );
5883 zone->SetIsRuleArea(
true );
5907 if( elems.first == elems.second )
5910 std::vector<std::pair<PCB_LAYER_ID, int>> layerExpansionPairs;
5912 for(
auto it = elems.first; it != elems.second; ++it )
5952 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 #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.
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 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
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.
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 SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void SetStart(const VECTOR2I &aStart) override
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)
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.
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