46#include <compoundfilereader.h>
53#include <wx/docview.h>
55#include <wx/mstream.h>
56#include <wx/wfstream.h>
57#include <wx/zstream.h>
59#include <magic_enum.hpp>
81 THROW_IO_ERROR( wxString::Format( wxT(
"Component creator tries to access component id %u "
82 "of %u existing components" ),
91 const std::vector<ALTIUM_VERTICE>& aVertices )
100 double startradiant =
DEG2RAD( vertex.startangle );
101 double endradiant =
DEG2RAD( vertex.endangle );
103 -
KiROUND( std::sin( startradiant ) * vertex.radius ) );
106 -
KiROUND( std::sin( endradiant ) * vertex.radius ) );
108 VECTOR2I arcStart = vertex.center + arcStartOffset;
109 VECTOR2I arcEnd = vertex.center + arcEndOffset;
111 if( arcStart.
Distance( vertex.position )
112 < arcEnd.
Distance( vertex.position ) )
123 aLine.
Append( vertex.position );
133 auto override =
m_layermap.find( aAltiumLayer );
137 return override->second;
140 switch( aAltiumLayer )
144 case ALTIUM_LAYER::TOP_LAYER:
return F_Cu;
145 case ALTIUM_LAYER::MID_LAYER_1:
return In1_Cu;
146 case ALTIUM_LAYER::MID_LAYER_2:
return In2_Cu;
147 case ALTIUM_LAYER::MID_LAYER_3:
return In3_Cu;
148 case ALTIUM_LAYER::MID_LAYER_4:
return In4_Cu;
149 case ALTIUM_LAYER::MID_LAYER_5:
return In5_Cu;
150 case ALTIUM_LAYER::MID_LAYER_6:
return In6_Cu;
151 case ALTIUM_LAYER::MID_LAYER_7:
return In7_Cu;
152 case ALTIUM_LAYER::MID_LAYER_8:
return In8_Cu;
153 case ALTIUM_LAYER::MID_LAYER_9:
return In9_Cu;
154 case ALTIUM_LAYER::MID_LAYER_10:
return In10_Cu;
155 case ALTIUM_LAYER::MID_LAYER_11:
return In11_Cu;
156 case ALTIUM_LAYER::MID_LAYER_12:
return In12_Cu;
157 case ALTIUM_LAYER::MID_LAYER_13:
return In13_Cu;
158 case ALTIUM_LAYER::MID_LAYER_14:
return In14_Cu;
159 case ALTIUM_LAYER::MID_LAYER_15:
return In15_Cu;
160 case ALTIUM_LAYER::MID_LAYER_16:
return In16_Cu;
161 case ALTIUM_LAYER::MID_LAYER_17:
return In17_Cu;
162 case ALTIUM_LAYER::MID_LAYER_18:
return In18_Cu;
163 case ALTIUM_LAYER::MID_LAYER_19:
return In19_Cu;
164 case ALTIUM_LAYER::MID_LAYER_20:
return In20_Cu;
165 case ALTIUM_LAYER::MID_LAYER_21:
return In21_Cu;
166 case ALTIUM_LAYER::MID_LAYER_22:
return In22_Cu;
167 case ALTIUM_LAYER::MID_LAYER_23:
return In23_Cu;
168 case ALTIUM_LAYER::MID_LAYER_24:
return In24_Cu;
169 case ALTIUM_LAYER::MID_LAYER_25:
return In25_Cu;
170 case ALTIUM_LAYER::MID_LAYER_26:
return In26_Cu;
171 case ALTIUM_LAYER::MID_LAYER_27:
return In27_Cu;
172 case ALTIUM_LAYER::MID_LAYER_28:
return In28_Cu;
173 case ALTIUM_LAYER::MID_LAYER_29:
return In29_Cu;
174 case ALTIUM_LAYER::MID_LAYER_30:
return In30_Cu;
175 case ALTIUM_LAYER::BOTTOM_LAYER:
return B_Cu;
177 case ALTIUM_LAYER::TOP_OVERLAY:
return F_SilkS;
178 case ALTIUM_LAYER::BOTTOM_OVERLAY:
return B_SilkS;
179 case ALTIUM_LAYER::TOP_PASTE:
return F_Paste;
180 case ALTIUM_LAYER::BOTTOM_PASTE:
return B_Paste;
181 case ALTIUM_LAYER::TOP_SOLDER:
return F_Mask;
182 case ALTIUM_LAYER::BOTTOM_SOLDER:
return B_Mask;
201 case ALTIUM_LAYER::DRILL_GUIDE:
return Dwgs_User;
202 case ALTIUM_LAYER::KEEP_OUT_LAYER:
return Margin;
204 case ALTIUM_LAYER::MECHANICAL_1:
return User_1;
205 case ALTIUM_LAYER::MECHANICAL_2:
return User_2;
206 case ALTIUM_LAYER::MECHANICAL_3:
return User_3;
207 case ALTIUM_LAYER::MECHANICAL_4:
return User_4;
208 case ALTIUM_LAYER::MECHANICAL_5:
return User_5;
209 case ALTIUM_LAYER::MECHANICAL_6:
return User_6;
210 case ALTIUM_LAYER::MECHANICAL_7:
return User_7;
211 case ALTIUM_LAYER::MECHANICAL_8:
return User_8;
212 case ALTIUM_LAYER::MECHANICAL_9:
return User_9;
213 case ALTIUM_LAYER::MECHANICAL_10:
return Dwgs_User;
214 case ALTIUM_LAYER::MECHANICAL_11:
return Eco2_User;
215 case ALTIUM_LAYER::MECHANICAL_12:
return F_Fab;
216 case ALTIUM_LAYER::MECHANICAL_13:
return B_Fab;
221 case ALTIUM_LAYER::DRILL_DRAWING:
return Dwgs_User;
239 static std::set<ALTIUM_LAYER> altiumLayersWithWarning;
241 if( aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER || aAltiumLayer == ALTIUM_LAYER::KEEP_OUT_LAYER )
243 std::vector<PCB_LAYER_ID> layers;
249 layers.emplace_back( layer );
260 wxString layerName = it !=
m_layerNames.end() ? it->second : wxString::Format( wxT(
"(%d)" ),
261 (
int) aAltiumLayer );
263 if(
m_reporter && altiumLayersWithWarning.insert( aAltiumLayer ).second )
266 _(
"Altium layer %s has no KiCad equivalent. It has been moved to KiCad "
280 const wxString& aLibrary,
const wxString& aFootprintName )
300 const unsigned PROGRESS_DELTA = 250;
318 const std::map<ALTIUM_PCB_DIR, std::string>& aFileMapping )
321 const std::vector<std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>> parserOrder = {
322 {
true, ALTIUM_PCB_DIR::FILE_HEADER,
327 {
true, ALTIUM_PCB_DIR::BOARD6,
332 {
false, ALTIUM_PCB_DIR::EXTENDPRIMITIVEINFORMATION,
337 {
true, ALTIUM_PCB_DIR::COMPONENTS6,
342 {
false, ALTIUM_PCB_DIR::MODELS,
345 std::vector<std::string> dir{ aFileMapping.at( ALTIUM_PCB_DIR::MODELS ) };
348 {
true, ALTIUM_PCB_DIR::COMPONENTBODIES6,
353 {
true, ALTIUM_PCB_DIR::NETS6,
358 {
true, ALTIUM_PCB_DIR::CLASSES6,
363 {
true, ALTIUM_PCB_DIR::RULES6,
368 {
true, ALTIUM_PCB_DIR::DIMENSIONS6,
373 {
true, ALTIUM_PCB_DIR::POLYGONS6,
378 {
true, ALTIUM_PCB_DIR::ARCS6,
383 {
true, ALTIUM_PCB_DIR::PADS6,
388 {
true, ALTIUM_PCB_DIR::VIAS6,
393 {
true, ALTIUM_PCB_DIR::TRACKS6,
398 {
false, ALTIUM_PCB_DIR::WIDESTRINGS6,
403 {
true, ALTIUM_PCB_DIR::TEXTS6,
408 {
true, ALTIUM_PCB_DIR::FILLS6,
413 {
false, ALTIUM_PCB_DIR::BOARDREGIONS,
418 {
true, ALTIUM_PCB_DIR::SHAPEBASEDREGIONS6,
423 {
true, ALTIUM_PCB_DIR::REGIONS6,
433 for(
const std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>& cur : parserOrder )
438 std::tie( isRequired,
directory, fp ) = cur;
440 if(
directory == ALTIUM_PCB_DIR::FILE_HEADER )
443 const auto& mappedDirectory = aFileMapping.find(
directory );
445 if( mappedDirectory == aFileMapping.end() )
448 const std::vector<std::string> mappedFile{ mappedDirectory->second,
"Header" };
449 const CFB::COMPOUND_FILE_ENTRY* file = altiumPcbFile.
FindStream( mappedFile );
451 if( file ==
nullptr )
455 uint32_t numOfRecords = reader.
Read<uint32_t>();
485 const auto& boardDirectory = aFileMapping.find( ALTIUM_PCB_DIR::BOARD6 );
487 if( boardDirectory != aFileMapping.end() )
489 std::vector<std::string> mappedFile{ boardDirectory->second,
"Data" };
491 const CFB::COMPOUND_FILE_ENTRY* file = altiumPcbFile.
FindStream( mappedFile );
496 "This file does not appear to be in a valid PCB Binary Version 6.0 format. In "
498 "make sure to save as \"PCB Binary Files (*.PcbDoc)\"." ) );
503 for(
const std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>& cur : parserOrder )
508 std::tie( isRequired,
directory, fp ) = cur;
510 const auto& mappedDirectory = aFileMapping.find(
directory );
512 if( mappedDirectory == aFileMapping.end() )
514 wxASSERT_MSG( !isRequired, wxString::Format( wxT(
"Altium Directory of kind %d was "
515 "expected, but no mapping is "
516 "present in the code" ),
521 std::vector<std::string> mappedFile{ mappedDirectory->second };
523 if(
directory != ALTIUM_PCB_DIR::FILE_HEADER )
524 mappedFile.emplace_back(
"Data" );
526 const CFB::COMPOUND_FILE_ENTRY* file = altiumPcbFile.
FindStream( mappedFile );
528 if( file !=
nullptr )
530 fp( altiumPcbFile, file );
532 else if( isRequired )
536 m_reporter->
Report( wxString::Format(
_(
"File not found: '%s' for directory '%s'." ),
551 if( zone->GetAssignedPriority() == 1000 )
562 zone->SetAssignedPriority( priority >= 0 ? priority : 0 );
566 for( std::pair<const ALTIUM_LAYER, ZONE*>& zone :
m_outer_plane )
567 zone.second->SetAssignedPriority( 0 );
577 if( !zone->HasFilledPolysForLayer( layer ) )
599 if( shape->
GetShape() != SHAPE_T::ARC && shape->
GetShape() != SHAPE_T::CIRCLE )
618 if( arc->
GetCenter() == dim->GetPosition() )
627 VECTOR2I radialLine = dim->GetEnd() - dim->GetStart();
632 radialLine = radialLine.
Resize( std::max( radius, 2 ) );
633 dim->SetEnd( dim->GetStart() + (
VECTOR2I) radialLine );
634 dim->SetLeaderLength( totalLength - radius );
644 int desired_x = ( w - bbbox.
GetWidth() ) / 2;
645 int desired_y = ( h - bbbox.
GetHeight() ) / 2;
647 VECTOR2I movementVector( desired_x - bbbox.
GetX(), desired_y - bbbox.
GetY() );
659 const wxString& aFootprintName )
661 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
679 std::tuple<wxString, const CFB::COMPOUND_FILE_ENTRY*> ret =
682 wxString fpDirName = std::get<0>( ret );
683 const CFB::COMPOUND_FILE_ENTRY* footprintStream = std::get<1>( ret );
685 if( fpDirName.IsEmpty() )
688 wxString::Format(
_(
"Footprint directory not found: '%s'." ), aFootprintName ) );
691 const std::vector<std::string> streamName{ fpDirName.ToStdString(),
"Data" };
692 const CFB::COMPOUND_FILE_ENTRY* footprintData = altiumLibFile.
FindStream( footprintStream, {
"Data" } );
694 if( footprintData ==
nullptr )
707 footprint->SetFPID( fpID );
709 const std::vector<std::string> parametersStreamName{ fpDirName.ToStdString(),
711 const CFB::COMPOUND_FILE_ENTRY* parametersData =
712 altiumLibFile.
FindStream( footprintStream, {
"Parameters" } );
714 if( parametersData !=
nullptr )
717 std::map<wxString, wxString> parameterProperties = parametersReader.
ReadProperties();
719 wxT(
"DESCRIPTION" ), wxT(
"" ) );
720 footprint->SetLibDescription( description );
731 footprint->SetLibDescription( wxT(
"" ) );
734 const std::vector<std::string> extendedPrimitiveInformationStreamName{
735 "ExtendedPrimitiveInformation",
"Data"
737 const CFB::COMPOUND_FILE_ENTRY* extendedPrimitiveInformationData =
738 altiumLibFile.
FindStream( footprintStream, extendedPrimitiveInformationStreamName );
740 if( extendedPrimitiveInformationData !=
nullptr )
743 footprint->SetReference( wxT(
"REF**" ) );
744 footprint->SetValue( aFootprintName );
745 footprint->Reference().SetVisible(
true );
746 footprint->Value().SetVisible(
true );
751 for(
PCB_FIELD* field : footprint->Fields() )
753 field->SetTextSize( defaultTextSize );
754 field->SetTextThickness( defaultTextThickness );
763 case ALTIUM_RECORD::ARC:
769 case ALTIUM_RECORD::PAD:
775 case ALTIUM_RECORD::VIA:
781 case ALTIUM_RECORD::TRACK:
787 case ALTIUM_RECORD::TEXT:
793 case ALTIUM_RECORD::FILL:
799 case ALTIUM_RECORD::REGION:
805 case ALTIUM_RECORD::MODEL:
812 THROW_IO_ERROR( wxString::Format(
_(
"Record of unknown type: '%d'." ), recordtype ) );
818 for(
bool changes =
true; changes; )
823 [&changes](
PAD* aPad1,
PAD* aPad2 )
825 if( !( aPad1->GetNumber().IsEmpty() ^ aPad2->GetNumber().IsEmpty() ) )
828 for( PCB_LAYER_ID layer : aPad1->GetLayerSet().Seq() )
830 std::shared_ptr<SHAPE> shape1 = aPad1->GetEffectiveShape( layer );
831 std::shared_ptr<SHAPE> shape2 = aPad2->GetEffectiveShape( layer );
833 if( shape1->Collide( shape2.get() ) )
835 if( aPad1->GetNumber().IsEmpty() )
836 aPad1->SetNumber( aPad2->GetNumber() );
838 aPad2->SetNumber( aPad1->GetNumber() );
847 footprint->AutoPositionFields();
849 if( parser.HasParsingError() )
851 THROW_IO_ERROR( wxString::Format( wxT(
"%s stream was not parsed correctly" ),
855 if( parser.GetRemainingBytes() != 0 )
857 THROW_IO_ERROR( wxString::Format( wxT(
"%s stream is not fully parsed" ),
861 return footprint.release();
872 THROW_IO_ERROR( wxString::Format( wxT(
"Netcode with id %d does not exist. Only %d nets "
884 const auto rules =
m_rules.find( aKind );
889 for(
const ARULE6& rule : rules->second )
891 if( rule.
name == aName )
900 const auto rules =
m_rules.find( aKind );
905 for(
const ARULE6& rule : rules->second )
915 const CFB::COMPOUND_FILE_ENTRY* aEntry )
933 const CFB::COMPOUND_FILE_ENTRY* aEntry )
950 THROW_IO_ERROR( wxT(
"ExtendedPrimitiveInformation stream is not fully parsed" ) );
955 const CFB::COMPOUND_FILE_ENTRY* aEntry )
972 size_t layercount = 0;
973 size_t layerid =
static_cast<size_t>( ALTIUM_LAYER::TOP_LAYER );
975 while( layerid < elem.
stackup.size() && layerid != 0 )
977 layerid = elem.
stackup[ layerid - 1 ].nextId;
981 size_t kicadLayercount = ( layercount % 2 == 0 ) ? layercount : layercount + 1;
991 auto it = stackup.
GetList().begin();
997 auto curLayer =
static_cast<int>(
F_Cu );
999 for(
size_t altiumLayerId =
static_cast<size_t>( ALTIUM_LAYER::TOP_LAYER );
1000 altiumLayerId < elem.
stackup.size() && altiumLayerId != 0;
1001 altiumLayerId = elem.
stackup[altiumLayerId - 1].nextId )
1007 if( layer.
nextId == 0 && layercount != kicadLayercount )
1012 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
1014 ( *it )->SetThickness( 0 );
1019 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
1021 ( *it )->SetThickness( 0, 0 );
1022 ( *it )->SetThicknessLocked(
true, 0 );
1030 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
1044 if( klayer ==
B_Cu )
1047 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected id while parsing last stackup layer" ) );
1057 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
1071 for(
size_t altiumLayerId =
static_cast<size_t>( ALTIUM_LAYER::TOP_OVERLAY );
1072 altiumLayerId <= static_cast<size_t>( ALTIUM_LAYER::BOTTOM_SOLDER ); altiumLayerId++ )
1083 for(
size_t altiumLayerId =
static_cast<size_t>( ALTIUM_LAYER::MECHANICAL_1 );
1084 altiumLayerId <= static_cast<size_t>( ALTIUM_LAYER::MECHANICAL_16 ); altiumLayerId++ )
1105 std::vector<INPUT_LAYER_DESC> inputLayers;
1106 std::map<wxString, ALTIUM_LAYER> altiumLayerNameMap;
1108 for(
size_t ii = 0; ii < aStackup.size(); ii++ )
1115 && !( layer_num >= ALTIUM_LAYER::TOP_OVERLAY
1116 && layer_num <= ALTIUM_LAYER::BOTTOM_SOLDER )
1117 && !( layer_num >= ALTIUM_LAYER::MECHANICAL_1
1118 && layer_num <= ALTIUM_LAYER::MECHANICAL_16 ) )
1120 if( layer_num < ALTIUM_LAYER::BOTTOM_LAYER )
1134 inputLayers.push_back( iLdesc );
1135 altiumLayerNameMap.insert( { curLayer.
name, layer_num } );
1139 if( inputLayers.size() == 0 )
1144 enabledLayers =
LSET();
1147 for( std::pair<wxString, PCB_LAYER_ID> layerPair : reMappedLayers )
1149 if( layerPair.second == PCB_LAYER_ID::UNDEFINED_LAYER )
1151 wxFAIL_MSG( wxT(
"Unexpected Layer ID" ) );
1155 ALTIUM_LAYER altiumID = altiumLayerNameMap.at( layerPair.first );
1156 m_layermap.insert_or_assign( altiumID, layerPair.second );
1157 enabledLayers |=
LSET( layerPair.second );
1171 LINE_STYLE::SOLID );
1178 int nextShape = lineChain.
NextShape( i );
1179 bool isLastShape = nextShape < 0;
1181 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::ARC );
1183 shape->SetStroke( stroke );
1187 m_board->
Add( shape.release(), ADD_MODE::APPEND );
1193 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
1195 shape->SetStroke( stroke );
1197 shape->SetStart( seg.
A );
1198 shape->SetEnd( seg.
B );
1200 m_board->
Add( shape.release(), ADD_MODE::APPEND );
1207 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1219 if( elem.
kind == ALTIUM_CLASS_KIND::NET_CLASS )
1221 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( elem.
name );
1223 for(
const wxString&
name : elem.
names )
1239 msg.Printf(
_(
"More than one Altium netclass with name '%s' found. "
1240 "Only the first one will be imported." ), elem.
name );
1259 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1266 uint16_t componentId = 0;
1273 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
1277 footprint->SetFPID( fpID );
1279 footprint->SetPosition( elem.
position );
1280 footprint->SetOrientationDegrees( elem.
rotation );
1286 if( reference.find_first_not_of(
"0123456789" ) == wxString::npos )
1287 reference.Prepend( wxT(
"UNK" ) );
1289 footprint->SetReference( reference );
1291 footprint->SetLocked( elem.
locked );
1292 footprint->Reference().SetVisible( elem.
nameon );
1293 footprint->Value().SetVisible( elem.
commenton );
1294 footprint->SetLayer( elem.
layer == ALTIUM_LAYER::TOP_LAYER ?
F_Cu :
B_Cu );
1297 m_board->
Add( footprint.release(), ADD_MODE::APPEND );
1303 THROW_IO_ERROR( wxT(
"Components6 stream is not fully parsed" ) );
1310 while( Angle < aMin )
1313 while( Angle >= aMax )
1336 m_reporter->
Report( wxString::Format( wxT(
"Model %s not found for footprint %s" ),
1350 std::vector<char> decompressedData;
1351 wxMemoryInputStream compressedStream( model->second.data(), model->second.size() );
1352 wxZlibInputStream zlibStream( compressedStream );
1356 decompressedData.resize( model->second.size() * 6 );
1359 while( !zlibStream.Eof() )
1361 zlibStream.Read( decompressedData.data() + offset, decompressedData.size() - offset );
1362 size_t bytesRead = zlibStream.LastRead();
1367 offset += bytesRead;
1369 if( offset >= decompressedData.size() )
1370 decompressedData.resize( 2 * decompressedData.size() );
1373 decompressedData.resize( offset );
1394 orientation = -orientation;
1403 + model->first.rotation.z,
1407 aFootprint->
Models().push_back( modelSettings );
1412 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1429 THROW_IO_ERROR( wxString::Format( wxT(
"ComponentsBodies6 stream tries to access "
1430 "component id %d of %zu existing components" ),
1445 msg.Printf( wxT(
"ComponentsBodies6 stream tries to access model id %s which does "
1446 "not exist" ), elem.
modelId );
1456 file->
name = modelTuple->second.m_modelname;
1458 wxMemoryInputStream compressedStream(modelTuple->second.m_data.data(), modelTuple->second.m_data.size());
1459 wxZlibInputStream zlibStream(compressedStream);
1460 wxMemoryOutputStream decompressedStream;
1461 zlibStream.Read(decompressedStream);
1480 + modelTuple->second.m_rotation.z,
1484 footprint->
Models().push_back( modelSettings );
1488 THROW_IO_ERROR( wxT(
"ComponentsBodies6 stream is not fully parsed" ) );
1495 THROW_IO_ERROR( wxT(
"Incorrect number of reference points for linear dimension object" ) );
1504 _(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1505 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer ),
1518 dimension->SetLayer( klayer );
1519 dimension->SetStart( referencePoint0 );
1521 if( referencePoint0 != aElem.
xy1 )
1534 SEG segm1( referencePoint0, referencePoint0 + directionNormalVector );
1535 SEG segm2( referencePoint1, referencePoint1 + direction );
1539 THROW_IO_ERROR( wxT(
"Invalid dimension. This should never happen." ) );
1541 dimension->SetEnd( *intersection );
1545 if( ( direction.
x > 0 || direction.
y < 0 ) != ( aElem.
angle >= 180.0 ) )
1548 dimension->SetHeight( height );
1552 dimension->SetEnd( referencePoint1 );
1555 dimension->SetLineThickness( aElem.
linewidth );
1557 dimension->SetUnitsFormat( DIM_UNITS_FORMAT::NO_SUFFIX );
1561 wxRegEx units( wxS(
"(mm)|(in)|(mils)|(thou)|(')|(\")" ), wxRE_ADVANCED );
1564 dimension->SetUnitsFormat( DIM_UNITS_FORMAT::BARE_SUFFIX );
1573 dimension->Text().SetBold( aElem.
textbold );
1576 dimension->SetTextThickness( dimension->GetTextThickness() *
BOLD_FACTOR );
1581 case ALTIUM_UNIT::INCHES:
1582 dimension->SetUnits( EDA_UNITS::INCHES );
1584 case ALTIUM_UNIT::MILS:
1585 dimension->SetUnits( EDA_UNITS::MILS );
1587 case ALTIUM_UNIT::MILLIMETERS:
1588 case ALTIUM_UNIT::CENTIMETER:
1589 dimension->SetUnits( EDA_UNITS::MILLIMETRES );
1595 m_board->
Add( dimension.release(), ADD_MODE::APPEND );
1602 THROW_IO_ERROR( wxT(
"Not enough reference points for radial dimension object" ) );
1611 _(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1612 "It has been moved to KiCad layer Eco1_User." ),
1622 std::unique_ptr<PCB_DIM_RADIAL> dimension = std::make_unique<PCB_DIM_RADIAL>(
m_board );
1625 dimension->SetLayer( klayer );
1626 dimension->SetStart( referencePoint0 );
1627 dimension->SetEnd( aElem.
xy1 );
1628 dimension->SetLineThickness( aElem.
linewidth );
1629 dimension->SetKeepTextAligned(
false );
1634 dimension->SetUnitsFormat( aElem.
textsuffix.IsEmpty() ? DIM_UNITS_FORMAT::NO_SUFFIX
1635 : DIM_UNITS_FORMAT::BARE_SUFFIX );
1639 case ALTIUM_UNIT::INCHES:
1640 dimension->SetUnits( EDA_UNITS::INCHES );
1642 case ALTIUM_UNIT::MILS:
1643 dimension->SetUnits( EDA_UNITS::MILS );
1645 case ALTIUM_UNIT::MILLIMETERS:
1646 case ALTIUM_UNIT::CENTIMETER:
1647 dimension->SetUnits( EDA_UNITS::MILLIMETRES );
1657 m_reporter->
Report( wxT(
"No text position present for leader dimension object" ),
1664 dimension->SetTextPos( aElem.
textPoint.at( 0 ) );
1670 dimension->SetBold( aElem.
textbold );
1673 dimension->SetTextThickness( dimension->GetTextThickness() *
BOLD_FACTOR );
1681 int yAdjust = dimension->GetTextBox().GetCenter().y - dimension->GetTextPos().y;
1682 dimension->SetTextPos( dimension->GetTextPos() +
VECTOR2I( 0, yAdjust + aElem.
textgap ) );
1686 m_board->
Add( dimension.release(), ADD_MODE::APPEND );
1699 msg.Printf(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1700 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer );
1715 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
1717 shape->SetLayer( klayer );
1719 shape->SetStart( last );
1723 m_board->
Add( shape.release(), ADD_MODE::APPEND );
1731 if( dirVec.
x != 0 || dirVec.
y != 0 )
1739 std::unique_ptr<PCB_SHAPE> shape1 =
1740 std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
1742 shape1->SetLayer( klayer );
1744 shape1->SetStart( referencePoint0 );
1745 shape1->SetEnd( referencePoint0 + arrVec );
1747 m_board->
Add( shape1.release(), ADD_MODE::APPEND );
1753 std::unique_ptr<PCB_SHAPE> shape2 =
1754 std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
1756 shape2->SetLayer( klayer );
1758 shape2->SetStart( referencePoint0 );
1759 shape2->SetEnd( referencePoint0 + arrVec );
1761 m_board->
Add( shape2.release(), ADD_MODE::APPEND );
1771 m_reporter->
Report( wxT(
"No text position present for leader dimension object" ),
1778 std::unique_ptr<PCB_TEXT>
text = std::make_unique<PCB_TEXT>(
m_board );
1782 text->SetLayer( klayer );
1801 msg.Printf(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1802 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer );
1811 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
1813 shape->SetLayer( klayer );
1818 m_board->
Add( shape.release(), ADD_MODE::APPEND );
1832 msg.Printf(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1833 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer );
1843 std::unique_ptr<PCB_DIM_CENTER> dimension = std::make_unique<PCB_DIM_CENTER>(
m_board );
1845 dimension->SetLayer( klayer );
1846 dimension->SetLineThickness( aElem.
linewidth );
1847 dimension->SetStart( aElem.
xy1 );
1848 dimension->SetEnd( aElem.
xy1 + vec );
1850 m_board->
Add( dimension.release(), ADD_MODE::APPEND );
1855 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1869 case ALTIUM_DIMENSION_KIND::LINEAR:
1872 case ALTIUM_DIMENSION_KIND::ANGULAR:
1876 wxString::Format(
_(
"Ignored Angular dimension (not yet supported)." ) ),
1880 case ALTIUM_DIMENSION_KIND::RADIAL:
1883 case ALTIUM_DIMENSION_KIND::LEADER:
1886 case ALTIUM_DIMENSION_KIND::DATUM:
1890 wxString::Format(
_(
"Ignored Datum dimension (not yet supported)." ) ),
1895 case ALTIUM_DIMENSION_KIND::BASELINE:
1899 wxString::Format(
_(
"Ignored Baseline dimension (not yet supported)." ) ),
1903 case ALTIUM_DIMENSION_KIND::CENTER:
1906 case ALTIUM_DIMENSION_KIND::LINEAR_DIAMETER:
1910 wxString::Format(
_(
"Ignored Linear dimension (not yet supported)." ) ),
1914 case ALTIUM_DIMENSION_KIND::RADIAL_DIAMETER:
1918 wxString::Format(
_(
"Ignored Radial dimension (not yet supported)." ) ),
1926 msg.Printf(
_(
"Ignored dimension of kind %d (not yet supported)." ), elem.
kind );
1934 THROW_IO_ERROR( wxT(
"Dimensions6 stream is not fully parsed" ) );
1939 const CFB::COMPOUND_FILE_ENTRY* aEntry,
1940 const std::vector<std::string>& aRootDir )
1951 wxString invalidChars = wxFileName::GetForbiddenChars();
1958 std::vector<std::string> stepPath = aRootDir;
1959 stepPath.emplace_back( std::to_string( idx ) );
1961 bool validName = !elem.
name.IsEmpty() && elem.
name.IsAscii() &&
1962 wxString::npos == elem.
name.find_first_of( invalidChars );
1963 wxString storageName = !validName ? wxString::Format( wxT(
"model_%d" ), idx )
1968 const CFB::COMPOUND_FILE_ENTRY* stepEntry = aAltiumPcbFile.
FindStream( stepPath );
1970 if( stepEntry ==
nullptr )
1975 msg.Printf(
_(
"File not found: '%s'. 3D-model not imported." ),
1983 size_t stepSize =
static_cast<size_t>( stepEntry->size );
1984 std::vector<char> stepContent( stepSize );
1992 std::move( stepContent ) ) ) );
2001 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2013 ANET6 elem( reader );
2027 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2060 if( elem.
hatchstyle != ALTIUM_POLYGON_HATCHSTYLE::SOLID )
2070 msg.Printf(
_(
"Polygon outline count is %d, expected 1." ), outline.
OutlineCount() );
2078 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board);
2082 zone->SetPosition( elem.
vertices.at( 0 ).position );
2083 zone->SetLocked( elem.
locked );
2085 zone->Outline()->AddOutline( outline.
Outline( 0 ) );
2093 const ARULE6* zoneClearanceRule =
GetRule( ALTIUM_RULE_KIND::CLEARANCE,
2094 wxT(
"PolygonClearance" ) );
2095 int planeLayers = 0;
2096 int signalLayers = 0;
2110 if( planeLayers > 0 && planeClearanceRule )
2113 if( signalLayers > 0 && zoneClearanceRule )
2114 clearance = std::max( clearance, zoneClearanceRule->
clearanceGap );
2117 zone->SetLocalClearance( clearance );
2121 if( polygonConnectRule !=
nullptr )
2125 case ALTIUM_CONNECT_STYLE::DIRECT:
2126 zone->SetPadConnection( ZONE_CONNECTION::FULL );
2129 case ALTIUM_CONNECT_STYLE::NONE:
2130 zone->SetPadConnection( ZONE_CONNECTION::NONE );
2134 case ALTIUM_CONNECT_STYLE::RELIEF:
2135 zone->SetPadConnection( ZONE_CONNECTION::THERMAL );
2140 zone->SetThermalReliefSpokeWidth(
2151 zone->SetAssignedPriority( 1 );
2156 || zone->GetBoundingBox().Contains( outer_plane->second->GetBoundingBox() ) )
2162 if( elem.
hatchstyle != ALTIUM_POLYGON_HATCHSTYLE::SOLID
2163 && elem.
hatchstyle != ALTIUM_POLYGON_HATCHSTYLE::UNKNOWN )
2165 zone->SetFillMode( ZONE_FILL_MODE::HATCH_PATTERN );
2168 if( elem.
hatchstyle == ALTIUM_POLYGON_HATCHSTYLE::NONE )
2171 const BOX2I& bbox = zone->GetBoundingBox();
2179 if( elem.
hatchstyle == ALTIUM_POLYGON_HATCHSTYLE::DEGREE_45 )
2180 zone->SetHatchOrientation(
ANGLE_45 );
2183 zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE,
2186 m_board->
Add( zone.release(), ADD_MODE::APPEND );
2194 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2212 std::sort( val.second.begin(), val.second.end(),
2215 return lhs.priority < rhs.priority;
2228 if( trackWidthRule )
2234 if( routingViasRule )
2245 if( holeToHoleRule )
2251 if( soldermaskRule )
2262 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2278 THROW_IO_ERROR( wxT(
"BoardRegions stream is not fully parsed" ) );
2282 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2290 for(
int primitiveIndex = 0; reader.
GetRemainingBytes() >= 4; primitiveIndex++ )
2296 || elem.
kind == ALTIUM_REGION_KIND::BOARD_CUTOUT )
2309 THROW_IO_ERROR(
"ShapeBasedRegions6 stream is not fully parsed" );
2315 if( aElem.
kind == ALTIUM_REGION_KIND::BOARD_CUTOUT )
2319 else if( aElem.
kind == ALTIUM_REGION_KIND::POLYGON_CUTOUT || aElem.
is_keepout )
2333 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board );
2335 zone->SetIsRuleArea(
true );
2341 else if( aElem.
kind == ALTIUM_REGION_KIND::POLYGON_CUTOUT )
2343 zone->SetDoNotAllowCopperPour(
true );
2344 zone->SetDoNotAllowVias(
false );
2345 zone->SetDoNotAllowTracks(
false );
2346 zone->SetDoNotAllowPads(
false );
2347 zone->SetDoNotAllowFootprints(
false );
2350 zone->SetPosition( aElem.
outline.at( 0 ).position );
2351 zone->Outline()->AddOutline( linechain );
2355 zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE,
2358 m_board->
Add( zone.release(), ADD_MODE::APPEND );
2360 else if( aElem.
kind == ALTIUM_REGION_KIND::DASHED_OUTLINE )
2369 msg.Printf(
_(
"Dashed outline found on an Altium layer (%d) with no KiCad equivalent. "
2370 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer );
2389 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::POLY );
2391 shape->SetPolyShape( linechain );
2392 shape->SetFilled(
false );
2393 shape->SetLayer( klayer );
2396 m_board->
Add( shape.release(), ADD_MODE::APPEND );
2398 else if( aElem.
kind == ALTIUM_REGION_KIND::COPPER )
2406 else if( aElem.
kind == ALTIUM_REGION_KIND::BOARD_CUTOUT )
2415 msg.Printf(
_(
"Ignored polygon shape of kind %d (not yet supported)." ), aElem.
kind );
2424 const int aPrimitiveIndex )
2426 if( aElem.
kind == ALTIUM_REGION_KIND::POLYGON_CUTOUT || aElem.
is_keepout )
2440 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aFootprint );
2442 zone->SetIsRuleArea(
true );
2448 else if( aElem.
kind == ALTIUM_REGION_KIND::POLYGON_CUTOUT )
2450 zone->SetDoNotAllowCopperPour(
true );
2451 zone->SetDoNotAllowVias(
false );
2452 zone->SetDoNotAllowTracks(
false );
2453 zone->SetDoNotAllowPads(
false );
2454 zone->SetDoNotAllowFootprints(
false );
2457 zone->SetPosition( aElem.
outline.at( 0 ).position );
2458 zone->Outline()->AddOutline( linechain );
2462 zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE,
2465 aFootprint->
Add( zone.release(), ADD_MODE::APPEND );
2467 else if( aElem.
kind == ALTIUM_REGION_KIND::COPPER )
2478 else if( aElem.
kind == ALTIUM_REGION_KIND::DASHED_OUTLINE
2479 || aElem.
kind == ALTIUM_REGION_KIND::BOARD_CUTOUT )
2492 msg.Printf(
_(
"Loading library '%s':\n"
2493 "Footprint %s contains a dashed outline on Altium layer (%d) with "
2494 "no KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
2506 msg.Printf(
_(
"Footprint %s contains a dashed outline on Altium layer (%d) with "
2507 "no KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
2529 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aFootprint, SHAPE_T::POLY );
2531 shape->SetPolyShape( linechain );
2532 shape->SetFilled(
false );
2533 shape->SetLayer( klayer );
2535 if( aElem.
kind == ALTIUM_REGION_KIND::DASHED_OUTLINE )
2540 aFootprint->
Add( shape.release(), ADD_MODE::APPEND );
2549 msg.Printf(
_(
"Error loading library '%s':\n"
2550 "Footprint %s contains polygon shape of kind %d (not yet supported)." ),
2562 msg.Printf(
_(
"Footprint %s contains polygon shape of kind %d (not yet supported)." ),
2590 for(
const std::vector<ALTIUM_VERTICE>& hole : aElem.
holes )
2598 polySet.
AddHole( hole_linechain );
2601 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::POLY );
2603 shape->SetPolyShape( polySet );
2604 shape->SetFilled(
true );
2605 shape->SetLayer( aLayer );
2613 m_board->
Add( shape.release(), ADD_MODE::APPEND );
2620 const int aPrimitiveIndex )
2637 for(
const std::vector<ALTIUM_VERTICE>& hole : aElem.
holes )
2645 polySet.
AddHole( hole_linechain );
2648 if( aLayer ==
F_Cu || aLayer ==
B_Cu )
2650 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
2653 padLayers.
set( aLayer );
2655 pad->SetAttribute( PAD_ATTRIB::SMD );
2656 pad->SetShape( PAD_SHAPE::CUSTOM );
2662 pad->SetShape( PAD_SHAPE::CUSTOM );
2663 pad->SetAnchorPadShape( PAD_SHAPE::CIRCLE );
2664 pad->SetSize( { anchorSize, anchorSize } );
2665 pad->SetPosition( anchorPos );
2668 shapePolys.
Move( -anchorPos );
2669 pad->AddPrimitivePoly( shapePolys, 0,
true );
2672 auto it = map.find( aPrimitiveIndex );
2674 if( it != map.end() )
2678 if(
info.pastemaskexpansionmode == ALTIUM_MODE::MANUAL )
2680 pad->SetLocalSolderPasteMargin(
2681 info.pastemaskexpansionmanual ?
info.pastemaskexpansionmanual : 1 );
2684 if(
info.soldermaskexpansionmode == ALTIUM_MODE::MANUAL )
2686 pad->SetLocalSolderMaskMargin(
2687 info.soldermaskexpansionmanual ?
info.soldermaskexpansionmanual : 1 );
2690 if(
info.pastemaskexpansionmode != ALTIUM_MODE::NONE )
2693 if(
info.soldermaskexpansionmode != ALTIUM_MODE::NONE )
2697 pad->SetLayerSet( padLayers );
2699 aFootprint->
Add(
pad.release(), ADD_MODE::APPEND );
2703 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aFootprint, SHAPE_T::POLY );
2705 shape->SetPolyShape( polySet );
2706 shape->SetFilled(
true );
2707 shape->SetLayer( aLayer );
2710 aFootprint->
Add( shape.release(), ADD_MODE::APPEND );
2716 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2732 THROW_IO_ERROR( wxString::Format(
"Region stream tries to access polygon id %d "
2733 "of %d existing polygons.",
2740 if( zone ==
nullptr )
2762 for(
const std::vector<ALTIUM_VERTICE>& hole : elem.
holes )
2769 hole_linechain.
Append( hole.at( 0 ).position );
2771 fill.
AddHole( hole_linechain );
2791 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2798 for(
int primitiveIndex = 0; reader.
GetRemainingBytes() >= 4; primitiveIndex++ )
2801 AARC6 elem( reader );
2823 aShape->
SetShape( SHAPE_T::CIRCLE );
2852 THROW_IO_ERROR( wxString::Format(
"Tracks stream tries to access polygon id %u "
2853 "of %zu existing polygons.",
2859 if( zone ==
nullptr )
2907 for(
const auto& layerExpansionMask :
2910 int width = aElem.
width + ( layerExpansionMask.second * 2 );
2914 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>(
m_board );
2917 arc->SetStroke(
STROKE_PARAMS( width, LINE_STYLE::SOLID ) );
2918 arc->SetLayer( layerExpansionMask.first );
2920 m_board->
Add( arc.release(), ADD_MODE::APPEND );
2927 const int aPrimitiveIndex,
const bool aIsBoardImport )
2931 wxFAIL_MSG( wxString::Format(
"Altium: Unexpected footprint Arc with polygon id %d",
2964 for(
const auto& layerExpansionMask :
2967 int width = aElem.
width + ( layerExpansionMask.second * 2 );
2971 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>( aFootprint );
2974 arc->SetStroke(
STROKE_PARAMS( width, LINE_STYLE::SOLID ) );
2975 arc->SetLayer( layerExpansionMask.first );
2977 aFootprint->
Add( arc.release(), ADD_MODE::APPEND );
2988 PCB_SHAPE shape(
nullptr, SHAPE_T::ARC );
3002 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board, &shapeArc );
3004 arc->SetWidth( aElem.
width );
3005 arc->SetLayer( aLayer );
3008 m_board->
Add( arc.release(), ADD_MODE::APPEND );
3012 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>(
m_board );
3016 arc->SetLayer( aLayer );
3018 m_board->
Add( arc.release(), ADD_MODE::APPEND );
3026 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>( aFootprint );
3030 arc->SetLayer( aLayer );
3032 aFootprint->
Add( arc.release(), ADD_MODE::APPEND );
3037 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3047 APAD6 elem( reader );
3069 && aElem.
layer != ALTIUM_LAYER::MULTI_LAYER )
3076 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
3077 footprint->SetPosition( aElem.
position );
3081 m_board->
Add( footprint.release(), ADD_MODE::APPEND );
3088 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
3090 pad->SetNumber(
"" );
3096 pad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
3097 pad->SetShape( PAD_SHAPE::CIRCLE );
3098 pad->SetAttribute( PAD_ATTRIB::PTH );
3101 pad->SetLayerSet(
LSET().AllCuMask() );
3103 if( aElem.
viamode == ALTIUM_PAD_MODE::SIMPLE )
3105 else if( aElem.
viamode == ALTIUM_PAD_MODE::TOP_MIDDLE_BOTTOM )
3114 for(
int ii = 0; ii < 32; ++ii )
3123 pad->Padstack().FrontOuterLayers().has_solder_mask =
true;
3127 pad->Padstack().FrontOuterLayers().has_solder_mask =
false;
3133 pad->Padstack().BackOuterLayers().has_solder_mask =
true;
3137 pad->Padstack().BackOuterLayers().has_solder_mask =
false;
3142 pad->SetLocked(
true );
3151 aFootprint->
Add(
pad.release(), ADD_MODE::APPEND );
3159 && aElem.
layer != ALTIUM_LAYER::MULTI_LAYER )
3172 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
3184 pad->SetAttribute( PAD_ATTRIB::SMD );
3188 if( aElem.
layer != ALTIUM_LAYER::MULTI_LAYER )
3196 msg.Printf(
_(
"Error loading library '%s':\n"
3197 "Footprint %s pad %s is not marked as multilayer, but is a TH pad." ),
3209 msg.Printf(
_(
"Footprint %s pad %s is not marked as multilayer, but is a TH pad." ),
3217 pad->SetAttribute( aElem.
plated ? PAD_ATTRIB::PTH : PAD_ATTRIB::NPTH );
3221 pad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
3228 case ALTIUM_PAD_HOLE_SHAPE::ROUND:
3229 wxFAIL_MSG( wxT(
"Round holes are handled before the switch" ) );
3232 case ALTIUM_PAD_HOLE_SHAPE::SQUARE:
3238 msg.Printf(
_(
"Loading library '%s':\n"
3239 "Footprint %s pad %s has a square hole (not yet supported)." ),
3251 msg.Printf(
_(
"Footprint %s pad %s has a square hole (not yet supported)." ),
3258 pad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
3264 case ALTIUM_PAD_HOLE_SHAPE::SLOT:
3266 pad->SetDrillShape( PAD_DRILL_SHAPE::OBLONG );
3286 msg.Printf(
_(
"Loading library '%s':\n"
3287 "Footprint %s pad %s has a hole-rotation of %f degrees. "
3288 "KiCad only supports 90 degree rotations." ),
3301 msg.Printf(
_(
"Footprint %s pad %s has a hole-rotation of %f degrees. "
3302 "KiCad only supports 90 degree rotations." ),
3315 case ALTIUM_PAD_HOLE_SHAPE::UNKNOWN:
3321 msg.Printf(
_(
"Error loading library '%s':\n"
3322 "Footprint %s pad %s uses a hole of unknown kind %d." ),
3335 msg.Printf(
_(
"Footprint %s pad %s uses a hole of unknown kind %d." ),
3343 pad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
3353 if( aElem.
padmode != ALTIUM_PAD_MODE::SIMPLE )
3360 msg.Printf(
_(
"Error loading library '%s':\n"
3361 "Footprint %s pad %s uses a complex pad stack (not yet supported)." ),
3373 msg.Printf(
_(
"Footprint %s pad %s uses a complex pad stack (not yet supported)." ),
3383 case ALTIUM_PAD_SHAPE::RECT:
3384 pad->SetShape( PAD_SHAPE::RECTANGLE );
3387 case ALTIUM_PAD_SHAPE::CIRCLE:
3389 && aElem.
sizeAndShape->alt_shape[0] == ALTIUM_PAD_SHAPE_ALT::ROUNDRECT )
3391 pad->SetShape( PAD_SHAPE::ROUNDRECT );
3392 double ratio = aElem.
sizeAndShape->cornerradius[0] / 200.;
3393 pad->SetRoundRectRadiusRatio( ratio );
3397 pad->SetShape( PAD_SHAPE::CIRCLE );
3401 pad->SetShape( PAD_SHAPE::OVAL );
3406 case ALTIUM_PAD_SHAPE::OCTAGONAL:
3407 pad->SetShape( PAD_SHAPE::CHAMFERED_RECT );
3409 pad->SetChamferRectRatio( 0.25 );
3412 case ALTIUM_PAD_SHAPE::UNKNOWN:
3419 msg.Printf(
_(
"Error loading library '%s':\n"
3420 "Footprint %s pad %s uses an unknown pad-shape." ),
3432 msg.Printf(
_(
"Footprint %s pad %s uses an unknown pad-shape." ),
3441 if(
pad->GetAttribute() == PAD_ATTRIB::NPTH &&
pad->HasHole() )
3444 pad->SetShape(
pad->GetDrillShape() == PAD_DRILL_SHAPE::CIRCLE ? PAD_SHAPE::CIRCLE
3445 : PAD_SHAPE::OVAL );
3446 pad->SetSize(
pad->GetDrillSize() );
3449 switch( aElem.
layer )
3451 case ALTIUM_LAYER::TOP_LAYER:
3456 case ALTIUM_LAYER::BOTTOM_LAYER:
3461 case ALTIUM_LAYER::MULTI_LAYER:
3467 pad->SetLayer( klayer );
3468 pad->SetLayerSet(
LSET( klayer ) );
3479 pad->SetLayerSet(
pad->GetLayerSet().reset(
F_Mask ) );
3482 pad->SetLayerSet(
pad->GetLayerSet().reset(
B_Mask ) );
3484 aFootprint->
Add(
pad.release(), ADD_MODE::APPEND );
3497 msg.Printf(
_(
"Non-copper pad %s found on an Altium layer (%d) with no KiCad "
3498 "equivalent. It has been moved to KiCad layer Eco1_User." ),
3506 std::unique_ptr<PCB_SHAPE>
pad = std::make_unique<PCB_SHAPE>(
m_board );
3525 msg.Printf(
_(
"Loading library '%s':\n"
3526 "Footprint %s non-copper pad %s found on an Altium layer (%d) with no "
3527 "KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
3540 msg.Printf(
_(
"Footprint %s non-copper pad %s found on an Altium layer (%d) with no "
3541 "KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
3552 std::unique_ptr<PCB_SHAPE>
pad = std::make_unique<PCB_SHAPE>( aFootprint );
3556 aFootprint->
Add(
pad.release(), ADD_MODE::APPEND );
3568 msg.Printf(
_(
"Non-copper pad %s is connected to a net, which is not supported." ),
3579 msg.Printf(
_(
"Non-copper pad %s has a hole, which is not supported." ), aElem.
name );
3584 if( aElem.
padmode != ALTIUM_PAD_MODE::SIMPLE )
3589 msg.Printf(
_(
"Non-copper pad %s has a complex pad stack (not yet supported)." ),
3597 case ALTIUM_PAD_SHAPE::RECT:
3616 case ALTIUM_PAD_SHAPE::CIRCLE:
3618 && aElem.
sizeAndShape->alt_shape[0] == ALTIUM_PAD_SHAPE_ALT::ROUNDRECT )
3621 int cornerradius = aElem.
sizeAndShape->cornerradius[0];
3622 int offset = ( std::min( aElem.
topsize.
x, aElem.
topsize.
y ) * cornerradius ) / 200;
3627 if( cornerradius < 100 )
3629 int offsetX = aElem.
topsize.
x / 2 - offset;
3630 int offsetY = aElem.
topsize.
y / 2 - offset;
3644 aShape->
SetShape( SHAPE_T::CIRCLE );
3653 aShape->
SetShape( SHAPE_T::SEGMENT );
3661 aShape->
SetShape( SHAPE_T::SEGMENT );
3673 aShape->
SetShape( SHAPE_T::CIRCLE );
3683 aShape->
SetShape( SHAPE_T::SEGMENT );
3686 LINE_STYLE::SOLID ) );
3706 case ALTIUM_PAD_SHAPE::OCTAGONAL:
3723 aShape->
SetPolyPoints( { p11 - chamferX, p11 - chamferY, p12 + chamferY, p12 - chamferX,
3724 p22 + chamferX, p22 + chamferY, p21 - chamferY, p21 + chamferX } );
3731 case ALTIUM_PAD_SHAPE::UNKNOWN:
3736 msg.Printf(
_(
"Non-copper pad %s uses an unknown pad-shape." ), aElem.
name );
3746 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3756 AVIA6 elem( reader );
3758 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
3766 bool start_layer_outside = elem.
layer_start == ALTIUM_LAYER::TOP_LAYER
3767 || elem.
layer_start == ALTIUM_LAYER::BOTTOM_LAYER;
3768 bool end_layer_outside = elem.
layer_end == ALTIUM_LAYER::TOP_LAYER
3769 || elem.
layer_end == ALTIUM_LAYER::BOTTOM_LAYER;
3771 if( start_layer_outside && end_layer_outside )
3773 via->SetViaType( VIATYPE::THROUGH );
3775 else if( ( !start_layer_outside ) && ( !end_layer_outside ) )
3777 via->SetViaType( VIATYPE::BLIND_BURIED );
3781 via->SetViaType( VIATYPE::MICROVIA );
3792 msg.Printf(
_(
"Via from layer %d to %d uses a non-copper layer, which is not "
3803 via->SetLayerPair( start_klayer, end_klayer );
3807 via->SetFrontTentingMode( elem.
is_tent_top ? TENTING_MODE::TENTED
3808 : TENTING_MODE::NOT_TENTED );
3810 : TENTING_MODE::NOT_TENTED );
3821 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3828 for(
int primitiveIndex = 0; reader.
GetRemainingBytes() >= 4; primitiveIndex++ )
3859 msg.Printf( wxT(
"ATRACK6 stream tries to access polygon id %u "
3860 "of %u existing polygons; skipping it" ),
3861 static_cast<unsigned>( aElem.
polygon ),
3862 static_cast<unsigned>(
m_polygons.size() ) );
3871 if( zone ==
nullptr )
3887 PCB_SHAPE shape(
nullptr, SHAPE_T::SEGMENT );
3905 PCB_SHAPE shape(
nullptr, SHAPE_T::SEGMENT );
3919 ALTIUM_RECORD::TRACK, aPrimitiveIndex, aElem.
layer ) )
3921 int width = aElem.
width + ( layerExpansionMask.second * 2 );
3924 std::unique_ptr<PCB_SHAPE> seg = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
3926 seg->SetStart( aElem.
start );
3927 seg->SetEnd( aElem.
end );
3928 seg->SetStroke(
STROKE_PARAMS( width, LINE_STYLE::SOLID ) );
3929 seg->SetLayer( layerExpansionMask.first );
3931 m_board->
Add( seg.release(), ADD_MODE::APPEND );
3938 const int aPrimitiveIndex,
3939 const bool aIsBoardImport )
3943 wxFAIL_MSG( wxString::Format(
"Altium: Unexpected footprint Track with polygon id %u",
3952 PCB_SHAPE shape(
nullptr, SHAPE_T::SEGMENT );
3977 ALTIUM_RECORD::TRACK, aPrimitiveIndex, aElem.
layer ) )
3979 int width = aElem.
width + ( layerExpansionMask.second * 2 );
3982 std::unique_ptr<PCB_SHAPE> seg = std::make_unique<PCB_SHAPE>( aFootprint, SHAPE_T::SEGMENT );
3984 seg->SetStart( aElem.
start );
3985 seg->SetEnd( aElem.
end );
3986 seg->SetStroke(
STROKE_PARAMS( width, LINE_STYLE::SOLID ) );
3987 seg->SetLayer( layerExpansionMask.first );
3989 aFootprint->
Add( seg.release(), ADD_MODE::APPEND );
3999 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
4001 track->SetStart( aElem.
start );
4002 track->SetEnd( aElem.
end );
4003 track->SetWidth( aElem.
width );
4004 track->SetLayer( aLayer );
4007 m_board->
Add( track.release(), ADD_MODE::APPEND );
4011 std::unique_ptr<PCB_SHAPE> seg = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
4013 seg->SetStart( aElem.
start );
4014 seg->SetEnd( aElem.
end );
4016 seg->SetLayer( aLayer );
4018 m_board->
Add( seg.release(), ADD_MODE::APPEND );
4026 std::unique_ptr<PCB_SHAPE> seg = std::make_unique<PCB_SHAPE>( aFootprint, SHAPE_T::SEGMENT );
4028 seg->SetStart( aElem.
start );
4029 seg->SetEnd( aElem.
end );
4031 seg->SetLayer( aLayer );
4033 aFootprint->
Add( seg.release(), ADD_MODE::APPEND );
4038 const CFB::COMPOUND_FILE_ENTRY* aEntry )
4048 THROW_IO_ERROR( wxT(
"WideStrings6 stream is not fully parsed" ) );
4052 const CFB::COMPOUND_FILE_ENTRY* aEntry )
4082 if( aElem.
fonttype == ALTIUM_TEXT_TYPE::BARCODE )
4087 msg.Printf(
_(
"Ignored barcode on Altium layer %d (not yet supported)." ),
4102 if( aElem.
fonttype == ALTIUM_TEXT_TYPE::BARCODE )
4109 msg.Printf(
_(
"Error loading library '%s':\n"
4110 "Footprint %s contains barcode on Altium layer %d (not yet supported)." ),
4122 msg.Printf(
_(
"Footprint %s contains barcode on Altium layer %d (not yet supported)." ),
4139 std::unique_ptr<PCB_TEXTBOX> pcbTextbox = std::make_unique<PCB_TEXTBOX>(
m_board );
4140 std::unique_ptr<PCB_TEXT> pcbText = std::make_unique<PCB_TEXT>(
m_board );
4143 static const std::map<wxString, wxString> variableMap = {
4144 {
"LAYER_NAME",
"LAYER" },
4145 {
"PRINT_DATE",
"CURRENT_DATE"},
4155 pcbTextbox->SetBorderEnabled(
false );
4157 item = pcbTextbox.get();
4158 text = pcbTextbox.get();
4165 case ALTIUM_TEXT_POSITION::LEFT_TOP:
4166 case ALTIUM_TEXT_POSITION::LEFT_CENTER:
4167 case ALTIUM_TEXT_POSITION::LEFT_BOTTOM:
4171 case ALTIUM_TEXT_POSITION::CENTER_TOP:
4172 case ALTIUM_TEXT_POSITION::CENTER_CENTER:
4173 case ALTIUM_TEXT_POSITION::CENTER_BOTTOM:
4177 case ALTIUM_TEXT_POSITION::RIGHT_TOP:
4178 case ALTIUM_TEXT_POSITION::RIGHT_CENTER:
4179 case ALTIUM_TEXT_POSITION::RIGHT_BOTTOM:
4187 msg.Printf(
_(
"Unknown textbox justification %d, text %s" ),
4200 pcbText->SetPosition( aElem.
position );
4205 text->SetText(kicadText);
4212 m_board->
Add( pcbTextbox.release(), ADD_MODE::APPEND );
4214 m_board->
Add( pcbText.release(), ADD_MODE::APPEND );
4221 std::unique_ptr<PCB_TEXTBOX> fpTextbox = std::make_unique<PCB_TEXTBOX>( aFootprint );
4222 std::unique_ptr<PCB_TEXT> fpText = std::make_unique<PCB_TEXT>( aFootprint );
4239 item = &aFootprint->
Value();
4241 field = &aFootprint->
Value();
4245 item = fpText.get();
4246 text = fpText.get();
4250 static const std::map<wxString, wxString> variableMap = {
4251 {
"DESIGNATOR",
"REFERENCE" },
4252 {
"COMMENT",
"VALUE" },
4253 {
"VALUE",
"ALTIUM_VALUE" },
4254 {
"LAYER_NAME",
"LAYER" },
4255 {
"PRINT_DATE",
"CURRENT_DATE"},
4260 item = fpTextbox.get();
4261 text = fpTextbox.get();
4266 fpTextbox->SetBorderEnabled(
false );
4271 case ALTIUM_TEXT_POSITION::LEFT_TOP:
4272 case ALTIUM_TEXT_POSITION::LEFT_CENTER:
4273 case ALTIUM_TEXT_POSITION::LEFT_BOTTOM:
4277 case ALTIUM_TEXT_POSITION::CENTER_TOP:
4278 case ALTIUM_TEXT_POSITION::CENTER_CENTER:
4279 case ALTIUM_TEXT_POSITION::CENTER_BOTTOM:
4283 case ALTIUM_TEXT_POSITION::RIGHT_TOP:
4284 case ALTIUM_TEXT_POSITION::RIGHT_CENTER:
4285 case ALTIUM_TEXT_POSITION::RIGHT_BOTTOM:
4293 msg.Printf(
_(
"Unknown textbox justification %d, text %s" ),
4312 text->SetText( kicadText );
4313 text->SetKeepUpright(
false );
4322 aFootprint->
Add( fpTextbox.release(), ADD_MODE::APPEND );
4324 aFootprint->
Add( fpText.release(), ADD_MODE::APPEND );
4336 if( aElem.
fonttype == ALTIUM_TEXT_TYPE::TRUETYPE )
4344 if( font->
GetName().Contains( wxS(
"Arial" ) ) )
4360 const CFB::COMPOUND_FILE_ENTRY* aEntry )
4393 PCB_SHAPE shape(
nullptr, SHAPE_T::RECTANGLE );
4418 const bool aIsBoardImport )
4421 || aElem.
layer == ALTIUM_LAYER::KEEP_OUT_LAYER )
4424 PCB_SHAPE shape(
nullptr, SHAPE_T::RECTANGLE );
4458 std::unique_ptr<PCB_SHAPE> fill = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::RECTANGLE );
4460 fill->SetFilled(
true );
4461 fill->SetLayer( aLayer );
4464 fill->SetStart( aElem.
pos1 );
4465 fill->SetEnd( aElem.
pos2 );
4480 m_board->
Add( fill.release(), ADD_MODE::APPEND );
4487 if( aLayer ==
F_Cu || aLayer ==
B_Cu )
4489 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
4492 padLayers.
set( aLayer );
4494 pad->SetAttribute( PAD_ATTRIB::SMD );
4500 pad->SetShape( PAD_SHAPE::RECTANGLE );
4507 std::swap( width, height );
4509 pad->SetSize( { width, height } );
4510 pad->SetPosition( aElem.
pos1 / 2 + aElem.
pos2 / 2 );
4514 pad->SetShape( PAD_SHAPE::CUSTOM );
4520 pad->SetAnchorPadShape( PAD_SHAPE::CIRCLE );
4521 pad->SetSize( { anchorSize, anchorSize } );
4522 pad->SetPosition( anchorPos );
4533 aElem.
pos1.
y / 2 + aElem.
pos2.
y / 2 - anchorPos.
y );
4535 pad->AddPrimitivePoly( shapePolys, 0,
true );
4539 pad->SetLayerSet( padLayers );
4541 aFootprint->
Add(
pad.release(), ADD_MODE::APPEND );
4545 std::unique_ptr<PCB_SHAPE> fill =
4546 std::make_unique<PCB_SHAPE>( aFootprint, SHAPE_T::RECTANGLE );
4548 fill->SetFilled(
true );
4549 fill->SetLayer( aLayer );
4552 fill->SetStart( aElem.
pos1 );
4553 fill->SetEnd( aElem.
pos2 );
4562 aFootprint->
Add( fill.release(), ADD_MODE::APPEND );
4572 layerSet.
set( klayer );
4580 bool keepoutRestrictionVia = ( aKeepoutRestrictions & 0x01 ) != 0;
4581 bool keepoutRestrictionTrack = ( aKeepoutRestrictions & 0x02 ) != 0;
4582 bool keepoutRestrictionCopper = ( aKeepoutRestrictions & 0x04 ) != 0;
4583 bool keepoutRestrictionSMDPad = ( aKeepoutRestrictions & 0x08 ) != 0;
4584 bool keepoutRestrictionTHPad = ( aKeepoutRestrictions & 0x10 ) != 0;
4596 const uint8_t aKeepoutRestrictions )
4598 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board );
4600 zone->SetIsRuleArea(
true );
4607 zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE,
4610 m_board->
Add( zone.release(), ADD_MODE::APPEND );
4617 const uint8_t aKeepoutRestrictions )
4619 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aFootprint );
4621 zone->SetIsRuleArea(
true );
4628 zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE,
4632 aFootprint->
Add( zone.release(), ADD_MODE::APPEND );
4645 if( elems.first == elems.second )
4648 std::vector<std::pair<PCB_LAYER_ID, int>> layerExpansionPairs;
4650 for(
auto it = elems.first; it != elems.second; ++it )
4654 if( pInf.
type == AEXTENDED_PRIMITIVE_INFORMATION_TYPE::MASK )
4660 if( aAltiumLayer == ALTIUM_LAYER::TOP_LAYER
4661 || aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER )
4666 if( aAltiumLayer == ALTIUM_LAYER::BOTTOM_LAYER
4667 || aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER )
4675 if( aAltiumLayer == ALTIUM_LAYER::TOP_LAYER
4676 || aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER )
4681 if( aAltiumLayer == ALTIUM_LAYER::BOTTOM_LAYER
4682 || aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER )
4690 return layerExpansionPairs;
std::string FormatPath(const std::vector< std::string > &aVectorPath)
Helper for debug logging (vector -> string)
const uint16_t ALTIUM_NET_UNCONNECTED
const uint16_t ALTIUM_POLYGON_NONE
const uint16_t ALTIUM_POLYGON_BOARD
const int ALTIUM_COMPONENT_NONE
LIB_ID AltiumToKiCadLibID(const wxString &aLibName, const wxString &aLibReference)
wxString AltiumPcbSpecialStringsToKiCadStrings(const wxString &aString, const std::map< wxString, wxString > &aOverrides)
void HelperShapeLineChainFromAltiumVertices(SHAPE_LINE_CHAIN &aLine, const std::vector< ALTIUM_VERTICE > &aVertices)
double normalizeAngleDegrees(double Angle, double aMin, double aMax)
Normalize angle to be aMin < angle <= aMax angle is in degrees.
constexpr double BOLD_FACTOR
bool IsAltiumLayerCopper(ALTIUM_LAYER aLayer)
bool IsAltiumLayerAPlane(ALTIUM_LAYER aLayer)
std::function< void(const ALTIUM_PCB_COMPOUND_FILE &, const CFB::COMPOUND_FILE_ENTRY *)> PARSE_FUNCTION_POINTER_fp
constexpr int ARC_HIGH_DEF
constexpr EDA_IU_SCALE pcbIUScale
LAYER_T
The allowed types of layers, same as Specctra DSN spec.
@ BS_ITEM_TYPE_DIELECTRIC
size_t GetRemainingBytes() const
std::map< uint32_t, wxString > ReadWideStringTable()
size_t ReadAndSetSubrecordLength()
std::map< wxString, wxString > ReadProperties(std::function< std::map< wxString, wxString >(const std::string &)> handleBinaryData=[](const std::string &) { return std::map< wxString, wxString >();})
const CFB::CompoundFileReader & GetCompoundFileReader() const
const CFB::COMPOUND_FILE_ENTRY * FindStream(const std::vector< std::string > &aStreamPath) const
const std::pair< AMODEL, std::vector< char > > * GetLibModel(const wxString &aModelID) const
std::tuple< wxString, const CFB::COMPOUND_FILE_ENTRY * > FindLibFootprintDirName(const wxString &aFpUnicodeName)
PROGRESS_REPORTER * m_progressReporter
optional; may be nullptr
void ParseClasses6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
std::vector< PCB_DIM_RADIAL * > m_radialDimensions
void ConvertArcs6ToFootprintItemOnLayer(FOOTPRINT *aFootprint, const AARC6 &aElem, PCB_LAYER_ID aLayer)
void ConvertTracks6ToBoardItem(const ATRACK6 &aElem, const int aPrimitiveIndex)
void ConvertTracks6ToFootprintItem(FOOTPRINT *aFootprint, const ATRACK6 &aElem, const int aPrimitiveIndex, const bool aIsBoardImport)
int m_highest_pour_index
Altium stores pour order across all layers.
void ConvertTexts6ToFootprintItemOnLayer(FOOTPRINT *aFootprint, const ATEXT6 &aElem, PCB_LAYER_ID aLayer)
std::map< ALTIUM_LAYER, PCB_LAYER_ID > m_layermap
void ConvertShapeBasedRegions6ToBoardItemOnLayer(const AREGION6 &aElem, PCB_LAYER_ID aLayer)
void ParseVias6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void HelperParseDimensions6Leader(const ADIMENSION6 &aElem)
wxString m_footprintName
for footprint library loading error reporting
std::vector< FOOTPRINT * > m_components
void ParseShapeBasedRegions6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
const ARULE6 * GetRuleDefault(ALTIUM_RULE_KIND aKind) const
void HelperParsePad6NonCopper(const APAD6 &aElem, PCB_LAYER_ID aLayer, PCB_SHAPE *aShape)
void ParseRegions6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
std::vector< PCB_LAYER_ID > GetKicadLayersToIterate(ALTIUM_LAYER aAltiumLayer) const
void ConvertShapeBasedRegions6ToFootprintItem(FOOTPRINT *aFootprint, const AREGION6 &aElem, const int aPrimitiveIndex)
void HelperPcpShapeAsFootprintKeepoutRegion(FOOTPRINT *aFootprint, const PCB_SHAPE &aShape, const ALTIUM_LAYER aAltiumLayer, const uint8_t aKeepoutRestrictions)
void ConvertArcs6ToBoardItem(const AARC6 &aElem, const int aPrimitiveIndex)
void ConvertShapeBasedRegions6ToFootprintItemOnLayer(FOOTPRINT *aFootprint, const AREGION6 &aElem, PCB_LAYER_ID aLayer, const int aPrimitiveIndex)
std::map< ALTIUM_LAYER, ZONE * > m_outer_plane
std::vector< int > m_altiumToKicadNetcodes
unsigned m_totalCount
for progress reporting
void ParseComponents6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void HelperPcpShapeAsBoardKeepoutRegion(const PCB_SHAPE &aShape, const ALTIUM_LAYER aAltiumLayer, const uint8_t aKeepoutRestrictions)
std::map< wxString, ALTIUM_EMBEDDED_MODEL_DATA > m_EmbeddedModels
void ConvertFills6ToBoardItemOnLayer(const AFILL6 &aElem, PCB_LAYER_ID aLayer)
std::vector< std::pair< PCB_LAYER_ID, int > > HelperGetSolderAndPasteMaskExpansions(const ALTIUM_RECORD aType, const int aPrimitiveIndex, const ALTIUM_LAYER aAltiumLayer)
void ConvertComponentBody6ToFootprintItem(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, FOOTPRINT *aFootprint, const ACOMPONENTBODY6 &aElem)
void ParseBoard6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ConvertFills6ToFootprintItem(FOOTPRINT *aFootprint, const AFILL6 &aElem, const bool aIsBoardImport)
void ParseExtendedPrimitiveInformationData(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ParseFileHeader(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ConvertShapeBasedRegions6ToBoardItem(const AREGION6 &aElem)
void HelperCreateBoardOutline(const std::vector< ALTIUM_VERTICE > &aVertices)
std::map< ALTIUM_RULE_KIND, std::vector< ARULE6 > > m_rules
void ConvertVias6ToFootprintItem(FOOTPRINT *aFootprint, const AVIA6 &aElem)
void ParseRules6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void HelperSetZoneKeepoutRestrictions(ZONE &aZone, const uint8_t aKeepoutRestrictions)
void HelperParseDimensions6Linear(const ADIMENSION6 &aElem)
void ParseTracks6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
std::map< uint32_t, wxString > m_unicodeStrings
void ConvertTexts6ToBoardItem(const ATEXT6 &aElem)
void HelperParseDimensions6Center(const ADIMENSION6 &aElem)
void HelperParseDimensions6Radial(const ADIMENSION6 &aElem)
void ParseBoardRegionsData(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ParseArcs6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ConvertTexts6ToBoardItemOnLayer(const ATEXT6 &aElem, PCB_LAYER_ID aLayer)
void ConvertPads6ToFootprintItemOnCopper(FOOTPRINT *aFootprint, const APAD6 &aElem)
FOOTPRINT * ParseFootprint(ALTIUM_PCB_COMPOUND_FILE &altiumLibFile, const wxString &aFootprintName)
REPORTER * m_reporter
optional; may be nullptr
int GetNetCode(uint16_t aId) const
void ConvertTexts6ToEdaTextSettings(const ATEXT6 &aElem, EDA_TEXT &aEdaText)
wxString m_library
for footprint library loading error reporting
void ConvertPads6ToFootprintItemOnNonCopper(FOOTPRINT *aFootprint, const APAD6 &aElem)
void ConvertTexts6ToFootprintItem(FOOTPRINT *aFootprint, const ATEXT6 &aElem)
unsigned m_lastProgressCount
void ParseFills6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ConvertArcs6ToFootprintItem(FOOTPRINT *aFootprint, const AARC6 &aElem, const int aPrimitiveIndex, const bool aIsBoardImport)
void HelperParseDimensions6Datum(const ADIMENSION6 &aElem)
void ConvertPads6ToBoardItem(const APAD6 &aElem)
void ConvertFills6ToFootprintItemOnLayer(FOOTPRINT *aFootprint, const AFILL6 &aElem, PCB_LAYER_ID aLayer)
void ParseWideStrings6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void remapUnsureLayers(std::vector< ABOARD6_LAYER_STACKUP > &aStackup)
std::vector< ZONE * > m_polygons
void ParsePads6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ConvertArcs6ToPcbShape(const AARC6 &aElem, PCB_SHAPE *aShape)
void ConvertTracks6ToBoardItemOnLayer(const ATRACK6 &aElem, PCB_LAYER_ID aLayer)
void ConvertFills6ToBoardItem(const AFILL6 &aElem)
FOOTPRINT * HelperGetFootprint(uint16_t aComponent) const
LAYER_MAPPING_HANDLER m_layerMappingHandler
void ParsePolygons6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
PCB_LAYER_ID GetKicadLayer(ALTIUM_LAYER aAltiumLayer) const
void ParseComponentsBodies6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ConvertTracks6ToFootprintItemOnLayer(FOOTPRINT *aFootprint, const ATRACK6 &aElem, PCB_LAYER_ID aLayer)
void Parse(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const std::map< ALTIUM_PCB_DIR, std::string > &aFileMapping)
ALTIUM_PCB(BOARD *aBoard, PROGRESS_REPORTER *aProgressReporter, LAYER_MAPPING_HANDLER &aLayerMappingHandler, REPORTER *aReporter=nullptr, const wxString &aLibrary=wxEmptyString, const wxString &aFootprintName=wxEmptyString)
void ConvertArcs6ToBoardItemOnLayer(const AARC6 &aElem, PCB_LAYER_ID aLayer)
void ParseTexts6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
std::map< ALTIUM_RECORD, std::multimap< int, const AEXTENDED_PRIMITIVE_INFORMATION > > m_extendedPrimitiveInformationMaps
void ParseModelsData(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry, const std::vector< std::string > &aRootDir)
std::map< ALTIUM_LAYER, wxString > m_layerNames
void ConvertPads6ToBoardItemOnNonCopper(const APAD6 &aElem)
void ParseNets6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ConvertPads6ToFootprintItem(FOOTPRINT *aFootprint, const APAD6 &aElem)
const ARULE6 * GetRule(ALTIUM_RULE_KIND aKind, const wxString &aName) const
void ParseDimensions6Data(const ALTIUM_PCB_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void HelperSetZoneLayers(ZONE &aZone, const ALTIUM_LAYER aAltiumLayer)
static wxString ReadString(const std::map< wxString, wxString > &aProps, const wxString &aKey, const wxString &aDefault)
BASE_SET & set(size_t pos=std::numeric_limits< size_t >::max(), bool value=true)
Container for design settings for a BOARD object.
std::shared_ptr< NET_SETTINGS > m_NetSettings
void SetGridOrigin(const VECTOR2I &aOrigin)
const VECTOR2I & GetGridOrigin()
const VECTOR2I & GetAuxOrigin()
void SetAuxOrigin(const VECTOR2I &aOrigin)
int m_SolderMaskExpansion
BOARD_STACKUP & GetStackupDescriptor()
int GetLineThickness(PCB_LAYER_ID aLayer) const
Return the default graphic segment thickness from the layer class for the given layer.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual void SetIsKnockout(bool aKnockout)
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Manage layers needed to make a physical board.
void RemoveAll()
Delete all items in list and clear the list.
const std::vector< BOARD_STACKUP_ITEM * > & GetList() const
void BuildDefaultStackupList(const BOARD_DESIGN_SETTINGS *aSettings, int aActiveCopperLayersCount=0)
Create a default stackup, according to the current BOARD_DESIGN_SETTINGS settings.
Information pertinent to a Pcbnew printed circuit board.
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
EMBEDDED_FILES * GetEmbeddedFiles() override
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
const BOX2I GetBoardEdgesBoundingBox() const
Return the board bounding box calculated using exclusively the board edges (graphics on Edge....
void SetEnabledLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings.
const PAGE_INFO & GetPageSettings() const
bool IsLayerEnabled(PCB_LAYER_ID aLayer) const
A proxy function that calls the correspondent function in m_BoardSettings tests whether a given layer...
LAYER_T GetLayerType(PCB_LAYER_ID aLayer) const
Return the type of the copper layer given by aLayer.
bool SetLayerName(PCB_LAYER_ID aLayer, const wxString &aLayerName)
Changes the name of the layer given by aLayer.
void Move(const VECTOR2I &aMoveVector) override
Move this object.
int GetCopperLayerCount() const
const TRACKS & Tracks() const
void SetVisibleLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings changes the bit-mask of vis...
bool m_LegacyNetclassesLoaded
True if netclasses were loaded from the file.
void SetCopperLayerCount(int aCount)
bool SetLayerType(PCB_LAYER_ID aLayer, LAYER_T aLayerType)
Change the type of the layer given by aLayer.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
const DRAWINGS & Drawings() const
size_type GetHeight() const
size_type GetWidth() const
bool IsHorizontal() const
bool IsCardinal90() const
EDA_ANGLE GetArcAngle() const
void SetCenter(const VECTOR2I &aCenter)
void SetFilled(bool aFlag)
void SetStart(const VECTOR2I &aStart)
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
void SetShape(SHAPE_T aShape)
void SetEnd(const VECTOR2I &aEnd)
void SetArcAngleAndEnd(const EDA_ANGLE &aAngle, bool aCheckNegativeAngle=false)
Set the end point from the angle center and start.
void SetPolyPoints(const std::vector< VECTOR2I > &aPoints)
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
void SetMirrored(bool isMirrored)
void SetBoldFlag(bool aBold)
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
void SetItalic(bool aItalic)
void SetFont(KIFONT::FONT *aFont)
wxString GetEmbeddedFileLink(const EMBEDDED_FILE &aFile) const
Returns the link for an embedded file.
EMBEDDED_FILE * AddFile(const wxFileName &aName, bool aOverwrite)
Loads a file from disk and adds it to the collection.
static RETURN_CODE CompressAndEncode(EMBEDDED_FILE &aFile)
Takes data from the #decompressedData buffer and compresses it using ZSTD into the #compressedEncoded...
VECTOR3D m_Offset
3D model offset (mm)
VECTOR3D m_Rotation
3D model rotation (degrees)
wxString m_Filename
The 3D shape filename in 3D library.
FONT is an abstract base class for both outline and stroke fonts.
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false, const std::vector< wxString > *aEmbeddedFiles=nullptr)
const wxString & GetName() const
virtual bool IsOutline() const
A logical library item identifier and consists of various portions much like a URI.
LSET is a set of PCB_LAYER_IDs.
static LSET AllBoardTechMask()
Return a mask holding board technical layers (no CU layer) on both side.
static LSET UserDefinedLayers()
Return a mask with all of the allowable user defined layers.
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Handle the data for a net.
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
@ NORMAL
Shape is the same on all layers.
@ CUSTOM
Shapes can be defined on arbitrary layers.
@ TOP_INNER_BOTTOM
Up to three shapes can be defined (top, inner, bottom)
static LSET PTHMask()
layer set for a through hole pad
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
static LSET SMDMask()
layer set for a SMD pad on Front layer
int GetHeightIU(double aIUScale) const
Gets the page height in IU.
int GetWidthIU(double aIUScale) const
Gets the page width in IU.
virtual VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
A radial dimension indicates either the radius or diameter of an arc or circle.
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void SetStroke(const STROKE_PARAMS &aStroke) override
VECTOR2I GetPosition() const override
A progress reporter interface for use in multi-threaded environments.
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void Report(const wxString &aMessage)=0
Display aMessage in the progress bar dialog.
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).
A pure virtual class used to derive REPORTER objects from.
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
OPT_VECTOR2I Intersect(const SEG &aSeg, bool aIgnoreEndpoints=false, bool aLines=false) const
Compute intersection point of segment (this) with segment aSeg.
const VECTOR2I & GetArcMid() const
const VECTOR2I & GetP1() const
const VECTOR2I & GetP0() const
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const SHAPE_ARC & Arc(size_t aArc) const
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
int PointCount() const
Return the number of points (vertices) in this line chain.
ssize_t ArcIndex(size_t aSegment) const
Return the arc index for the given segment index.
SEG Segment(int aIndex) const
Return a copy of the aIndex-th segment in the line chain.
int NextShape(int aPointIndex) const
Return the vertex index of the next shape in the chain, or -1 if aPointIndex is the last shape.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
bool IsArcStart(size_t aIndex) const
Represent a set of closed polygons.
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
void Fracture(POLYGON_MODE aFastMode)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
void BooleanAdd(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset union For aFastMode meaning, see function booleanOp.
void Inflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify=false)
Perform outline inflation/deflation.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Adds a new hole to the given outline (default: last) and returns its index.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
int OutlineCount() const
Return the number of outlines in the set.
void Move(const VECTOR2I &aVector) override
Simple container to manage line stroke parameters.
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).
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)
void SetDoNotAllowCopperPour(bool aEnable)
SHAPE_POLY_SET * GetFill(PCB_LAYER_ID aLayer)
void SetDoNotAllowTracks(bool aEnable)
void SetFilledPolysList(PCB_LAYER_ID aLayer, const SHAPE_POLY_SET &aPolysList)
Set the list of filled polygons.
void SetIsFilled(bool isFilled)
bool HasFilledPolysForLayer(PCB_LAYER_ID aLayer) const
void SetDoNotAllowVias(bool aEnable)
void SetLayerSet(LSET aLayerSet) override
void SetDoNotAllowFootprints(bool aEnable)
static int GetDefaultHatchPitch()
static constexpr EDA_ANGLE ANGLE_90
static constexpr EDA_ANGLE ANGLE_45
#define THROW_IO_ERROR(msg)
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
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)
std::function< std::map< wxString, PCB_LAYER_ID >(const std::vector< INPUT_LAYER_DESC > &)> LAYER_MAPPING_HANDLER
Pointer to a function that takes a map of source and KiCad layers and returns a re-mapped version.
std::optional< VECTOR2I > OPT_VECTOR2I
wxString NotSpecifiedPrm()
uint8_t keepoutrestrictions
wxString dielectricmaterial
std::vector< ABOARD6_LAYER_STACKUP > stackup
std::vector< ALTIUM_VERTICE > board_vertices
std::vector< wxString > names
wxString sourcefootprintlibrary
wxString sourcedesignator
std::vector< VECTOR2I > textPoint
ALTIUM_DIMENSION_KIND kind
std::vector< VECTOR2I > referencePoint
uint8_t keepoutrestrictions
int32_t soldermaskexpansionmanual
std::unique_ptr< APAD6_SIZE_AND_SHAPE > sizeAndShape
ALTIUM_PAD_SHAPE topshape
ALTIUM_MODE pastemaskexpansionmode
ALTIUM_MODE soldermaskexpansionmode
int32_t pastemaskexpansionmanual
std::vector< ALTIUM_VERTICE > vertices
ALTIUM_POLYGON_HATCHSTYLE hatchstyle
uint8_t keepoutrestrictions
std::vector< ALTIUM_VERTICE > outline
std::vector< std::vector< ALTIUM_VERTICE > > holes
ALTIUM_CONNECT_STYLE polygonconnectStyle
int planeclearanceClearance
int32_t polygonconnectReliefconductorwidth
int32_t polygonconnectAirgapwidth
uint32_t textbox_rect_height
ALTIUM_TEXT_POSITION textbox_rect_justification
uint32_t textbox_rect_width
ALTIUM_TEXT_TYPE fonttype
uint8_t keepoutrestrictions
int32_t soldermask_expansion_front
bool soldermask_expansion_manual
int32_t soldermask_expansion_back
uint32_t diameter_by_layer[32]
constexpr double IUTomm(int iu) const
constexpr int mmToIU(double mm) const
std::vector< char > decompressedData
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
double DEG2RAD(double deg)
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
VECTOR2< int32_t > VECTOR2I