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 )
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 =
345 [&](
double val,
bool is_x )
359 long long origin_nm =
static_cast<long long>( std::round( origin *
m_scaleFactor ) );
360 long long val_nm =
static_cast<long long>( std::round( val * part_factor ) );
362 long long res_nm = val_nm - origin_nm;
367 return static_cast<int>( std::clamp<long long>( res_nm, INT_MIN, INT_MAX ) );
371 partCoordScaler( pads_part.location.y,
false ) ) );
385 auto ptIt = part_types.find( pads_part.decal );
387 if( ptIt != part_types.end() )
388 partType = &ptIt->second;
390 const std::map<std::string, std::string>* instanceAttrs =
nullptr;
391 auto iaIt = partInstanceAttrs.find( pads_part.name );
393 if( iaIt != partInstanceAttrs.end() )
394 instanceAttrs = &iaIt->second;
396 auto applyAttributes =
397 [&](
const std::vector<PADS_IO::ATTRIBUTE>& attrs, std::function<int(
double)> scaler )
399 for(
const auto& attr : attrs )
402 bool ownsField =
false;
404 if( attr.name ==
"Ref.Des." )
408 else if( attr.name ==
"Part Type" || attr.name ==
"VALUE" )
410 field = &footprint->
Value();
414 std::string attrValue;
418 auto valIt = instanceAttrs->find( attr.name );
420 if( valIt != instanceAttrs->end() )
421 attrValue = valIt->second;
424 if( attrValue.empty() && partType )
426 auto valIt = partType->
attributes.find( attr.name );
429 attrValue = valIt->second;
432 if( !attrValue.empty() )
435 wxString::FromUTF8( attr.name ) );
436 field->
SetText( wxString::FromUTF8( attrValue ) );
455 int scaledSize = scaler( attr.height );
467 VECTOR2I offset( scaler( attr.x ), -scaler( attr.y ) );
483 if( attr.hjust ==
"LEFT" )
485 else if( attr.hjust ==
"RIGHT" )
490 if( attr.vjust ==
"UP" )
492 else if( attr.vjust ==
"DOWN" )
498 footprint->
Add( field );
502 auto decal_it = decals.find( decal_name );
504 double decalScale = ( decal_it != decals.end() ) ?
decalUnitScale( decal_it->second.units )
508 [&, decalScale](
double val )
513 if( decal_it != decals.end() )
515 applyAttributes( decal_it->second.attributes, decalScaler );
521 m_reporter->Report( wxString::Format(
_(
"Footprint '%s' not found in decal list, part skipped" ),
532 if( pads_part.units ==
"M" )
536 if( pads_part.units ==
"M" )
542 applyAttributes( pads_part.attributes, partScaler );
557 blockField->
SetText( wxString::FromUTF8( blockIt->second ) );
558 footprint->
Add( blockField );
561 if( decal_it == decals.end() )
571 auto applyCornerRadius =
573 const VECTOR2I& aSize,
bool aDefaultRound )
577 int min_dim = std::min( aSize.x, aSize.y );
579 double ratio = ( min_dim > 0 ) ? std::min(
radius / min_dim, 0.5 ) : 0.25;
584 pad->SetRoundRectRadiusRatio( kicad_layer, 0.0 );
585 pad->SetChamferRectRatio( kicad_layer, ratio );
591 pad->SetRoundRectRadiusRatio( kicad_layer, ratio );
594 else if( aDefaultRound )
597 pad->SetRoundRectRadiusRatio( kicad_layer, 0.25 );
605 auto convertPadShape =
608 const std::string& shape = layer_def.
shape;
613 if( shape ==
"R" || shape ==
"C" || shape ==
"A" || shape ==
"RT" )
618 else if( shape ==
"S" || shape ==
"ST" )
622 int side = ( layer_def.
sizeB > 0 ) ? size.
x : size.
y;
624 applyCornerRadius( layer_def,
pad, kicad_layer, sq_size,
false );
625 pad->SetSize( kicad_layer, sq_size );
627 else if( shape ==
"O" || shape ==
"OT" )
630 pad->SetSize( kicad_layer, size );
632 else if( shape ==
"RF" )
634 applyCornerRadius( layer_def,
pad, kicad_layer, size,
false );
635 pad->SetSize( kicad_layer, size );
637 else if( shape ==
"OF" )
640 pad->SetSize( kicad_layer, size );
642 else if( shape ==
"RC" || shape ==
"OC" )
644 applyCornerRadius( layer_def,
pad, kicad_layer, size,
true );
645 pad->SetSize( kicad_layer, size );
665 for(
size_t term_idx = 0; term_idx < decal.
terminals.size(); ++term_idx )
667 const auto& term = decal.
terminals[term_idx];
671 pad->SetNumber( term.name );
673 VECTOR2I pad_pos( decalScaler( term.x ), -decalScaler( term.y ) );
679 int pin_num =
static_cast<int>( term_idx + 1 );
681 auto stack_it = decal.
pad_stacks.find( pin_num );
686 if( stack_it != decal.
pad_stacks.end() && !stack_it->second.empty() )
688 const std::vector<PADS_IO::PAD_STACK_LAYER>& stack = stack_it->second;
692 double slot_length = 0.0;
693 double slot_orientation = 0.0;
694 double pad_rotation = 0.0;
696 for(
const auto& layer_def : stack )
698 if( layer_def.
drill > 0 )
700 drill = layer_def.
drill;
701 plated = layer_def.
plated;
714 if( pads_layer == -2 || pads_layer == 1 )
718 else if( pads_layer == -1 || pads_layer ==
m_parser->GetParameters().layer_count )
722 else if( pads_layer > 1 && pads_layer < m_parser->GetParameters().layer_count )
724 int inner_idx = pads_layer - 2;
726 if( inner_idx >= 0 && inner_idx < 30 )
733 bool has_explicit_layers =
false;
735 for(
const auto& layer_def : stack )
737 if( layer_def.
layer == -2 || layer_def.
layer == -1
738 || layer_def.
layer == 1
739 || layer_def.
layer ==
m_parser->GetParameters().layer_count )
741 has_explicit_layers =
true;
749 double shape_rotation = 0.0;
750 bool shape_rotation_set =
false;
752 auto convertGeometry =
755 convertPadShape( aLayerDef,
pad, aKicadLayer );
757 if( !shape_rotation_set )
759 shape_rotation = aLayerDef.
rotation;
760 shape_rotation_set =
true;
767 LSET explicitly_seen_tech;
769 for(
const auto& layer_def : stack )
771 if( layer_def.
layer > 0 )
776 explicitly_seen_tech.
set( check );
787 if( has_explicit_layers )
797 +
"|" + std::to_string( aLayerDef.
chamfered );
800 std::string front_shape;
801 std::string back_shape;
803 for(
const auto& layer_def : stack )
805 if( layer_def.
sizeA <= 0 )
808 if( layer_def.
shape ==
"RT" || layer_def.
shape ==
"ST"
809 || layer_def.
shape ==
"RA" || layer_def.
shape ==
"SA" )
816 if( mapped ==
F_Cu && front_shape.empty() )
817 front_shape = shapeKey( layer_def );
818 else if( mapped ==
B_Cu && back_shape.empty() )
819 back_shape = shapeKey( layer_def );
827 if( !front_shape.empty() && !back_shape.empty()
828 && front_shape != back_shape )
838 bool normal_copper_set =
false;
840 for(
const auto& layer_def : stack )
842 if( layer_def.
layer == 0 )
844 if( !has_explicit_layers )
848 convertGeometry( layer_def,
F_Cu );
863 if( layer_def.
sizeA <= 0 )
872 if( layer_def.
shape ==
"RT" || layer_def.
shape ==
"ST" )
882 int scaledGap = decalScaler( gap );
887 pad->SetLocalThermalGapOverride( scaledGap );
892 pad->SetThermalSpokeAngleDegrees(
899 if( layer_def.
shape ==
"RA" || layer_def.
shape ==
"SA" )
916 layer_set.
set( tech_layer );
921 layer_set.
set( kicad_layer );
936 convertGeometry( layer_def, kicad_layer );
939 normal_copper_set =
true;
943 if( layer_set.none() )
946 convertGeometry( stack[0],
F_Cu );
959 if( layer_set.test(
F_Cu ) && !layer_set.test(
F_Mask )
960 && !explicitly_seen_tech.test(
F_Mask ) )
965 if( layer_set.test(
F_Cu ) && !layer_set.test(
F_Paste )
966 && !explicitly_seen_tech.test(
F_Paste ) )
971 if( layer_set.test(
B_Cu ) && !layer_set.test(
B_Mask )
972 && !explicitly_seen_tech.test(
B_Mask ) )
977 if( layer_set.test(
B_Cu ) && !layer_set.test(
B_Paste )
978 && !explicitly_seen_tech.test(
B_Paste ) )
984 if( slot_length > 0 && slot_length != drill )
988 int drillMinor = decalScaler( drill );
989 int drillMajor = decalScaler( slot_length );
994 double relAngle = slot_orientation - pad_rotation;
996 relAngle = fmod( relAngle, 360.0 );
1001 bool vertical = ( relAngle > 45.0 && relAngle < 135.0 )
1002 || ( relAngle > 225.0 && relAngle < 315.0 );
1005 pad->SetDrillSize(
VECTOR2I( drillMinor, drillMajor ) );
1007 pad->SetDrillSize(
VECTOR2I( drillMajor, drillMinor ) );
1011 pad->SetDrillSize(
VECTOR2I( decalScaler( drill ), decalScaler( drill ) ) );
1031 pad->SetLayerSet( layer_set );
1042 std::string pinKey = pads_part.name +
"." + term.name;
1054 for(
const auto& item : decal.
items )
1056 if( item.points.empty() )
1063 if( item.layer == 0 )
1073 if( mapped_layer ==
B_Cu )
1080 shape_layer = mapped_layer;
1088 m_reporter->Report( wxString::Format(
_(
"Skipping decal item on unmapped layer %d" ),
1095 bool is_circle = ( item.type ==
"CIRCLE" );
1096 bool is_closed = ( item.type ==
"CLOSED" || is_circle );
1100 if( is_circle && item.points.size() >= 2 )
1105 double x1 = item.points[0].x;
1106 double y1 = item.points[0].y;
1107 double x2 = item.points[1].x;
1108 double y2 = item.points[1].y;
1110 double cx = ( x1 + x2 ) / 2.0;
1111 double cy = ( y1 + y2 ) / 2.0;
1113 double radius = std::sqrt( ( x2 - x1 ) * ( x2 - x1 )
1114 + ( y2 - y1 ) * ( y2 - y1 ) )
1126 shape->
SetEnd( fp_pos + pt_on_circle );
1129 footprint->
Add( shape );
1134 if( item.points.size() < 2 )
1137 for(
size_t i = 0; i < item.points.size() - 1; ++i )
1150 VECTOR2I start( decalScaler( p1.
x ), -decalScaler( p1.
y ) );
1155 std::swap( start,
end );
1169 VECTOR2I start( decalScaler( p1.
x ), -decalScaler( p1.
y ) );
1180 footprint->
Add( shape );
1183 if( is_closed && item.points.size() > 2 )
1196 VECTOR2I start( decalScaler( pLast.
x ), -decalScaler( pLast.
y ) );
1197 VECTOR2I end( decalScaler( pFirst.
x ), -decalScaler( pFirst.
y ) );
1200 std::swap( start,
end );
1214 VECTOR2I start( decalScaler( pLast.
x ), -decalScaler( pLast.
y ) );
1215 VECTOR2I end( decalScaler( pFirst.
x ), -decalScaler( pFirst.
y ) );
1225 footprint->
Add( shape );
1230 if( pads_part.bottom_layer )
1238 const auto& reuse_blocks =
m_parser->GetReuseBlocks();
1240 if( reuse_blocks.empty() )
1243 std::map<std::string, PCB_GROUP*> blockGroups;
1245 for(
const auto& [blockName, block] : reuse_blocks )
1247 if( !block.instances.empty() || !block.part_names.empty() )
1250 group->SetName( wxString::FromUTF8( blockName ) );
1252 blockGroups[blockName] =
group;
1258 for(
PCB_FIELD* field : fp->GetFields() )
1260 if( field->GetName() == wxT(
"PADS_Reuse_Block" ) )
1262 std::string blockName = field->GetText().ToStdString();
1263 auto groupIt = blockGroups.find( blockName );
1265 if( groupIt != blockGroups.end() )
1266 groupIt->second->AddItem( fp );
1277 const auto& test_points =
m_parser->GetTestPoints();
1278 const auto& via_defs =
m_parser->GetViaDefs();
1280 for(
const auto&
tp : test_points )
1286 footprint->
SetValue( wxString::FromUTF8(
tp.symbol_name ) );
1295 auto it = via_defs.find(
tp.symbol_name );
1297 if( it != via_defs.end() )
1307 double stackSize = def.
size;
1308 bool hasTopPad =
false;
1309 bool hasBottomPad =
false;
1310 bool hasMaskTop =
false;
1311 bool hasMaskBot =
false;
1313 for(
const auto& stackLayer : def.
stack )
1315 if( def.
size <= 0.0 && stackLayer.sizeA > stackSize )
1316 stackSize = stackLayer.sizeA;
1319 && stackLayer.sizeA > 0.0 )
1324 && stackLayer.sizeA > 0.0 )
1326 hasBottomPad =
true;
1338 if( stackSize > 0.0 )
1341 if( hasTopPad && !hasBottomPad )
1343 else if( hasBottomPad && !hasTopPad )
1345 else if( hasMaskBot && !hasMaskTop )
1347 else if( hasMaskTop && !hasMaskBot )
1354 pad->SetNumber( wxT(
"1" ) );
1355 pad->SetPosition( pos );
1361 if( !
tp.net_name.empty() )
1376 tpField->
SetText( wxString::FromUTF8(
tp.type ) );
1377 footprint->
Add( tpField );
1386 const auto& texts =
m_parser->GetTexts();
1388 for(
const auto& pads_text : texts )
1396 m_reporter->Report( wxString::Format(
_(
"Text on unmapped layer %d assigned to Comments layer" ),
1409 int scaledSize =
scaleSize( pads_text.height );
1412 text->SetTextSize(
VECTOR2I( charWidth, charHeight ) );
1414 if( pads_text.width > 0 )
1418 text->SetTextAngle( textAngle );
1425 text->SetPosition( pos + textShift );
1427 if( pads_text.hjust ==
"LEFT" )
1429 else if( pads_text.hjust ==
"RIGHT" )
1434 if( pads_text.vjust ==
"UP" )
1436 else if( pads_text.vjust ==
"DOWN" )
1441 text->SetKeepUpright(
false );
1442 text->SetLayer( textLayer );
1445 text->SetMirrored( pads_text.mirrored );
1454 const auto& routes =
m_parser->GetRoutes();
1455 std::set<std::pair<int, int>> placedThroughVias;
1459 std::set<std::pair<int, int>> testPointPositions;
1461 for(
const auto&
tp :
m_parser->GetTestPoints() )
1463 if(
tp.type ==
"VIA" )
1467 for(
const auto& route : routes )
1474 for(
const auto& track_def : route.tracks )
1476 if( track_def.points.size() < 2 )
1485 m_reporter->Report( wxString::Format(
_(
"Skipping track on non-copper layer %d" ),
1495 for(
size_t i = 0; i < track_def.points.size() - 1; ++i )
1506 if( ( start -
end ).EuclideanNorm() < 1000 )
1532 for(
const auto& via_def : route.vias )
1537 if( testPointPositions.count( { pos.x, pos.y } ) )
1541 auto it =
m_parser->GetViaDefs().find( via_def.name );
1543 if( it !=
m_parser->GetViaDefs().end() )
1545 switch( it->second.via_type )
1558 auto key = std::make_pair( pos.
x, pos.
y );
1560 if( placedThroughVias.count( key ) )
1563 placedThroughVias.insert( key );
1568 via->SetPosition( pos );
1570 if( it !=
m_parser->GetViaDefs().end() )
1584 via->SetLayerPair( startLayer, endLayer );
1585 via->SetViaType( viaType );
1615 const auto& copperShapes =
m_parser->GetCopperShapes();
1619 auto isRectCandidate =
1622 return cs.outline.size() == 2 && !cs.outline[1].is_arc
1623 && !cs.filled && !cs.is_cutout;
1629 auto tryFormRectangle =
1632 if( idx + 3 >= copperShapes.size() )
1635 const auto& c0 = copperShapes[idx];
1636 const auto& c1 = copperShapes[idx + 1];
1637 const auto& c2 = copperShapes[idx + 2];
1638 const auto& c3 = copperShapes[idx + 3];
1640 if( !isRectCandidate( c0 ) || !isRectCandidate( c1 )
1641 || !isRectCandidate( c2 ) || !isRectCandidate( c3 ) )
1646 if( c1.net_name != c0.net_name || c2.net_name != c0.net_name || c3.net_name != c0.net_name )
1649 if( c1.layer != c0.layer || c2.layer != c0.layer || c3.layer != c0.layer )
1656 for(
int i = 0; i < 4; ++i )
1659 scaleCoord( segs[i]->outline[0].y,
false ) );
1661 scaleCoord( segs[i]->outline[1].y,
false ) );
1665 for(
int i = 0; i < 4; ++i )
1670 if( s.
x != e.
x && s.
y != e.
y )
1675 for(
int i = 0; i < 3; ++i )
1677 if( pts[i * 2 + 1] != pts[( i + 1 ) * 2] )
1682 if( pts[7] != pts[0] )
1686 int minX = pts[0].
x, maxX = pts[0].
x;
1687 int minY = pts[0].
y, maxY = pts[0].
y;
1689 for(
int i = 0; i < 8; ++i )
1691 minX = std::min( minX, pts[i].x );
1692 maxX = std::max( maxX, pts[i].x );
1693 minY = std::min( minY, pts[i].y );
1694 maxY = std::max( maxY, pts[i].y );
1697 minCorner =
VECTOR2I( minX, minY );
1698 maxCorner =
VECTOR2I( maxX, maxY );
1702 for(
size_t idx = 0; idx < copperShapes.size(); ++idx )
1704 const auto& copper = copperShapes[idx];
1706 if( copper.outline.size() < 2 )
1709 if( copper.is_cutout )
1718 m_reporter->Report( wxString::Format(
_(
"COPPER item on unmapped layer %d defaulting to F.Cu" ),
1733 if( tryFormRectangle( idx, minCorner, maxCorner ) )
1738 rect->
SetEnd( maxCorner );
1750 for(
size_t i = 0; i < copper.outline.size() - 1; ++i )
1752 const auto& p1 = copper.outline[i];
1753 const auto& p2 = copper.outline[i + 1];
1758 if( ( start -
end ).EuclideanNorm() < 1000 )
1784 if( !copper.net_name.empty() )
1789 if( copper.outline.size() < 3 )
1809 for(
size_t i = 0; i < copper.outline.size() - 1; ++i )
1811 const auto& p1 = copper.outline[i];
1812 const auto& p2 = copper.outline[i + 1];
1817 if( ( start -
end ).EuclideanNorm() < 1000 )
1854 const auto& clusters =
m_parser->GetClusters();
1856 if( clusters.empty() )
1859 std::map<std::string, const PADS_IO::CLUSTER*> netToClusterMap;
1861 for(
const auto& cluster : clusters )
1863 for(
const std::string& netName : cluster.net_names )
1866 netToClusterMap[converted] = &cluster;
1870 std::map<int, PCB_GROUP*> clusterGroups;
1872 for(
const auto& cluster : clusters )
1875 group->SetName( wxString::FromUTF8( cluster.name ) );
1877 clusterGroups[cluster.id] =
group;
1886 std::string netName = net->
GetNetname().ToStdString();
1887 auto clusterIt = netToClusterMap.find( netName );
1889 if( clusterIt != netToClusterMap.end() )
1891 int clusterId = clusterIt->second->id;
1892 auto groupIt = clusterGroups.find( clusterId );
1894 if( groupIt != clusterGroups.end() )
1895 groupIt->second->AddItem( track );
1904 const auto& pours =
m_parser->GetPours();
1905 const auto& params =
m_parser->GetParameters();
1910 [](
const std::vector<PADS_IO::ARC_POINT>& pts )
1912 if( pts.size() >= 3 )
1915 if( pts.size() == 1 && pts[0].is_arc &&
std::abs( pts[0].arc.delta_angle ) >= 359.0 )
1923 int maxPriority = 0;
1925 for(
const auto& pour_def : pours )
1927 if( pour_def.priority > maxPriority )
1928 maxPriority = pour_def.priority;
1932 std::map<std::string, ZONE*> pourZoneMap;
1935 std::map<std::string, std::string> hatoutToParent;
1938 for(
const auto& pour_def : pours )
1942 hatoutToParent[pour_def.name] = pour_def.owner_pour;
1952 if( pour_def.points.size() < 3 )
1961 m_reporter->Report( wxString::Format(
_(
"Skipping pour on unmapped layer %d" ), pour_def.layer ),
1975 if( pour_def.is_cutout )
1983 zone->
SetZoneName( wxString::Format( wxT(
"Cutout_%s" ), pour_def.owner_pour ) );
1992 int kicadPriority = maxPriority - pour_def.priority + 1;
2002 pourZoneMap[pour_def.name] = zone;
2007 for(
const auto& pour_def : pours )
2012 if( !isValidPoly( pour_def.points ) )
2015 auto zoneIt = pourZoneMap.find( pour_def.owner_pour );
2017 if( zoneIt == pourZoneMap.end() )
2020 ZONE* zone = zoneIt->second;
2044 for(
const auto& void_def : pours )
2049 if( !isValidPoly( void_def.points ) )
2054 auto parentIt = hatoutToParent.find( void_def.owner_pour );
2056 if( parentIt == hatoutToParent.end() )
2059 if( parentIt->second != pour_def.owner_pour )
2067 allVoids.
Append( voidPoly );
2083 const auto& pts = polyline.points;
2085 if( pts.size() < 2 )
2088 for(
size_t i = 0; i < pts.size() - 1; ++i )
2116 if( polyline.closed && pts.size() > 2 )
2121 bool needsClosing = (
std::abs( pLast.
x - pFirst.
x ) > 0.001
2150 const auto& dimensions =
m_parser->GetDimensions();
2152 for(
const auto& dim : dimensions )
2154 if( dim.points.size() < 2 )
2166 if( dim.is_horizontal )
2176 if( dim.is_horizontal )
2178 double heightOffset = dim.crossbar_pos - dim.points[0].y;
2179 int height = -
scaleSize( heightOffset );
2184 double heightOffset = dim.crossbar_pos - dim.points[0].x;
2198 if( dim.text_height > 0 )
2200 int scaledSize =
scaleSize( dim.text_height );
2205 if( dim.text_width > 0 )
2209 if( !dim.text.empty() )
2217 if( dim.rotation != 0.0 )
2228 const auto& keepouts =
m_parser->GetKeepouts();
2229 int keepoutIndex = 0;
2231 for(
const auto& ko : keepouts )
2233 if( ko.outline.size() < 3 )
2239 if( ko.layers.empty() )
2243 else if( ko.layers.size() == 1 )
2251 m_reporter->Report( wxString::Format(
_(
"Skipping keepout on unmapped layer %d" ), ko.layers[0] ),
2265 for(
int layer : ko.layers )
2270 layerSet.
set( mappedLayer );
2273 if( layerSet.none() )
2302 zone->
SetZoneName( wxString::Format( wxT(
"%s_%d" ), typeName, ++keepoutIndex ) );
2308 if( ko.outline.size() > 2 )
2310 const auto& first = ko.outline.front();
2311 const auto& last = ko.outline.back();
2313 if(
std::abs( first.x - last.x ) > 0.001 ||
std::abs( first.y - last.y ) > 0.001 )
2330 const auto& pts = graphic.points;
2337 if( pts.size() == 1 && pts[0].is_arc &&
std::abs( pts[0].arc.delta_angle - 360.0 ) < 0.1 )
2351 if( pts.size() < 2 )
2354 for(
size_t i = 0; i < pts.size() - 1; ++i )
2380 if( graphic.closed && pts.size() > 2 )
2385 bool needsClosing = (
std::abs( pLast.
x - pFirst.
x ) > 0.001
2414 wxFileName fn( aFileName );
2415 fn.SetExt( wxT(
"kicad_dru" ) );
2417 wxString customRules = wxT(
"(version 2)\n" );
2419 const auto& diffPairs =
m_parser->GetDiffPairs();
2421 for(
const auto& dp : diffPairs )
2423 if( dp.name.empty() || ( dp.gap <= 0 && dp.width <= 0 ) )
2426 wxString ruleName = wxString::Format( wxT(
"DiffPair_%s" ), wxString::FromUTF8( dp.name ) );
2428 if( dp.gap > 0 && !dp.positive_net.empty() && !dp.negative_net.empty() )
2433 wxString gapStr = wxString::FromUTF8(
FormatDouble2Str( gapMm ) ) + wxT(
"mm" );
2435 customRules += wxString::Format( wxT(
"\n(rule \"%s_gap\"\n "
2436 "(condition \"A.NetName == '%s' && B.NetName == '%s'\")\n "
2437 "(constraint clearance (min %s)))\n" ),
2445 if( customRules.length() > 15 )
2447 wxFile rulesFile( fn.GetFullPath(), wxFile::write );
2449 if( rulesFile.IsOpened() )
2450 rulesFile.Write( customRules );
2460 size_t trackCount = 0;
2461 size_t viaCount = 0;
2471 m_reporter->Report( wxString::Format(
_(
"Imported %zu footprints, %d nets, %zu tracks, %zu vias, %zu zones" ),
2474 trackCount, viaCount,
2481 const std::vector<INPUT_LAYER_DESC>& aInputLayerDescriptionVector )
2483 std::map<wxString, PCB_LAYER_ID> layer_map;
2486 layer_map[layer.Name] = layer.AutoMapLayer;
2495 return static_cast<int>( std::clamp<int64_t>( nm, INT_MIN, INT_MAX ) );
2504 if( aUnits ==
"I" || aUnits ==
"MIL" || aUnits ==
"MILS" )
2507 if( aUnits ==
"M" || aUnits ==
"MM" || aUnits ==
"METRIC" )
2510 if( aUnits ==
"INCH" || aUnits ==
"INCHES" )
2521 long long origin_nm =
static_cast<long long>( std::round( origin *
m_scaleFactor ) );
2522 long long val_nm =
static_cast<long long>( std::round( aVal *
m_scaleFactor ) );
2524 long long result = aIsX ? ( val_nm - origin_nm ) : ( origin_nm - val_nm );
2525 return static_cast<int>( std::clamp<long long>(
result, INT_MIN, INT_MAX ) );
2533 if(
info.padsLayerNum == aPadsLayer )
2550 if( aNetName.empty() )
2585 if( aPts.size() == 1 && aPts[0].is_arc &&
std::abs( aPts[0].arc.delta_angle ) >= 359.0 )
2590 constexpr int NUM_SEGS = 36;
2592 for(
int i = 0; i < NUM_SEGS; i++ )
2594 double angle = 2.0 *
M_PI * i / NUM_SEGS;
2604 for(
size_t i = 1; i < aPts.size(); i++ )
2613 for(
int j = 1; j < arcPoly.
PointCount(); j++ )
2635 std::swap( start,
end );
2657 double dx = aCurr.
x - aPrev.
x;
2658 double dy = aCurr.
y - aPrev.
y;
2663 midX = ( aPrev.
x + aCurr.
x ) / 2.0 - dy / 2.0;
2664 midY = ( aPrev.
y + aCurr.
y ) / 2.0 + dx / 2.0;
2669 midX = ( aPrev.
x + aCurr.
x ) / 2.0 + dy / 2.0;
2670 midY = ( aPrev.
y + aCurr.
y ) / 2.0 - dx / 2.0;
2678 double startAngleRad = atan2( aPrev.
y - aCurr.
arc.
cy, aPrev.
x - aCurr.
arc.
cx );
2695 std::vector<PADS_IO::LAYER_INFO> padsLayerInfos =
m_parser->GetLayerInfos();
2697 auto convertLayerType =
2726 info.padsLayerNum = padsInfo.number;
2727 info.name = padsInfo.name;
2732 info.type = convertLayerType( padsInfo.layer_type );
2734 std::string lowerName = padsInfo.name;
2735 std::transform( lowerName.begin(), lowerName.end(), lowerName.begin(),
2736 [](
unsigned char c )
2738 return std::tolower( c );
2741 bool isBottom = lowerName.find(
"bottom" ) != std::string::npos
2742 || lowerName.find(
"bot" ) != std::string::npos;
2754 if( padsInfo.number == 1 )
2756 else if( padsInfo.number ==
m_parser->GetParameters().layer_count )
2765 info.required = padsInfo.required;
2774 int copperLayerCount =
m_parser->GetParameters().layer_count;
2776 if( copperLayerCount < 1 )
2777 copperLayerCount = 2;
2779 m_loadBoard->SetCopperLayerCount( copperLayerCount );
2787 switch(
m_parser->GetParameters().units )
2826 if( defaultNetclass )
2834 const std::map<std::string, PADS_IO::VIA_DEF>& viaDefs =
m_parser->GetViaDefs();
2836 if( !viaDefs.empty() )
2840 const std::string& defaultViaName =
m_parser->GetParameters().default_signal_via;
2841 auto defaultIt = viaDefs.find( defaultViaName );
2843 if( defaultIt == viaDefs.end() )
2844 defaultIt = viaDefs.begin();
2846 int viaDia =
scaleSize( defaultIt->second.size );
2847 int viaDrill =
scaleSize( defaultIt->second.drill );
2852 if( defaultNetclass )
2854 defaultNetclass->SetViaDiameter( viaDia );
2855 defaultNetclass->SetViaDrill( viaDrill );
2858 for(
const auto& [
name, def] : viaDefs )
2862 const std::vector<PADS_IO::NET_CLASS_DEF>& netClasses =
m_parser->GetNetClasses();
2866 if( nc.name.empty() )
2869 wxString ncName = wxString::FromUTF8( nc.name );
2870 std::shared_ptr<NETCLASS> netclass = std::make_shared<NETCLASS>( ncName );
2872 if( nc.clearance > 0 )
2873 netclass->SetClearance(
scaleSize( nc.clearance ) );
2875 if( nc.track_width > 0 )
2876 netclass->SetTrackWidth(
scaleSize( nc.track_width ) );
2878 if( nc.via_size > 0 )
2879 netclass->SetViaDiameter(
scaleSize( nc.via_size ) );
2881 if( nc.via_drill > 0 )
2882 netclass->SetViaDrill(
scaleSize( nc.via_drill ) );
2884 if( nc.diff_pair_width > 0 )
2885 netclass->SetDiffPairWidth(
scaleSize( nc.diff_pair_width ) );
2887 if( nc.diff_pair_gap > 0 )
2888 netclass->SetDiffPairGap(
scaleSize( nc.diff_pair_gap ) );
2892 for(
const std::string& netName : nc.net_names )
2899 const std::vector<PADS_IO::DIFF_PAIR_DEF>& diffPairs =
m_parser->GetDiffPairs();
2903 if( dp.name.empty() )
2906 wxString dpClassName = wxString::Format( wxT(
"DiffPair_%s" ), wxString::FromUTF8( dp.name ) );
2907 std::shared_ptr<NETCLASS> dpNetclass = std::make_shared<NETCLASS>( dpClassName );
2910 dpNetclass->SetDiffPairGap(
scaleSize( dp.gap ) );
2914 dpNetclass->SetDiffPairWidth(
scaleSize( dp.width ) );
2915 dpNetclass->SetTrackWidth(
scaleSize( dp.width ) );
2920 if( !dp.positive_net.empty() )
2926 if( !dp.negative_net.empty() )
2936 const std::vector<PADS_IO::POLYLINE>& boardOutlines =
m_parser->GetBoardOutlines();
2938 if( !boardOutlines.empty() )
2940 double min_x = std::numeric_limits<double>::max();
2941 double max_x = std::numeric_limits<double>::lowest();
2942 double min_y = std::numeric_limits<double>::max();
2943 double max_y = std::numeric_limits<double>::lowest();
2949 min_x = std::min( min_x, pt.
x );
2950 max_x = std::max( max_x, pt.
x );
2951 min_y = std::min( min_y, pt.
y );
2952 max_y = std::max( max_y, pt.
y );
2956 if( min_x < max_x && min_y < max_y )
2965 std::vector<const PADS_IO::LAYER_INFO*> copperLayerInfos;
2970 copperLayerInfos.push_back( &li );
2973 bool hasStackupData =
false;
2977 if( li->layer_thickness > 0.0 || li->dielectric_constant > 0.0 )
2979 hasStackupData =
true;
2984 if( hasStackupData )
2991 std::map<PCB_LAYER_ID, const PADS_IO::LAYER_INFO*> copperInfoMap;
2998 copperInfoMap[kicadLayer] = li;
3008 auto it = copperInfoMap.find( item->GetBrdLayerId() );
3010 if( it != copperInfoMap.end() )
3012 prevCopperInfo = it->second;
3014 if( it->second->copper_thickness > 0.0 )
3015 item->SetThickness(
scaleSize( it->second->copper_thickness ) );
3020 if( prevCopperInfo )
3031 item->SetColor( wxT(
"White" ) );
3035 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_ERRORF(msg,...)
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).
Design rule definitions from PCB section.
double silk_clearance
Minimum silkscreen clearance (SILKCLEAR)
double default_track_width
Default track width (DEFAULTTRACKWID)
double default_via_drill
Default via drill diameter (DEFAULTVIADRILL)
double min_track_width
Minimum track width (MINTRACKWID)
double min_via_size
Minimum via outer diameter (MINVIASIZE)
double min_via_drill
Minimum via drill diameter (MINVIADRILL)
double min_clearance
Minimum copper clearance (MINCLEAR)
double default_via_size
Default via outer diameter (DEFAULTVIASIZE)
double copper_edge_clearance
Board outline clearance (OUTLINE_TO_*)
double default_clearance
Default copper clearance (DEFAULTCLEAR)
double hole_to_hole
Minimum hole-to-hole spacing (HOLEHOLE)
double mask_clearance
Solder mask clearance (MASKCLEAR)
Differential pair definition.
A 2D graphic line/shape from the LINES section (type=LINES).
double layer_thickness
Dielectric thickness (BASIC units)
double dielectric_constant
Relative permittivity (Er)
Net class definition with routing constraints.
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