43#include <compoundfilereader.h>
49#include <wx/docview.h>
51#include <wx/mstream.h>
52#include <wx/wfstream.h>
53#include <wx/zstream.h>
55#include <magic_enum.hpp>
77 THROW_IO_ERROR( wxString::Format( wxT(
"Component creator tries to access component id %u "
78 "of %u existing components" ),
87 const std::vector<ALTIUM_VERTICE>& aVertices )
96 double startradiant =
DEG2RAD( vertex.startangle );
97 double endradiant =
DEG2RAD( vertex.endangle );
99 -
KiROUND( std::sin( startradiant ) * vertex.radius ) );
102 -
KiROUND( std::sin( endradiant ) * vertex.radius ) );
104 VECTOR2I arcStart = vertex.center + arcStartOffset;
105 VECTOR2I arcEnd = vertex.center + arcEndOffset;
119 aLine.
Append( vertex.position );
129 auto override =
m_layermap.find( aAltiumLayer );
133 return override->second;
136 switch( aAltiumLayer )
140 case ALTIUM_LAYER::TOP_LAYER:
return F_Cu;
141 case ALTIUM_LAYER::MID_LAYER_1:
return In1_Cu;
142 case ALTIUM_LAYER::MID_LAYER_2:
return In2_Cu;
143 case ALTIUM_LAYER::MID_LAYER_3:
return In3_Cu;
144 case ALTIUM_LAYER::MID_LAYER_4:
return In4_Cu;
145 case ALTIUM_LAYER::MID_LAYER_5:
return In5_Cu;
146 case ALTIUM_LAYER::MID_LAYER_6:
return In6_Cu;
147 case ALTIUM_LAYER::MID_LAYER_7:
return In7_Cu;
148 case ALTIUM_LAYER::MID_LAYER_8:
return In8_Cu;
149 case ALTIUM_LAYER::MID_LAYER_9:
return In9_Cu;
150 case ALTIUM_LAYER::MID_LAYER_10:
return In10_Cu;
151 case ALTIUM_LAYER::MID_LAYER_11:
return In11_Cu;
152 case ALTIUM_LAYER::MID_LAYER_12:
return In12_Cu;
153 case ALTIUM_LAYER::MID_LAYER_13:
return In13_Cu;
154 case ALTIUM_LAYER::MID_LAYER_14:
return In14_Cu;
155 case ALTIUM_LAYER::MID_LAYER_15:
return In15_Cu;
156 case ALTIUM_LAYER::MID_LAYER_16:
return In16_Cu;
157 case ALTIUM_LAYER::MID_LAYER_17:
return In17_Cu;
158 case ALTIUM_LAYER::MID_LAYER_18:
return In18_Cu;
159 case ALTIUM_LAYER::MID_LAYER_19:
return In19_Cu;
160 case ALTIUM_LAYER::MID_LAYER_20:
return In20_Cu;
161 case ALTIUM_LAYER::MID_LAYER_21:
return In21_Cu;
162 case ALTIUM_LAYER::MID_LAYER_22:
return In22_Cu;
163 case ALTIUM_LAYER::MID_LAYER_23:
return In23_Cu;
164 case ALTIUM_LAYER::MID_LAYER_24:
return In24_Cu;
165 case ALTIUM_LAYER::MID_LAYER_25:
return In25_Cu;
166 case ALTIUM_LAYER::MID_LAYER_26:
return In26_Cu;
167 case ALTIUM_LAYER::MID_LAYER_27:
return In27_Cu;
168 case ALTIUM_LAYER::MID_LAYER_28:
return In28_Cu;
169 case ALTIUM_LAYER::MID_LAYER_29:
return In29_Cu;
170 case ALTIUM_LAYER::MID_LAYER_30:
return In30_Cu;
171 case ALTIUM_LAYER::BOTTOM_LAYER:
return B_Cu;
173 case ALTIUM_LAYER::TOP_OVERLAY:
return F_SilkS;
174 case ALTIUM_LAYER::BOTTOM_OVERLAY:
return B_SilkS;
175 case ALTIUM_LAYER::TOP_PASTE:
return F_Paste;
176 case ALTIUM_LAYER::BOTTOM_PASTE:
return B_Paste;
177 case ALTIUM_LAYER::TOP_SOLDER:
return F_Mask;
178 case ALTIUM_LAYER::BOTTOM_SOLDER:
return B_Mask;
197 case ALTIUM_LAYER::DRILL_GUIDE:
return Dwgs_User;
198 case ALTIUM_LAYER::KEEP_OUT_LAYER:
return Margin;
200 case ALTIUM_LAYER::MECHANICAL_1:
return User_1;
201 case ALTIUM_LAYER::MECHANICAL_2:
return User_2;
202 case ALTIUM_LAYER::MECHANICAL_3:
return User_3;
203 case ALTIUM_LAYER::MECHANICAL_4:
return User_4;
204 case ALTIUM_LAYER::MECHANICAL_5:
return User_5;
205 case ALTIUM_LAYER::MECHANICAL_6:
return User_6;
206 case ALTIUM_LAYER::MECHANICAL_7:
return User_7;
207 case ALTIUM_LAYER::MECHANICAL_8:
return User_8;
208 case ALTIUM_LAYER::MECHANICAL_9:
return User_9;
209 case ALTIUM_LAYER::MECHANICAL_10:
return Dwgs_User;
210 case ALTIUM_LAYER::MECHANICAL_11:
return Eco2_User;
211 case ALTIUM_LAYER::MECHANICAL_12:
return F_Fab;
212 case ALTIUM_LAYER::MECHANICAL_13:
return B_Fab;
217 case ALTIUM_LAYER::DRILL_DRAWING:
return Dwgs_User;
235 static std::set<ALTIUM_LAYER> altiumLayersWithWarning;
237 if( aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER || aAltiumLayer == ALTIUM_LAYER::KEEP_OUT_LAYER )
239 std::vector<PCB_LAYER_ID> layers;
245 layers.emplace_back( layer );
255 wxLogWarning(
_(
"Altium layer (%d) has no KiCad equivalent. It has been moved to KiCad "
256 "layer Eco1_User." ),
266 const wxString& aLibrary,
const wxString& aFootprintName )
284 const unsigned PROGRESS_DELTA = 250;
302 const std::map<ALTIUM_PCB_DIR, std::string>& aFileMapping )
305 const std::vector<std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>> parserOrder = {
306 {
true, ALTIUM_PCB_DIR::FILE_HEADER,
311 {
true, ALTIUM_PCB_DIR::BOARD6,
316 {
false, ALTIUM_PCB_DIR::EXTENDPRIMITIVEINFORMATION,
321 {
true, ALTIUM_PCB_DIR::COMPONENTS6,
326 {
false, ALTIUM_PCB_DIR::MODELS,
329 std::vector<std::string> dir{ aFileMapping.at( ALTIUM_PCB_DIR::MODELS ) };
332 {
true, ALTIUM_PCB_DIR::COMPONENTBODIES6,
337 {
true, ALTIUM_PCB_DIR::NETS6,
342 {
true, ALTIUM_PCB_DIR::CLASSES6,
347 {
true, ALTIUM_PCB_DIR::RULES6,
352 {
true, ALTIUM_PCB_DIR::DIMENSIONS6,
357 {
true, ALTIUM_PCB_DIR::POLYGONS6,
362 {
true, ALTIUM_PCB_DIR::ARCS6,
367 {
true, ALTIUM_PCB_DIR::PADS6,
372 {
true, ALTIUM_PCB_DIR::VIAS6,
377 {
true, ALTIUM_PCB_DIR::TRACKS6,
382 {
false, ALTIUM_PCB_DIR::WIDESTRINGS6,
387 {
true, ALTIUM_PCB_DIR::TEXTS6,
392 {
true, ALTIUM_PCB_DIR::FILLS6,
397 {
false, ALTIUM_PCB_DIR::BOARDREGIONS,
402 {
true, ALTIUM_PCB_DIR::SHAPEBASEDREGIONS6,
407 {
true, ALTIUM_PCB_DIR::REGIONS6,
417 for(
const std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>& cur : parserOrder )
422 std::tie( isRequired,
directory, fp ) = cur;
424 if(
directory == ALTIUM_PCB_DIR::FILE_HEADER )
427 const auto& mappedDirectory = aFileMapping.find(
directory );
429 if( mappedDirectory == aFileMapping.end() )
432 const std::vector<std::string> mappedFile{ mappedDirectory->second,
"Header" };
433 const CFB::COMPOUND_FILE_ENTRY* file = altiumPcbFile.
FindStream( mappedFile );
435 if( file ==
nullptr )
439 uint32_t numOfRecords = reader.
Read<uint32_t>();
443 wxLogError(
_(
"'%s' was not parsed correctly." ),
FormatPath( mappedFile ) );
451 wxLogError(
_(
"'%s' was not fully parsed." ),
FormatPath( mappedFile ) );
457 const auto& boardDirectory = aFileMapping.find( ALTIUM_PCB_DIR::BOARD6 );
459 if( boardDirectory != aFileMapping.end() )
461 std::vector<std::string> mappedFile{ boardDirectory->second,
"Data" };
463 const CFB::COMPOUND_FILE_ENTRY* file = altiumPcbFile.
FindStream( mappedFile );
468 "This file does not appear to be in a valid PCB Binary Version 6.0 format. In "
470 "make sure to save as \"PCB Binary Files (*.PcbDoc)\"." ) );
475 for(
const std::tuple<bool, ALTIUM_PCB_DIR, PARSE_FUNCTION_POINTER_fp>& cur : parserOrder )
480 std::tie( isRequired,
directory, fp ) = cur;
482 const auto& mappedDirectory = aFileMapping.find(
directory );
484 if( mappedDirectory == aFileMapping.end() )
486 wxASSERT_MSG( !isRequired, wxString::Format( wxT(
"Altium Directory of kind %d was "
487 "expected, but no mapping is "
488 "present in the code" ),
493 std::vector<std::string> mappedFile{ mappedDirectory->second };
495 if(
directory != ALTIUM_PCB_DIR::FILE_HEADER )
496 mappedFile.emplace_back(
"Data" );
498 const CFB::COMPOUND_FILE_ENTRY* file = altiumPcbFile.
FindStream( mappedFile );
500 if( file !=
nullptr )
502 fp( altiumPcbFile, file );
504 else if( isRequired )
506 wxLogError(
_(
"File not found: '%s' for directory '%s'." ),
FormatPath( mappedFile ),
518 if( zone->GetAssignedPriority() == 1000 )
529 zone->SetAssignedPriority( priority >= 0 ? priority : 0 );
533 for( std::pair<const ALTIUM_LAYER, ZONE*>& zone :
m_outer_plane )
534 zone.second->SetAssignedPriority( 0 );
544 if( !zone->HasFilledPolysForLayer( layer ) )
566 if( shape->
GetShape() != SHAPE_T::ARC && shape->
GetShape() != SHAPE_T::CIRCLE )
585 if( arc->
GetCenter() == dim->GetPosition() )
594 VECTOR2I radialLine = dim->GetEnd() - dim->GetStart();
599 radialLine = radialLine.
Resize( std::max( radius, 2 ) );
600 dim->SetEnd( dim->GetStart() + (
VECTOR2I) radialLine );
601 dim->SetLeaderLength( totalLength - radius );
611 int desired_x = ( w - bbbox.
GetWidth() ) / 2;
612 int desired_y = ( h - bbbox.
GetHeight() ) / 2;
614 VECTOR2I movementVector( desired_x - bbbox.
GetX(), desired_y - bbbox.
GetY() );
626 const wxString& aFootprintName )
628 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
646 std::tuple<wxString, const CFB::COMPOUND_FILE_ENTRY*> ret = altiumLibFile.
FindLibFootprintDirName(aFootprintName);
648 wxString fpDirName = std::get<0>( ret );
649 const CFB::COMPOUND_FILE_ENTRY* footprintStream = std::get<1>( ret );
651 if( fpDirName.IsEmpty() )
654 wxString::Format(
_(
"Footprint directory not found: '%s'." ), aFootprintName ) );
657 const std::vector<std::string> streamName{ fpDirName.ToStdString(),
"Data" };
658 const CFB::COMPOUND_FILE_ENTRY* footprintData = altiumLibFile.
FindStream( footprintStream, {
"Data" } );
660 if( footprintData ==
nullptr )
673 footprint->SetFPID( fpID );
675 const std::vector<std::string> parametersStreamName{ fpDirName.ToStdString(),
677 const CFB::COMPOUND_FILE_ENTRY* parametersData =
678 altiumLibFile.
FindStream( footprintStream, {
"Parameters" } );
680 if( parametersData !=
nullptr )
683 std::map<wxString, wxString> parameterProperties = parametersReader.
ReadProperties();
685 wxT(
"DESCRIPTION" ), wxT(
"" ) );
686 footprint->SetLibDescription( description );
690 wxLogError(
_(
"File not found: '%s'." ),
FormatPath( parametersStreamName ) );
691 footprint->SetLibDescription( wxT(
"" ) );
694 const std::vector<std::string> extendedPrimitiveInformationStreamName{
695 "ExtendedPrimitiveInformation",
"Data"
697 const CFB::COMPOUND_FILE_ENTRY* extendedPrimitiveInformationData =
698 altiumLibFile.
FindStream( footprintStream, extendedPrimitiveInformationStreamName );
700 if( extendedPrimitiveInformationData !=
nullptr )
703 footprint->SetReference( wxT(
"REF**" ) );
704 footprint->SetValue( aFootprintName );
705 footprint->Reference().SetVisible(
true );
706 footprint->Value().SetVisible(
true );
711 for(
PCB_FIELD* field : footprint->Fields() )
713 field->SetTextSize( defaultTextSize );
714 field->SetTextThickness( defaultTextThickness );
723 case ALTIUM_RECORD::ARC:
729 case ALTIUM_RECORD::PAD:
735 case ALTIUM_RECORD::VIA:
741 case ALTIUM_RECORD::TRACK:
747 case ALTIUM_RECORD::TEXT:
753 case ALTIUM_RECORD::FILL:
759 case ALTIUM_RECORD::REGION:
765 case ALTIUM_RECORD::MODEL:
772 THROW_IO_ERROR( wxString::Format(
_(
"Record of unknown type: '%d'." ), recordtype ) );
777 footprint->AutoPositionFields();
781 THROW_IO_ERROR( wxString::Format( wxT(
"%s stream was not parsed correctly" ),
787 THROW_IO_ERROR( wxString::Format( wxT(
"%s stream is not fully parsed" ),
791 return footprint.release();
802 THROW_IO_ERROR( wxString::Format( wxT(
"Netcode with id %d does not exist. Only %d nets "
814 const auto rules =
m_rules.find( aKind );
819 for(
const ARULE6& rule : rules->second )
821 if( rule.
name == aName )
830 const auto rules =
m_rules.find( aKind );
835 for(
const ARULE6& rule : rules->second )
845 const CFB::COMPOUND_FILE_ENTRY* aEntry )
862 const CFB::COMPOUND_FILE_ENTRY* aEntry )
879 THROW_IO_ERROR( wxT(
"ExtendedPrimitiveInformation stream is not fully parsed" ) );
883 const CFB::COMPOUND_FILE_ENTRY* aEntry )
900 size_t layercount = 0;
901 size_t layerid =
static_cast<size_t>( ALTIUM_LAYER::TOP_LAYER );
903 while( layerid < elem.
stackup.size() && layerid != 0 )
905 layerid = elem.
stackup[ layerid - 1 ].nextId;
909 size_t kicadLayercount = ( layercount % 2 == 0 ) ? layercount : layercount + 1;
919 auto it = stackup.
GetList().begin();
925 auto curLayer =
static_cast<int>(
F_Cu );
927 for(
size_t altiumLayerId =
static_cast<size_t>( ALTIUM_LAYER::TOP_LAYER );
928 altiumLayerId < elem.
stackup.size() && altiumLayerId != 0;
929 altiumLayerId = elem.
stackup[altiumLayerId - 1].nextId )
935 if( layer.
nextId == 0 && layercount != kicadLayercount )
940 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
942 ( *it )->SetThickness( 0 );
947 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
949 ( *it )->SetThickness( 0, 0 );
950 ( *it )->SetThicknessLocked(
true, 0 );
958 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
975 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected id while parsing last stackup layer" ) );
985 THROW_IO_ERROR( wxT(
"Board6 stream, unexpected item while parsing stackup" ) );
997 for(
size_t altiumLayerId =
static_cast<size_t>( ALTIUM_LAYER::TOP_OVERLAY );
998 altiumLayerId <= static_cast<size_t>( ALTIUM_LAYER::BOTTOM_SOLDER ); altiumLayerId++ )
1009 for(
size_t altiumLayerId =
static_cast<size_t>( ALTIUM_LAYER::MECHANICAL_1 );
1010 altiumLayerId <= static_cast<size_t>( ALTIUM_LAYER::MECHANICAL_16 ); altiumLayerId++ )
1030 LINE_STYLE::SOLID );
1037 int nextShape = lineChain.
NextShape( i );
1038 bool isLastShape = nextShape < 0;
1040 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::ARC );
1042 shape->SetStroke( stroke );
1046 m_board->
Add( shape.release(), ADD_MODE::APPEND );
1052 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
1054 shape->SetStroke( stroke );
1056 shape->SetStart( seg.
A );
1057 shape->SetEnd( seg.
B );
1059 m_board->
Add( shape.release(), ADD_MODE::APPEND );
1065 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1077 if( elem.
kind == ALTIUM_CLASS_KIND::NET_CLASS )
1079 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( elem.
name );
1081 for(
const wxString&
name : elem.
names )
1094 wxLogWarning(
_(
"More than one Altium netclass with name '%s' found. "
1095 "Only the first one will be imported." ), elem.
name );
1111 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1118 uint16_t componentId = 0;
1125 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
1129 footprint->SetFPID( fpID );
1131 footprint->SetPosition( elem.
position );
1132 footprint->SetOrientationDegrees( elem.
rotation );
1138 if( reference.find_first_not_of(
"0123456789" ) == wxString::npos )
1139 reference.Prepend( wxT(
"UNK" ) );
1141 footprint->SetReference( reference );
1143 footprint->SetLocked( elem.
locked );
1144 footprint->Reference().SetVisible( elem.
nameon );
1145 footprint->Value().SetVisible( elem.
commenton );
1146 footprint->SetLayer( elem.
layer == ALTIUM_LAYER::TOP_LAYER ?
F_Cu :
B_Cu );
1149 m_board->
Add( footprint.release(), ADD_MODE::APPEND );
1155 THROW_IO_ERROR( wxT(
"Components6 stream is not fully parsed" ) );
1162 while( Angle < aMin )
1165 while( Angle >= aMax )
1173 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1190 THROW_IO_ERROR( wxString::Format( wxT(
"ComponentsBodies6 stream tries to access "
1191 "component id %d of %d existing components" ),
1203 wxLogError( wxT(
"ComponentsBodies6 stream tries to access model id %s which does not "
1214 modelSettings.
m_Filename = modelTuple->second;
1225 orientation = -orientation;
1238 footprint->
Models().push_back( modelSettings );
1242 THROW_IO_ERROR( wxT(
"ComponentsBodies6 stream is not fully parsed" ) );
1249 THROW_IO_ERROR( wxT(
"Incorrect number of reference points for linear dimension object" ) );
1255 wxLogWarning(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1256 "It has been moved to KiCad layer Eco1_User." ),
1267 dimension->SetLayer( klayer );
1268 dimension->SetStart( referencePoint0 );
1270 if( referencePoint0 != aElem.
xy1 )
1283 SEG segm1( referencePoint0, referencePoint0 + directionNormalVector );
1284 SEG segm2( referencePoint1, referencePoint1 + direction );
1288 THROW_IO_ERROR( wxT(
"Invalid dimension. This should never happen." ) );
1290 dimension->SetEnd( *intersection );
1292 int height =
static_cast<int>(
EuclideanNorm( direction ) );
1294 if( ( direction.
x > 0 || direction.
y < 0 ) != ( aElem.
angle >= 180.0 ) )
1297 dimension->SetHeight( height );
1301 dimension->SetEnd( referencePoint1 );
1304 dimension->SetLineThickness( aElem.
linewidth );
1306 dimension->SetUnitsFormat( DIM_UNITS_FORMAT::NO_SUFFIX );
1310 wxRegEx units( wxS(
"(mm)|(in)|(mils)|(thou)|(')|(\")" ), wxRE_ADVANCED );
1313 dimension->SetUnitsFormat( DIM_UNITS_FORMAT::BARE_SUFFIX );
1322 dimension->Text().SetBold( aElem.
textbold );
1325 dimension->SetTextThickness( dimension->GetTextThickness() *
BOLD_FACTOR );
1330 case ALTIUM_UNIT::INCHES:
1331 dimension->SetUnits( EDA_UNITS::INCHES );
1333 case ALTIUM_UNIT::MILS:
1334 dimension->SetUnits( EDA_UNITS::MILS );
1336 case ALTIUM_UNIT::MILLIMETERS:
1337 case ALTIUM_UNIT::CENTIMETER:
1338 dimension->SetUnits( EDA_UNITS::MILLIMETRES );
1344 m_board->
Add( dimension.release(), ADD_MODE::APPEND );
1351 THROW_IO_ERROR( wxT(
"Not enough reference points for radial dimension object" ) );
1357 wxLogWarning(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1358 "It has been moved to KiCad layer Eco1_User." ),
1366 std::unique_ptr<PCB_DIM_RADIAL> dimension = std::make_unique<PCB_DIM_RADIAL>(
m_board );
1369 dimension->SetLayer( klayer );
1370 dimension->SetStart( referencePoint0 );
1371 dimension->SetEnd( aElem.
xy1 );
1372 dimension->SetLineThickness( aElem.
linewidth );
1373 dimension->SetKeepTextAligned(
false );
1378 dimension->SetUnitsFormat( aElem.
textsuffix.IsEmpty() ? DIM_UNITS_FORMAT::NO_SUFFIX
1379 : DIM_UNITS_FORMAT::BARE_SUFFIX );
1383 case ALTIUM_UNIT::INCHES:
1384 dimension->SetUnits( EDA_UNITS::INCHES );
1386 case ALTIUM_UNIT::MILS:
1387 dimension->SetUnits( EDA_UNITS::MILS );
1389 case ALTIUM_UNIT::MILLIMETERS:
1390 case ALTIUM_UNIT::CENTIMETER:
1391 dimension->SetUnits( EDA_UNITS::MILLIMETRES );
1399 wxLogError( wxT(
"No text position present for leader dimension object" ) );
1403 dimension->SetTextPos( aElem.
textPoint.at( 0 ) );
1409 dimension->SetBold( aElem.
textbold );
1412 dimension->SetTextThickness( dimension->GetTextThickness() *
BOLD_FACTOR );
1420 int yAdjust = dimension->GetTextBox().GetCenter().y - dimension->GetTextPos().y;
1421 dimension->SetTextPos( dimension->GetTextPos() +
VECTOR2I( 0, yAdjust + aElem.
textgap ) );
1425 m_board->
Add( dimension.release(), ADD_MODE::APPEND );
1435 wxLogWarning(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1436 "It has been moved to KiCad layer Eco1_User." ),
1449 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
1451 shape->SetLayer( klayer );
1453 shape->SetStart( last );
1457 m_board->
Add( shape.release(), ADD_MODE::APPEND );
1465 if( dirVec.
x != 0 || dirVec.
y != 0 )
1473 std::unique_ptr<PCB_SHAPE> shape1 =
1474 std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
1476 shape1->SetLayer( klayer );
1478 shape1->SetStart( referencePoint0 );
1479 shape1->SetEnd( referencePoint0 + arrVec );
1481 m_board->
Add( shape1.release(), ADD_MODE::APPEND );
1487 std::unique_ptr<PCB_SHAPE> shape2 =
1488 std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
1490 shape2->SetLayer( klayer );
1492 shape2->SetStart( referencePoint0 );
1493 shape2->SetEnd( referencePoint0 + arrVec );
1495 m_board->
Add( shape2.release(), ADD_MODE::APPEND );
1503 wxLogError( wxT(
"No text position present for leader dimension object" ) );
1507 std::unique_ptr<PCB_TEXT>
text = std::make_unique<PCB_TEXT>(
m_board );
1511 text->SetLayer( klayer );
1527 wxLogWarning(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1528 "It has been moved to KiCad layer Eco1_User." ),
1535 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
1537 shape->SetLayer( klayer );
1542 m_board->
Add( shape.release(), ADD_MODE::APPEND );
1553 wxLogWarning(
_(
"Dimension found on an Altium layer (%d) with no KiCad equivalent. "
1554 "It has been moved to KiCad layer Eco1_User." ),
1562 std::unique_ptr<PCB_DIM_CENTER> dimension = std::make_unique<PCB_DIM_CENTER>(
m_board );
1564 dimension->SetLayer( klayer );
1565 dimension->SetLineThickness( aElem.
linewidth );
1566 dimension->SetStart( aElem.
xy1 );
1567 dimension->SetEnd( aElem.
xy1 + vec );
1569 m_board->
Add( dimension.release(), ADD_MODE::APPEND );
1574 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1588 case ALTIUM_DIMENSION_KIND::LINEAR:
1591 case ALTIUM_DIMENSION_KIND::RADIAL:
1594 case ALTIUM_DIMENSION_KIND::LEADER:
1597 case ALTIUM_DIMENSION_KIND::DATUM:
1598 wxLogError(
_(
"Ignored dimension of kind %d (not yet supported)." ), elem.
kind );
1601 case ALTIUM_DIMENSION_KIND::CENTER:
1605 wxLogError(
_(
"Ignored dimension of kind %d (not yet supported)." ), elem.
kind );
1611 THROW_IO_ERROR( wxT(
"Dimensions6 stream is not fully parsed" ) );
1616 const CFB::COMPOUND_FILE_ENTRY* aEntry,
1617 const std::vector<std::string>& aRootDir )
1632 const wxString altiumModelDir = wxT(
"ALTIUM_EMBEDDED_MODELS" );
1634 wxFileName altiumModelsPath = wxFileName::DirName( projectPath );
1635 wxString kicadModelPrefix = wxT(
"${KIPRJMOD}/" ) + altiumModelDir + wxT(
"/" );
1637 if( !altiumModelsPath.AppendDir( altiumModelDir ) )
1638 THROW_IO_ERROR( wxT(
"Cannot construct directory path for step models" ) );
1641 if( !altiumModelsPath.DirExists() )
1643 if( !altiumModelsPath.Mkdir() )
1645 wxLogError(
_(
"Failed to create folder '%s'." ) + wxS(
" " )
1646 +
_(
"No 3D-models will be imported." ),
1647 altiumModelsPath.GetFullPath() );
1653 wxString invalidChars = wxFileName::GetForbiddenChars();
1660 std::vector<std::string> stepPath = aRootDir;
1661 stepPath.emplace_back( std::to_string( idx ) );
1663 bool validName = !elem.
name.IsEmpty() && elem.
name.IsAscii() &&
1664 wxString::npos == elem.
name.find_first_of( invalidChars );
1665 wxString storageName = !validName ? wxString::Format( wxT(
"model_%d" ), idx )
1667 wxFileName storagePath( altiumModelsPath.GetPath(), storageName );
1671 const CFB::COMPOUND_FILE_ENTRY* stepEntry = aAltiumPcbFile.
FindStream( stepPath );
1673 if( stepEntry ==
nullptr )
1675 wxLogError(
_(
"File not found: '%s'. 3D-model not imported." ),
1680 size_t stepSize =
static_cast<size_t>( stepEntry->size );
1681 std::vector<char> stepContent( stepSize );
1687 if( !storagePath.IsDirWritable() )
1689 wxLogError(
_(
"Insufficient permissions to save file '%s'." ),
1690 storagePath.GetFullPath() );
1694 wxMemoryInputStream stepStream( stepContent.data(), stepSize );
1695 wxZlibInputStream zlibInputStream( stepStream );
1697 wxFFileOutputStream outputStream( storagePath.GetFullPath() );
1699 if( !outputStream.IsOk() )
1701 wxLogError(
_(
"Unable to write file '%s'." ), storagePath.GetFullPath() );
1705 outputStream.Write( zlibInputStream );
1706 outputStream.Close();
1708 m_models.insert( { elem.
id, kicadModelPrefix + storageName } );
1717 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1728 ANET6 elem( reader );
1742 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1773 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board );
1777 zone->SetPosition( elem.
vertices.at( 0 ).position );
1778 zone->SetLocked( elem.
locked );
1780 zone->Outline()->AddOutline( linechain );
1788 const ARULE6* zoneClearanceRule =
GetRule( ALTIUM_RULE_KIND::CLEARANCE,
1789 wxT(
"PolygonClearance" ) );
1790 int planeLayers = 0;
1791 int signalLayers = 0;
1805 if( planeLayers > 0 && planeClearanceRule )
1808 if( signalLayers > 0 && zoneClearanceRule )
1809 clearance = std::max( clearance, zoneClearanceRule->
clearanceGap );
1812 zone->SetLocalClearance( clearance );
1816 if( polygonConnectRule !=
nullptr )
1820 case ALTIUM_CONNECT_STYLE::DIRECT:
1821 zone->SetPadConnection( ZONE_CONNECTION::FULL );
1824 case ALTIUM_CONNECT_STYLE::NONE:
1825 zone->SetPadConnection( ZONE_CONNECTION::NONE );
1829 case ALTIUM_CONNECT_STYLE::RELIEF:
1830 zone->SetPadConnection( ZONE_CONNECTION::THERMAL );
1835 zone->SetThermalReliefSpokeWidth(
1846 zone->SetAssignedPriority( 1 );
1851 || zone->GetBoundingBox().Contains( outer_plane->second->GetBoundingBox() ) )
1857 if( elem.
hatchstyle != ALTIUM_POLYGON_HATCHSTYLE::SOLID
1858 && elem.
hatchstyle != ALTIUM_POLYGON_HATCHSTYLE::UNKNOWN )
1860 zone->SetFillMode( ZONE_FILL_MODE::HATCH_PATTERN );
1863 if( elem.
hatchstyle == ALTIUM_POLYGON_HATCHSTYLE::NONE )
1866 const BOX2I& bbox = zone->GetBoundingBox();
1874 if( elem.
hatchstyle == ALTIUM_POLYGON_HATCHSTYLE::DEGREE_45 )
1875 zone->SetHatchOrientation(
ANGLE_45 );
1878 zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE,
1881 m_board->
Add( zone.release(), ADD_MODE::APPEND );
1889 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1907 std::sort( val.second.begin(), val.second.end(),
1910 return lhs.priority < rhs.priority;
1923 if( trackWidthRule )
1929 if( routingViasRule )
1940 if( holeToHoleRule )
1946 if( soldermaskRule )
1957 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1973 THROW_IO_ERROR( wxT(
"BoardRegions stream is not fully parsed" ) );
1977 const CFB::COMPOUND_FILE_ENTRY* aEntry )
1985 for(
int primitiveIndex = 0; reader.
GetRemainingBytes() >= 4; primitiveIndex++ )
1991 || elem.
kind == ALTIUM_REGION_KIND::BOARD_CUTOUT )
2004 THROW_IO_ERROR(
"ShapeBasedRegions6 stream is not fully parsed" );
2010 if( aElem.
kind == ALTIUM_REGION_KIND::BOARD_CUTOUT )
2014 else if( aElem.
kind == ALTIUM_REGION_KIND::POLYGON_CUTOUT || aElem.
is_keepout )
2028 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board );
2030 zone->SetIsRuleArea(
true );
2036 else if( aElem.
kind == ALTIUM_REGION_KIND::POLYGON_CUTOUT )
2038 zone->SetDoNotAllowCopperPour(
true );
2039 zone->SetDoNotAllowVias(
false );
2040 zone->SetDoNotAllowTracks(
false );
2041 zone->SetDoNotAllowPads(
false );
2042 zone->SetDoNotAllowFootprints(
false );
2045 zone->SetPosition( aElem.
outline.at( 0 ).position );
2046 zone->Outline()->AddOutline( linechain );
2050 zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE,
2053 m_board->
Add( zone.release(), ADD_MODE::APPEND );
2055 else if( aElem.
kind == ALTIUM_REGION_KIND::DASHED_OUTLINE )
2062 _(
"Dashed outline found on an Altium layer (%d) with no KiCad equivalent. "
2063 "It has been moved to KiCad layer Eco1_User." ),
2080 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::POLY );
2082 shape->SetPolyShape( linechain );
2083 shape->SetFilled(
false );
2084 shape->SetLayer( klayer );
2087 m_board->
Add( shape.release(), ADD_MODE::APPEND );
2089 else if( aElem.
kind == ALTIUM_REGION_KIND::COPPER )
2097 else if( aElem.
kind == ALTIUM_REGION_KIND::BOARD_CUTOUT )
2103 wxLogError(
_(
"Ignored polygon shape of kind %d (not yet supported)." ), aElem.
kind );
2110 const int aPrimitiveIndex )
2112 if( aElem.
kind == ALTIUM_REGION_KIND::POLYGON_CUTOUT || aElem.
is_keepout )
2126 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aFootprint );
2128 zone->SetIsRuleArea(
true );
2134 else if( aElem.
kind == ALTIUM_REGION_KIND::POLYGON_CUTOUT )
2136 zone->SetDoNotAllowCopperPour(
true );
2137 zone->SetDoNotAllowVias(
false );
2138 zone->SetDoNotAllowTracks(
false );
2139 zone->SetDoNotAllowPads(
false );
2140 zone->SetDoNotAllowFootprints(
false );
2143 zone->SetPosition( aElem.
outline.at( 0 ).position );
2144 zone->Outline()->AddOutline( linechain );
2148 zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE,
2151 aFootprint->
Add( zone.release(), ADD_MODE::APPEND );
2153 else if( aElem.
kind == ALTIUM_REGION_KIND::COPPER )
2164 else if( aElem.
kind == ALTIUM_REGION_KIND::DASHED_OUTLINE
2165 || aElem.
kind == ALTIUM_REGION_KIND::BOARD_CUTOUT )
2175 wxLogWarning(
_(
"Loading library '%s':\n"
2176 "Footprint %s contains a dashed outline on Altium layer (%d) with "
2177 "no KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
2184 wxLogWarning(
_(
"Footprint %s contains a dashed outline on Altium layer (%d) with "
2185 "no KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
2205 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aFootprint, SHAPE_T::POLY );
2207 shape->SetPolyShape( linechain );
2208 shape->SetFilled(
false );
2209 shape->SetLayer( klayer );
2211 if( aElem.
kind == ALTIUM_REGION_KIND::DASHED_OUTLINE )
2216 aFootprint->
Add( shape.release(), ADD_MODE::APPEND );
2222 wxLogError(
_(
"Error loading library '%s':\n"
2223 "Footprint %s contains polygon shape of kind %d (not yet supported)." ),
2230 wxLogError(
_(
"Footprint %s contains polygon shape of kind %d (not yet supported)." ),
2256 for(
const std::vector<ALTIUM_VERTICE>& hole : aElem.
holes )
2264 polySet.
AddHole( hole_linechain );
2267 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::POLY );
2269 shape->SetPolyShape( polySet );
2270 shape->SetFilled(
true );
2271 shape->SetLayer( aLayer );
2279 m_board->
Add( shape.release(), ADD_MODE::APPEND );
2286 const int aPrimitiveIndex )
2303 for(
const std::vector<ALTIUM_VERTICE>& hole : aElem.
holes )
2311 polySet.
AddHole( hole_linechain );
2314 if( aLayer ==
F_Cu || aLayer ==
B_Cu )
2316 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
2319 padLayers.set( aLayer );
2321 pad->SetKeepTopBottom(
false );
2322 pad->SetAttribute( PAD_ATTRIB::SMD );
2323 pad->SetShape( PAD_SHAPE::CUSTOM );
2329 pad->SetShape( PAD_SHAPE::CUSTOM );
2330 pad->SetAnchorPadShape( PAD_SHAPE::CIRCLE );
2331 pad->SetSize( { anchorSize, anchorSize } );
2332 pad->SetPosition( anchorPos );
2335 shapePolys.
Move( -anchorPos );
2336 pad->AddPrimitivePoly( shapePolys, 0,
true );
2339 auto it = map.find( aPrimitiveIndex );
2341 if( it != map.end() )
2345 if(
info.pastemaskexpansionmode == ALTIUM_MODE::MANUAL )
2347 pad->SetLocalSolderPasteMargin(
2348 info.pastemaskexpansionmanual ?
info.pastemaskexpansionmanual : 1 );
2351 if(
info.soldermaskexpansionmode == ALTIUM_MODE::MANUAL )
2353 pad->SetLocalSolderMaskMargin(
2354 info.soldermaskexpansionmanual ?
info.soldermaskexpansionmanual : 1 );
2357 if(
info.pastemaskexpansionmode != ALTIUM_MODE::NONE )
2360 if(
info.soldermaskexpansionmode != ALTIUM_MODE::NONE )
2364 pad->SetLayerSet( padLayers );
2366 aFootprint->
Add(
pad.release(), ADD_MODE::APPEND );
2370 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aFootprint, SHAPE_T::POLY );
2372 shape->SetPolyShape( polySet );
2373 shape->SetFilled(
true );
2374 shape->SetLayer( aLayer );
2377 aFootprint->
Add( shape.release(), ADD_MODE::APPEND );
2383 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2399 THROW_IO_ERROR( wxString::Format(
"Region stream tries to access polygon id %d "
2400 "of %d existing polygons.",
2407 if( zone ==
nullptr )
2429 for(
const std::vector<ALTIUM_VERTICE>& hole : elem.
holes )
2436 hole_linechain.
Append( hole.at( 0 ).position );
2438 fill.
AddHole( hole_linechain );
2458 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2465 for(
int primitiveIndex = 0; reader.
GetRemainingBytes() >= 4; primitiveIndex++ )
2468 AARC6 elem( reader );
2490 aShape->
SetShape( SHAPE_T::CIRCLE );
2519 THROW_IO_ERROR( wxString::Format(
"Tracks stream tries to access polygon id %u "
2520 "of %zu existing polygons.",
2526 if( zone ==
nullptr )
2571 for(
const auto& layerExpansionMask :
2574 int width = aElem.
width + ( layerExpansionMask.second * 2 );
2578 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>(
m_board );
2581 arc->SetStroke(
STROKE_PARAMS( width, LINE_STYLE::SOLID ) );
2582 arc->SetLayer( layerExpansionMask.first );
2584 m_board->
Add( arc.release(), ADD_MODE::APPEND );
2591 const int aPrimitiveIndex,
const bool aIsBoardImport )
2595 wxFAIL_MSG( wxString::Format(
"Altium: Unexpected footprint Arc with polygon id %d",
2628 for(
const auto& layerExpansionMask :
2631 int width = aElem.
width + ( layerExpansionMask.second * 2 );
2635 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>( aFootprint );
2638 arc->SetStroke(
STROKE_PARAMS( width, LINE_STYLE::SOLID ) );
2639 arc->SetLayer( layerExpansionMask.first );
2641 aFootprint->
Add( arc.release(), ADD_MODE::APPEND );
2652 PCB_SHAPE shape(
nullptr, SHAPE_T::ARC );
2666 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board, &shapeArc );
2668 arc->SetWidth( aElem.
width );
2669 arc->SetLayer( aLayer );
2672 m_board->
Add( arc.release(), ADD_MODE::APPEND );
2676 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>(
m_board );
2680 arc->SetLayer( aLayer );
2682 m_board->
Add( arc.release(), ADD_MODE::APPEND );
2690 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>( aFootprint );
2694 arc->SetLayer( aLayer );
2696 aFootprint->
Add( arc.release(), ADD_MODE::APPEND );
2701 const CFB::COMPOUND_FILE_ENTRY* aEntry )
2711 APAD6 elem( reader );
2733 && aElem.
layer != ALTIUM_LAYER::MULTI_LAYER )
2740 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
2741 footprint->SetPosition( aElem.
position );
2745 m_board->
Add( footprint.release(), ADD_MODE::APPEND );
2754 && aElem.
layer != ALTIUM_LAYER::MULTI_LAYER )
2767 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
2769 pad->SetKeepTopBottom(
false );
2781 pad->SetAttribute( PAD_ATTRIB::SMD );
2785 if( aElem.
layer != ALTIUM_LAYER::MULTI_LAYER )
2790 wxLogError(
_(
"Error loading library '%s':\n"
2791 "Footprint %s pad %s is not marked as multilayer, but is a TH pad." ),
2798 wxLogError(
_(
"Footprint %s pad %s is not marked as multilayer, but is a TH pad." ),
2804 pad->SetAttribute( aElem.
plated ? PAD_ATTRIB::PTH : PAD_ATTRIB::NPTH );
2808 pad->SetDrillShape( PAD_DRILL_SHAPE_T::PAD_DRILL_SHAPE_CIRCLE );
2815 case ALTIUM_PAD_HOLE_SHAPE::ROUND:
2816 wxFAIL_MSG( wxT(
"Round holes are handled before the switch" ) );
2819 case ALTIUM_PAD_HOLE_SHAPE::SQUARE:
2822 wxLogWarning(
_(
"Loading library '%s':\n"
2823 "Footprint %s pad %s has a square hole (not yet supported)." ),
2830 wxLogWarning(
_(
"Footprint %s pad %s has a square hole (not yet supported)." ),
2835 pad->SetDrillShape( PAD_DRILL_SHAPE_T::PAD_DRILL_SHAPE_CIRCLE );
2841 case ALTIUM_PAD_HOLE_SHAPE::SLOT:
2843 pad->SetDrillShape( PAD_DRILL_SHAPE_T::PAD_DRILL_SHAPE_OBLONG );
2860 wxLogWarning(
_(
"Loading library '%s':\n"
2861 "Footprint %s pad %s has a hole-rotation of %f degrees. "
2862 "KiCad only supports 90 degree rotations." ),
2870 wxLogWarning(
_(
"Footprint %s pad %s has a hole-rotation of %f degrees. "
2871 "KiCad only supports 90 degree rotations." ),
2882 case ALTIUM_PAD_HOLE_SHAPE::UNKNOWN:
2885 wxLogError(
_(
"Error loading library '%s':\n"
2886 "Footprint %s pad %s uses a hole of unknown kind %d." ),
2894 wxLogError(
_(
"Footprint %s pad %s uses a hole of unknown kind %d." ),
2900 pad->SetDrillShape( PAD_DRILL_SHAPE_T::PAD_DRILL_SHAPE_CIRCLE );
2910 if( aElem.
padmode != ALTIUM_PAD_MODE::SIMPLE )
2914 wxLogError(
_(
"Error loading library '%s':\n"
2915 "Footprint %s pad %s uses a complex pad stack (not yet supported)." ),
2922 wxLogError(
_(
"Footprint %s pad %s uses a complex pad stack (not yet supported)." ),
2930 case ALTIUM_PAD_SHAPE::RECT:
2931 pad->SetShape( PAD_SHAPE::RECTANGLE );
2934 case ALTIUM_PAD_SHAPE::CIRCLE:
2936 && aElem.
sizeAndShape->alt_shape[0] == ALTIUM_PAD_SHAPE_ALT::ROUNDRECT )
2938 pad->SetShape( PAD_SHAPE::ROUNDRECT );
2939 double ratio = aElem.
sizeAndShape->cornerradius[0] / 200.;
2940 pad->SetRoundRectRadiusRatio( ratio );
2944 pad->SetShape( PAD_SHAPE::CIRCLE );
2948 pad->SetShape( PAD_SHAPE::OVAL );
2953 case ALTIUM_PAD_SHAPE::OCTAGONAL:
2954 pad->SetShape( PAD_SHAPE::CHAMFERED_RECT );
2956 pad->SetChamferRectRatio( 0.25 );
2959 case ALTIUM_PAD_SHAPE::UNKNOWN:
2963 wxLogError(
_(
"Error loading library '%s':\n"
2964 "Footprint %s pad %s uses an unknown pad-shape." ),
2971 wxLogError(
_(
"Footprint %s pad %s uses an unknown pad-shape." ),
2978 if(
pad->GetAttribute() == PAD_ATTRIB::NPTH &&
pad->HasHole() )
2982 : PAD_SHAPE::OVAL );
2983 pad->SetSize(
pad->GetDrillSize() );
2986 switch( aElem.
layer )
2988 case ALTIUM_LAYER::TOP_LAYER:
2993 case ALTIUM_LAYER::BOTTOM_LAYER:
2998 case ALTIUM_LAYER::MULTI_LAYER:
3004 pad->SetLayer( klayer );
3005 pad->SetLayerSet(
LSET( 1, klayer ) );
3016 pad->SetLayerSet(
pad->GetLayerSet().reset(
F_Mask ) );
3019 pad->SetLayerSet(
pad->GetLayerSet().reset(
B_Mask ) );
3021 aFootprint->
Add(
pad.release(), ADD_MODE::APPEND );
3031 wxLogWarning(
_(
"Non-copper pad %s found on an Altium layer (%d) with no KiCad "
3032 "equivalent. It has been moved to KiCad layer Eco1_User." ),
3037 std::unique_ptr<PCB_SHAPE>
pad = std::make_unique<PCB_SHAPE>(
m_board );
3053 wxLogWarning(
_(
"Loading library '%s':\n"
3054 "Footprint %s non-copper pad %s found on an Altium layer (%d) with no "
3055 "KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
3063 wxLogWarning(
_(
"Footprint %s non-copper pad %s found on an Altium layer (%d) with no "
3064 "KiCad equivalent. It has been moved to KiCad layer Eco1_User." ),
3073 std::unique_ptr<PCB_SHAPE>
pad = std::make_unique<PCB_SHAPE>( aFootprint );
3077 aFootprint->
Add(
pad.release(), ADD_MODE::APPEND );
3086 wxLogError(
_(
"Non-copper pad %s is connected to a net, which is not supported." ),
3092 wxLogError(
_(
"Non-copper pad %s has a hole, which is not supported." ), aElem.
name );
3095 if( aElem.
padmode != ALTIUM_PAD_MODE::SIMPLE )
3097 wxLogWarning(
_(
"Non-copper pad %s has a complex pad stack (not yet supported)." ),
3103 case ALTIUM_PAD_SHAPE::RECT:
3122 case ALTIUM_PAD_SHAPE::CIRCLE:
3124 && aElem.
sizeAndShape->alt_shape[0] == ALTIUM_PAD_SHAPE_ALT::ROUNDRECT )
3127 int cornerradius = aElem.
sizeAndShape->cornerradius[0];
3128 int offset = ( std::min( aElem.
topsize.
x, aElem.
topsize.
y ) * cornerradius ) / 200;
3133 if( cornerradius < 100 )
3135 int offsetX = aElem.
topsize.
x / 2 - offset;
3136 int offsetY = aElem.
topsize.
y / 2 - offset;
3150 aShape->
SetShape( SHAPE_T::CIRCLE );
3159 aShape->
SetShape( SHAPE_T::SEGMENT );
3167 aShape->
SetShape( SHAPE_T::SEGMENT );
3179 aShape->
SetShape( SHAPE_T::CIRCLE );
3189 aShape->
SetShape( SHAPE_T::SEGMENT );
3192 LINE_STYLE::SOLID ) );
3212 case ALTIUM_PAD_SHAPE::OCTAGONAL:
3229 aShape->
SetPolyPoints( { p11 - chamferX, p11 - chamferY, p12 + chamferY, p12 - chamferX,
3230 p22 + chamferX, p22 + chamferY, p21 - chamferY, p21 + chamferX } );
3237 case ALTIUM_PAD_SHAPE::UNKNOWN:
3239 wxLogError(
_(
"Non-copper pad %s uses an unknown pad-shape." ), aElem.
name );
3246 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3256 AVIA6 elem( reader );
3258 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
3266 bool start_layer_outside = elem.
layer_start == ALTIUM_LAYER::TOP_LAYER
3267 || elem.
layer_start == ALTIUM_LAYER::BOTTOM_LAYER;
3268 bool end_layer_outside = elem.
layer_end == ALTIUM_LAYER::TOP_LAYER
3269 || elem.
layer_end == ALTIUM_LAYER::BOTTOM_LAYER;
3271 if( start_layer_outside && end_layer_outside )
3273 via->SetViaType( VIATYPE::THROUGH );
3275 else if( ( !start_layer_outside ) && ( !end_layer_outside ) )
3277 via->SetViaType( VIATYPE::BLIND_BURIED );
3281 via->SetViaType( VIATYPE::MICROVIA );
3289 wxLogError(
_(
"Via from layer %d to %d uses a non-copper layer, which is not "
3297 via->SetLayerPair( start_klayer, end_klayer );
3307 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3314 for(
int primitiveIndex = 0; reader.
GetRemainingBytes() >= 4; primitiveIndex++ )
3342 wxLogError(
"ATRACK6 stream tries to access polygon id %u "
3343 "of %u existing polygons. Skip it",
3351 if( zone ==
nullptr )
3364 PCB_SHAPE shape(
nullptr, SHAPE_T::SEGMENT );
3382 PCB_SHAPE shape(
nullptr, SHAPE_T::SEGMENT );
3396 ALTIUM_RECORD::TRACK, aPrimitiveIndex, aElem.
layer ) )
3398 int width = aElem.
width + ( layerExpansionMask.second * 2 );
3401 std::unique_ptr<PCB_SHAPE> seg = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
3403 seg->SetStart( aElem.
start );
3404 seg->SetEnd( aElem.
end );
3405 seg->SetStroke(
STROKE_PARAMS( width, LINE_STYLE::SOLID ) );
3406 seg->SetLayer( layerExpansionMask.first );
3408 m_board->
Add( seg.release(), ADD_MODE::APPEND );
3415 const int aPrimitiveIndex,
3416 const bool aIsBoardImport )
3420 wxFAIL_MSG( wxString::Format(
"Altium: Unexpected footprint Track with polygon id %u",
3429 PCB_SHAPE shape(
nullptr, SHAPE_T::SEGMENT );
3454 ALTIUM_RECORD::TRACK, aPrimitiveIndex, aElem.
layer ) )
3456 int width = aElem.
width + ( layerExpansionMask.second * 2 );
3459 std::unique_ptr<PCB_SHAPE> seg = std::make_unique<PCB_SHAPE>( aFootprint, SHAPE_T::SEGMENT );
3461 seg->SetStart( aElem.
start );
3462 seg->SetEnd( aElem.
end );
3463 seg->SetStroke(
STROKE_PARAMS( width, LINE_STYLE::SOLID ) );
3464 seg->SetLayer( layerExpansionMask.first );
3466 aFootprint->
Add( seg.release(), ADD_MODE::APPEND );
3476 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
3478 track->SetStart( aElem.
start );
3479 track->SetEnd( aElem.
end );
3480 track->SetWidth( aElem.
width );
3481 track->SetLayer( aLayer );
3484 m_board->
Add( track.release(), ADD_MODE::APPEND );
3488 std::unique_ptr<PCB_SHAPE> seg = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::SEGMENT );
3490 seg->SetStart( aElem.
start );
3491 seg->SetEnd( aElem.
end );
3493 seg->SetLayer( aLayer );
3495 m_board->
Add( seg.release(), ADD_MODE::APPEND );
3503 std::unique_ptr<PCB_SHAPE> seg = std::make_unique<PCB_SHAPE>( aFootprint, SHAPE_T::SEGMENT );
3505 seg->SetStart( aElem.
start );
3506 seg->SetEnd( aElem.
end );
3508 seg->SetLayer( aLayer );
3510 aFootprint->
Add( seg.release(), ADD_MODE::APPEND );
3515 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3525 THROW_IO_ERROR( wxT(
"WideStrings6 stream is not fully parsed" ) );
3529 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3559 if( aElem.
fonttype == ALTIUM_TEXT_TYPE::BARCODE )
3561 wxLogError(
_(
"Ignored barcode on Altium layer %d (not yet supported)." ), aElem.
layer );
3572 if( aElem.
fonttype == ALTIUM_TEXT_TYPE::BARCODE )
3576 wxLogError(
_(
"Error loading library '%s':\n"
3577 "Footprint %s contains barcode on Altium layer %d (not yet supported)." ),
3584 wxLogError(
_(
"Footprint %s contains barcode on Altium layer %d (not yet supported)." ),
3599 std::unique_ptr<PCB_TEXT> pcbText = std::make_unique<PCB_TEXT>(
m_board );
3601 static const std::map<wxString, wxString> variableMap = {
3602 {
"LAYER_NAME",
"LAYER" },
3603 {
"PRINT_DATE",
"CURRENT_DATE"},
3608 pcbText->SetText(kicadText);
3609 pcbText->SetLayer( aLayer );
3610 pcbText->SetPosition( aElem.
position );
3615 m_board->
Add( pcbText.release(), ADD_MODE::APPEND );
3630 fpText = &aFootprint->
Value();
3634 fpText =
new PCB_TEXT( aFootprint );
3635 aFootprint->
Add( fpText, ADD_MODE::APPEND );
3638 static const std::map<wxString, wxString> variableMap = {
3639 {
"DESIGNATOR",
"REFERENCE" },
3640 {
"COMMENT",
"VALUE" },
3641 {
"VALUE",
"ALTIUM_VALUE" },
3642 {
"LAYER_NAME",
"LAYER" },
3643 {
"PRINT_DATE",
"CURRENT_DATE"},
3662 if( aElem.
fonttype == ALTIUM_TEXT_TYPE::TRUETYPE )
3670 if( font->
GetName().Contains( wxS(
"Arial" ) ) )
3691 const CFB::COMPOUND_FILE_ENTRY* aEntry )
3724 PCB_SHAPE shape(
nullptr, SHAPE_T::RECTANGLE );
3749 const bool aIsBoardImport )
3752 || aElem.
layer == ALTIUM_LAYER::KEEP_OUT_LAYER )
3755 PCB_SHAPE shape(
nullptr, SHAPE_T::RECTANGLE );
3789 std::unique_ptr<PCB_SHAPE> fill = std::make_unique<PCB_SHAPE>(
m_board, SHAPE_T::RECTANGLE );
3791 fill->SetFilled(
true );
3792 fill->SetLayer( aLayer );
3795 fill->SetStart( aElem.
pos1 );
3796 fill->SetEnd( aElem.
pos2 );
3810 m_board->
Add( fill.release(), ADD_MODE::APPEND );
3817 std::unique_ptr<PCB_SHAPE> fill = std::make_unique<PCB_SHAPE>( aFootprint, SHAPE_T::RECTANGLE );
3819 fill->SetFilled(
true );
3820 fill->SetLayer( aLayer );
3823 fill->SetStart( aElem.
pos1 );
3824 fill->SetEnd( aElem.
pos2 );
3833 aFootprint->
Add( fill.release(), ADD_MODE::APPEND );
3842 layerSet.set( klayer );
3850 bool keepoutRestrictionVia = ( aKeepoutRestrictions & 0x01 ) != 0;
3851 bool keepoutRestrictionTrack = ( aKeepoutRestrictions & 0x02 ) != 0;
3852 bool keepoutRestrictionCopper = ( aKeepoutRestrictions & 0x04 ) != 0;
3853 bool keepoutRestrictionSMDPad = ( aKeepoutRestrictions & 0x08 ) != 0;
3854 bool keepoutRestrictionTHPad = ( aKeepoutRestrictions & 0x10 ) != 0;
3866 const uint8_t aKeepoutRestrictions )
3868 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>(
m_board );
3870 zone->SetIsRuleArea(
true );
3877 zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE,
3880 m_board->
Add( zone.release(), ADD_MODE::APPEND );
3887 const uint8_t aKeepoutRestrictions )
3889 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aFootprint );
3891 zone->SetIsRuleArea(
true );
3898 zone->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE,
3902 aFootprint->
Add( zone.release(), ADD_MODE::APPEND );
3915 if( elems.first == elems.second )
3918 std::vector<std::pair<PCB_LAYER_ID, int>> layerExpansionPairs;
3920 for(
auto it = elems.first; it != elems.second; ++it )
3924 if( pInf.
type == AEXTENDED_PRIMITIVE_INFORMATION_TYPE::MASK )
3930 if( aAltiumLayer == ALTIUM_LAYER::TOP_LAYER
3931 || aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER )
3936 if( aAltiumLayer == ALTIUM_LAYER::BOTTOM_LAYER
3937 || aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER )
3945 if( aAltiumLayer == ALTIUM_LAYER::TOP_LAYER
3946 || aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER )
3951 if( aAltiumLayer == ALTIUM_LAYER::BOTTOM_LAYER
3952 || aAltiumLayer == ALTIUM_LAYER::MULTI_LAYER )
3960 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)
ALTIUM_PCB(BOARD *aBoard, PROGRESS_REPORTER *aProgressReporter, const wxString &aLibrary=wxEmptyString, const wxString &aFootprintName=wxEmptyString)
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)
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)
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
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)
void ConvertArcs6ToBoardItemOnLayer(const AARC6 &aElem, PCB_LAYER_ID aLayer)
std::map< ALTIUM_RECORD, std::multimap< int, const AEXTENDED_PRIMITIVE_INFORMATION > > m_extendedPrimitiveInformationMaps
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.
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....
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.
const TRACKS & Tracks() const
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 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).
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.
#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".