42#include <wx/filename.h>
100 std::ifstream file( aFileName.fn_str() );
102 if( !file.is_open() )
107 if( std::getline( file, line ) )
109 if( line.find(
"!PADS-" ) != std::string::npos )
118 const std::map<std::string, UTF8>* aProperties,
PROJECT* aProject )
122 std::unique_ptr<BOARD> board( aAppendToMe ? aAppendToMe :
new BOARD() );
134 parser.
Parse( aFileName );
136 catch(
const std::exception& e )
138 THROW_IO_ERROR( wxString::Format(
"Error parsing PADS file: %s", e.what() ) );
183 return board.release();
189 const auto& nets =
m_parser->GetNets();
191 for(
const auto& pads_net : nets )
194 for(
const auto& pads_net : nets )
196 for(
const auto&
pin : pads_net.pins )
198 std::string key =
pin.ref_des +
"." +
pin.pin_name;
203 const auto& route_nets =
m_parser->GetRoutes();
205 for(
const auto& route : route_nets )
207 for(
const auto&
pin : route.pins )
209 std::string key =
pin.ref_des +
"." +
pin.pin_name;
216 for(
const auto& route : route_nets )
219 for(
const auto& pour_def :
m_parser->GetPours() )
222 for(
const auto& copper :
m_parser->GetCopperShapes() )
228 const auto& reuse_blocks =
m_parser->GetReuseBlocks();
230 for(
const auto& [blockName, block] : reuse_blocks )
232 for(
const std::string& partName : block.part_names )
242 const auto& decals =
m_parser->GetPartDecals();
243 const auto& part_types =
m_parser->GetPartTypes();
244 const auto& partInstanceAttrs =
m_parser->GetPartInstanceAttrs();
245 const auto& parts =
m_parser->GetParts();
247 for(
const auto& pads_part : parts )
256 path.push_back( symbolUuid );
260 std::string decal_name = pads_part.decal;
266 if( !pads_part.explicit_decal )
268 auto part_type_it = part_types.find( decal_name );
270 if( part_type_it != part_types.end() )
271 decal_name = part_type_it->second.decal_name;
276 std::stringstream ss( decal_name );
278 std::vector<std::string> decal_list;
280 while( std::getline( ss, segment,
':' ) )
282 decal_list.push_back( segment );
285 std::string actual_decal_name;
286 bool found_valid_decal =
false;
288 if( pads_part.alt_decal_index >= 0
289 &&
static_cast<size_t>( pads_part.alt_decal_index ) < decal_list.size() )
291 const std::string& alt_decal = decal_list[pads_part.alt_decal_index];
293 if( decals.find( alt_decal ) != decals.end() )
295 actual_decal_name = alt_decal;
296 found_valid_decal =
true;
300 if( !found_valid_decal )
302 for(
const std::string& decal : decal_list )
304 if( decals.find( decal ) != decals.end() )
306 actual_decal_name = decal;
307 found_valid_decal =
true;
313 if( found_valid_decal )
315 decal_name = actual_decal_name;
322 footprint->
SetValue( pads_part.decal );
324 if( !pads_part.alternate_decals.empty() )
328 for(
size_t i = 0; i < pads_part.alternate_decals.size(); ++i )
331 alternates += wxT(
", " );
333 alternates += wxString::FromUTF8( pads_part.alternate_decals[i] );
340 footprint->
Add( field );
343 auto partCoordScaler = [&](
double val,
bool is_x ) {
356 long long origin_nm =
static_cast<long long>( std::round( origin *
m_scaleFactor ) );
357 long long val_nm =
static_cast<long long>( std::round( val * part_factor ) );
359 long long res_nm = val_nm - origin_nm;
364 return static_cast<int>( std::clamp<long long>( res_nm, INT_MIN, INT_MAX ) );
368 partCoordScaler( pads_part.location.y,
false ) ) );
382 auto ptIt = part_types.find( pads_part.decal );
384 if( ptIt != part_types.end() )
385 partType = &ptIt->second;
387 const std::map<std::string, std::string>* instanceAttrs =
nullptr;
388 auto iaIt = partInstanceAttrs.find( pads_part.name );
390 if( iaIt != partInstanceAttrs.end() )
391 instanceAttrs = &iaIt->second;
393 auto applyAttributes = [&](
const std::vector<PADS_IO::ATTRIBUTE>& attrs,
394 std::function<int(
double)> scaler )
396 for(
const auto& attr : attrs )
399 bool ownsField =
false;
401 if( attr.name ==
"Ref.Des." )
405 else if( attr.name ==
"Part Type" || attr.name ==
"VALUE" )
407 field = &footprint->
Value();
411 std::string attrValue;
415 auto valIt = instanceAttrs->find( attr.name );
417 if( valIt != instanceAttrs->end() )
418 attrValue = valIt->second;
421 if( attrValue.empty() && partType )
423 auto valIt = partType->
attributes.find( attr.name );
426 attrValue = valIt->second;
429 if( !attrValue.empty() )
432 wxString::FromUTF8( attr.name ) );
433 field->
SetText( wxString::FromUTF8( attrValue ) );
452 int scaledSize = scaler( attr.height );
464 VECTOR2I offset( scaler( attr.x ), -scaler( attr.y ) );
480 if( attr.hjust ==
"LEFT" )
482 else if( attr.hjust ==
"RIGHT" )
487 if( attr.vjust ==
"UP" )
489 else if( attr.vjust ==
"DOWN" )
495 footprint->
Add( field );
499 auto decal_it = decals.find( decal_name );
501 double decalScale = ( decal_it != decals.end() )
505 auto decalScaler = [&, decalScale](
double val ) {
509 if( decal_it != decals.end() )
510 applyAttributes( decal_it->second.attributes, decalScaler );
516 wxString::Format(
_(
"Footprint '%s' not found in decal list, part skipped" ),
522 auto partScaler = [&](
double val ) {
528 if( pads_part.units ==
"M" )
return KiROUND( val );
533 applyAttributes( pads_part.attributes, partScaler );
549 blockField->
SetText( wxString::FromUTF8( blockIt->second ) );
550 footprint->
Add( blockField );
553 if( decal_it == decals.end() )
564 const std::string& shape = layer_def.
shape;
569 if( shape ==
"R" || shape ==
"C" || shape ==
"A" || shape ==
"RT" )
574 else if( shape ==
"S" || shape ==
"ST" )
579 else if( shape ==
"O" || shape ==
"OT" )
582 pad->SetSize( kicad_layer, size );
584 else if( shape ==
"RF" )
587 pad->SetSize( kicad_layer, size );
589 else if( shape ==
"OF" )
592 pad->SetSize( kicad_layer, size );
594 else if( shape ==
"RC" || shape ==
"OC" )
597 pad->SetSize( kicad_layer, size );
601 double min_dim = std::min( size.
x, size.
y );
603 double ratio = ( min_dim > 0 ) ? (
radius / min_dim ) : 0.25;
604 ratio = std::min( ratio, 0.5 );
605 pad->SetRoundRectRadiusRatio( kicad_layer, ratio );
609 pad->SetRoundRectRadiusRatio( kicad_layer, 0.25 );
624 pad->SetOffset( kicad_layer,
631 for(
size_t term_idx = 0; term_idx < decal.
terminals.size(); ++term_idx )
633 const auto& term = decal.
terminals[term_idx];
637 pad->SetNumber( term.name );
639 VECTOR2I pad_pos( decalScaler( term.x ), -decalScaler( term.y ) );
645 int pin_num =
static_cast<int>( term_idx + 1 );
647 auto stack_it = decal.
pad_stacks.find( pin_num );
652 if( stack_it != decal.
pad_stacks.end() && !stack_it->second.empty() )
654 const std::vector<PADS_IO::PAD_STACK_LAYER>& stack = stack_it->second;
658 double slot_length = 0.0;
659 double slot_orientation = 0.0;
660 double pad_rotation = 0.0;
662 for(
const auto& layer_def : stack )
664 if( layer_def.
drill > 0 )
666 drill = layer_def.
drill;
667 plated = layer_def.
plated;
677 auto mapPadsLayer = [&](
int pads_layer ) ->
PCB_LAYER_ID {
678 if( pads_layer == -2 || pads_layer == 1 )
680 else if( pads_layer == -1
681 || pads_layer ==
m_parser->GetParameters().layer_count )
683 else if( pads_layer > 1
684 && pads_layer < m_parser->GetParameters().layer_count )
686 int inner_idx = pads_layer - 2;
688 if( inner_idx >= 0 && inner_idx < 30 )
695 bool has_explicit_layers =
false;
697 for(
const auto& layer_def : stack )
699 if( layer_def.
layer == -2 || layer_def.
layer == -1
700 || layer_def.
layer == 1
701 || layer_def.
layer ==
m_parser->GetParameters().layer_count )
703 has_explicit_layers =
true;
711 double shape_rotation = 0.0;
712 bool shape_rotation_set =
false;
717 convertPadShape( aLayerDef,
pad, aKicadLayer );
719 if( !shape_rotation_set )
721 shape_rotation = aLayerDef.
rotation;
722 shape_rotation_set =
true;
729 LSET explicitly_seen_tech;
731 for(
const auto& layer_def : stack )
733 if( layer_def.
layer > 0 )
740 explicitly_seen_tech.
set( check );
752 if( has_explicit_layers )
754 std::string front_shape;
755 std::string back_shape;
757 for(
const auto& layer_def : stack )
759 if( layer_def.
sizeA <= 0 )
762 if( layer_def.
shape ==
"RT" || layer_def.
shape ==
"ST"
763 || layer_def.
shape ==
"RA" || layer_def.
shape ==
"SA" )
770 if( mapped ==
F_Cu && front_shape.empty() )
771 front_shape = layer_def.
shape;
772 else if( mapped ==
B_Cu && back_shape.empty() )
773 back_shape = layer_def.
shape;
781 if( !front_shape.empty() && !back_shape.empty()
782 && front_shape != back_shape )
792 bool normal_copper_set =
false;
794 for(
const auto& layer_def : stack )
796 if( layer_def.
layer == 0 )
798 if( !has_explicit_layers )
802 convertGeometry( layer_def,
F_Cu );
817 if( layer_def.
sizeA <= 0 )
826 if( layer_def.
shape ==
"RT" || layer_def.
shape ==
"ST" )
832 pad->SetLocalThermalSpokeWidthOverride(
838 pad->SetThermalSpokeAngleDegrees(
845 if( layer_def.
shape ==
"RA" || layer_def.
shape ==
"SA" )
864 layer_set.
set( tech_layer );
869 layer_set.
set( kicad_layer );
884 convertGeometry( layer_def, kicad_layer );
887 normal_copper_set =
true;
891 if( layer_set.none() )
894 convertGeometry( stack[0],
F_Cu );
907 if( layer_set.test(
F_Cu ) && !layer_set.test(
F_Mask )
908 && !explicitly_seen_tech.test(
F_Mask ) )
913 if( layer_set.test(
F_Cu ) && !layer_set.test(
F_Paste )
914 && !explicitly_seen_tech.test(
F_Paste ) )
919 if( layer_set.test(
B_Cu ) && !layer_set.test(
B_Mask )
920 && !explicitly_seen_tech.test(
B_Mask ) )
925 if( layer_set.test(
B_Cu ) && !layer_set.test(
B_Paste )
926 && !explicitly_seen_tech.test(
B_Paste ) )
932 if( slot_length > 0 && slot_length != drill )
936 int drillMinor = decalScaler( drill );
937 int drillMajor = decalScaler( slot_length );
942 double relAngle = slot_orientation - pad_rotation;
944 relAngle = fmod( relAngle, 360.0 );
949 bool vertical = ( relAngle > 45.0 && relAngle < 135.0 )
950 || ( relAngle > 225.0 && relAngle < 315.0 );
953 pad->SetDrillSize(
VECTOR2I( drillMinor, drillMajor ) );
955 pad->SetDrillSize(
VECTOR2I( drillMajor, drillMinor ) );
960 decalScaler( drill ) ) );
976 LSET mask_paste_bits =
981 pad->SetLayerSet( layer_set );
992 std::string pinKey = pads_part.name +
"." + term.name;
1005 for(
const auto& item : decal.
items )
1007 if( item.points.empty() )
1014 if( item.layer == 0 )
1024 if( mapped_layer ==
B_Cu )
1031 shape_layer = mapped_layer;
1040 _(
"Skipping decal item on unmapped layer %d" ), item.layer ),
1046 bool is_circle = ( item.type ==
"CIRCLE" );
1047 bool is_closed = ( item.type ==
"CLOSED" || is_circle );
1051 if( is_circle && item.points.size() >= 2 )
1056 double x1 = item.points[0].x;
1057 double y1 = item.points[0].y;
1058 double x2 = item.points[1].x;
1059 double y2 = item.points[1].y;
1061 double cx = ( x1 + x2 ) / 2.0;
1062 double cy = ( y1 + y2 ) / 2.0;
1064 double radius = std::sqrt( ( x2 - x1 ) * ( x2 - x1 )
1065 + ( y2 - y1 ) * ( y2 - y1 ) )
1077 shape->
SetEnd( fp_pos + pt_on_circle );
1081 footprint->
Add( shape );
1086 if( item.points.size() < 2 )
1089 for(
size_t i = 0; i < item.points.size() - 1; ++i )
1103 VECTOR2I start( decalScaler( p1.
x ), -decalScaler( p1.
y ) );
1108 std::swap( start,
end );
1122 VECTOR2I start( decalScaler( p1.
x ), -decalScaler( p1.
y ) );
1133 footprint->
Add( shape );
1136 if( is_closed && item.points.size() > 2 )
1150 -decalScaler( pFirst.
arc.
cy ) );
1151 VECTOR2I start( decalScaler( pLast.
x ), -decalScaler( pLast.
y ) );
1152 VECTOR2I end( decalScaler( pFirst.
x ), -decalScaler( pFirst.
y ) );
1155 std::swap( start,
end );
1169 VECTOR2I start( decalScaler( pLast.
x ), -decalScaler( pLast.
y ) );
1170 VECTOR2I end( decalScaler( pFirst.
x ), -decalScaler( pFirst.
y ) );
1180 footprint->
Add( shape );
1185 if( pads_part.bottom_layer )
1195 const auto& reuse_blocks =
m_parser->GetReuseBlocks();
1197 if( reuse_blocks.empty() )
1200 std::map<std::string, PCB_GROUP*> blockGroups;
1202 for(
const auto& [blockName, block] : reuse_blocks )
1204 if( !block.instances.empty() || !block.part_names.empty() )
1207 group->SetName( wxString::FromUTF8( blockName ) );
1209 blockGroups[blockName] =
group;
1215 for(
PCB_FIELD* field : fp->GetFields() )
1217 if( field->GetName() == wxT(
"PADS_Reuse_Block" ) )
1219 std::string blockName = field->GetText().ToStdString();
1220 auto groupIt = blockGroups.find( blockName );
1222 if( groupIt != blockGroups.end() )
1224 groupIt->second->AddItem( fp );
1236 const auto& test_points =
m_parser->GetTestPoints();
1237 const auto& via_defs =
m_parser->GetViaDefs();
1239 for(
const auto&
tp : test_points )
1245 footprint->
SetValue( wxString::FromUTF8(
tp.symbol_name ) );
1254 auto it = via_defs.find(
tp.symbol_name );
1256 if( it != via_defs.end() )
1266 double stackSize = def.
size;
1267 bool hasTopPad =
false;
1268 bool hasBottomPad =
false;
1269 bool hasMaskTop =
false;
1270 bool hasMaskBot =
false;
1272 for(
const auto& stackLayer : def.
stack )
1274 if( def.
size <= 0.0 && stackLayer.sizeA > stackSize )
1275 stackSize = stackLayer.sizeA;
1278 && stackLayer.sizeA > 0.0 )
1283 && stackLayer.sizeA > 0.0 )
1285 hasBottomPad =
true;
1297 if( stackSize > 0.0 )
1300 if( hasTopPad && !hasBottomPad )
1302 else if( hasBottomPad && !hasTopPad )
1304 else if( hasMaskBot && !hasMaskTop )
1306 else if( hasMaskTop && !hasMaskBot )
1313 pad->SetNumber( wxT(
"1" ) );
1314 pad->SetPosition( pos );
1320 if( !
tp.net_name.empty() )
1335 tpField->
SetText( wxString::FromUTF8(
tp.type ) );
1336 footprint->
Add( tpField );
1345 const auto& texts =
m_parser->GetTexts();
1347 for(
const auto& pads_text : texts )
1356 _(
"Text on unmapped layer %d assigned to Comments layer" ),
1367 int scaledSize =
scaleSize( pads_text.height );
1372 text->SetTextSize(
VECTOR2I( charWidth, charHeight ) );
1374 if( pads_text.width > 0 )
1378 text->SetTextAngle( textAngle );
1386 text->SetPosition( pos + textShift );
1388 if( pads_text.hjust ==
"LEFT" )
1390 else if( pads_text.hjust ==
"RIGHT" )
1395 if( pads_text.vjust ==
"UP" )
1397 else if( pads_text.vjust ==
"DOWN" )
1402 text->SetKeepUpright(
false );
1403 text->SetLayer( textLayer );
1406 text->SetMirrored( pads_text.mirrored );
1415 const auto& routes =
m_parser->GetRoutes();
1416 std::set<std::pair<int, int>> placedThroughVias;
1420 std::set<std::pair<int, int>> testPointPositions;
1422 for(
const auto&
tp :
m_parser->GetTestPoints() )
1424 if(
tp.type ==
"VIA" )
1431 for(
const auto& route : routes )
1438 for(
const auto& track_def : route.tracks )
1440 if( track_def.points.size() < 2 )
1450 _(
"Skipping track on non-copper layer %d" ), track_def.layer ),
1458 for(
size_t i = 0; i < track_def.points.size() - 1; ++i )
1469 if( ( start -
end ).EuclideanNorm() < 1000 )
1495 for(
const auto& via_def : route.vias )
1501 if( testPointPositions.count( { pos.x, pos.y } ) )
1505 auto it =
m_parser->GetViaDefs().find( via_def.name );
1507 if( it !=
m_parser->GetViaDefs().end() )
1509 switch( it->second.via_type )
1522 auto key = std::make_pair( pos.
x, pos.
y );
1524 if( placedThroughVias.count( key ) )
1527 placedThroughVias.insert( key );
1532 via->SetPosition( pos );
1534 if( it !=
m_parser->GetViaDefs().end() )
1550 via->SetLayerPair( startLayer, endLayer );
1551 via->SetViaType( viaType );
1582 const auto& copperShapes =
m_parser->GetCopperShapes();
1588 return cs.outline.size() == 2 && !cs.outline[1].is_arc
1589 && !cs.filled && !cs.is_cutout;
1595 auto tryFormRectangle = [&](
size_t idx,
VECTOR2I& minCorner,
VECTOR2I& maxCorner ) ->
bool
1597 if( idx + 3 >= copperShapes.size() )
1600 const auto& c0 = copperShapes[idx];
1601 const auto& c1 = copperShapes[idx + 1];
1602 const auto& c2 = copperShapes[idx + 2];
1603 const auto& c3 = copperShapes[idx + 3];
1605 if( !isRectCandidate( c0 ) || !isRectCandidate( c1 )
1606 || !isRectCandidate( c2 ) || !isRectCandidate( c3 ) )
1611 if( c1.net_name != c0.net_name || c2.net_name != c0.net_name
1612 || c3.net_name != c0.net_name )
1617 if( c1.layer != c0.layer || c2.layer != c0.layer || c3.layer != c0.layer )
1624 for(
int i = 0; i < 4; ++i )
1627 scaleCoord( segs[i]->outline[0].y,
false ) );
1629 scaleCoord( segs[i]->outline[1].y,
false ) );
1633 for(
int i = 0; i < 4; ++i )
1638 if( s.
x != e.
x && s.
y != e.
y )
1643 for(
int i = 0; i < 3; ++i )
1645 if( pts[i * 2 + 1] != pts[( i + 1 ) * 2] )
1650 if( pts[7] != pts[0] )
1654 int minX = pts[0].
x, maxX = pts[0].
x;
1655 int minY = pts[0].
y, maxY = pts[0].
y;
1657 for(
int i = 0; i < 8; ++i )
1659 minX = std::min( minX, pts[i].x );
1660 maxX = std::max( maxX, pts[i].x );
1661 minY = std::min( minY, pts[i].y );
1662 maxY = std::max( maxY, pts[i].y );
1665 minCorner =
VECTOR2I( minX, minY );
1666 maxCorner =
VECTOR2I( maxX, maxY );
1670 for(
size_t idx = 0; idx < copperShapes.size(); ++idx )
1672 const auto& copper = copperShapes[idx];
1674 if( copper.outline.size() < 2 )
1677 if( copper.is_cutout )
1687 _(
"COPPER item on unmapped layer %d defaulting to F.Cu" ),
1702 if( tryFormRectangle( idx, minCorner, maxCorner ) )
1707 rect->
SetEnd( maxCorner );
1719 for(
size_t i = 0; i < copper.outline.size() - 1; ++i )
1721 const auto& p1 = copper.outline[i];
1722 const auto& p2 = copper.outline[i + 1];
1727 if( ( start -
end ).EuclideanNorm() < 1000 )
1753 if( !copper.net_name.empty() )
1758 if( copper.outline.size() < 3 )
1778 for(
size_t i = 0; i < copper.outline.size() - 1; ++i )
1780 const auto& p1 = copper.outline[i];
1781 const auto& p2 = copper.outline[i + 1];
1786 if( ( start -
end ).EuclideanNorm() < 1000 )
1823 const auto& clusters =
m_parser->GetClusters();
1825 if( clusters.empty() )
1828 std::map<std::string, const PADS_IO::CLUSTER*> netToClusterMap;
1830 for(
const auto& cluster : clusters )
1832 for(
const std::string& netName : cluster.net_names )
1835 netToClusterMap[converted] = &cluster;
1839 std::map<int, PCB_GROUP*> clusterGroups;
1841 for(
const auto& cluster : clusters )
1844 group->SetName( wxString::FromUTF8( cluster.name ) );
1846 clusterGroups[cluster.id] =
group;
1855 std::string netName = net->
GetNetname().ToStdString();
1856 auto clusterIt = netToClusterMap.find( netName );
1858 if( clusterIt != netToClusterMap.end() )
1860 int clusterId = clusterIt->second->id;
1861 auto groupIt = clusterGroups.find( clusterId );
1863 if( groupIt != clusterGroups.end() )
1865 groupIt->second->AddItem( track );
1875 const auto& pours =
m_parser->GetPours();
1876 const auto& params =
m_parser->GetParameters();
1880 auto isValidPoly = [](
const std::vector<PADS_IO::ARC_POINT>& pts )
1882 if( pts.size() >= 3 )
1885 if( pts.size() == 1 && pts[0].is_arc
1886 &&
std::abs( pts[0].arc.delta_angle ) >= 359.0 )
1896 int maxPriority = 0;
1898 for(
const auto& pour_def : pours )
1900 if( pour_def.priority > maxPriority )
1901 maxPriority = pour_def.priority;
1905 std::map<std::string, ZONE*> pourZoneMap;
1908 std::map<std::string, std::string> hatoutToParent;
1911 for(
const auto& pour_def : pours )
1915 hatoutToParent[pour_def.name] = pour_def.owner_pour;
1925 if( pour_def.points.size() < 3 )
1935 _(
"Skipping pour on unmapped layer %d" ), pour_def.layer ),
1949 if( pour_def.is_cutout )
1957 zone->
SetZoneName( wxString::Format( wxT(
"Cutout_%s" ), pour_def.owner_pour ) );
1967 int kicadPriority = maxPriority - pour_def.priority + 1;
1977 pourZoneMap[pour_def.name] = zone;
1982 for(
const auto& pour_def : pours )
1987 if( !isValidPoly( pour_def.points ) )
1990 auto zoneIt = pourZoneMap.find( pour_def.owner_pour );
1992 if( zoneIt == pourZoneMap.end() )
1995 ZONE* zone = zoneIt->second;
2022 for(
const auto& void_def : pours )
2027 if( !isValidPoly( void_def.points ) )
2032 auto parentIt = hatoutToParent.find( void_def.owner_pour );
2034 if( parentIt == hatoutToParent.end() )
2037 if( parentIt->second != pour_def.owner_pour )
2045 allVoids.
Append( voidPoly );
2061 const auto& pts = polyline.points;
2063 if( pts.size() < 2 )
2066 for(
size_t i = 0; i < pts.size() - 1; ++i )
2096 if( polyline.closed && pts.size() > 2 )
2101 bool needsClosing = (
std::abs( pLast.
x - pFirst.
x ) > 0.001
2132 const auto& dimensions =
m_parser->GetDimensions();
2134 for(
const auto& dim : dimensions )
2136 if( dim.points.size() < 2 )
2150 if( dim.is_horizontal )
2160 if( dim.is_horizontal )
2162 double heightOffset = dim.crossbar_pos - dim.points[0].y;
2163 int height = -
scaleSize( heightOffset );
2168 double heightOffset = dim.crossbar_pos - dim.points[0].x;
2182 if( dim.text_height > 0 )
2184 int scaledSize =
scaleSize( dim.text_height );
2191 if( dim.text_width > 0 )
2195 if( !dim.text.empty() )
2203 if( dim.rotation != 0.0 )
2214 const auto& keepouts =
m_parser->GetKeepouts();
2215 int keepoutIndex = 0;
2217 for(
const auto& ko : keepouts )
2219 if( ko.outline.size() < 3 )
2225 if( ko.layers.empty() )
2229 else if( ko.layers.size() == 1 )
2238 _(
"Skipping keepout on unmapped layer %d" ), ko.layers[0] ),
2251 for(
int layer : ko.layers )
2256 layerSet.
set( mappedLayer );
2259 if( layerSet.none() )
2287 zone->
SetZoneName( wxString::Format( wxT(
"%s_%d" ), typeName, ++keepoutIndex ) );
2293 if( ko.outline.size() > 2 )
2295 const auto& first = ko.outline.front();
2296 const auto& last = ko.outline.back();
2298 if(
std::abs( first.x - last.x ) > 0.001 ||
std::abs( first.y - last.y ) > 0.001 )
2315 const auto& pts = graphic.points;
2322 if( pts.size() == 1 && pts[0].is_arc
2323 &&
std::abs( pts[0].arc.delta_angle - 360.0 ) < 0.1 )
2338 if( pts.size() < 2 )
2341 for(
size_t i = 0; i < pts.size() - 1; ++i )
2369 if( graphic.closed && pts.size() > 2 )
2374 bool needsClosing = (
std::abs( pLast.
x - pFirst.
x ) > 0.001
2405 wxFileName fn( aFileName );
2406 fn.SetExt( wxT(
"kicad_dru" ) );
2408 wxString customRules = wxT(
"(version 2)\n" );
2410 const auto& diffPairs =
m_parser->GetDiffPairs();
2412 for(
const auto& dp : diffPairs )
2414 if( dp.name.empty() || ( dp.gap <= 0 && dp.width <= 0 ) )
2417 wxString ruleName = wxString::Format( wxT(
"DiffPair_%s" ), wxString::FromUTF8( dp.name ) );
2419 if( dp.gap > 0 && !dp.positive_net.empty() && !dp.negative_net.empty() )
2424 wxString gapStr = wxString::FromUTF8(
FormatDouble2Str( gapMm ) ) + wxT(
"mm" );
2426 customRules += wxString::Format(
2427 wxT(
"\n(rule \"%s_gap\"\n" )
2428 wxT(
" (condition \"A.NetName == '%s' && B.NetName == '%s'\")\n" )
2429 wxT(
" (constraint clearance (min %s)))\n" ),
2430 ruleName, posNet, negNet, gapStr );
2434 if( customRules.length() > 15 )
2436 wxFile rulesFile( fn.GetFullPath(), wxFile::write );
2438 if( rulesFile.IsOpened() )
2439 rulesFile.Write( customRules );
2449 size_t trackCount = 0;
2450 size_t viaCount = 0;
2460 m_reporter->Report( wxString::Format(
_(
"Imported %zu footprints, %d nets, %zu tracks,"
2461 " %zu vias, %zu zones" ),
2464 trackCount, viaCount,
2471 const std::vector<INPUT_LAYER_DESC>& aInputLayerDescriptionVector )
2473 std::map<wxString, PCB_LAYER_ID> layer_map;
2477 layer_map[layer.Name] = layer.AutoMapLayer;
2487 return static_cast<int>( std::clamp<int64_t>( nm, INT_MIN, INT_MAX ) );
2496 if( aUnits ==
"I" || aUnits ==
"MIL" || aUnits ==
"MILS" )
2499 if( aUnits ==
"M" || aUnits ==
"MM" || aUnits ==
"METRIC" )
2502 if( aUnits ==
"INCH" || aUnits ==
"INCHES" )
2513 long long origin_nm =
static_cast<long long>( std::round( origin *
m_scaleFactor ) );
2514 long long val_nm =
static_cast<long long>( std::round( aVal *
m_scaleFactor ) );
2516 long long result = aIsX ? ( val_nm - origin_nm ) : ( origin_nm - val_nm );
2517 return static_cast<int>( std::clamp<long long>(
result, INT_MIN, INT_MAX ) );
2525 if(
info.padsLayerNum == aPadsLayer )
2542 if( aNetName.empty() )
2573 const std::vector<PADS_IO::ARC_POINT>& aPts )
2579 if( aPts.size() == 1 && aPts[0].is_arc
2580 &&
std::abs( aPts[0].arc.delta_angle ) >= 359.0 )
2586 constexpr int NUM_SEGS = 36;
2588 for(
int i = 0; i < NUM_SEGS; i++ )
2590 double angle = 2.0 *
M_PI * i / NUM_SEGS;
2600 for(
size_t i = 1; i < aPts.size(); i++ )
2602 const auto& pt = aPts[i];
2609 for(
int j = 1; j < arcPoly.
PointCount(); j++ )
2631 std::swap( start,
end );
2653 double dx = aCurr.
x - aPrev.
x;
2654 double dy = aCurr.
y - aPrev.
y;
2659 midX = ( aPrev.
x + aCurr.
x ) / 2.0 - dy / 2.0;
2660 midY = ( aPrev.
y + aCurr.
y ) / 2.0 + dx / 2.0;
2665 midX = ( aPrev.
x + aCurr.
x ) / 2.0 + dy / 2.0;
2666 midY = ( aPrev.
y + aCurr.
y ) / 2.0 - dx / 2.0;
2674 double startAngleRad = atan2( aPrev.
y - aCurr.
arc.
cy, aPrev.
x - aCurr.
arc.
cx );
2691 std::vector<PADS_IO::LAYER_INFO> padsLayerInfos =
m_parser->GetLayerInfos();
2717 for(
const auto& padsInfo : padsLayerInfos )
2720 info.padsLayerNum = padsInfo.number;
2721 info.name = padsInfo.name;
2726 info.type = convertLayerType( padsInfo.layer_type );
2728 std::string lowerName = padsInfo.name;
2729 std::transform( lowerName.begin(), lowerName.end(), lowerName.begin(),
2730 [](
unsigned char c ){ return std::tolower( c ); } );
2732 bool isBottom = lowerName.find(
"bottom" ) != std::string::npos
2733 || lowerName.find(
"bot" ) != std::string::npos;
2745 if( padsInfo.number == 1 )
2747 else if( padsInfo.number ==
m_parser->GetParameters().layer_count )
2756 info.required = padsInfo.required;
2760 std::vector<INPUT_LAYER_DESC> inputDescs =
2766 int copperLayerCount =
m_parser->GetParameters().layer_count;
2768 if( copperLayerCount < 1 )
2769 copperLayerCount = 2;
2771 m_loadBoard->SetCopperLayerCount( copperLayerCount );
2779 switch(
m_parser->GetParameters().units )
2801 const auto& designRules =
m_parser->GetDesignRules();
2824 if( defaultNetclass )
2826 defaultNetclass->SetClearance(
scaleSize( designRules.default_clearance ) );
2827 defaultNetclass->SetTrackWidth(
scaleSize( designRules.default_track_width ) );
2828 defaultNetclass->SetViaDiameter(
scaleSize( designRules.default_via_size ) );
2829 defaultNetclass->SetViaDrill(
scaleSize( designRules.default_via_drill ) );
2832 const auto& viaDefs =
m_parser->GetViaDefs();
2834 if( !viaDefs.empty() )
2838 const std::string& defaultViaName =
m_parser->GetParameters().default_signal_via;
2839 auto defaultIt = viaDefs.find( defaultViaName );
2841 if( defaultIt == viaDefs.end() )
2842 defaultIt = viaDefs.begin();
2844 int viaDia =
scaleSize( defaultIt->second.size );
2845 int viaDrill =
scaleSize( defaultIt->second.drill );
2850 if( defaultNetclass )
2852 defaultNetclass->SetViaDiameter( viaDia );
2853 defaultNetclass->SetViaDrill( viaDrill );
2856 for(
const auto& [
name, def] : viaDefs )
2860 const auto& netClasses =
m_parser->GetNetClasses();
2862 for(
const auto& nc : netClasses )
2864 if( nc.name.empty() )
2867 wxString ncName = wxString::FromUTF8( nc.name );
2868 std::shared_ptr<NETCLASS> netclass = std::make_shared<NETCLASS>( ncName );
2870 if( nc.clearance > 0 )
2871 netclass->SetClearance(
scaleSize( nc.clearance ) );
2873 if( nc.track_width > 0 )
2874 netclass->SetTrackWidth(
scaleSize( nc.track_width ) );
2876 if( nc.via_size > 0 )
2877 netclass->SetViaDiameter(
scaleSize( nc.via_size ) );
2879 if( nc.via_drill > 0 )
2880 netclass->SetViaDrill(
scaleSize( nc.via_drill ) );
2882 if( nc.diff_pair_width > 0 )
2883 netclass->SetDiffPairWidth(
scaleSize( nc.diff_pair_width ) );
2885 if( nc.diff_pair_gap > 0 )
2886 netclass->SetDiffPairGap(
scaleSize( nc.diff_pair_gap ) );
2890 for(
const std::string& netName : nc.net_names )
2897 const auto& diffPairs =
m_parser->GetDiffPairs();
2899 for(
const auto& dp : diffPairs )
2901 if( dp.name.empty() )
2904 wxString dpClassName =
2905 wxString::Format( wxT(
"DiffPair_%s" ), wxString::FromUTF8( dp.name ) );
2906 std::shared_ptr<NETCLASS> dpNetclass = std::make_shared<NETCLASS>( dpClassName );
2909 dpNetclass->SetDiffPairGap(
scaleSize( dp.gap ) );
2913 dpNetclass->SetDiffPairWidth(
scaleSize( dp.width ) );
2914 dpNetclass->SetTrackWidth(
scaleSize( dp.width ) );
2919 if( !dp.positive_net.empty() )
2925 if( !dp.negative_net.empty() )
2935 const auto& boardOutlines =
m_parser->GetBoardOutlines();
2937 if( !boardOutlines.empty() )
2939 double min_x = std::numeric_limits<double>::max();
2940 double max_x = std::numeric_limits<double>::lowest();
2941 double min_y = std::numeric_limits<double>::max();
2942 double max_y = std::numeric_limits<double>::lowest();
2944 for(
const auto& outline : boardOutlines )
2946 for(
const auto& pt : outline.points )
2948 min_x = std::min( min_x, pt.x );
2949 max_x = std::max( max_x, pt.x );
2950 min_y = std::min( min_y, pt.y );
2951 max_y = std::max( max_y, pt.y );
2955 if( min_x < max_x && min_y < max_y )
2964 std::vector<const PADS_IO::LAYER_INFO*> copperLayerInfos;
2966 for(
const auto& li : padsLayerInfos )
2969 copperLayerInfos.push_back( &li );
2972 bool hasStackupData =
false;
2974 for(
const auto* li : copperLayerInfos )
2976 if( li->layer_thickness > 0.0 || li->dielectric_constant > 0.0 )
2978 hasStackupData =
true;
2983 if( hasStackupData )
2990 std::map<PCB_LAYER_ID, const PADS_IO::LAYER_INFO*> copperInfoMap;
2992 for(
const auto* li : copperLayerInfos )
2997 copperInfoMap[kicadLayer] = li;
3007 auto it = copperInfoMap.find( item->GetBrdLayerId() );
3009 if( it != copperInfoMap.end() )
3011 prevCopperInfo = it->second;
3013 if( it->second->copper_thickness > 0.0 )
3014 item->SetThickness(
scaleSize( it->second->copper_thickness ) );
3019 if( prevCopperInfo )
3030 item->SetColor( wxT(
"White" ) );
3034 item->SetColor( wxT(
"Green" ) );
constexpr int ARC_HIGH_DEF
@ BS_ITEM_TYPE_SILKSCREEN
@ BS_ITEM_TYPE_DIELECTRIC
@ BS_ITEM_TYPE_SOLDERMASK
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
BASE_SET & set(size_t pos)
virtual void SetNet(NETINFO_ITEM *aNetInfo)
Set a NET_INFO object for the item.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Container for design settings for a BOARD object.
std::shared_ptr< NET_SETTINGS > m_NetSettings
void SetCustomTrackWidth(int aWidth)
Sets custom width for track (i.e.
int m_CopperEdgeClearance
void SetCustomViaSize(int aSize)
Set custom size for via diameter (i.e.
int m_SolderMaskExpansion
BOARD_STACKUP & GetStackupDescriptor()
void SetCustomViaDrill(int aDrill)
Sets custom size for via drill (i.e.
void SetBoardThickness(int aThickness)
std::vector< VIA_DIMENSION > m_ViasDimensionsList
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Manage one layer needed to make a physical board.
Manage layers needed to make a physical board.
void RemoveAll()
Delete all items in list and clear the list.
const std::vector< BOARD_STACKUP_ITEM * > & GetList() const
int BuildBoardThicknessFromStackup() const
void BuildDefaultStackupList(const BOARD_DESIGN_SETTINGS *aSettings, int aActiveCopperLayersCount=0)
Create a default stackup, according to the current BOARD_DESIGN_SETTINGS settings.
Information pertinent to a Pcbnew printed circuit board.
void SetCenter(const VECTOR2I &aCenter)
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
virtual void SetVisible(bool aVisible)
void SetKeepUpright(bool aKeepUpright)
virtual void SetText(const wxString &aText)
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
REPORTER * m_reporter
Reporter to log errors/warnings to, may be nullptr.
PROGRESS_REPORTER * m_progressReporter
Progress reporter to track the progress of the operation, may be nullptr.
virtual void RegisterCallback(LAYER_MAPPING_HANDLER aLayerMappingHandler)
Register a different handler to be called when mapping of input layers to KiCad layers occurs.
LAYER_MAPPING_HANDLER m_layer_mapping_handler
Callback to get layer mapping.
A logical library item identifier and consists of various portions much like a URI.
int SetLibItemName(const UTF8 &aLibItemName)
Override the library item name portion of the LIB_ID to aLibItemName.
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
LSET is a set of PCB_LAYER_IDs.
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Handle the data for a net.
const wxString & GetNetname() const
void SetNetclassPatternAssignment(const wxString &pattern, const wxString &netclass)
Sets a netclass pattern assignment Calling this method will reset the effective netclass calculation ...
std::shared_ptr< NETCLASS > GetDefaultNetclass() const
Gets the default netclass for the project.
void SetNetclass(const wxString &netclassName, std::shared_ptr< NETCLASS > &netclass)
Sets the given netclass Calling user is responsible for resetting the effective netclass calculation ...
@ NORMAL
Shape is the same on all layers.
@ FRONT_INNER_BACK
Up to three shapes can be defined (F_Cu, inner copper layers, B_Cu)
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
void Parse(const wxString &aFileName)
Maps PADS layer numbers and names to KiCad layer IDs.
static constexpr int LAYER_SOLDERMASK_TOP
static constexpr int LAYER_PAD_STACK_BOTTOM
Pad stack: Bottom copper.
static constexpr int LAYER_PAD_STACK_TOP
Pad stack: Top copper.
static constexpr int LAYER_SOLDERMASK_BOTTOM
Converts PADS file format units to KiCad internal units (nanometers).
static constexpr double MILS_TO_NM
static constexpr double INCHES_TO_NM
static constexpr double BASIC_TO_NM
static constexpr double MM_TO_NM
void Update()
Update the dimension's cached text and geometry.
virtual void SetEnd(const VECTOR2I &aPoint)
virtual void SetStart(const VECTOR2I &aPoint)
void SetOverrideTextEnabled(bool aOverride)
void SetLineThickness(int aWidth)
void SetOverrideText(const wxString &aValue)
For better understanding of the points that make a dimension:
void SetHeight(int aHeight)
Set the distance from the feature points to the crossbar line.
A set of BOARD_ITEMs (i.e., without duplicates).
const IO_FILE_DESC GetBoardFileDesc() const override
Returns board file description for the PCB_IO.
int scaleSize(double aVal) const
std::vector< PADS_LAYER_INFO > m_layerInfos
SHAPE_ARC makeMidpointArc(const PADS_IO::ARC_POINT &aPrev, const PADS_IO::ARC_POINT &aCurr, int aWidth)
Build a SHAPE_ARC from two consecutive PADS points using the midpoint approach.
std::map< std::string, std::string > m_partToBlockMap
int scaleCoord(double aVal, bool aIsX) const
void setPcbShapeArc(PCB_SHAPE *aShape, const PADS_IO::ARC_POINT &aPrev, const PADS_IO::ARC_POINT &aCurr)
Configure a PCB_SHAPE as an arc from two consecutive PADS points using board-level scaleCoord.
std::map< std::string, std::string > m_pinToNetMap
PCB_LAYER_ID getMappedLayer(int aPadsLayer) const
void appendArcPoints(SHAPE_LINE_CHAIN &aChain, const std::vector< PADS_IO::ARC_POINT > &aPts)
Interpolate arc segments from an ARC_POINT vector into polyline vertices on a SHAPE_LINE_CHAIN.
std::map< wxString, PCB_LAYER_ID > m_layer_map
PADS layer names to KiCad layers.
void generateDrcRules(const wxString &aFileName)
BOARD * LoadBoard(const wxString &aFileName, BOARD *aAppendToMe, const std::map< std::string, UTF8 > *aProperties, PROJECT *aProject) override
Load information from some input file format that this PCB_IO implementation knows about into either ...
bool CanReadBoard(const wxString &aFileName) const override
Checks if this PCB_IO can read the specified board file.
long long GetLibraryTimestamp(const wxString &aLibraryPath) const override
Generate a timestamp representing all the files in the library (including the library directory).
const IO_FILE_DESC GetLibraryDesc() const override
Get the descriptor for the library container that this IO plugin operates on.
void ensureNet(const std::string &aNetName)
PADS_LAYER_MAPPER m_layerMapper
double decalUnitScale(const std::string &aUnits) const
Resolve a PADS decal/part UNITS letter to a nm-per-unit scale factor.
PADS_UNIT_CONVERTER m_unitConverter
std::map< wxString, PCB_LAYER_ID > DefaultLayerMappingCallback(const std::vector< INPUT_LAYER_DESC > &aInputLayerDescriptionVector)
Return the automapped layers.
const PADS_IO::PARSER * m_parser
void loadReuseBlockGroups()
virtual bool CanReadBoard(const wxString &aFileName) const
Checks if this PCB_IO can read the specified board file.
PCB_IO(const wxString &aName)
void SetWidth(int aWidth) override
void SetShape(SHAPE_T aShape) override
void SetEnd(const VECTOR2I &aEnd) override
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void SetStart(const VECTOR2I &aStart) override
void SetStroke(const STROKE_PARAMS &aStroke) override
void SetTextThickness(int aWidth) override
The TextThickness is that set by the user.
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true) override
virtual void SetPosition(const VECTOR2I &aPos) override
void SetTextAngle(const EDA_ANGLE &aAngle) override
void SetEnd(const VECTOR2I &aEnd)
void SetStart(const VECTOR2I &aStart)
virtual void SetWidth(int aWidth)
Container for project specific data.
const SHAPE_LINE_CHAIN ConvertToPolyline(int aMaxError=DefaultAccuracyForPCB(), int *aActualError=nullptr) const
Construct a SHAPE_LINE_CHAIN of segments from a given arc.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
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.
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.
Represent a set of closed polygons.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
bool IsPolygonSelfIntersecting(int aPolygonIndex) const
Check whether the aPolygonIndex-th polygon in the set is self intersecting.
void Inflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify=false)
Perform outline inflation/deflation.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
int OutlineCount() const
Return the number of outlines in the set.
void BooleanSubtract(const SHAPE_POLY_SET &b)
Perform boolean polyset difference.
Simple container to manage line stroke parameters.
Handle a list of polygons defining a copper zone.
void SetDoNotAllowPads(bool aEnable)
void SetBorderDisplayStyle(ZONE_BORDER_DISPLAY_STYLE aBorderHatchStyle, int aBorderHatchPitch, bool aRebuilBorderdHatch)
Set all hatch parameters for the zone.
void SetMinThickness(int aMinThickness)
void SetThermalReliefSpokeWidth(int aThermalReliefSpokeWidth)
virtual PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
SHAPE_POLY_SET * Outline()
void SetIsRuleArea(bool aEnable)
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)
void SetLayerSet(const LSET &aLayerSet) override
void SetDoNotAllowVias(bool aEnable)
void SetNet(NETINFO_ITEM *aNetInfo) override
Override that drops aNetInfo when this zone is in copper-thieving fill mode.
void SetThermalReliefGap(int aThermalReliefGap)
void SetDoNotAllowFootprints(bool aEnable)
void SetDoNotAllowZoneFills(bool aEnable)
void SetAssignedPriority(unsigned aPriority)
void SetPadConnection(ZONE_CONNECTION aPadConnection)
void SetZoneName(const wxString &aName)
static int GetDefaultHatchPitch()
@ ROUND_ALL_CORNERS
All angles are rounded.
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
double m_PadsPcbTextWidthScale
PADS text width scale factor for PCB imports.
double m_PadsPcbTextHeightScale
PADS text height scale factor for PCB imports.
int m_PcbImportMinObjectSizeNm
Minimum object size in nanometers for PCB imports.
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
@ LEFT_RIGHT
Flip left to right (around the Y axis)
wxString ConvertText(const std::string &aText)
Decode text from a PADS file, which uses an 8-bit codepage rather than UTF-8.
wxString ConvertInvertedNetName(const std::string &aNetName)
Convert a PADS net name to KiCad format, handling inverted signal notation.
KIID GenerateDeterministicUuid(const std::string &aIdentifier)
Generate a deterministic KIID from a PADS component identifier.
@ NONE
No thermal relief defined.
@ BURIED
Via spans only inner layers.
@ THROUGH
Via spans all copper layers.
@ BLIND
Via starts at top or bottom and ends at inner layer.
@ MICROVIA
Single-layer blind via (typically HDI)
@ ROUTE
Routing keepout (traces)
@ PLACEMENT
Component placement keepout.
@ COPPER
Copper pour keepout.
@ VOIDOUT
Void/empty region (VOIDOUT)
@ HATCHED
Hatched pour (HATOUT)
PADS_LAYER_FUNCTION
Layer types from PADS LAYER_TYPE field.
@ ASSEMBLY
Assembly drawing.
@ ROUTING
Copper routing layer.
@ PASTE_MASK
Solder paste mask.
@ MIXED
Mixed signal/plane.
@ UNASSIGNED
Unassigned layer.
@ DOCUMENTATION
Documentation layer.
@ SILK_SCREEN
Silkscreen/legend.
@ PLANE
Power/ground plane.
@ SOLDER_MASK
Solder mask.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Common utilities and types for parsing PADS file formats.
PADS_LAYER_TYPE
PADS layer types.
@ MILS
Thousandths of an inch (1 mil = 0.001 inch)
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
@ SMD
Smd pad, appears on the solder paste layer (default)
@ PTH
Plated through hole pad.
Class to handle a set of BOARD_ITEMs.
std::string FormatDouble2Str(double aValue)
Print a float number without using scientific notation and no trailing 0 This function is intended in...
Container that describes file type info.
wxString m_Description
Description shown in the file picker dialog.
std::vector< std::string > m_FileExtensions
Filter used for file pickers if m_IsFile is true.
A point that may be either a line endpoint or an arc segment.
ARC arc
Arc parameters (only valid when is_arc is true)
bool is_arc
True if this segment is an arc, false for line.
double y
Endpoint Y coordinate.
double x
Endpoint X coordinate.
double cx
Center X coordinate.
double delta_angle
Arc sweep angle in degrees (positive = CCW)
double cy
Center Y coordinate.
A copper shape from the LINES section (type=COPPER).
A 2D graphic line/shape from the LINES section (type=LINES).
double layer_thickness
Dielectric thickness (BASIC units)
double dielectric_constant
Relative permittivity (Er)
double drill
Drill hole diameter (0 for SMD)
std::string shape
Shape code: R, S, A, O, OF, RF, RT, ST, RA, SA, RC, OC.
bool plated
True if drill is plated (PTH vs NPTH)
double rotation
Pad rotation angle in degrees.
double slot_orientation
Slot orientation in degrees (0-179.999)
double thermal_spoke_orientation
First spoke orientation in degrees.
double slot_length
Slot length.
double thermal_spoke_width
Width of thermal spokes.
double finger_offset
Finger pad offset along orientation axis.
double sizeB
Secondary size (height for rectangles/ovals)
double corner_radius
Corner radius magnitude (always positive)
double sizeA
Primary size (diameter or width)
std::vector< DECAL_ITEM > items
std::vector< TERMINAL > terminals
std::map< int, std::vector< PAD_STACK_LAYER > > pad_stacks
std::map< std::string, std::string > attributes
Attribute name-value pairs from {...} block.
A polyline that may contain arc segments.
bool has_mask_front
Stack includes top soldermask opening (layer 25)
int start_layer
First PADS layer number in via span.
int end_layer
Last PADS layer number in via span.
std::vector< PAD_STACK_LAYER > stack
bool has_mask_back
Stack includes bottom soldermask opening (layer 28)
Information about a single PADS layer.
@ USER
The field ID hasn't been set yet; field is invalid.
wxString result
Test unit parsing edge cases and error handling.
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.
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
VECTOR2< int32_t > VECTOR2I
@ THERMAL
Use thermal relief for pads.
@ FULL
pads are covered by copper