43#include <compoundfilereader.h>
50#include <wx/docview.h>
52#include <wx/mstream.h>
53#include <wx/wfstream.h>
54#include <wx/zstream.h>
56#include <magic_enum.hpp>
78 THROW_IO_ERROR( wxString::Format( wxT(
"Component creator tries to access component id %u "
79 "of %u existing components" ),
88 const std::vector<ALTIUM_VERTICE>& aVertices )
97 double startradiant =
DEG2RAD( vertex.startangle );
98 double endradiant =
DEG2RAD( vertex.endangle );
100 -
KiROUND( std::sin( startradiant ) * vertex.radius ) );
103 -
KiROUND( std::sin( endradiant ) * vertex.radius ) );
105 VECTOR2I arcStart = vertex.center + arcStartOffset;
106 VECTOR2I arcEnd = vertex.center + arcEndOffset;
120 aLine.
Append( vertex.position );
130 auto override =
m_layermap.find( aAltiumLayer );
134 return override->second;
137 switch( aAltiumLayer )
141 case ALTIUM_LAYER::TOP_LAYER:
return F_Cu;
142 case ALTIUM_LAYER::MID_LAYER_1:
return In1_Cu;
143 case ALTIUM_LAYER::MID_LAYER_2:
return In2_Cu;
144 case ALTIUM_LAYER::MID_LAYER_3:
return In3_Cu;
145 case ALTIUM_LAYER::MID_LAYER_4:
return In4_Cu;
146 case ALTIUM_LAYER::MID_LAYER_5:
return In5_Cu;
147 case ALTIUM_LAYER::MID_LAYER_6:
return In6_Cu;
148 case ALTIUM_LAYER::MID_LAYER_7:
return In7_Cu;
149 case ALTIUM_LAYER::MID_LAYER_8:
return In8_Cu;
150 case ALTIUM_LAYER::MID_LAYER_9:
return In9_Cu;
151 case ALTIUM_LAYER::MID_LAYER_10:
return In10_Cu;
152 case ALTIUM_LAYER::MID_LAYER_11:
return In11_Cu;
153 case ALTIUM_LAYER::MID_LAYER_12:
return In12_Cu;
154 case ALTIUM_LAYER::MID_LAYER_13:
return In13_Cu;
155 case ALTIUM_LAYER::MID_LAYER_14:
return In14_Cu;
156 case ALTIUM_LAYER::MID_LAYER_15:
return In15_Cu;
157 case ALTIUM_LAYER::MID_LAYER_16:
return In16_Cu;
158 case ALTIUM_LAYER::MID_LAYER_17:
return In17_Cu;
159 case ALTIUM_LAYER::MID_LAYER_18:
return In18_Cu;
160 case ALTIUM_LAYER::MID_LAYER_19:
return In19_Cu;
161 case ALTIUM_LAYER::MID_LAYER_20:
return In20_Cu;
162 case ALTIUM_LAYER::MID_LAYER_21:
return In21_Cu;
163 case ALTIUM_LAYER::MID_LAYER_22:
return In22_Cu;
164 case ALTIUM_LAYER::MID_LAYER_23:
return In23_Cu;
165 case ALTIUM_LAYER::MID_LAYER_24:
return In24_Cu;
166 case ALTIUM_LAYER::MID_LAYER_25:
return In25_Cu;
167 case ALTIUM_LAYER::MID_LAYER_26:
return In26_Cu;
168 case ALTIUM_LAYER::MID_LAYER_27:
return In27_Cu;
169 case ALTIUM_LAYER::MID_LAYER_28:
return In28_Cu;
170 case ALTIUM_LAYER::MID_LAYER_29:
return In29_Cu;
171 case ALTIUM_LAYER::MID_LAYER_30:
return In30_Cu;
172 case ALTIUM_LAYER::BOTTOM_LAYER:
return B_Cu;
174 case ALTIUM_LAYER::TOP_OVERLAY:
return F_SilkS;
175 case ALTIUM_LAYER::BOTTOM_OVERLAY:
return B_SilkS;
176 case ALTIUM_LAYER::TOP_PASTE:
return F_Paste;
177 case ALTIUM_LAYER::BOTTOM_PASTE:
return B_Paste;
178 case ALTIUM_LAYER::TOP_SOLDER:
return F_Mask;
179 case ALTIUM_LAYER::BOTTOM_SOLDER:
return B_Mask;
198 case ALTIUM_LAYER::DRILL_GUIDE:
return Dwgs_User;
199 case ALTIUM_LAYER::KEEP_OUT_LAYER:
return Margin;
201 case ALTIUM_LAYER::MECHANICAL_1:
return User_1;
202 case ALTIUM_LAYER::MECHANICAL_2:
return User_2;
203 case ALTIUM_LAYER::MECHANICAL_3:
return User_3;
204 case ALTIUM_LAYER::MECHANICAL_4:
return User_4;
205 case ALTIUM_LAYER::MECHANICAL_5:
return User_5;
206 case ALTIUM_LAYER::MECHANICAL_6:
return User_6;
207 case ALTIUM_LAYER::MECHANICAL_7:
return User_7;
208 case ALTIUM_LAYER::MECHANICAL_8:
return User_8;
209 case ALTIUM_LAYER::MECHANICAL_9:
return User_9;
210 case ALTIUM_LAYER::MECHANICAL_10:
return Dwgs_User;
211 case ALTIUM_LAYER::MECHANICAL_11:
return Eco2_User;
212 case ALTIUM_LAYER::MECHANICAL_12:
return F_Fab;
213 case ALTIUM_LAYER::MECHANICAL_13:
return B_Fab;
218 case ALTIUM_LAYER::DRILL_DRAWING:
return Dwgs_User;
236 static std::set<ALTIUM_LAYER> altiumLayersWithWarning;
238 if( aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER || aAltiumLayer == ALTIUM_LAYER::KEEP_OUT_LAYER )
240 std::vector<PCB_LAYER_ID> layers;
246 layers.emplace_back( layer );
257 wxString layerName = it !=
m_layerNames.end() ? it->second : wxString::Format( wxT(
"(%d)" ),
258 (
int) aAltiumLayer );
260 if(
m_reporter && altiumLayersWithWarning.insert( aAltiumLayer ).second )
263 _(
"Altium layer %s has no KiCad equivalent. It has been moved to KiCad "
277 const wxString& aLibrary,
const wxString& aFootprintName )
297 const unsigned PROGRESS_DELTA = 250;
315 const std::map<ALTIUM_PCB_DIR, std::string>& aFileMapping )
318 const std::vector<std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>> parserOrder = {
319 {
true, ALTIUM_PCB_DIR::FILE_HEADER,
324 {
true, ALTIUM_PCB_DIR::BOARD6,
329 {
false, ALTIUM_PCB_DIR::EXTENDPRIMITIVEINFORMATION,
334 {
true, ALTIUM_PCB_DIR::COMPONENTS6,
339 {
false, ALTIUM_PCB_DIR::MODELS,
342 std::vector<std::string> dir{ aFileMapping.at( ALTIUM_PCB_DIR::MODELS ) };
345 {
true, ALTIUM_PCB_DIR::COMPONENTBODIES6,
350 {
true, ALTIUM_PCB_DIR::NETS6,
355 {
true, ALTIUM_PCB_DIR::CLASSES6,
360 {
true, ALTIUM_PCB_DIR::RULES6,
365 {
true, ALTIUM_PCB_DIR::DIMENSIONS6,
370 {
true, ALTIUM_PCB_DIR::POLYGONS6,
375 {
true, ALTIUM_PCB_DIR::ARCS6,
380 {
true, ALTIUM_PCB_DIR::PADS6,
385 {
true, ALTIUM_PCB_DIR::VIAS6,
390 {
true, ALTIUM_PCB_DIR::TRACKS6,
395 {
false, ALTIUM_PCB_DIR::WIDESTRINGS6,
400 {
true, ALTIUM_PCB_DIR::TEXTS6,
405 {
true, ALTIUM_PCB_DIR::FILLS6,
410 {
false, ALTIUM_PCB_DIR::BOARDREGIONS,
415 {
true, ALTIUM_PCB_DIR::SHAPEBASEDREGIONS6,
420 {
true, ALTIUM_PCB_DIR::REGIONS6,
430 for(
const std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>& cur : parserOrder )
435 std::tie( isRequired,
directory, fp ) = cur;
437 if(
directory == ALTIUM_PCB_DIR::FILE_HEADER )
440 const auto& mappedDirectory = aFileMapping.find(
directory );
442 if( mappedDirectory == aFileMapping.end() )
445 const std::vector<std::string> mappedFile{ mappedDirectory->second,
"Header" };
446 const CFB::COMPOUND_FILE_ENTRY* file = altiumPcbFile.
FindStream( mappedFile );
448 if( file ==
nullptr )
452 uint32_t numOfRecords = reader.
Read<uint32_t>();
482 const auto& boardDirectory = aFileMapping.find( ALTIUM_PCB_DIR::BOARD6 );
484 if( boardDirectory != aFileMapping.end() )
486 std::vector<std::string> mappedFile{ boardDirectory->second,
"Data" };
488 const CFB::COMPOUND_FILE_ENTRY* file = altiumPcbFile.
FindStream( mappedFile );
493 "This file does not appear to be in a valid PCB Binary Version 6.0 format. In "
495 "make sure to save as \"PCB Binary Files (*.PcbDoc)\"." ) );
500 for(
const std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>& cur : parserOrder )
505 std::tie( isRequired,
directory, fp ) = cur;
507 const auto& mappedDirectory = aFileMapping.find(
directory );
509 if( mappedDirectory == aFileMapping.end() )
511 wxASSERT_MSG( !isRequired, wxString::Format( wxT(
"Altium Directory of kind %d was "
512 "expected, but no mapping is "
513 "present in the code" ),
518 std::vector<std::string> mappedFile{ mappedDirectory->second };
520 if(
directory != ALTIUM_PCB_DIR::FILE_HEADER )
521 mappedFile.emplace_back(
"Data" );
523 const CFB::COMPOUND_FILE_ENTRY* file = altiumPcbFile.
FindStream( mappedFile );
525 if( file !=
nullptr )
527 fp( altiumPcbFile, file );
529 else if( isRequired )
533 m_reporter->
Report( wxString::Format(
_(
"File not found: '%s' for directory '%s'." ),
548 if( zone->GetAssignedPriority() == 1000 )
559 zone->SetAssignedPriority( priority >= 0 ? priority : 0 );
563 for( std::pair<const ALTIUM_LAYER, ZONE*>& zone :
m_outer_plane )
564 zone.second->SetAssignedPriority( 0 );
574 if( !zone->HasFilledPolysForLayer( layer ) )
596 if( shape->
GetShape() != SHAPE_T::ARC && shape->
GetShape() != SHAPE_T::CIRCLE )
615 if( arc->
GetCenter() == dim->GetPosition() )
624 VECTOR2I radialLine = dim->GetEnd() - dim->GetStart();
629 radialLine = radialLine.
Resize( std::max( radius, 2 ) );
630 dim->SetEnd( dim->GetStart() + (
VECTOR2I) radialLine );
631 dim->SetLeaderLength( totalLength - radius );
641 int desired_x = ( w - bbbox.
GetWidth() ) / 2;
642 int desired_y = ( h - bbbox.
GetHeight() ) / 2;
644 VECTOR2I movementVector( desired_x - bbbox.
GetX(), desired_y - bbbox.
GetY() );
656 const wxString& aFootprintName )
658 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
676 std::tuple<wxString, const CFB::COMPOUND_FILE_ENTRY*> ret = altiumLibFile.
FindLibFootprintDirName(aFootprintName);
678 wxString fpDirName = std::get<0>( ret );
679 const CFB::COMPOUND_FILE_ENTRY* footprintStream = std::get<1>( ret );
681 if( fpDirName.IsEmpty() )
684 wxString::Format(
_(
"Footprint directory not found: '%s'." ), aFootprintName ) );
687 const std::vector<std::string> streamName{ fpDirName.ToStdString(),
"Data" };
688 const CFB::COMPOUND_FILE_ENTRY* footprintData = altiumLibFile.
FindStream( footprintStream, {
"Data" } );
690 if( footprintData ==
nullptr )
703 footprint->SetFPID( fpID );
705 const std::vector<std::string> parametersStreamName{ fpDirName.ToStdString(),
707 const CFB::COMPOUND_FILE_ENTRY* parametersData =
708 altiumLibFile.
FindStream( footprintStream, {
"Parameters" } );
710 if( parametersData !=
nullptr )
713 std::map<wxString, wxString> parameterProperties = parametersReader.
ReadProperties();
715 wxT(
"DESCRIPTION" ), wxT(
"" ) );
716 footprint->SetLibDescription( description );
727 footprint->SetLibDescription( wxT(
"" ) );
730 const std::vector<std::string> extendedPrimitiveInformationStreamName{
731 "ExtendedPrimitiveInformation",
"Data"
733 const CFB::COMPOUND_FILE_ENTRY* extendedPrimitiveInformationData =
734 altiumLibFile.
FindStream( footprintStream, extendedPrimitiveInformationStreamName );
736 if( extendedPrimitiveInformationData !=
nullptr )
739 footprint->SetReference( wxT(
"REF**" ) );
740 footprint->SetValue( aFootprintName );
741 footprint->Reference().SetVisible(
true );
742 footprint->Value().SetVisible(
true );
747 for(
PCB_FIELD* field : footprint->Fields() )
749 field->SetTextSize( defaultTextSize );
750 field->SetTextThickness( defaultTextThickness );
759 case ALTIUM_RECORD::ARC:
765 case ALTIUM_RECORD::PAD:
771 case ALTIUM_RECORD::VIA:
777 case ALTIUM_RECORD::TRACK:
783 case ALTIUM_RECORD::TEXT:
789 case ALTIUM_RECORD::FILL:
795 case ALTIUM_RECORD::REGION:
801 case ALTIUM_RECORD::MODEL:
808 THROW_IO_ERROR( wxString::Format(
_(
"Record of unknown type: '%d'." ), recordtype ) );
813 footprint->AutoPositionFields();
817 THROW_IO_ERROR( wxString::Format( wxT(
"%s stream was not parsed correctly" ),
823 THROW_IO_ERROR( wxString::Format( wxT(
"%s stream is not fully parsed" ),
827 return footprint.release();
838 THROW_IO_ERROR( wxString::Format( wxT(
"Netcode with id %d does not exist. Only %d nets "
850 const auto rules =
m_rules.find( aKind );
855 for(
const ARULE6& rule : rules->second )
857 if( rule.
name == aName )
866 const auto rules =
m_rules.find( aKind );
871 for(
const ARULE6& rule : rules->second )
881 const CFB::COMPOUND_FILE_ENTRY* aEntry )
899 const CFB::COMPOUND_FILE_ENTRY* aEntry )
916 THROW_IO_ERROR( wxT(
"ExtendedPrimitiveInformation stream is not fully parsed" ) );
921 const CFB::COMPOUND_FILE_ENTRY* aEntry )
938 size_t layercount = 0;
939 size_t layerid =
static_cast<size_t>( ALTIUM_LAYER::TOP_LAYER );
941 while( layerid < elem.
stackup.size() && layerid != 0 )
943 layerid = elem.
stackup[ layerid - 1 ].nextId;
947 size_t kicadLayercount = ( layercount % 2 == 0 ) ? layercount : layercount + 1;
957 auto it = stackup.
GetList().begin();
963 auto curLayer =
static_cast<int>(
F_Cu );
965 for(
size_t altiumLayerId =
static_cast<size_t>( ALTIUM_LAYER::TOP_LAYER );
966 altiumLayerId < elem.
stackup.size() && altiumLayerId != 0;
967 altiumLayerId = elem.
stackup[altiumLayerId - 1].nextId )
973 if( layer.
nextId == 0 && layercount != kicadLayercount )
978 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
980 ( *it )->SetThickness( 0 );
985 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
987 ( *it )->SetThickness( 0, 0 );
988 ( *it )->SetThicknessLocked(
true, 0 );
996 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
1010 if( klayer ==
B_Cu )
1013 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected id while parsing last stackup layer" ) );
1023 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
1037 for(
size_t altiumLayerId =
static_cast<size_t>( ALTIUM_LAYER::TOP_OVERLAY );
1038 altiumLayerId <= static_cast<size_t>( ALTIUM_LAYER::BOTTOM_SOLDER ); altiumLayerId++ )
1049 for(
size_t altiumLayerId =
static_cast<size_t>( ALTIUM_LAYER::MECHANICAL_1 );
1050 altiumLayerId <= static_cast<size_t>( ALTIUM_LAYER::MECHANICAL_16 ); altiumLayerId++ )
1071 std::vector<INPUT_LAYER_DESC> inputLayers;
1072 std::map<wxString, ALTIUM_LAYER> altiumLayerNameMap;
1074 for(
size_t ii = 0; ii < aStackup.size(); ii++ )
1081 && !( layer_num >= ALTIUM_LAYER::TOP_OVERLAY
1082 && layer_num <= ALTIUM_LAYER::BOTTOM_SOLDER )
1083 && !( layer_num >= ALTIUM_LAYER::MECHANICAL_1
1084 && layer_num <= ALTIUM_LAYER::MECHANICAL_16 ) )
1086 if( layer_num < ALTIUM_LAYER::BOTTOM_LAYER )
1100 inputLayers.push_back( iLdesc );
1101 altiumLayerNameMap.insert( { curLayer.
name, layer_num } );
1105 if( inputLayers.size() == 0 )
1110 enabledLayers =
LSET();
1113 for( std::pair<wxString, PCB_LAYER_ID> layerPair : reMappedLayers )
1115 if( layerPair.second == PCB_LAYER_ID::UNDEFINED_LAYER )
1117 wxFAIL_MSG( wxT(
"Unexpected Layer ID" ) );
1121 ALTIUM_LAYER altiumID = altiumLayerNameMap.at( layerPair.first );
1122 m_layermap.insert_or_assign( altiumID, layerPair.second );
1123 enabledLayers |=
LSET( layerPair.second );
1137 LINE_STYLE::SOLID );
1144 int nextShape = lineChain.
NextShape( i );
1145 bool isLastShape = nextShape < 0;
1147 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::ARC );
1149 shape->SetStroke( stroke );
1153 m_board->
Add( shape.release(), ADD_MODE::APPEND );
1159 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
1161 shape->SetStroke( stroke );
1163 shape->SetStart( seg.
A );
1164 shape->SetEnd( seg.
B );
1166 m_board->
Add( shape.release(), ADD_MODE::APPEND );
1173 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1185 if( elem.
kind == ALTIUM_CLASS_KIND::NET_CLASS )
1187 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( elem.
name );
1189 for(
const wxString&
name : elem.
names )
1205 msg.Printf(
_(
"More than one Altium netclass with name '%s' found. "
1206 "Only the first one will be imported." ), elem.
name );
1225 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1232 uint16_t componentId = 0;
1239 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
1243 footprint->SetFPID( fpID );
1245 footprint->SetPosition( elem.
position );
1246 footprint->SetOrientationDegrees( elem.
rotation );
1252 if( reference.find_first_not_of(
"0123456789" ) == wxString::npos )
1253 reference.Prepend( wxT(
"UNK" ) );
1255 footprint->SetReference( reference );
1257 footprint->SetLocked( elem.
locked );
1258 footprint->Reference().SetVisible( elem.
nameon );
1259 footprint->Value().SetVisible( elem.
commenton );
1260 footprint->SetLayer( elem.
layer == ALTIUM_LAYER::TOP_LAYER ?
F_Cu :
B_Cu );
1263 m_board->
Add( footprint.release(), ADD_MODE::APPEND );
1269 THROW_IO_ERROR( wxT(
"Components6 stream is not fully parsed" ) );
1276 while( Angle < aMin )
1279 while( Angle >= aMax )
1287 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1304 THROW_IO_ERROR( wxString::Format( wxT(
"ComponentsBodies6 stream tries to access "
1305 "component id %d of %d existing components" ),
1320 msg.Printf( wxT(
"ComponentsBodies6 stream tries to access model id %s which does "
1321 "not exist" ), elem.
modelId );
1333 modelSettings.
m_Filename = modelTuple->second;
1344 orientation = -orientation;
1357 footprint->
Models().push_back( modelSettings );
1361 THROW_IO_ERROR( wxT(
"ComponentsBodies6 stream is not fully parsed" ) );
1368 THROW_IO_ERROR( wxT(
"Incorrect number of reference points for linear dimension object" ) );
1377 _(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1378 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer ),
1391 dimension->SetLayer( klayer );
1392 dimension->SetStart( referencePoint0 );
1394 if( referencePoint0 != aElem.
xy1 )
1407 SEG segm1( referencePoint0, referencePoint0 + directionNormalVector );
1408 SEG segm2( referencePoint1, referencePoint1 + direction );
1412 THROW_IO_ERROR( wxT(
"Invalid dimension. This should never happen." ) );
1414 dimension->SetEnd( *intersection );
1416 int height =
static_cast<int>(
EuclideanNorm( direction ) );
1418 if( ( direction.
x > 0 || direction.
y < 0 ) != ( aElem.
angle >= 180.0 ) )
1421 dimension->SetHeight( height );
1425 dimension->SetEnd( referencePoint1 );
1428 dimension->SetLineThickness( aElem.
linewidth );
1430 dimension->SetUnitsFormat( DIM_UNITS_FORMAT::NO_SUFFIX );
1434 wxRegEx units( wxS(
"(mm)|(in)|(mils)|(thou)|(')|(\")" ), wxRE_ADVANCED );
1437 dimension->SetUnitsFormat( DIM_UNITS_FORMAT::BARE_SUFFIX );
1446 dimension->Text().SetBold( aElem.
textbold );
1449 dimension->SetTextThickness( dimension->GetTextThickness() *
BOLD_FACTOR );
1454 case ALTIUM_UNIT::INCHES:
1455 dimension->SetUnits( EDA_UNITS::INCHES );
1457 case ALTIUM_UNIT::MILS:
1458 dimension->SetUnits( EDA_UNITS::MILS );
1460 case ALTIUM_UNIT::MILLIMETERS:
1461 case ALTIUM_UNIT::CENTIMETER:
1462 dimension->SetUnits( EDA_UNITS::MILLIMETRES );
1468 m_board->
Add( dimension.release(), ADD_MODE::APPEND );
1475 THROW_IO_ERROR( wxT(
"Not enough reference points for radial dimension object" ) );
1484 _(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1485 "It has been moved to KiCad layer Eco1_User." ),
1495 std::unique_ptr<PCB_DIM_RADIAL> dimension = std::make_unique<PCB_DIM_RADIAL>(
m_board );
1498 dimension->SetLayer( klayer );
1499 dimension->SetStart( referencePoint0 );
1500 dimension->SetEnd( aElem.
xy1 );
1501 dimension->SetLineThickness( aElem.
linewidth );
1502 dimension->SetKeepTextAligned(
false );
1507 dimension->SetUnitsFormat( aElem.
textsuffix.IsEmpty() ? DIM_UNITS_FORMAT::NO_SUFFIX
1508 : DIM_UNITS_FORMAT::BARE_SUFFIX );
1512 case ALTIUM_UNIT::INCHES:
1513 dimension->SetUnits( EDA_UNITS::INCHES );
1515 case ALTIUM_UNIT::MILS:
1516 dimension->SetUnits( EDA_UNITS::MILS );
1518 case ALTIUM_UNIT::MILLIMETERS:
1519 case ALTIUM_UNIT::CENTIMETER:
1520 dimension->SetUnits( EDA_UNITS::MILLIMETRES );
1530 m_reporter->
Report( wxT(
"No text position present for leader dimension object" ),
1537 dimension->SetTextPos( aElem.
textPoint.at( 0 ) );
1543 dimension->SetBold( aElem.
textbold );
1546 dimension->SetTextThickness( dimension->GetTextThickness() *
BOLD_FACTOR );
1554 int yAdjust = dimension->GetTextBox().GetCenter().y - dimension->GetTextPos().y;
1555 dimension->SetTextPos( dimension->GetTextPos() +
VECTOR2I( 0, yAdjust + aElem.
textgap ) );
1559 m_board->
Add( dimension.release(), ADD_MODE::APPEND );
1572 msg.Printf(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1573 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer );
1588 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
1590 shape->SetLayer( klayer );
1592 shape->SetStart( last );
1596 m_board->
Add( shape.release(), ADD_MODE::APPEND );
1604 if( dirVec.
x != 0 || dirVec.
y != 0 )
1612 std::unique_ptr<PCB_SHAPE> shape1 =
1613 std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
1615 shape1->SetLayer( klayer );
1617 shape1->SetStart( referencePoint0 );
1618 shape1->SetEnd( referencePoint0 + arrVec );
1620 m_board->
Add( shape1.release(), ADD_MODE::APPEND );
1626 std::unique_ptr<PCB_SHAPE> shape2 =
1627 std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
1629 shape2->SetLayer( klayer );
1631 shape2->SetStart( referencePoint0 );
1632 shape2->SetEnd( referencePoint0 + arrVec );
1634 m_board->
Add( shape2.release(), ADD_MODE::APPEND );
1644 m_reporter->
Report( wxT(
"No text position present for leader dimension object" ),
1651 std::unique_ptr<PCB_TEXT>
text = std::make_unique<PCB_TEXT>(
m_board );
1655 text->SetLayer( klayer );
1674 msg.Printf(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1675 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer );
1684 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
1686 shape->SetLayer( klayer );
1691 m_board->
Add( shape.release(), ADD_MODE::APPEND );
1705 msg.Printf(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1706 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer );
1716 std::unique_ptr<PCB_DIM_CENTER> dimension = std::make_unique<PCB_DIM_CENTER>(
m_board );
1718 dimension->SetLayer( klayer );
1719 dimension->SetLineThickness( aElem.
linewidth );
1720 dimension->SetStart( aElem.
xy1 );
1721 dimension->SetEnd( aElem.
xy1 + vec );
1723 m_board->
Add( dimension.release(), ADD_MODE::APPEND );
1728 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1742 case ALTIUM_DIMENSION_KIND::LINEAR:
1745 case ALTIUM_DIMENSION_KIND::ANGULAR:
1749 wxString::Format(
_(
"Ignored Angular dimension (not yet supported)." ) ),
1753 case ALTIUM_DIMENSION_KIND::RADIAL:
1756 case ALTIUM_DIMENSION_KIND::LEADER:
1759 case ALTIUM_DIMENSION_KIND::DATUM:
1763 wxString::Format(
_(
"Ignored Datum dimension (not yet supported)." ) ),
1768 case ALTIUM_DIMENSION_KIND::BASELINE:
1772 wxString::Format(
_(
"Ignored Baseline dimension (not yet supported)." ) ),
1776 case ALTIUM_DIMENSION_KIND::CENTER:
1779 case ALTIUM_DIMENSION_KIND::LINEAR_DIAMETER:
1783 wxString::Format(
_(
"Ignored Linear dimension (not yet supported)." ) ),
1787 case ALTIUM_DIMENSION_KIND::RADIAL_DIAMETER:
1791 wxString::Format(
_(
"Ignored Radial dimension (not yet supported)." ) ),
1799 msg.Printf(
_(
"Ignored dimension of kind %d (not yet supported)." ), elem.
kind );
1807 THROW_IO_ERROR( wxT(
"Dimensions6 stream is not fully parsed" ) );
1812 const CFB::COMPOUND_FILE_ENTRY* aEntry,
1813 const std::vector<std::string>& aRootDir )
1828 const wxString altiumModelDir = wxT(
"ALTIUM_EMBEDDED_MODELS" );
1830 wxFileName altiumModelsPath = wxFileName::DirName( projectPath );
1831 wxString kicadModelPrefix = wxT(
"${KIPRJMOD}/" ) + altiumModelDir + wxT(
"/" );
1833 if( !altiumModelsPath.AppendDir( altiumModelDir ) )
1834 THROW_IO_ERROR( wxT(
"Cannot construct directory path for step models" ) );
1837 if( !altiumModelsPath.DirExists() )
1839 if( !altiumModelsPath.Mkdir() )
1844 msg.Printf(
_(
"Failed to create folder '%s'." ) + wxS(
" " )
1845 +
_(
"No 3D-models will be imported." ),
1846 altiumModelsPath.GetFullPath() );
1855 wxString invalidChars = wxFileName::GetForbiddenChars();
1862 std::vector<std::string> stepPath = aRootDir;
1863 stepPath.emplace_back( std::to_string( idx ) );
1865 bool validName = !elem.
name.IsEmpty() && elem.
name.IsAscii() &&
1866 wxString::npos == elem.
name.find_first_of( invalidChars );
1867 wxString storageName = !validName ? wxString::Format( wxT(
"model_%d" ), idx )
1869 wxFileName storagePath( altiumModelsPath.GetPath(), storageName );
1873 const CFB::COMPOUND_FILE_ENTRY* stepEntry = aAltiumPcbFile.
FindStream( stepPath );
1875 if( stepEntry ==
nullptr )
1880 msg.Printf(
_(
"File not found: '%s'. 3D-model not imported." ),
1888 size_t stepSize =
static_cast<size_t>( stepEntry->size );
1889 std::vector<char> stepContent( stepSize );
1895 if( !storagePath.IsDirWritable() )
1900 msg.Printf(
_(
"Insufficient permissions to save file '%s'." ),
1901 storagePath.GetFullPath() );
1908 wxMemoryInputStream stepStream( stepContent.data(), stepSize );
1909 wxZlibInputStream zlibInputStream( stepStream );
1911 wxFFileOutputStream outputStream( storagePath.GetFullPath() );
1913 if( !outputStream.IsOk() )
1918 msg.Printf(
_(
"Unable to write file '%s'." ), storagePath.GetFullPath() );
1925 outputStream.Write( zlibInputStream );
1926 outputStream.Close();
1928 m_models.insert( { elem.
id, kicadModelPrefix + storageName } );
1937 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1949 ANET6 elem( reader );
1963 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1994 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board );
1998 zone->SetPosition( elem.
vertices.at( 0 ).position );
1999 zone->SetLocked( elem.
locked );
2001 zone->Outline()->AddOutline( linechain );
2009 const ARULE6* zoneClearanceRule =
GetRule( ALTIUM_RULE_KIND::CLEARANCE,
2010 wxT(
"PolygonClearance" ) );
2011 int planeLayers = 0;
2012 int signalLayers = 0;
2026 if( planeLayers > 0 && planeClearanceRule )
2029 if( signalLayers > 0 && zoneClearanceRule )
2030 clearance = std::max( clearance, zoneClearanceRule->
clearanceGap );
2033 zone->SetLocalClearance( clearance );
2037 if( polygonConnectRule !=
nullptr )
2041 case ALTIUM_CONNECT_STYLE::DIRECT:
2042 zone->SetPadConnection( ZONE_CONNECTION::FULL );
2045 case ALTIUM_CONNECT_STYLE::NONE:
2046 zone->SetPadConnection( ZONE_CONNECTION::NONE );
2050 case ALTIUM_CONNECT_STYLE::RELIEF:
2051 zone->SetPadConnection( ZONE_CONNECTION::THERMAL );
2056 zone->SetThermalReliefSpokeWidth(
2067 zone->SetAssignedPriority( 1 );
2072 || zone->GetBoundingBox().Contains( outer_plane->second->GetBoundingBox() ) )
2078 if( elem.
hatchstyle != ALTIUM_POLYGON_HATCHSTYLE::SOLID
2079 && elem.
hatchstyle != ALTIUM_POLYGON_HATCHSTYLE::UNKNOWN )
2081 zone->SetFillMode( ZONE_FILL_MODE::HATCH_PATTERN );
2084 if( elem.
hatchstyle == ALTIUM_POLYGON_HATCHSTYLE::NONE )
2087 const BOX2I& bbox = zone->GetBoundingBox();
2095 if( elem.
hatchstyle == ALTIUM_POLYGON_HATCHSTYLE::DEGREE_45 )
2096 zone->SetHatchOrientation(
ANGLE_45 );
2099 zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE,
2102 m_board->
Add( zone.release(), ADD_MODE::APPEND );
2110 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2128 std::sort( val.second.begin(), val.second.end(),
2131 return lhs.priority < rhs.priority;
2144 if( trackWidthRule )
2150 if( routingViasRule )
2161 if( holeToHoleRule )
2167 if( soldermaskRule )
2178 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2194 THROW_IO_ERROR( wxT(
"BoardRegions stream is not fully parsed" ) );
2198 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2206 for(
int primitiveIndex = 0; reader.
GetRemainingBytes() >= 4; primitiveIndex++ )
2212 || elem.
kind == ALTIUM_REGION_KIND::BOARD_CUTOUT )
2225 THROW_IO_ERROR(
"ShapeBasedRegions6 stream is not fully parsed" );
2231 if( aElem.
kind == ALTIUM_REGION_KIND::BOARD_CUTOUT )
2235 else if( aElem.
kind == ALTIUM_REGION_KIND::POLYGON_CUTOUT || aElem.
is_keepout )
2249 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board );
2251 zone->SetIsRuleArea(
true );
2257 else if( aElem.
kind == ALTIUM_REGION_KIND::POLYGON_CUTOUT )
2259 zone->SetDoNotAllowCopperPour(
true );
2260 zone->SetDoNotAllowVias(
false );
2261 zone->SetDoNotAllowTracks(
false );
2262 zone->SetDoNotAllowPads(
false );
2263 zone->SetDoNotAllowFootprints(
false );
2266 zone->SetPosition( aElem.
outline.at( 0 ).position );
2267 zone->Outline()->AddOutline( linechain );
2271 zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE,
2274 m_board->
Add( zone.release(), ADD_MODE::APPEND );
2276 else if( aElem.
kind == ALTIUM_REGION_KIND::DASHED_OUTLINE )
2285 msg.Printf(
_(
"Dashed outline found on an Altium layer (%d) with no KiCad equivalent. "
2286 "It has been moved to KiCad layer Eco1_User." ), aElem.
layer );
2305 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::POLY );
2307 shape->SetPolyShape( linechain );
2308 shape->SetFilled(
false );
2309 shape->SetLayer( klayer );
2312 m_board->
Add( shape.release(), ADD_MODE::APPEND );
2314 else if( aElem.
kind == ALTIUM_REGION_KIND::COPPER )
2322 else if( aElem.
kind == ALTIUM_REGION_KIND::BOARD_CUTOUT )
2331 msg.Printf(
_(
"Ignored polygon shape of kind %d (not yet supported)." ), aElem.
kind );
2340 const int aPrimitiveIndex )
2342 if( aElem.
kind == ALTIUM_REGION_KIND::POLYGON_CUTOUT || aElem.
is_keepout )
2356 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aFootprint );
2358 zone->SetIsRuleArea(
true );
2364 else if( aElem.
kind == ALTIUM_REGION_KIND::POLYGON_CUTOUT )
2366 zone->SetDoNotAllowCopperPour(
true );
2367 zone->SetDoNotAllowVias(
false );
2368 zone->SetDoNotAllowTracks(
false );
2369 zone->SetDoNotAllowPads(
false );
2370 zone->SetDoNotAllowFootprints(
false );
2373 zone->SetPosition( aElem.
outline.at( 0 ).position );
2374 zone->Outline()->AddOutline( linechain );
2378 zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE,
2381 aFootprint->
Add( zone.release(), ADD_MODE::APPEND );
2383 else if( aElem.
kind == ALTIUM_REGION_KIND::COPPER )
2394 else if( aElem.
kind == ALTIUM_REGION_KIND::DASHED_OUTLINE
2395 || aElem.
kind == ALTIUM_REGION_KIND::BOARD_CUTOUT )
2408 msg.Printf(
_(
"Loading library '%s':\n"
2409 "Footprint %s contains a dashed outline on Altium layer (%d) with "
2410 "no KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
2422 msg.Printf(
_(
"Footprint %s contains a dashed outline on Altium layer (%d) with "
2423 "no KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
2445 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aFootprint, SHAPE_T::POLY );
2447 shape->SetPolyShape( linechain );
2448 shape->SetFilled(
false );
2449 shape->SetLayer( klayer );
2451 if( aElem.
kind == ALTIUM_REGION_KIND::DASHED_OUTLINE )
2456 aFootprint->
Add( shape.release(), ADD_MODE::APPEND );
2465 msg.Printf(
_(
"Error loading library '%s':\n"
2466 "Footprint %s contains polygon shape of kind %d (not yet supported)." ),
2478 msg.Printf(
_(
"Footprint %s contains polygon shape of kind %d (not yet supported)." ),
2506 for(
const std::vector<ALTIUM_VERTICE>& hole : aElem.
holes )
2514 polySet.
AddHole( hole_linechain );
2517 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::POLY );
2519 shape->SetPolyShape( polySet );
2520 shape->SetFilled(
true );
2521 shape->SetLayer( aLayer );
2529 m_board->
Add( shape.release(), ADD_MODE::APPEND );
2536 const int aPrimitiveIndex )
2553 for(
const std::vector<ALTIUM_VERTICE>& hole : aElem.
holes )
2561 polySet.
AddHole( hole_linechain );
2564 if( aLayer ==
F_Cu || aLayer ==
B_Cu )
2566 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
2569 padLayers.set( aLayer );
2571 pad->SetAttribute( PAD_ATTRIB::SMD );
2572 pad->SetShape( PAD_SHAPE::CUSTOM );
2578 pad->SetShape( PAD_SHAPE::CUSTOM );
2579 pad->SetAnchorPadShape( PAD_SHAPE::CIRCLE );
2580 pad->SetSize( { anchorSize, anchorSize } );
2581 pad->SetPosition( anchorPos );
2584 shapePolys.
Move( -anchorPos );
2585 pad->AddPrimitivePoly( shapePolys, 0,
true );
2588 auto it = map.find( aPrimitiveIndex );
2590 if( it != map.end() )
2594 if(
info.pastemaskexpansionmode == ALTIUM_MODE::MANUAL )
2596 pad->SetLocalSolderPasteMargin(
2597 info.pastemaskexpansionmanual ?
info.pastemaskexpansionmanual : 1 );
2600 if(
info.soldermaskexpansionmode == ALTIUM_MODE::MANUAL )
2602 pad->SetLocalSolderMaskMargin(
2603 info.soldermaskexpansionmanual ?
info.soldermaskexpansionmanual : 1 );
2606 if(
info.pastemaskexpansionmode != ALTIUM_MODE::NONE )
2609 if(
info.soldermaskexpansionmode != ALTIUM_MODE::NONE )
2613 pad->SetLayerSet( padLayers );
2615 aFootprint->
Add(
pad.release(), ADD_MODE::APPEND );
2619 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aFootprint, SHAPE_T::POLY );
2621 shape->SetPolyShape( polySet );
2622 shape->SetFilled(
true );
2623 shape->SetLayer( aLayer );
2626 aFootprint->
Add( shape.release(), ADD_MODE::APPEND );
2632 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2648 THROW_IO_ERROR( wxString::Format(
"Region stream tries to access polygon id %d "
2649 "of %d existing polygons.",
2656 if( zone ==
nullptr )
2678 for(
const std::vector<ALTIUM_VERTICE>& hole : elem.
holes )
2685 hole_linechain.
Append( hole.at( 0 ).position );
2687 fill.
AddHole( hole_linechain );
2707 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2714 for(
int primitiveIndex = 0; reader.
GetRemainingBytes() >= 4; primitiveIndex++ )
2717 AARC6 elem( reader );
2739 aShape->
SetShape( SHAPE_T::CIRCLE );
2768 THROW_IO_ERROR( wxString::Format(
"Tracks stream tries to access polygon id %u "
2769 "of %zu existing polygons.",
2775 if( zone ==
nullptr )
2820 for(
const auto& layerExpansionMask :
2823 int width = aElem.
width + ( layerExpansionMask.second * 2 );
2827 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>(
m_board );
2830 arc->SetStroke(
STROKE_PARAMS( width, LINE_STYLE::SOLID ) );
2831 arc->SetLayer( layerExpansionMask.first );
2833 m_board->
Add( arc.release(), ADD_MODE::APPEND );
2840 const int aPrimitiveIndex,
const bool aIsBoardImport )
2844 wxFAIL_MSG( wxString::Format(
"Altium: Unexpected footprint Arc with polygon id %d",
2877 for(
const auto& layerExpansionMask :
2880 int width = aElem.
width + ( layerExpansionMask.second * 2 );
2884 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>( aFootprint );
2887 arc->SetStroke(
STROKE_PARAMS( width, LINE_STYLE::SOLID ) );
2888 arc->SetLayer( layerExpansionMask.first );
2890 aFootprint->
Add( arc.release(), ADD_MODE::APPEND );
2901 PCB_SHAPE shape(
nullptr, SHAPE_T::ARC );
2915 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board, &shapeArc );
2917 arc->SetWidth( aElem.
width );
2918 arc->SetLayer( aLayer );
2921 m_board->
Add( arc.release(), ADD_MODE::APPEND );
2925 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>(
m_board );
2929 arc->SetLayer( aLayer );
2931 m_board->
Add( arc.release(), ADD_MODE::APPEND );
2939 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>( aFootprint );
2943 arc->SetLayer( aLayer );
2945 aFootprint->
Add( arc.release(), ADD_MODE::APPEND );
2950 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2960 APAD6 elem( reader );
2982 && aElem.
layer != ALTIUM_LAYER::MULTI_LAYER )
2989 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
2990 footprint->SetPosition( aElem.
position );
2994 m_board->
Add( footprint.release(), ADD_MODE::APPEND );
3003 && aElem.
layer != ALTIUM_LAYER::MULTI_LAYER )
3016 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
3028 pad->SetAttribute( PAD_ATTRIB::SMD );
3032 if( aElem.
layer != ALTIUM_LAYER::MULTI_LAYER )
3040 msg.Printf(
_(
"Error loading library '%s':\n"
3041 "Footprint %s pad %s is not marked as multilayer, but is a TH pad." ),
3053 msg.Printf(
_(
"Footprint %s pad %s is not marked as multilayer, but is a TH pad." ),
3061 pad->SetAttribute( aElem.
plated ? PAD_ATTRIB::PTH : PAD_ATTRIB::NPTH );
3065 pad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
3072 case ALTIUM_PAD_HOLE_SHAPE::ROUND:
3073 wxFAIL_MSG( wxT(
"Round holes are handled before the switch" ) );
3076 case ALTIUM_PAD_HOLE_SHAPE::SQUARE:
3082 msg.Printf(
_(
"Loading library '%s':\n"
3083 "Footprint %s pad %s has a square hole (not yet supported)." ),
3095 msg.Printf(
_(
"Footprint %s pad %s has a square hole (not yet supported)." ),
3102 pad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
3108 case ALTIUM_PAD_HOLE_SHAPE::SLOT:
3110 pad->SetDrillShape( PAD_DRILL_SHAPE::OBLONG );
3130 msg.Printf(
_(
"Loading library '%s':\n"
3131 "Footprint %s pad %s has a hole-rotation of %f degrees. "
3132 "KiCad only supports 90 degree rotations." ),
3145 msg.Printf(
_(
"Footprint %s pad %s has a hole-rotation of %f degrees. "
3146 "KiCad only supports 90 degree rotations." ),
3159 case ALTIUM_PAD_HOLE_SHAPE::UNKNOWN:
3165 msg.Printf(
_(
"Error loading library '%s':\n"
3166 "Footprint %s pad %s uses a hole of unknown kind %d." ),
3179 msg.Printf(
_(
"Footprint %s pad %s uses a hole of unknown kind %d." ),
3187 pad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
3197 if( aElem.
padmode != ALTIUM_PAD_MODE::SIMPLE )
3204 msg.Printf(
_(
"Error loading library '%s':\n"
3205 "Footprint %s pad %s uses a complex pad stack (not yet supported)." ),
3217 msg.Printf(
_(
"Footprint %s pad %s uses a complex pad stack (not yet supported)." ),
3227 case ALTIUM_PAD_SHAPE::RECT:
3228 pad->SetShape( PAD_SHAPE::RECTANGLE );
3231 case ALTIUM_PAD_SHAPE::CIRCLE:
3233 && aElem.
sizeAndShape->alt_shape[0] == ALTIUM_PAD_SHAPE_ALT::ROUNDRECT )
3235 pad->SetShape( PAD_SHAPE::ROUNDRECT );
3236 double ratio = aElem.
sizeAndShape->cornerradius[0] / 200.;
3237 pad->SetRoundRectRadiusRatio( ratio );
3241 pad->SetShape( PAD_SHAPE::CIRCLE );
3245 pad->SetShape( PAD_SHAPE::OVAL );
3250 case ALTIUM_PAD_SHAPE::OCTAGONAL:
3251 pad->SetShape( PAD_SHAPE::CHAMFERED_RECT );
3253 pad->SetChamferRectRatio( 0.25 );
3256 case ALTIUM_PAD_SHAPE::UNKNOWN:
3263 msg.Printf(
_(
"Error loading library '%s':\n"
3264 "Footprint %s pad %s uses an unknown pad-shape." ),
3276 msg.Printf(
_(
"Footprint %s pad %s uses an unknown pad-shape." ),
3285 if(
pad->GetAttribute() == PAD_ATTRIB::NPTH &&
pad->HasHole() )
3288 pad->SetShape(
pad->GetDrillShape() == PAD_DRILL_SHAPE::CIRCLE ? PAD_SHAPE::CIRCLE
3289 : PAD_SHAPE::OVAL );
3290 pad->SetSize(
pad->GetDrillSize() );
3293 switch( aElem.
layer )
3295 case ALTIUM_LAYER::TOP_LAYER:
3300 case ALTIUM_LAYER::BOTTOM_LAYER:
3305 case ALTIUM_LAYER::MULTI_LAYER:
3311 pad->SetLayer( klayer );
3312 pad->SetLayerSet(
LSET( 1, klayer ) );
3323 pad->SetLayerSet(
pad->GetLayerSet().reset(
F_Mask ) );
3326 pad->SetLayerSet(
pad->GetLayerSet().reset(
B_Mask ) );
3328 aFootprint->
Add(
pad.release(), ADD_MODE::APPEND );
3341 msg.Printf(
_(
"Non-copper pad %s found on an Altium layer (%d) with no KiCad "
3342 "equivalent. It has been moved to KiCad layer Eco1_User." ),
3350 std::unique_ptr<PCB_SHAPE>
pad = std::make_unique<PCB_SHAPE>(
m_board );
3369 msg.Printf(
_(
"Loading library '%s':\n"
3370 "Footprint %s non-copper pad %s found on an Altium layer (%d) with no "
3371 "KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
3384 msg.Printf(
_(
"Footprint %s non-copper pad %s found on an Altium layer (%d) with no "
3385 "KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
3396 std::unique_ptr<PCB_SHAPE>
pad = std::make_unique<PCB_SHAPE>( aFootprint );
3400 aFootprint->
Add(
pad.release(), ADD_MODE::APPEND );
3412 msg.Printf(
_(
"Non-copper pad %s is connected to a net, which is not supported." ),
3423 msg.Printf(
_(
"Non-copper pad %s has a hole, which is not supported." ), aElem.
name );
3428 if( aElem.
padmode != ALTIUM_PAD_MODE::SIMPLE )
3433 msg.Printf(
_(
"Non-copper pad %s has a complex pad stack (not yet supported)." ),
3441 case ALTIUM_PAD_SHAPE::RECT:
3460 case ALTIUM_PAD_SHAPE::CIRCLE:
3462 && aElem.
sizeAndShape->alt_shape[0] == ALTIUM_PAD_SHAPE_ALT::ROUNDRECT )
3465 int cornerradius = aElem.
sizeAndShape->cornerradius[0];
3466 int offset = ( std::min( aElem.
topsize.
x, aElem.
topsize.
y ) * cornerradius ) / 200;
3471 if( cornerradius < 100 )
3473 int offsetX = aElem.
topsize.
x / 2 - offset;
3474 int offsetY = aElem.
topsize.
y / 2 - offset;
3488 aShape->
SetShape( SHAPE_T::CIRCLE );
3497 aShape->
SetShape( SHAPE_T::SEGMENT );
3505 aShape->
SetShape( SHAPE_T::SEGMENT );
3517 aShape->
SetShape( SHAPE_T::CIRCLE );
3527 aShape->
SetShape( SHAPE_T::SEGMENT );
3530 LINE_STYLE::SOLID ) );
3550 case ALTIUM_PAD_SHAPE::OCTAGONAL:
3567 aShape->
SetPolyPoints( { p11 - chamferX, p11 - chamferY, p12 + chamferY, p12 - chamferX,
3568 p22 + chamferX, p22 + chamferY, p21 - chamferY, p21 + chamferX } );
3575 case ALTIUM_PAD_SHAPE::UNKNOWN:
3580 msg.Printf(
_(
"Non-copper pad %s uses an unknown pad-shape." ), aElem.
name );
3590 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3600 AVIA6 elem( reader );
3602 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
3610 bool start_layer_outside = elem.
layer_start == ALTIUM_LAYER::TOP_LAYER
3611 || elem.
layer_start == ALTIUM_LAYER::BOTTOM_LAYER;
3612 bool end_layer_outside = elem.
layer_end == ALTIUM_LAYER::TOP_LAYER
3613 || elem.
layer_end == ALTIUM_LAYER::BOTTOM_LAYER;
3615 if( start_layer_outside && end_layer_outside )
3617 via->SetViaType( VIATYPE::THROUGH );
3619 else if( ( !start_layer_outside ) && ( !end_layer_outside ) )
3621 via->SetViaType( VIATYPE::BLIND_BURIED );
3625 via->SetViaType( VIATYPE::MICROVIA );
3636 msg.Printf(
_(
"Via from layer %d to %d uses a non-copper layer, which is not "
3647 via->SetLayerPair( start_klayer, end_klayer );
3657 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3664 for(
int primitiveIndex = 0; reader.
GetRemainingBytes() >= 4; primitiveIndex++ )
3695 msg.Printf( wxT(
"ATRACK6 stream tries to access polygon id %u "
3696 "of %u existing polygons; skipping it" ),
3697 static_cast<unsigned>( aElem.
polygon ),
3698 static_cast<unsigned>(
m_polygons.size() ) );
3707 if( zone ==
nullptr )
3720 PCB_SHAPE shape(
nullptr, SHAPE_T::SEGMENT );
3738 PCB_SHAPE shape(
nullptr, SHAPE_T::SEGMENT );
3752 ALTIUM_RECORD::TRACK, aPrimitiveIndex, aElem.
layer ) )
3754 int width = aElem.
width + ( layerExpansionMask.second * 2 );
3757 std::unique_ptr<PCB_SHAPE> seg = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
3759 seg->SetStart( aElem.
start );
3760 seg->SetEnd( aElem.
end );
3761 seg->SetStroke(
STROKE_PARAMS( width, LINE_STYLE::SOLID ) );
3762 seg->SetLayer( layerExpansionMask.first );
3764 m_board->
Add( seg.release(), ADD_MODE::APPEND );
3771 const int aPrimitiveIndex,
3772 const bool aIsBoardImport )
3776 wxFAIL_MSG( wxString::Format(
"Altium: Unexpected footprint Track with polygon id %u",
3785 PCB_SHAPE shape(
nullptr, SHAPE_T::SEGMENT );
3810 ALTIUM_RECORD::TRACK, aPrimitiveIndex, aElem.
layer ) )
3812 int width = aElem.
width + ( layerExpansionMask.second * 2 );
3815 std::unique_ptr<PCB_SHAPE> seg = std::make_unique<PCB_SHAPE>( aFootprint, SHAPE_T::SEGMENT );
3817 seg->SetStart( aElem.
start );
3818 seg->SetEnd( aElem.
end );
3819 seg->SetStroke(
STROKE_PARAMS( width, LINE_STYLE::SOLID ) );
3820 seg->SetLayer( layerExpansionMask.first );
3822 aFootprint->
Add( seg.release(), ADD_MODE::APPEND );
3832 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
3834 track->SetStart( aElem.
start );
3835 track->SetEnd( aElem.
end );
3836 track->SetWidth( aElem.
width );
3837 track->SetLayer( aLayer );
3840 m_board->
Add( track.release(), ADD_MODE::APPEND );
3844 std::unique_ptr<PCB_SHAPE> seg = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
3846 seg->SetStart( aElem.
start );
3847 seg->SetEnd( aElem.
end );
3849 seg->SetLayer( aLayer );
3851 m_board->
Add( seg.release(), ADD_MODE::APPEND );
3859 std::unique_ptr<PCB_SHAPE> seg = std::make_unique<PCB_SHAPE>( aFootprint, SHAPE_T::SEGMENT );
3861 seg->SetStart( aElem.
start );
3862 seg->SetEnd( aElem.
end );
3864 seg->SetLayer( aLayer );
3866 aFootprint->
Add( seg.release(), ADD_MODE::APPEND );
3871 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3881 THROW_IO_ERROR( wxT(
"WideStrings6 stream is not fully parsed" ) );
3885 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3915 if( aElem.
fonttype == ALTIUM_TEXT_TYPE::BARCODE )
3920 msg.Printf(
_(
"Ignored barcode on Altium layer %d (not yet supported)." ),
3935 if( aElem.
fonttype == ALTIUM_TEXT_TYPE::BARCODE )
3942 msg.Printf(
_(
"Error loading library '%s':\n"
3943 "Footprint %s contains barcode on Altium layer %d (not yet supported)." ),
3955 msg.Printf(
_(
"Footprint %s contains barcode on Altium layer %d (not yet supported)." ),
3972 std::unique_ptr<PCB_TEXT> pcbText = std::make_unique<PCB_TEXT>(
m_board );
3974 static const std::map<wxString, wxString> variableMap = {
3975 {
"LAYER_NAME",
"LAYER" },
3976 {
"PRINT_DATE",
"CURRENT_DATE"},
3981 pcbText->SetText(kicadText);
3982 pcbText->SetLayer( aLayer );
3983 pcbText->SetPosition( aElem.
position );
3988 m_board->
Add( pcbText.release(), ADD_MODE::APPEND );
4003 fpText = &aFootprint->
Value();
4007 fpText =
new PCB_TEXT( aFootprint );
4008 aFootprint->
Add( fpText, ADD_MODE::APPEND );
4011 static const std::map<wxString, wxString> variableMap = {
4012 {
"DESIGNATOR",
"REFERENCE" },
4013 {
"COMMENT",
"VALUE" },
4014 {
"VALUE",
"ALTIUM_VALUE" },
4015 {
"LAYER_NAME",
"LAYER" },
4016 {
"PRINT_DATE",
"CURRENT_DATE"},
4035 if( aElem.
fonttype == ALTIUM_TEXT_TYPE::TRUETYPE )
4043 if( font->
GetName().Contains( wxS(
"Arial" ) ) )
4064 const CFB::COMPOUND_FILE_ENTRY* aEntry )
4097 PCB_SHAPE shape(
nullptr, SHAPE_T::RECTANGLE );
4122 const bool aIsBoardImport )
4125 || aElem.
layer == ALTIUM_LAYER::KEEP_OUT_LAYER )
4128 PCB_SHAPE shape(
nullptr, SHAPE_T::RECTANGLE );
4162 std::unique_ptr<PCB_SHAPE> fill = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::RECTANGLE );
4164 fill->SetFilled(
true );
4165 fill->SetLayer( aLayer );
4168 fill->SetStart( aElem.
pos1 );
4169 fill->SetEnd( aElem.
pos2 );
4183 m_board->
Add( fill.release(), ADD_MODE::APPEND );
4190 std::unique_ptr<PCB_SHAPE> fill = std::make_unique<PCB_SHAPE>( aFootprint, SHAPE_T::RECTANGLE );
4192 fill->SetFilled(
true );
4193 fill->SetLayer( aLayer );
4196 fill->SetStart( aElem.
pos1 );
4197 fill->SetEnd( aElem.
pos2 );
4206 aFootprint->
Add( fill.release(), ADD_MODE::APPEND );
4215 layerSet.set( klayer );
4223 bool keepoutRestrictionVia = ( aKeepoutRestrictions & 0x01 ) != 0;
4224 bool keepoutRestrictionTrack = ( aKeepoutRestrictions & 0x02 ) != 0;
4225 bool keepoutRestrictionCopper = ( aKeepoutRestrictions & 0x04 ) != 0;
4226 bool keepoutRestrictionSMDPad = ( aKeepoutRestrictions & 0x08 ) != 0;
4227 bool keepoutRestrictionTHPad = ( aKeepoutRestrictions & 0x10 ) != 0;
4239 const uint8_t aKeepoutRestrictions )
4241 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board );
4243 zone->SetIsRuleArea(
true );
4250 zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE,
4253 m_board->
Add( zone.release(), ADD_MODE::APPEND );
4260 const uint8_t aKeepoutRestrictions )
4262 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aFootprint );
4264 zone->SetIsRuleArea(
true );
4271 zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE,
4275 aFootprint->
Add( zone.release(), ADD_MODE::APPEND );
4288 if( elems.first == elems.second )
4291 std::vector<std::pair<PCB_LAYER_ID, int>> layerExpansionPairs;
4293 for(
auto it = elems.first; it != elems.second; ++it )
4297 if( pInf.
type == AEXTENDED_PRIMITIVE_INFORMATION_TYPE::MASK )
4303 if( aAltiumLayer == ALTIUM_LAYER::TOP_LAYER
4304 || aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER )
4309 if( aAltiumLayer == ALTIUM_LAYER::BOTTOM_LAYER
4310 || aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER )
4318 if( aAltiumLayer == ALTIUM_LAYER::TOP_LAYER
4319 || aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER )
4324 if( aAltiumLayer == ALTIUM_LAYER::BOTTOM_LAYER
4325 || aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER )
4333 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_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
std::tuple< wxString, const CFB::COMPOUND_FILE_ENTRY * > FindLibFootprintDirName(const wxString &aFpUnicodeName)
const CFB::COMPOUND_FILE_ENTRY * FindStream(const std::vector< std::string > &aStreamPath) const
void ParseFileHeader(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
PROGRESS_REPORTER * m_progressReporter
optional; may be nullptr
void ParseShapeBasedRegions6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
std::vector< PCB_DIM_RADIAL * > m_radialDimensions
void ConvertArcs6ToFootprintItemOnLayer(FOOTPRINT *aFootprint, const AARC6 &aElem, PCB_LAYER_ID aLayer)
void ConvertTracks6ToBoardItem(const ATRACK6 &aElem, const int aPrimitiveIndex)
void ConvertTracks6ToFootprintItem(FOOTPRINT *aFootprint, const ATRACK6 &aElem, const int aPrimitiveIndex, const bool aIsBoardImport)
int m_highest_pour_index
Altium stores pour order across all layers.
void ConvertTexts6ToFootprintItemOnLayer(FOOTPRINT *aFootprint, const ATEXT6 &aElem, PCB_LAYER_ID aLayer)
std::map< ALTIUM_LAYER, PCB_LAYER_ID > m_layermap
void ConvertShapeBasedRegions6ToBoardItemOnLayer(const AREGION6 &aElem, PCB_LAYER_ID aLayer)
void HelperParseDimensions6Leader(const ADIMENSION6 &aElem)
wxString m_footprintName
for footprint library loading error reporting
std::vector< FOOTPRINT * > m_components
const ARULE6 * GetRuleDefault(ALTIUM_RULE_KIND aKind) const
void HelperParsePad6NonCopper(const APAD6 &aElem, PCB_LAYER_ID aLayer, PCB_SHAPE *aShape)
std::vector< PCB_LAYER_ID > GetKicadLayersToIterate(ALTIUM_LAYER aAltiumLayer) const
void ParseRegions6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ParseBoard6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ParseComponentsBodies6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ConvertShapeBasedRegions6ToFootprintItem(FOOTPRINT *aFootprint, const AREGION6 &aElem, const int aPrimitiveIndex)
void HelperPcpShapeAsFootprintKeepoutRegion(FOOTPRINT *aFootprint, const PCB_SHAPE &aShape, const ALTIUM_LAYER aAltiumLayer, const uint8_t aKeepoutRestrictions)
void ParseFills6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void Parse(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const std::map< ALTIUM_PCB_DIR, std::string > &aFileMapping)
void ParseBoardRegionsData(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ConvertArcs6ToBoardItem(const AARC6 &aElem, const int aPrimitiveIndex)
void ConvertShapeBasedRegions6ToFootprintItemOnLayer(FOOTPRINT *aFootprint, const AREGION6 &aElem, PCB_LAYER_ID aLayer, const int aPrimitiveIndex)
std::map< ALTIUM_LAYER, ZONE * > m_outer_plane
std::vector< int > m_altiumToKicadNetcodes
unsigned m_totalCount
for progress reporting
void HelperPcpShapeAsBoardKeepoutRegion(const PCB_SHAPE &aShape, const ALTIUM_LAYER aAltiumLayer, const uint8_t aKeepoutRestrictions)
void ConvertFills6ToBoardItemOnLayer(const AFILL6 &aElem, PCB_LAYER_ID aLayer)
std::vector< std::pair< PCB_LAYER_ID, int > > HelperGetSolderAndPasteMaskExpansions(const ALTIUM_RECORD aType, const int aPrimitiveIndex, const ALTIUM_LAYER aAltiumLayer)
void ConvertFills6ToFootprintItem(FOOTPRINT *aFootprint, const AFILL6 &aElem, const bool aIsBoardImport)
void ConvertShapeBasedRegions6ToBoardItem(const AREGION6 &aElem)
void HelperCreateBoardOutline(const std::vector< ALTIUM_VERTICE > &aVertices)
void ParseVias6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
std::map< ALTIUM_RULE_KIND, std::vector< ARULE6 > > m_rules
void HelperSetZoneKeepoutRestrictions(ZONE &aZone, const uint8_t aKeepoutRestrictions)
void ParseClasses6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void HelperParseDimensions6Linear(const ADIMENSION6 &aElem)
std::map< uint32_t, wxString > m_unicodeStrings
void ConvertTexts6ToBoardItem(const ATEXT6 &aElem)
FOOTPRINT * ParseFootprint(ALTIUM_COMPOUND_FILE &altiumLibFile, const wxString &aFootprintName)
void ParseArcs6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void HelperParseDimensions6Center(const ADIMENSION6 &aElem)
void HelperParseDimensions6Radial(const ADIMENSION6 &aElem)
void ParsePads6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ParseWideStrings6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ConvertTexts6ToBoardItemOnLayer(const ATEXT6 &aElem, PCB_LAYER_ID aLayer)
void ConvertPads6ToFootprintItemOnCopper(FOOTPRINT *aFootprint, const APAD6 &aElem)
REPORTER * m_reporter
optional; may be nullptr
void ParseComponents6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
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 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 remapUnsureLayers(std::vector< ABOARD6_LAYER_STACKUP > &aStackup)
std::vector< ZONE * > m_polygons
std::map< wxString, wxString > m_models
void ConvertArcs6ToPcbShape(const AARC6 &aElem, PCB_SHAPE *aShape)
void ConvertTracks6ToBoardItemOnLayer(const ATRACK6 &aElem, PCB_LAYER_ID aLayer)
void ConvertFills6ToBoardItem(const AFILL6 &aElem)
void ParseModelsData(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry, const std::vector< std::string > &aRootDir)
void ParseRules6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
FOOTPRINT * HelperGetFootprint(uint16_t aComponent) const
LAYER_MAPPING_HANDLER m_layerMappingHandler
PCB_LAYER_ID GetKicadLayer(ALTIUM_LAYER aAltiumLayer) const
void ConvertTracks6ToFootprintItemOnLayer(FOOTPRINT *aFootprint, const ATRACK6 &aElem, PCB_LAYER_ID aLayer)
void ParseTexts6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ParsePolygons6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
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)
std::map< ALTIUM_RECORD, std::multimap< int, const AEXTENDED_PRIMITIVE_INFORMATION > > m_extendedPrimitiveInformationMaps
std::map< ALTIUM_LAYER, wxString > m_layerNames
void ParseTracks6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ConvertPads6ToBoardItemOnNonCopper(const APAD6 &aElem)
void ParseNets6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ParseExtendedPrimitiveInformationData(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ParseDimensions6Data(const ALTIUM_COMPOUND_FILE &aAltiumPcbFile, const CFB::COMPOUND_FILE_ENTRY *aEntry)
void ConvertPads6ToFootprintItem(FOOTPRINT *aFootprint, const APAD6 &aElem)
const ARULE6 * GetRule(ALTIUM_RULE_KIND aKind, const wxString &aName) const
void HelperSetZoneLayers(ZONE &aZone, const ALTIUM_LAYER aAltiumLayer)
static wxString ReadString(const std::map< wxString, wxString > &aProps, const wxString &aKey, const wxString &aDefault)
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 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.
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)
const wxString & GetFileName() const
bool SetLayerType(PCB_LAYER_ID aLayer, LAYER_T aLayerType)
Change the type of the layer given by aLayer.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
const DRAWINGS & Drawings() const
size_type GetHeight() const
size_type GetWidth() const
bool IsHorizontal() 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 SetVertJustify(GR_TEXT_V_ALIGN_T aType)
void SetBoldFlag(bool aBold)
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
void SetKeepUpright(bool aKeepUpright)
virtual void SetText(const wxString &aText)
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
void SetItalic(bool aItalic)
void SetFont(KIFONT::FONT *aFont)
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
VECTOR3D m_Offset
3D model offset (mm)
VECTOR3D m_Rotation
3D model rotation (degrees)
wxString m_Filename
The 3D shape filename in 3D library.
FONT is an abstract base class for both outline and stroke fonts.
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false)
const wxString & GetName() const
virtual bool IsOutline() const
A logical library item identifier and consists of various portions much like a URI.
LSET is a set of PCB_LAYER_IDs.
static LSET 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 ...
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
virtual void SetPosition(const VECTOR2I &aPos) 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 Fracture(POLYGON_MODE aFastMode)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
void BooleanAdd(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset union For aFastMode meaning, see function booleanOp.
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Adds a new hole to the given outline (default: last) and returns its index.
void Move(const VECTOR2I &aVector) override
Simple container to manage line stroke parameters.
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Handle a list of polygons defining a copper zone.
void 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:
LSET FlipLayerMask(LSET aMask, int aCopperLayersCount)
Calculate the mask layer when flipping a footprint.
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.
#define PROJECT_VAR_NAME
A variable name whose value holds the current project directory.
std::optional< VECTOR2I > OPT_VECTOR2I
wxString NotSpecifiedPrm()
uint8_t keepoutrestrictions
wxString dielectricmaterial
std::vector< ABOARD6_LAYER_STACKUP > stackup
std::vector< ALTIUM_VERTICE > board_vertices
std::vector< wxString > names
wxString sourcefootprintlibrary
wxString sourcedesignator
std::vector< VECTOR2I > textPoint
ALTIUM_DIMENSION_KIND kind
std::vector< VECTOR2I > referencePoint
uint8_t keepoutrestrictions
int32_t soldermaskexpansionmanual
std::unique_ptr< APAD6_SIZE_AND_SHAPE > sizeAndShape
ALTIUM_PAD_SHAPE topshape
ALTIUM_MODE pastemaskexpansionmode
ALTIUM_MODE soldermaskexpansionmode
int32_t pastemaskexpansionmanual
std::vector< ALTIUM_VERTICE > vertices
ALTIUM_POLYGON_HATCHSTYLE hatchstyle
uint8_t keepoutrestrictions
std::vector< ALTIUM_VERTICE > outline
std::vector< std::vector< ALTIUM_VERTICE > > holes
ALTIUM_CONNECT_STYLE polygonconnectStyle
int planeclearanceClearance
int32_t polygonconnectReliefconductorwidth
int32_t polygonconnectAirgapwidth
ALTIUM_TEXT_TYPE fonttype
uint8_t keepoutrestrictions
constexpr double IUTomm(int iu) const
constexpr int mmToIU(double mm) const
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
double DEG2RAD(double deg)
double GetLineLength(const VECTOR2I &aPointA, const VECTOR2I &aPointB)
Return the length of a line segment defined by aPointA and aPointB.
double EuclideanNorm(const VECTOR2I &vector)
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".