42#include <wx/filename.h>
101 std::ifstream file( aFileName.fn_str() );
103 if( !file.is_open() )
108 if( std::getline( file, line ) )
110 if( line.find(
"!PADS-" ) != std::string::npos )
119 const std::map<std::string, UTF8>* aProperties,
PROJECT* aProject )
123 std::unique_ptr<BOARD> board( aAppendToMe ? aAppendToMe :
new BOARD() );
135 parser.
Parse( aFileName );
137 catch(
const std::exception& e )
139 THROW_IO_ERROR( wxString::Format(
"Error parsing PADS file: %s", e.what() ) );
184 return board.release();
190 const auto& nets =
m_parser->GetNets();
192 for(
const auto& pads_net : nets )
195 for(
const auto& pads_net : nets )
197 for(
const auto&
pin : pads_net.pins )
199 std::string key =
pin.ref_des +
"." +
pin.pin_name;
204 const auto& route_nets =
m_parser->GetRoutes();
206 for(
const auto& route : route_nets )
208 for(
const auto&
pin : route.pins )
210 std::string key =
pin.ref_des +
"." +
pin.pin_name;
217 for(
const auto& route : route_nets )
220 for(
const auto& pour_def :
m_parser->GetPours() )
223 for(
const auto& copper :
m_parser->GetCopperShapes() )
229 const auto& reuse_blocks =
m_parser->GetReuseBlocks();
231 for(
const auto& [blockName, block] : reuse_blocks )
233 for(
const std::string& partName : block.part_names )
243 const auto& decals =
m_parser->GetPartDecals();
244 const auto& part_types =
m_parser->GetPartTypes();
245 const auto& partInstanceAttrs =
m_parser->GetPartInstanceAttrs();
246 const auto& parts =
m_parser->GetParts();
248 for(
const auto& pads_part : parts )
257 path.push_back( symbolUuid );
261 std::string decal_name = pads_part.decal;
267 if( !pads_part.explicit_decal )
269 auto part_type_it = part_types.find( decal_name );
271 if( part_type_it != part_types.end() )
272 decal_name = part_type_it->second.decal_name;
277 std::stringstream ss( decal_name );
279 std::vector<std::string> decal_list;
281 while( std::getline( ss, segment,
':' ) )
283 decal_list.push_back( segment );
286 std::string actual_decal_name;
287 bool found_valid_decal =
false;
289 if( pads_part.alt_decal_index >= 0
290 &&
static_cast<size_t>( pads_part.alt_decal_index ) < decal_list.size() )
292 const std::string& alt_decal = decal_list[pads_part.alt_decal_index];
294 if( decals.find( alt_decal ) != decals.end() )
296 actual_decal_name = alt_decal;
297 found_valid_decal =
true;
301 if( !found_valid_decal )
303 for(
const std::string& decal : decal_list )
305 if( decals.find( decal ) != decals.end() )
307 actual_decal_name = decal;
308 found_valid_decal =
true;
314 if( found_valid_decal )
316 decal_name = actual_decal_name;
323 footprint->
SetValue( pads_part.decal );
325 if( !pads_part.alternate_decals.empty() )
329 for(
size_t i = 0; i < pads_part.alternate_decals.size(); ++i )
332 alternates += wxT(
", " );
334 alternates += wxString::FromUTF8( pads_part.alternate_decals[i] );
341 footprint->
Add( field );
344 auto partCoordScaler = [&](
double val,
bool is_x ) {
357 long long origin_nm =
static_cast<long long>( std::round( origin *
m_scaleFactor ) );
358 long long val_nm =
static_cast<long long>( std::round( val * part_factor ) );
360 long long res_nm = val_nm - origin_nm;
365 return static_cast<int>( std::clamp<long long>( res_nm, INT_MIN, INT_MAX ) );
369 partCoordScaler( pads_part.location.y,
false ) ) );
383 auto ptIt = part_types.find( pads_part.decal );
385 if( ptIt != part_types.end() )
386 partType = &ptIt->second;
388 const std::map<std::string, std::string>* instanceAttrs =
nullptr;
389 auto iaIt = partInstanceAttrs.find( pads_part.name );
391 if( iaIt != partInstanceAttrs.end() )
392 instanceAttrs = &iaIt->second;
394 auto applyAttributes = [&](
const std::vector<PADS_IO::ATTRIBUTE>& attrs,
395 std::function<int(
double)> scaler )
397 for(
const auto& attr : attrs )
400 bool ownsField =
false;
402 if( attr.name ==
"Ref.Des." )
406 else if( attr.name ==
"Part Type" || attr.name ==
"VALUE" )
408 field = &footprint->
Value();
412 std::string attrValue;
416 auto valIt = instanceAttrs->find( attr.name );
418 if( valIt != instanceAttrs->end() )
419 attrValue = valIt->second;
422 if( attrValue.empty() && partType )
424 auto valIt = partType->
attributes.find( attr.name );
427 attrValue = valIt->second;
430 if( !attrValue.empty() )
433 wxString::FromUTF8( attr.name ) );
434 field->
SetText( wxString::FromUTF8( attrValue ) );
453 int scaledSize = scaler( attr.height );
465 VECTOR2I offset( scaler( attr.x ), -scaler( attr.y ) );
481 if( attr.hjust ==
"LEFT" )
483 else if( attr.hjust ==
"RIGHT" )
488 if( attr.vjust ==
"UP" )
490 else if( attr.vjust ==
"DOWN" )
496 footprint->
Add( field );
500 auto decal_it = decals.find( decal_name );
502 double decalScale = ( decal_it != decals.end() )
506 auto decalScaler = [&, decalScale](
double val ) {
510 if( decal_it != decals.end() )
511 applyAttributes( decal_it->second.attributes, decalScaler );
517 wxString::Format(
_(
"Footprint '%s' not found in decal list, part skipped" ),
523 auto partScaler = [&](
double val ) {
529 if( pads_part.units ==
"M" )
return KiROUND( val );
534 applyAttributes( pads_part.attributes, partScaler );
550 blockField->
SetText( wxString::FromUTF8( blockIt->second ) );
551 footprint->
Add( blockField );
554 if( decal_it == decals.end() )
572 int min_dim = std::min( aSize.x, aSize.y );
574 double ratio = ( min_dim > 0 ) ? std::min(
radius / min_dim, 0.5 ) : 0.25;
579 pad->SetRoundRectRadiusRatio( kicad_layer, 0.0 );
580 pad->SetChamferRectRatio( kicad_layer, ratio );
586 pad->SetRoundRectRadiusRatio( kicad_layer, ratio );
589 else if( aDefaultRound )
592 pad->SetRoundRectRadiusRatio( kicad_layer, 0.25 );
602 const std::string& shape = layer_def.
shape;
607 if( shape ==
"R" || shape ==
"C" || shape ==
"A" || shape ==
"RT" )
612 else if( shape ==
"S" || shape ==
"ST" )
616 int side = ( layer_def.
sizeB > 0 ) ? size.
x : size.
y;
618 applyCornerRadius( layer_def,
pad, kicad_layer, sq_size,
false );
619 pad->SetSize( kicad_layer, sq_size );
621 else if( shape ==
"O" || shape ==
"OT" )
624 pad->SetSize( kicad_layer, size );
626 else if( shape ==
"RF" )
628 applyCornerRadius( layer_def,
pad, kicad_layer, size,
false );
629 pad->SetSize( kicad_layer, size );
631 else if( shape ==
"OF" )
634 pad->SetSize( kicad_layer, size );
636 else if( shape ==
"RC" || shape ==
"OC" )
638 applyCornerRadius( layer_def,
pad, kicad_layer, size,
true );
639 pad->SetSize( kicad_layer, size );
653 pad->SetOffset( kicad_layer,
660 for(
size_t term_idx = 0; term_idx < decal.
terminals.size(); ++term_idx )
662 const auto& term = decal.
terminals[term_idx];
666 pad->SetNumber( term.name );
668 VECTOR2I pad_pos( decalScaler( term.x ), -decalScaler( term.y ) );
674 int pin_num =
static_cast<int>( term_idx + 1 );
676 auto stack_it = decal.
pad_stacks.find( pin_num );
681 if( stack_it != decal.
pad_stacks.end() && !stack_it->second.empty() )
683 const std::vector<PADS_IO::PAD_STACK_LAYER>& stack = stack_it->second;
687 double slot_length = 0.0;
688 double slot_orientation = 0.0;
689 double pad_rotation = 0.0;
691 for(
const auto& layer_def : stack )
693 if( layer_def.
drill > 0 )
695 drill = layer_def.
drill;
696 plated = layer_def.
plated;
706 auto mapPadsLayer = [&](
int pads_layer ) ->
PCB_LAYER_ID {
707 if( pads_layer == -2 || pads_layer == 1 )
709 else if( pads_layer == -1
710 || pads_layer ==
m_parser->GetParameters().layer_count )
712 else if( pads_layer > 1
713 && pads_layer < m_parser->GetParameters().layer_count )
715 int inner_idx = pads_layer - 2;
717 if( inner_idx >= 0 && inner_idx < 30 )
724 bool has_explicit_layers =
false;
726 for(
const auto& layer_def : stack )
728 if( layer_def.
layer == -2 || layer_def.
layer == -1
729 || layer_def.
layer == 1
730 || layer_def.
layer ==
m_parser->GetParameters().layer_count )
732 has_explicit_layers =
true;
740 double shape_rotation = 0.0;
741 bool shape_rotation_set =
false;
746 convertPadShape( aLayerDef,
pad, aKicadLayer );
748 if( !shape_rotation_set )
750 shape_rotation = aLayerDef.
rotation;
751 shape_rotation_set =
true;
758 LSET explicitly_seen_tech;
760 for(
const auto& layer_def : stack )
762 if( layer_def.
layer > 0 )
769 explicitly_seen_tech.
set( check );
781 if( has_explicit_layers )
790 +
"|" + std::to_string( aLayerDef.
chamfered );
793 std::string front_shape;
794 std::string back_shape;
796 for(
const auto& layer_def : stack )
798 if( layer_def.
sizeA <= 0 )
801 if( layer_def.
shape ==
"RT" || layer_def.
shape ==
"ST"
802 || layer_def.
shape ==
"RA" || layer_def.
shape ==
"SA" )
809 if( mapped ==
F_Cu && front_shape.empty() )
810 front_shape = shapeKey( layer_def );
811 else if( mapped ==
B_Cu && back_shape.empty() )
812 back_shape = shapeKey( layer_def );
820 if( !front_shape.empty() && !back_shape.empty()
821 && front_shape != back_shape )
831 bool normal_copper_set =
false;
833 for(
const auto& layer_def : stack )
835 if( layer_def.
layer == 0 )
837 if( !has_explicit_layers )
841 convertGeometry( layer_def,
F_Cu );
856 if( layer_def.
sizeA <= 0 )
865 if( layer_def.
shape ==
"RT" || layer_def.
shape ==
"ST" )
871 pad->SetLocalThermalSpokeWidthOverride(
878 int scaledGap = decalScaler( gap );
883 pad->SetLocalThermalGapOverride( scaledGap );
888 pad->SetThermalSpokeAngleDegrees(
895 if( layer_def.
shape ==
"RA" || layer_def.
shape ==
"SA" )
914 layer_set.
set( tech_layer );
919 layer_set.
set( kicad_layer );
934 convertGeometry( layer_def, kicad_layer );
937 normal_copper_set =
true;
941 if( layer_set.none() )
944 convertGeometry( stack[0],
F_Cu );
957 if( layer_set.test(
F_Cu ) && !layer_set.test(
F_Mask )
958 && !explicitly_seen_tech.test(
F_Mask ) )
963 if( layer_set.test(
F_Cu ) && !layer_set.test(
F_Paste )
964 && !explicitly_seen_tech.test(
F_Paste ) )
969 if( layer_set.test(
B_Cu ) && !layer_set.test(
B_Mask )
970 && !explicitly_seen_tech.test(
B_Mask ) )
975 if( layer_set.test(
B_Cu ) && !layer_set.test(
B_Paste )
976 && !explicitly_seen_tech.test(
B_Paste ) )
982 if( slot_length > 0 && slot_length != drill )
986 int drillMinor = decalScaler( drill );
987 int drillMajor = decalScaler( slot_length );
992 double relAngle = slot_orientation - pad_rotation;
994 relAngle = fmod( relAngle, 360.0 );
999 bool vertical = ( relAngle > 45.0 && relAngle < 135.0 )
1000 || ( relAngle > 225.0 && relAngle < 315.0 );
1003 pad->SetDrillSize(
VECTOR2I( drillMinor, drillMajor ) );
1005 pad->SetDrillSize(
VECTOR2I( drillMajor, drillMinor ) );
1009 pad->SetDrillSize(
VECTOR2I( decalScaler( drill ),
1010 decalScaler( drill ) ) );
1026 LSET mask_paste_bits =
1031 pad->SetLayerSet( layer_set );
1042 std::string pinKey = pads_part.name +
"." + term.name;
1055 for(
const auto& item : decal.
items )
1057 if( item.points.empty() )
1064 if( item.layer == 0 )
1074 if( mapped_layer ==
B_Cu )
1081 shape_layer = mapped_layer;
1090 _(
"Skipping decal item on unmapped layer %d" ), item.layer ),
1096 bool is_circle = ( item.type ==
"CIRCLE" );
1097 bool is_closed = ( item.type ==
"CLOSED" || is_circle );
1101 if( is_circle && item.points.size() >= 2 )
1106 double x1 = item.points[0].x;
1107 double y1 = item.points[0].y;
1108 double x2 = item.points[1].x;
1109 double y2 = item.points[1].y;
1111 double cx = ( x1 + x2 ) / 2.0;
1112 double cy = ( y1 + y2 ) / 2.0;
1114 double radius = std::sqrt( ( x2 - x1 ) * ( x2 - x1 )
1115 + ( y2 - y1 ) * ( y2 - y1 ) )
1127 shape->
SetEnd( fp_pos + pt_on_circle );
1131 footprint->
Add( shape );
1136 if( item.points.size() < 2 )
1139 for(
size_t i = 0; i < item.points.size() - 1; ++i )
1153 VECTOR2I start( decalScaler( p1.
x ), -decalScaler( p1.
y ) );
1158 std::swap( start,
end );
1172 VECTOR2I start( decalScaler( p1.
x ), -decalScaler( p1.
y ) );
1183 footprint->
Add( shape );
1186 if( is_closed && item.points.size() > 2 )
1200 -decalScaler( pFirst.
arc.
cy ) );
1201 VECTOR2I start( decalScaler( pLast.
x ), -decalScaler( pLast.
y ) );
1202 VECTOR2I end( decalScaler( pFirst.
x ), -decalScaler( pFirst.
y ) );
1205 std::swap( start,
end );
1219 VECTOR2I start( decalScaler( pLast.
x ), -decalScaler( pLast.
y ) );
1220 VECTOR2I end( decalScaler( pFirst.
x ), -decalScaler( pFirst.
y ) );
1230 footprint->
Add( shape );
1235 if( pads_part.bottom_layer )
1245 const auto& reuse_blocks =
m_parser->GetReuseBlocks();
1247 if( reuse_blocks.empty() )
1250 std::map<std::string, PCB_GROUP*> blockGroups;
1252 for(
const auto& [blockName, block] : reuse_blocks )
1254 if( !block.instances.empty() || !block.part_names.empty() )
1257 group->SetName( wxString::FromUTF8( blockName ) );
1259 blockGroups[blockName] =
group;
1265 for(
PCB_FIELD* field : fp->GetFields() )
1267 if( field->GetName() == wxT(
"PADS_Reuse_Block" ) )
1269 std::string blockName = field->GetText().ToStdString();
1270 auto groupIt = blockGroups.find( blockName );
1272 if( groupIt != blockGroups.end() )
1274 groupIt->second->AddItem( fp );
1286 const auto& test_points =
m_parser->GetTestPoints();
1287 const auto& via_defs =
m_parser->GetViaDefs();
1289 for(
const auto&
tp : test_points )
1295 footprint->
SetValue( wxString::FromUTF8(
tp.symbol_name ) );
1304 auto it = via_defs.find(
tp.symbol_name );
1306 if( it != via_defs.end() )
1316 double stackSize = def.
size;
1317 bool hasTopPad =
false;
1318 bool hasBottomPad =
false;
1319 bool hasMaskTop =
false;
1320 bool hasMaskBot =
false;
1322 for(
const auto& stackLayer : def.
stack )
1324 if( def.
size <= 0.0 && stackLayer.sizeA > stackSize )
1325 stackSize = stackLayer.sizeA;
1328 && stackLayer.sizeA > 0.0 )
1333 && stackLayer.sizeA > 0.0 )
1335 hasBottomPad =
true;
1347 if( stackSize > 0.0 )
1350 if( hasTopPad && !hasBottomPad )
1352 else if( hasBottomPad && !hasTopPad )
1354 else if( hasMaskBot && !hasMaskTop )
1356 else if( hasMaskTop && !hasMaskBot )
1363 pad->SetNumber( wxT(
"1" ) );
1364 pad->SetPosition( pos );
1370 if( !
tp.net_name.empty() )
1385 tpField->
SetText( wxString::FromUTF8(
tp.type ) );
1386 footprint->
Add( tpField );
1395 const auto& texts =
m_parser->GetTexts();
1397 for(
const auto& pads_text : texts )
1406 _(
"Text on unmapped layer %d assigned to Comments layer" ),
1417 int scaledSize =
scaleSize( pads_text.height );
1422 text->SetTextSize(
VECTOR2I( charWidth, charHeight ) );
1424 if( pads_text.width > 0 )
1428 text->SetTextAngle( textAngle );
1436 text->SetPosition( pos + textShift );
1438 if( pads_text.hjust ==
"LEFT" )
1440 else if( pads_text.hjust ==
"RIGHT" )
1445 if( pads_text.vjust ==
"UP" )
1447 else if( pads_text.vjust ==
"DOWN" )
1452 text->SetKeepUpright(
false );
1453 text->SetLayer( textLayer );
1456 text->SetMirrored( pads_text.mirrored );
1465 const auto& routes =
m_parser->GetRoutes();
1466 std::set<std::pair<int, int>> placedThroughVias;
1470 std::set<std::pair<int, int>> testPointPositions;
1472 for(
const auto&
tp :
m_parser->GetTestPoints() )
1474 if(
tp.type ==
"VIA" )
1481 for(
const auto& route : routes )
1488 for(
const auto& track_def : route.tracks )
1490 if( track_def.points.size() < 2 )
1500 _(
"Skipping track on non-copper layer %d" ), track_def.layer ),
1508 for(
size_t i = 0; i < track_def.points.size() - 1; ++i )
1519 if( ( start -
end ).EuclideanNorm() < 1000 )
1545 for(
const auto& via_def : route.vias )
1551 if( testPointPositions.count( { pos.x, pos.y } ) )
1555 auto it =
m_parser->GetViaDefs().find( via_def.name );
1557 if( it !=
m_parser->GetViaDefs().end() )
1559 switch( it->second.via_type )
1572 auto key = std::make_pair( pos.
x, pos.
y );
1574 if( placedThroughVias.count( key ) )
1577 placedThroughVias.insert( key );
1582 via->SetPosition( pos );
1584 if( it !=
m_parser->GetViaDefs().end() )
1600 via->SetLayerPair( startLayer, endLayer );
1601 via->SetViaType( viaType );
1632 const auto& copperShapes =
m_parser->GetCopperShapes();
1638 return cs.outline.size() == 2 && !cs.outline[1].is_arc
1639 && !cs.filled && !cs.is_cutout;
1645 auto tryFormRectangle = [&](
size_t idx,
VECTOR2I& minCorner,
VECTOR2I& maxCorner ) ->
bool
1647 if( idx + 3 >= copperShapes.size() )
1650 const auto& c0 = copperShapes[idx];
1651 const auto& c1 = copperShapes[idx + 1];
1652 const auto& c2 = copperShapes[idx + 2];
1653 const auto& c3 = copperShapes[idx + 3];
1655 if( !isRectCandidate( c0 ) || !isRectCandidate( c1 )
1656 || !isRectCandidate( c2 ) || !isRectCandidate( c3 ) )
1661 if( c1.net_name != c0.net_name || c2.net_name != c0.net_name
1662 || c3.net_name != c0.net_name )
1667 if( c1.layer != c0.layer || c2.layer != c0.layer || c3.layer != c0.layer )
1674 for(
int i = 0; i < 4; ++i )
1677 scaleCoord( segs[i]->outline[0].y,
false ) );
1679 scaleCoord( segs[i]->outline[1].y,
false ) );
1683 for(
int i = 0; i < 4; ++i )
1688 if( s.
x != e.
x && s.
y != e.
y )
1693 for(
int i = 0; i < 3; ++i )
1695 if( pts[i * 2 + 1] != pts[( i + 1 ) * 2] )
1700 if( pts[7] != pts[0] )
1704 int minX = pts[0].
x, maxX = pts[0].
x;
1705 int minY = pts[0].
y, maxY = pts[0].
y;
1707 for(
int i = 0; i < 8; ++i )
1709 minX = std::min( minX, pts[i].x );
1710 maxX = std::max( maxX, pts[i].x );
1711 minY = std::min( minY, pts[i].y );
1712 maxY = std::max( maxY, pts[i].y );
1715 minCorner =
VECTOR2I( minX, minY );
1716 maxCorner =
VECTOR2I( maxX, maxY );
1720 for(
size_t idx = 0; idx < copperShapes.size(); ++idx )
1722 const auto& copper = copperShapes[idx];
1724 if( copper.outline.size() < 2 )
1727 if( copper.is_cutout )
1737 _(
"COPPER item on unmapped layer %d defaulting to F.Cu" ),
1752 if( tryFormRectangle( idx, minCorner, maxCorner ) )
1757 rect->
SetEnd( maxCorner );
1769 for(
size_t i = 0; i < copper.outline.size() - 1; ++i )
1771 const auto& p1 = copper.outline[i];
1772 const auto& p2 = copper.outline[i + 1];
1777 if( ( start -
end ).EuclideanNorm() < 1000 )
1803 if( !copper.net_name.empty() )
1808 if( copper.outline.size() < 3 )
1828 for(
size_t i = 0; i < copper.outline.size() - 1; ++i )
1830 const auto& p1 = copper.outline[i];
1831 const auto& p2 = copper.outline[i + 1];
1836 if( ( start -
end ).EuclideanNorm() < 1000 )
1873 const auto& clusters =
m_parser->GetClusters();
1875 if( clusters.empty() )
1878 std::map<std::string, const PADS_IO::CLUSTER*> netToClusterMap;
1880 for(
const auto& cluster : clusters )
1882 for(
const std::string& netName : cluster.net_names )
1885 netToClusterMap[converted] = &cluster;
1889 std::map<int, PCB_GROUP*> clusterGroups;
1891 for(
const auto& cluster : clusters )
1894 group->SetName( wxString::FromUTF8( cluster.name ) );
1896 clusterGroups[cluster.id] =
group;
1905 std::string netName = net->
GetNetname().ToStdString();
1906 auto clusterIt = netToClusterMap.find( netName );
1908 if( clusterIt != netToClusterMap.end() )
1910 int clusterId = clusterIt->second->id;
1911 auto groupIt = clusterGroups.find( clusterId );
1913 if( groupIt != clusterGroups.end() )
1915 groupIt->second->AddItem( track );
1925 const auto& pours =
m_parser->GetPours();
1926 const auto& params =
m_parser->GetParameters();
1930 auto isValidPoly = [](
const std::vector<PADS_IO::ARC_POINT>& pts )
1932 if( pts.size() >= 3 )
1935 if( pts.size() == 1 && pts[0].is_arc
1936 &&
std::abs( pts[0].arc.delta_angle ) >= 359.0 )
1946 int maxPriority = 0;
1948 for(
const auto& pour_def : pours )
1950 if( pour_def.priority > maxPriority )
1951 maxPriority = pour_def.priority;
1955 std::map<std::string, ZONE*> pourZoneMap;
1958 std::map<std::string, std::string> hatoutToParent;
1961 for(
const auto& pour_def : pours )
1965 hatoutToParent[pour_def.name] = pour_def.owner_pour;
1975 if( pour_def.points.size() < 3 )
1985 _(
"Skipping pour on unmapped layer %d" ), pour_def.layer ),
1999 if( pour_def.is_cutout )
2007 zone->
SetZoneName( wxString::Format( wxT(
"Cutout_%s" ), pour_def.owner_pour ) );
2017 int kicadPriority = maxPriority - pour_def.priority + 1;
2027 pourZoneMap[pour_def.name] = zone;
2032 for(
const auto& pour_def : pours )
2037 if( !isValidPoly( pour_def.points ) )
2040 auto zoneIt = pourZoneMap.find( pour_def.owner_pour );
2042 if( zoneIt == pourZoneMap.end() )
2045 ZONE* zone = zoneIt->second;
2072 for(
const auto& void_def : pours )
2077 if( !isValidPoly( void_def.points ) )
2082 auto parentIt = hatoutToParent.find( void_def.owner_pour );
2084 if( parentIt == hatoutToParent.end() )
2087 if( parentIt->second != pour_def.owner_pour )
2095 allVoids.
Append( voidPoly );
2111 const auto& pts = polyline.points;
2113 if( pts.size() < 2 )
2116 for(
size_t i = 0; i < pts.size() - 1; ++i )
2146 if( polyline.closed && pts.size() > 2 )
2151 bool needsClosing = (
std::abs( pLast.
x - pFirst.
x ) > 0.001
2182 const auto& dimensions =
m_parser->GetDimensions();
2184 for(
const auto& dim : dimensions )
2186 if( dim.points.size() < 2 )
2200 if( dim.is_horizontal )
2210 if( dim.is_horizontal )
2212 double heightOffset = dim.crossbar_pos - dim.points[0].y;
2213 int height = -
scaleSize( heightOffset );
2218 double heightOffset = dim.crossbar_pos - dim.points[0].x;
2232 if( dim.text_height > 0 )
2234 int scaledSize =
scaleSize( dim.text_height );
2241 if( dim.text_width > 0 )
2245 if( !dim.text.empty() )
2253 if( dim.rotation != 0.0 )
2264 const auto& keepouts =
m_parser->GetKeepouts();
2265 int keepoutIndex = 0;
2267 for(
const auto& ko : keepouts )
2269 if( ko.outline.size() < 3 )
2275 if( ko.layers.empty() )
2279 else if( ko.layers.size() == 1 )
2288 _(
"Skipping keepout on unmapped layer %d" ), ko.layers[0] ),
2301 for(
int layer : ko.layers )
2306 layerSet.
set( mappedLayer );
2309 if( layerSet.none() )
2337 zone->
SetZoneName( wxString::Format( wxT(
"%s_%d" ), typeName, ++keepoutIndex ) );
2343 if( ko.outline.size() > 2 )
2345 const auto& first = ko.outline.front();
2346 const auto& last = ko.outline.back();
2348 if(
std::abs( first.x - last.x ) > 0.001 ||
std::abs( first.y - last.y ) > 0.001 )
2365 const auto& pts = graphic.points;
2372 if( pts.size() == 1 && pts[0].is_arc
2373 &&
std::abs( pts[0].arc.delta_angle - 360.0 ) < 0.1 )
2388 if( pts.size() < 2 )
2391 for(
size_t i = 0; i < pts.size() - 1; ++i )
2419 if( graphic.closed && pts.size() > 2 )
2424 bool needsClosing = (
std::abs( pLast.
x - pFirst.
x ) > 0.001
2455 wxFileName fn( aFileName );
2456 fn.SetExt( wxT(
"kicad_dru" ) );
2458 wxString customRules = wxT(
"(version 2)\n" );
2460 const auto& diffPairs =
m_parser->GetDiffPairs();
2462 for(
const auto& dp : diffPairs )
2464 if( dp.name.empty() || ( dp.gap <= 0 && dp.width <= 0 ) )
2467 wxString ruleName = wxString::Format( wxT(
"DiffPair_%s" ), wxString::FromUTF8( dp.name ) );
2469 if( dp.gap > 0 && !dp.positive_net.empty() && !dp.negative_net.empty() )
2474 wxString gapStr = wxString::FromUTF8(
FormatDouble2Str( gapMm ) ) + wxT(
"mm" );
2476 customRules += wxString::Format(
2477 wxT(
"\n(rule \"%s_gap\"\n" )
2478 wxT(
" (condition \"A.NetName == '%s' && B.NetName == '%s'\")\n" )
2479 wxT(
" (constraint clearance (min %s)))\n" ),
2480 ruleName, posNet, negNet, gapStr );
2484 if( customRules.length() > 15 )
2486 wxFile rulesFile( fn.GetFullPath(), wxFile::write );
2488 if( rulesFile.IsOpened() )
2489 rulesFile.Write( customRules );
2499 size_t trackCount = 0;
2500 size_t viaCount = 0;
2510 m_reporter->Report( wxString::Format(
_(
"Imported %zu footprints, %d nets, %zu tracks,"
2511 " %zu vias, %zu zones" ),
2514 trackCount, viaCount,
2521 const std::vector<INPUT_LAYER_DESC>& aInputLayerDescriptionVector )
2523 std::map<wxString, PCB_LAYER_ID> layer_map;
2527 layer_map[layer.Name] = layer.AutoMapLayer;
2537 return static_cast<int>( std::clamp<int64_t>( nm, INT_MIN, INT_MAX ) );
2546 if( aUnits ==
"I" || aUnits ==
"MIL" || aUnits ==
"MILS" )
2549 if( aUnits ==
"M" || aUnits ==
"MM" || aUnits ==
"METRIC" )
2552 if( aUnits ==
"INCH" || aUnits ==
"INCHES" )
2563 long long origin_nm =
static_cast<long long>( std::round( origin *
m_scaleFactor ) );
2564 long long val_nm =
static_cast<long long>( std::round( aVal *
m_scaleFactor ) );
2566 long long result = aIsX ? ( val_nm - origin_nm ) : ( origin_nm - val_nm );
2567 return static_cast<int>( std::clamp<long long>(
result, INT_MIN, INT_MAX ) );
2575 if(
info.padsLayerNum == aPadsLayer )
2592 if( aNetName.empty() )
2623 const std::vector<PADS_IO::ARC_POINT>& aPts )
2629 if( aPts.size() == 1 && aPts[0].is_arc
2630 &&
std::abs( aPts[0].arc.delta_angle ) >= 359.0 )
2636 constexpr int NUM_SEGS = 36;
2638 for(
int i = 0; i < NUM_SEGS; i++ )
2640 double angle = 2.0 *
M_PI * i / NUM_SEGS;
2650 for(
size_t i = 1; i < aPts.size(); i++ )
2652 const auto& pt = aPts[i];
2659 for(
int j = 1; j < arcPoly.
PointCount(); j++ )
2681 std::swap( start,
end );
2703 double dx = aCurr.
x - aPrev.
x;
2704 double dy = aCurr.
y - aPrev.
y;
2709 midX = ( aPrev.
x + aCurr.
x ) / 2.0 - dy / 2.0;
2710 midY = ( aPrev.
y + aCurr.
y ) / 2.0 + dx / 2.0;
2715 midX = ( aPrev.
x + aCurr.
x ) / 2.0 + dy / 2.0;
2716 midY = ( aPrev.
y + aCurr.
y ) / 2.0 - dx / 2.0;
2724 double startAngleRad = atan2( aPrev.
y - aCurr.
arc.
cy, aPrev.
x - aCurr.
arc.
cx );
2741 std::vector<PADS_IO::LAYER_INFO> padsLayerInfos =
m_parser->GetLayerInfos();
2767 for(
const auto& padsInfo : padsLayerInfos )
2770 info.padsLayerNum = padsInfo.number;
2771 info.name = padsInfo.name;
2776 info.type = convertLayerType( padsInfo.layer_type );
2778 std::string lowerName = padsInfo.name;
2779 std::transform( lowerName.begin(), lowerName.end(), lowerName.begin(),
2780 [](
unsigned char c ){ return std::tolower( c ); } );
2782 bool isBottom = lowerName.find(
"bottom" ) != std::string::npos
2783 || lowerName.find(
"bot" ) != std::string::npos;
2795 if( padsInfo.number == 1 )
2797 else if( padsInfo.number ==
m_parser->GetParameters().layer_count )
2806 info.required = padsInfo.required;
2810 std::vector<INPUT_LAYER_DESC> inputDescs =
2816 int copperLayerCount =
m_parser->GetParameters().layer_count;
2818 if( copperLayerCount < 1 )
2819 copperLayerCount = 2;
2821 m_loadBoard->SetCopperLayerCount( copperLayerCount );
2829 switch(
m_parser->GetParameters().units )
2851 const auto& designRules =
m_parser->GetDesignRules();
2874 if( defaultNetclass )
2876 defaultNetclass->SetClearance(
scaleSize( designRules.default_clearance ) );
2877 defaultNetclass->SetTrackWidth(
scaleSize( designRules.default_track_width ) );
2878 defaultNetclass->SetViaDiameter(
scaleSize( designRules.default_via_size ) );
2879 defaultNetclass->SetViaDrill(
scaleSize( designRules.default_via_drill ) );
2882 const auto& viaDefs =
m_parser->GetViaDefs();
2884 if( !viaDefs.empty() )
2888 const std::string& defaultViaName =
m_parser->GetParameters().default_signal_via;
2889 auto defaultIt = viaDefs.find( defaultViaName );
2891 if( defaultIt == viaDefs.end() )
2892 defaultIt = viaDefs.begin();
2894 int viaDia =
scaleSize( defaultIt->second.size );
2895 int viaDrill =
scaleSize( defaultIt->second.drill );
2900 if( defaultNetclass )
2902 defaultNetclass->SetViaDiameter( viaDia );
2903 defaultNetclass->SetViaDrill( viaDrill );
2906 for(
const auto& [
name, def] : viaDefs )
2910 const auto& netClasses =
m_parser->GetNetClasses();
2912 for(
const auto& nc : netClasses )
2914 if( nc.name.empty() )
2917 wxString ncName = wxString::FromUTF8( nc.name );
2918 std::shared_ptr<NETCLASS> netclass = std::make_shared<NETCLASS>( ncName );
2920 if( nc.clearance > 0 )
2921 netclass->SetClearance(
scaleSize( nc.clearance ) );
2923 if( nc.track_width > 0 )
2924 netclass->SetTrackWidth(
scaleSize( nc.track_width ) );
2926 if( nc.via_size > 0 )
2927 netclass->SetViaDiameter(
scaleSize( nc.via_size ) );
2929 if( nc.via_drill > 0 )
2930 netclass->SetViaDrill(
scaleSize( nc.via_drill ) );
2932 if( nc.diff_pair_width > 0 )
2933 netclass->SetDiffPairWidth(
scaleSize( nc.diff_pair_width ) );
2935 if( nc.diff_pair_gap > 0 )
2936 netclass->SetDiffPairGap(
scaleSize( nc.diff_pair_gap ) );
2940 for(
const std::string& netName : nc.net_names )
2947 const auto& diffPairs =
m_parser->GetDiffPairs();
2949 for(
const auto& dp : diffPairs )
2951 if( dp.name.empty() )
2954 wxString dpClassName =
2955 wxString::Format( wxT(
"DiffPair_%s" ), wxString::FromUTF8( dp.name ) );
2956 std::shared_ptr<NETCLASS> dpNetclass = std::make_shared<NETCLASS>( dpClassName );
2959 dpNetclass->SetDiffPairGap(
scaleSize( dp.gap ) );
2963 dpNetclass->SetDiffPairWidth(
scaleSize( dp.width ) );
2964 dpNetclass->SetTrackWidth(
scaleSize( dp.width ) );
2969 if( !dp.positive_net.empty() )
2975 if( !dp.negative_net.empty() )
2985 const auto& boardOutlines =
m_parser->GetBoardOutlines();
2987 if( !boardOutlines.empty() )
2989 double min_x = std::numeric_limits<double>::max();
2990 double max_x = std::numeric_limits<double>::lowest();
2991 double min_y = std::numeric_limits<double>::max();
2992 double max_y = std::numeric_limits<double>::lowest();
2994 for(
const auto& outline : boardOutlines )
2996 for(
const auto& pt : outline.points )
2998 min_x = std::min( min_x, pt.x );
2999 max_x = std::max( max_x, pt.x );
3000 min_y = std::min( min_y, pt.y );
3001 max_y = std::max( max_y, pt.y );
3005 if( min_x < max_x && min_y < max_y )
3014 std::vector<const PADS_IO::LAYER_INFO*> copperLayerInfos;
3016 for(
const auto& li : padsLayerInfos )
3019 copperLayerInfos.push_back( &li );
3022 bool hasStackupData =
false;
3024 for(
const auto* li : copperLayerInfos )
3026 if( li->layer_thickness > 0.0 || li->dielectric_constant > 0.0 )
3028 hasStackupData =
true;
3033 if( hasStackupData )
3040 std::map<PCB_LAYER_ID, const PADS_IO::LAYER_INFO*> copperInfoMap;
3042 for(
const auto* li : copperLayerInfos )
3047 copperInfoMap[kicadLayer] = li;
3057 auto it = copperInfoMap.find( item->GetBrdLayerId() );
3059 if( it != copperInfoMap.end() )
3061 prevCopperInfo = it->second;
3063 if( it->second->copper_thickness > 0.0 )
3064 item->SetThickness(
scaleSize( it->second->copper_thickness ) );
3069 if( prevCopperInfo )
3080 item->SetColor( wxT(
"White" ) );
3084 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)
bool chamfered
True if corners are chamfered (negative corner in PADS)
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 thermal_outer_diameter
Outer diameter of thermal or void in plane.
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