46#include <wx/filename.h>
104 std::ifstream file( aFileName.fn_str() );
106 if( !file.is_open() )
111 if( std::getline( file, line ) )
113 if( line.find(
"!PADS-" ) != std::string::npos )
122 const std::map<std::string, UTF8>* aProperties,
PROJECT* aProject )
126 std::unique_ptr<BOARD> board( aAppendToMe ? aAppendToMe :
new BOARD() );
138 parser.
Parse( aFileName );
140 catch(
const std::exception& e )
142 THROW_IO_ERROR( wxString::Format(
"Error parsing PADS file: %s", e.what() ) );
187 return board.release();
193 const auto& nets =
m_parser->GetNets();
195 for(
const auto& pads_net : nets )
198 for(
const auto& pads_net : nets )
200 for(
const auto&
pin : pads_net.pins )
202 std::string key =
pin.ref_des +
"." +
pin.pin_name;
207 const auto& route_nets =
m_parser->GetRoutes();
209 for(
const auto& route : route_nets )
211 for(
const auto&
pin : route.pins )
213 std::string key =
pin.ref_des +
"." +
pin.pin_name;
220 for(
const auto& route : route_nets )
223 for(
const auto& pour_def :
m_parser->GetPours() )
226 for(
const auto& copper :
m_parser->GetCopperShapes() )
232 const auto& reuse_blocks =
m_parser->GetReuseBlocks();
234 for(
const auto& [blockName, block] : reuse_blocks )
236 for(
const std::string& partName : block.part_names )
246 const auto& decals =
m_parser->GetPartDecals();
247 const auto& part_types =
m_parser->GetPartTypes();
248 const auto& partInstanceAttrs =
m_parser->GetPartInstanceAttrs();
249 const auto& parts =
m_parser->GetParts();
251 for(
const auto& pads_part : parts )
260 path.push_back( symbolUuid );
264 std::string decal_name = pads_part.decal;
270 if( !pads_part.explicit_decal )
272 auto part_type_it = part_types.find( decal_name );
274 if( part_type_it != part_types.end() )
275 decal_name = part_type_it->second.decal_name;
280 std::stringstream ss( decal_name );
282 std::vector<std::string> decal_list;
284 while( std::getline( ss, segment,
':' ) )
286 decal_list.push_back( segment );
289 std::string actual_decal_name;
290 bool found_valid_decal =
false;
292 if( pads_part.alt_decal_index >= 0
293 &&
static_cast<size_t>( pads_part.alt_decal_index ) < decal_list.size() )
295 const std::string& alt_decal = decal_list[pads_part.alt_decal_index];
297 if( decals.find( alt_decal ) != decals.end() )
299 actual_decal_name = alt_decal;
300 found_valid_decal =
true;
304 if( !found_valid_decal )
306 for(
const std::string& decal : decal_list )
308 if( decals.find( decal ) != decals.end() )
310 actual_decal_name = decal;
311 found_valid_decal =
true;
317 if( found_valid_decal )
319 decal_name = actual_decal_name;
326 footprint->
SetValue( pads_part.decal );
328 if( !pads_part.alternate_decals.empty() )
332 for(
size_t i = 0; i < pads_part.alternate_decals.size(); ++i )
335 alternates += wxT(
", " );
337 alternates += wxString::FromUTF8( pads_part.alternate_decals[i] );
344 footprint->
Add( field );
347 auto partCoordScaler = [&](
double val,
bool is_x ) {
360 long long origin_nm =
static_cast<long long>( std::round( origin *
m_scaleFactor ) );
361 long long val_nm =
static_cast<long long>( std::round( val * part_factor ) );
363 long long res_nm = val_nm - origin_nm;
368 return static_cast<int>( std::clamp<long long>( res_nm, INT_MIN, INT_MAX ) );
372 partCoordScaler( pads_part.location.y,
false ) ) );
386 auto ptIt = part_types.find( pads_part.decal );
388 if( ptIt != part_types.end() )
389 partType = &ptIt->second;
391 const std::map<std::string, std::string>* instanceAttrs =
nullptr;
392 auto iaIt = partInstanceAttrs.find( pads_part.name );
394 if( iaIt != partInstanceAttrs.end() )
395 instanceAttrs = &iaIt->second;
397 auto applyAttributes = [&](
const std::vector<PADS_IO::ATTRIBUTE>& attrs,
398 std::function<int(
double)> scaler )
400 for(
const auto& attr : attrs )
403 bool ownsField =
false;
405 if( attr.name ==
"Ref.Des." )
409 else if( attr.name ==
"Part Type" || attr.name ==
"VALUE" )
411 field = &footprint->
Value();
415 std::string attrValue;
419 auto valIt = instanceAttrs->find( attr.name );
421 if( valIt != instanceAttrs->end() )
422 attrValue = valIt->second;
425 if( attrValue.empty() && partType )
427 auto valIt = partType->
attributes.find( attr.name );
430 attrValue = valIt->second;
433 if( !attrValue.empty() )
436 wxString::FromUTF8( attr.name ) );
437 field->
SetText( wxString::FromUTF8( attrValue ) );
456 int scaledSize = scaler( attr.height );
468 VECTOR2I offset( scaler( attr.x ), -scaler( attr.y ) );
484 if( attr.hjust ==
"LEFT" )
486 else if( attr.hjust ==
"RIGHT" )
491 if( attr.vjust ==
"UP" )
493 else if( attr.vjust ==
"DOWN" )
499 footprint->
Add( field );
503 auto decal_it = decals.find( decal_name );
505 double decalScale = ( decal_it != decals.end() )
509 auto decalScaler = [&, decalScale](
double val ) {
513 if( decal_it != decals.end() )
514 applyAttributes( decal_it->second.attributes, decalScaler );
520 wxString::Format(
_(
"Footprint '%s' not found in decal list, part skipped" ),
526 auto partScaler = [&](
double val ) {
532 if( pads_part.units ==
"M" )
return KiROUND( val );
537 applyAttributes( pads_part.attributes, partScaler );
553 blockField->
SetText( wxString::FromUTF8( blockIt->second ) );
554 footprint->
Add( blockField );
557 if( decal_it == decals.end() )
569 const std::string& shape = layer_def.
shape;
574 if( shape ==
"R" || shape ==
"C" || shape ==
"A" || shape ==
"RT" )
579 else if( shape ==
"S" || shape ==
"ST" )
584 else if( shape ==
"O" || shape ==
"OT" )
587 pad->SetSize( kicad_layer, size );
589 else if( shape ==
"RF" )
592 pad->SetSize( kicad_layer, size );
594 else if( shape ==
"OF" )
597 pad->SetSize( kicad_layer, size );
599 else if( shape ==
"RC" || shape ==
"OC" )
602 pad->SetSize( kicad_layer, size );
606 double min_dim = std::min( size.
x, size.
y );
608 double ratio = ( min_dim > 0 ) ? (
radius / min_dim ) : 0.25;
609 ratio = std::min( ratio, 0.5 );
610 pad->SetRoundRectRadiusRatio( kicad_layer, ratio );
614 pad->SetRoundRectRadiusRatio( kicad_layer, 0.25 );
629 pad->SetOffset( kicad_layer,
638 for(
size_t term_idx = 0; term_idx < decal.
terminals.size(); ++term_idx )
640 const auto& term = decal.
terminals[term_idx];
644 pad->SetNumber( term.name );
646 VECTOR2I pad_pos( decalScaler( term.x ), -decalScaler( term.y ) );
652 int pin_num =
static_cast<int>( term_idx + 1 );
654 auto stack_it = decal.
pad_stacks.find( pin_num );
659 if( stack_it != decal.
pad_stacks.end() && !stack_it->second.empty() )
661 const std::vector<PADS_IO::PAD_STACK_LAYER>& stack = stack_it->second;
665 double slot_length = 0.0;
666 double slot_orientation = 0.0;
667 double pad_rotation = 0.0;
669 for(
const auto& layer_def : stack )
671 if( layer_def.
drill > 0 )
673 drill = layer_def.
drill;
674 plated = layer_def.
plated;
684 auto mapPadsLayer = [&](
int pads_layer ) ->
PCB_LAYER_ID {
685 if( pads_layer == -2 || pads_layer == 1 )
687 else if( pads_layer == -1
688 || pads_layer ==
m_parser->GetParameters().layer_count )
690 else if( pads_layer > 1
691 && pads_layer < m_parser->GetParameters().layer_count )
693 int inner_idx = pads_layer - 2;
695 if( inner_idx >= 0 && inner_idx < 30 )
702 bool has_explicit_layers =
false;
704 for(
const auto& layer_def : stack )
706 if( layer_def.
layer == -2 || layer_def.
layer == -1
707 || layer_def.
layer == 1
708 || layer_def.
layer ==
m_parser->GetParameters().layer_count )
710 has_explicit_layers =
true;
718 LSET explicitly_seen_tech;
720 for(
const auto& layer_def : stack )
722 if( layer_def.
layer > 0 )
729 explicitly_seen_tech.
set( check );
741 if( has_explicit_layers )
743 std::string front_shape;
744 std::string back_shape;
746 for(
const auto& layer_def : stack )
748 if( layer_def.
sizeA <= 0 )
751 if( layer_def.
shape ==
"RT" || layer_def.
shape ==
"ST"
752 || layer_def.
shape ==
"RA" || layer_def.
shape ==
"SA" )
759 if( mapped ==
F_Cu && front_shape.empty() )
760 front_shape = layer_def.
shape;
761 else if( mapped ==
B_Cu && back_shape.empty() )
762 back_shape = layer_def.
shape;
770 if( !front_shape.empty() && !back_shape.empty()
771 && front_shape != back_shape )
781 bool normal_copper_set =
false;
783 for(
const auto& layer_def : stack )
785 if( layer_def.
layer == 0 )
787 if( !has_explicit_layers )
791 convertPadShape( layer_def,
pad,
F_Cu, part_orient );
806 if( layer_def.
sizeA <= 0 )
815 if( layer_def.
shape ==
"RT" || layer_def.
shape ==
"ST" )
821 pad->SetLocalThermalSpokeWidthOverride(
827 pad->SetThermalSpokeAngleDegrees(
834 if( layer_def.
shape ==
"RA" || layer_def.
shape ==
"SA" )
853 layer_set.
set( tech_layer );
858 layer_set.
set( kicad_layer );
873 convertPadShape( layer_def,
pad, kicad_layer, part_orient );
876 normal_copper_set =
true;
880 if( layer_set.none() )
883 convertPadShape( stack[0],
pad,
F_Cu, part_orient );
892 if( layer_set.test(
F_Cu ) && !layer_set.test(
F_Mask )
893 && !explicitly_seen_tech.test(
F_Mask ) )
898 if( layer_set.test(
F_Cu ) && !layer_set.test(
F_Paste )
899 && !explicitly_seen_tech.test(
F_Paste ) )
904 if( layer_set.test(
B_Cu ) && !layer_set.test(
B_Mask )
905 && !explicitly_seen_tech.test(
B_Mask ) )
910 if( layer_set.test(
B_Cu ) && !layer_set.test(
B_Paste )
911 && !explicitly_seen_tech.test(
B_Paste ) )
917 if( slot_length > 0 && slot_length != drill )
921 int drillMinor = decalScaler( drill );
922 int drillMajor = decalScaler( slot_length );
927 double relAngle = slot_orientation - pad_rotation;
929 relAngle = fmod( relAngle, 360.0 );
934 bool vertical = ( relAngle > 45.0 && relAngle < 135.0 )
935 || ( relAngle > 225.0 && relAngle < 315.0 );
938 pad->SetDrillSize(
VECTOR2I( drillMinor, drillMajor ) );
940 pad->SetDrillSize(
VECTOR2I( drillMajor, drillMinor ) );
945 decalScaler( drill ) ) );
961 LSET mask_paste_bits =
966 pad->SetLayerSet( layer_set );
977 std::string pinKey = pads_part.name +
"." + term.name;
990 for(
const auto& item : decal.
items )
992 if( item.points.empty() )
999 if( item.layer == 0 )
1009 if( mapped_layer ==
B_Cu )
1016 shape_layer = mapped_layer;
1025 _(
"Skipping decal item on unmapped layer %d" ), item.layer ),
1031 bool is_circle = ( item.type ==
"CIRCLE" );
1032 bool is_closed = ( item.type ==
"CLOSED" || is_circle );
1036 if( is_circle && item.points.size() >= 2 )
1041 double x1 = item.points[0].x;
1042 double y1 = item.points[0].y;
1043 double x2 = item.points[1].x;
1044 double y2 = item.points[1].y;
1046 double cx = ( x1 + x2 ) / 2.0;
1047 double cy = ( y1 + y2 ) / 2.0;
1049 double radius = std::sqrt( ( x2 - x1 ) * ( x2 - x1 )
1050 + ( y2 - y1 ) * ( y2 - y1 ) )
1062 shape->
SetEnd( fp_pos + pt_on_circle );
1066 footprint->
Add( shape );
1071 if( item.points.size() < 2 )
1074 for(
size_t i = 0; i < item.points.size() - 1; ++i )
1088 VECTOR2I start( decalScaler( p1.
x ), -decalScaler( p1.
y ) );
1093 std::swap( start,
end );
1107 VECTOR2I start( decalScaler( p1.
x ), -decalScaler( p1.
y ) );
1118 footprint->
Add( shape );
1121 if( is_closed && item.points.size() > 2 )
1135 -decalScaler( pFirst.
arc.
cy ) );
1136 VECTOR2I start( decalScaler( pLast.
x ), -decalScaler( pLast.
y ) );
1137 VECTOR2I end( decalScaler( pFirst.
x ), -decalScaler( pFirst.
y ) );
1140 std::swap( start,
end );
1154 VECTOR2I start( decalScaler( pLast.
x ), -decalScaler( pLast.
y ) );
1155 VECTOR2I end( decalScaler( pFirst.
x ), -decalScaler( pFirst.
y ) );
1165 footprint->
Add( shape );
1170 if( pads_part.bottom_layer )
1180 const auto& reuse_blocks =
m_parser->GetReuseBlocks();
1182 if( reuse_blocks.empty() )
1185 std::map<std::string, PCB_GROUP*> blockGroups;
1187 for(
const auto& [blockName, block] : reuse_blocks )
1189 if( !block.instances.empty() || !block.part_names.empty() )
1192 group->SetName( wxString::FromUTF8( blockName ) );
1194 blockGroups[blockName] =
group;
1200 for(
PCB_FIELD* field : fp->GetFields() )
1202 if( field->GetName() == wxT(
"PADS_Reuse_Block" ) )
1204 std::string blockName = field->GetText().ToStdString();
1205 auto groupIt = blockGroups.find( blockName );
1207 if( groupIt != blockGroups.end() )
1209 groupIt->second->AddItem( fp );
1221 const auto& test_points =
m_parser->GetTestPoints();
1222 const auto& via_defs =
m_parser->GetViaDefs();
1224 for(
const auto&
tp : test_points )
1230 footprint->
SetValue( wxString::FromUTF8(
tp.symbol_name ) );
1239 auto it = via_defs.find(
tp.symbol_name );
1241 if( it != via_defs.end() )
1251 double stackSize = def.
size;
1252 bool hasTopPad =
false;
1253 bool hasBottomPad =
false;
1254 bool hasMaskTop =
false;
1255 bool hasMaskBot =
false;
1257 for(
const auto& stackLayer : def.
stack )
1259 if( def.
size <= 0.0 && stackLayer.sizeA > stackSize )
1260 stackSize = stackLayer.sizeA;
1263 && stackLayer.sizeA > 0.0 )
1268 && stackLayer.sizeA > 0.0 )
1270 hasBottomPad =
true;
1282 if( stackSize > 0.0 )
1285 if( hasTopPad && !hasBottomPad )
1287 else if( hasBottomPad && !hasTopPad )
1289 else if( hasMaskBot && !hasMaskTop )
1291 else if( hasMaskTop && !hasMaskBot )
1298 pad->SetNumber( wxT(
"1" ) );
1299 pad->SetPosition( pos );
1305 if( !
tp.net_name.empty() )
1320 tpField->
SetText( wxString::FromUTF8(
tp.type ) );
1321 footprint->
Add( tpField );
1330 const auto& texts =
m_parser->GetTexts();
1332 for(
const auto& pads_text : texts )
1341 _(
"Text on unmapped layer %d assigned to Comments layer" ),
1348 text->SetText( pads_text.content );
1352 int scaledSize =
scaleSize( pads_text.height );
1357 text->SetTextSize(
VECTOR2I( charWidth, charHeight ) );
1359 if( pads_text.width > 0 )
1363 text->SetTextAngle( textAngle );
1371 text->SetPosition( pos + textShift );
1373 if( pads_text.hjust ==
"LEFT" )
1375 else if( pads_text.hjust ==
"RIGHT" )
1380 if( pads_text.vjust ==
"UP" )
1382 else if( pads_text.vjust ==
"DOWN" )
1387 text->SetKeepUpright(
false );
1388 text->SetLayer( textLayer );
1396 const auto& routes =
m_parser->GetRoutes();
1397 std::set<std::pair<int, int>> placedThroughVias;
1401 std::set<std::pair<int, int>> testPointPositions;
1403 for(
const auto&
tp :
m_parser->GetTestPoints() )
1405 if(
tp.type ==
"VIA" )
1412 for(
const auto& route : routes )
1419 for(
const auto& track_def : route.tracks )
1421 if( track_def.points.size() < 2 )
1431 _(
"Skipping track on non-copper layer %d" ), track_def.layer ),
1439 for(
size_t i = 0; i < track_def.points.size() - 1; ++i )
1450 if( ( start -
end ).EuclideanNorm() < 1000 )
1476 for(
const auto& via_def : route.vias )
1482 if( testPointPositions.count( { pos.x, pos.y } ) )
1486 auto it =
m_parser->GetViaDefs().find( via_def.name );
1488 if( it !=
m_parser->GetViaDefs().end() )
1490 switch( it->second.via_type )
1503 auto key = std::make_pair( pos.
x, pos.
y );
1505 if( placedThroughVias.count( key ) )
1508 placedThroughVias.insert( key );
1513 via->SetPosition( pos );
1515 if( it !=
m_parser->GetViaDefs().end() )
1531 via->SetLayerPair( startLayer, endLayer );
1532 via->SetViaType( viaType );
1563 const auto& copperShapes =
m_parser->GetCopperShapes();
1569 return cs.outline.size() == 2 && !cs.outline[1].is_arc
1570 && !cs.filled && !cs.is_cutout;
1576 auto tryFormRectangle = [&](
size_t idx,
VECTOR2I& minCorner,
VECTOR2I& maxCorner ) ->
bool
1578 if( idx + 3 >= copperShapes.size() )
1581 const auto& c0 = copperShapes[idx];
1582 const auto& c1 = copperShapes[idx + 1];
1583 const auto& c2 = copperShapes[idx + 2];
1584 const auto& c3 = copperShapes[idx + 3];
1586 if( !isRectCandidate( c0 ) || !isRectCandidate( c1 )
1587 || !isRectCandidate( c2 ) || !isRectCandidate( c3 ) )
1592 if( c1.net_name != c0.net_name || c2.net_name != c0.net_name
1593 || c3.net_name != c0.net_name )
1598 if( c1.layer != c0.layer || c2.layer != c0.layer || c3.layer != c0.layer )
1605 for(
int i = 0; i < 4; ++i )
1608 scaleCoord( segs[i]->outline[0].y,
false ) );
1610 scaleCoord( segs[i]->outline[1].y,
false ) );
1614 for(
int i = 0; i < 4; ++i )
1619 if( s.
x != e.
x && s.
y != e.
y )
1624 for(
int i = 0; i < 3; ++i )
1626 if( pts[i * 2 + 1] != pts[( i + 1 ) * 2] )
1631 if( pts[7] != pts[0] )
1635 int minX = pts[0].
x, maxX = pts[0].
x;
1636 int minY = pts[0].
y, maxY = pts[0].
y;
1638 for(
int i = 0; i < 8; ++i )
1640 minX = std::min( minX, pts[i].x );
1641 maxX = std::max( maxX, pts[i].x );
1642 minY = std::min( minY, pts[i].y );
1643 maxY = std::max( maxY, pts[i].y );
1646 minCorner =
VECTOR2I( minX, minY );
1647 maxCorner =
VECTOR2I( maxX, maxY );
1651 for(
size_t idx = 0; idx < copperShapes.size(); ++idx )
1653 const auto& copper = copperShapes[idx];
1655 if( copper.outline.size() < 2 )
1658 if( copper.is_cutout )
1668 _(
"COPPER item on unmapped layer %d defaulting to F.Cu" ),
1683 if( tryFormRectangle( idx, minCorner, maxCorner ) )
1688 rect->
SetEnd( maxCorner );
1700 for(
size_t i = 0; i < copper.outline.size() - 1; ++i )
1702 const auto& p1 = copper.outline[i];
1703 const auto& p2 = copper.outline[i + 1];
1708 if( ( start -
end ).EuclideanNorm() < 1000 )
1734 if( !copper.net_name.empty() )
1739 if( copper.outline.size() < 3 )
1759 for(
size_t i = 0; i < copper.outline.size() - 1; ++i )
1761 const auto& p1 = copper.outline[i];
1762 const auto& p2 = copper.outline[i + 1];
1767 if( ( start -
end ).EuclideanNorm() < 1000 )
1804 const auto& clusters =
m_parser->GetClusters();
1806 if( clusters.empty() )
1809 std::map<std::string, const PADS_IO::CLUSTER*> netToClusterMap;
1811 for(
const auto& cluster : clusters )
1813 for(
const std::string& netName : cluster.net_names )
1816 netToClusterMap[converted] = &cluster;
1820 std::map<int, PCB_GROUP*> clusterGroups;
1822 for(
const auto& cluster : clusters )
1825 group->SetName( wxString::FromUTF8( cluster.name ) );
1827 clusterGroups[cluster.id] =
group;
1836 std::string netName = net->
GetNetname().ToStdString();
1837 auto clusterIt = netToClusterMap.find( netName );
1839 if( clusterIt != netToClusterMap.end() )
1841 int clusterId = clusterIt->second->id;
1842 auto groupIt = clusterGroups.find( clusterId );
1844 if( groupIt != clusterGroups.end() )
1846 groupIt->second->AddItem( track );
1856 const auto& pours =
m_parser->GetPours();
1857 const auto& params =
m_parser->GetParameters();
1861 auto isValidPoly = [](
const std::vector<PADS_IO::ARC_POINT>& pts )
1863 if( pts.size() >= 3 )
1866 if( pts.size() == 1 && pts[0].is_arc
1867 &&
std::abs( pts[0].arc.delta_angle ) >= 359.0 )
1877 int maxPriority = 0;
1879 for(
const auto& pour_def : pours )
1881 if( pour_def.priority > maxPriority )
1882 maxPriority = pour_def.priority;
1886 std::map<std::string, ZONE*> pourZoneMap;
1889 std::map<std::string, std::string> hatoutToParent;
1892 for(
const auto& pour_def : pours )
1896 hatoutToParent[pour_def.name] = pour_def.owner_pour;
1906 if( pour_def.points.size() < 3 )
1916 _(
"Skipping pour on unmapped layer %d" ), pour_def.layer ),
1930 if( pour_def.is_cutout )
1938 zone->
SetZoneName( wxString::Format( wxT(
"Cutout_%s" ), pour_def.owner_pour ) );
1948 int kicadPriority = maxPriority - pour_def.priority + 1;
1958 pourZoneMap[pour_def.name] = zone;
1963 for(
const auto& pour_def : pours )
1968 if( !isValidPoly( pour_def.points ) )
1971 auto zoneIt = pourZoneMap.find( pour_def.owner_pour );
1973 if( zoneIt == pourZoneMap.end() )
1976 ZONE* zone = zoneIt->second;
2003 for(
const auto& void_def : pours )
2008 if( !isValidPoly( void_def.points ) )
2013 auto parentIt = hatoutToParent.find( void_def.owner_pour );
2015 if( parentIt == hatoutToParent.end() )
2018 if( parentIt->second != pour_def.owner_pour )
2026 allVoids.
Append( voidPoly );
2042 const auto& pts = polyline.points;
2044 if( pts.size() < 2 )
2047 for(
size_t i = 0; i < pts.size() - 1; ++i )
2077 if( polyline.closed && pts.size() > 2 )
2082 bool needsClosing = (
std::abs( pLast.
x - pFirst.
x ) > 0.001
2113 const auto& dimensions =
m_parser->GetDimensions();
2115 for(
const auto& dim : dimensions )
2117 if( dim.points.size() < 2 )
2131 if( dim.is_horizontal )
2141 if( dim.is_horizontal )
2143 double heightOffset = dim.crossbar_pos - dim.points[0].y;
2144 int height = -
scaleSize( heightOffset );
2149 double heightOffset = dim.crossbar_pos - dim.points[0].x;
2163 if( dim.text_height > 0 )
2165 int scaledSize =
scaleSize( dim.text_height );
2172 if( dim.text_width > 0 )
2176 if( !dim.text.empty() )
2184 if( dim.rotation != 0.0 )
2195 const auto& keepouts =
m_parser->GetKeepouts();
2196 int keepoutIndex = 0;
2198 for(
const auto& ko : keepouts )
2200 if( ko.outline.size() < 3 )
2206 if( ko.layers.empty() )
2210 else if( ko.layers.size() == 1 )
2219 _(
"Skipping keepout on unmapped layer %d" ), ko.layers[0] ),
2232 for(
int layer : ko.layers )
2237 layerSet.
set( mappedLayer );
2240 if( layerSet.none() )
2268 zone->
SetZoneName( wxString::Format( wxT(
"%s_%d" ), typeName, ++keepoutIndex ) );
2274 if( ko.outline.size() > 2 )
2276 const auto& first = ko.outline.front();
2277 const auto& last = ko.outline.back();
2279 if(
std::abs( first.x - last.x ) > 0.001 ||
std::abs( first.y - last.y ) > 0.001 )
2296 const auto& pts = graphic.points;
2303 if( pts.size() == 1 && pts[0].is_arc
2304 &&
std::abs( pts[0].arc.delta_angle - 360.0 ) < 0.1 )
2319 if( pts.size() < 2 )
2322 for(
size_t i = 0; i < pts.size() - 1; ++i )
2350 if( graphic.closed && pts.size() > 2 )
2355 bool needsClosing = (
std::abs( pLast.
x - pFirst.
x ) > 0.001
2386 wxFileName fn( aFileName );
2387 fn.SetExt( wxT(
"kicad_dru" ) );
2389 wxString customRules = wxT(
"(version 1)\n" );
2391 const auto& diffPairs =
m_parser->GetDiffPairs();
2393 for(
const auto& dp : diffPairs )
2395 if( dp.name.empty() || ( dp.gap <= 0 && dp.width <= 0 ) )
2398 wxString ruleName = wxString::Format( wxT(
"DiffPair_%s" ), wxString::FromUTF8( dp.name ) );
2400 if( dp.gap > 0 && !dp.positive_net.empty() && !dp.negative_net.empty() )
2405 wxString gapStr = wxString::FromUTF8(
FormatDouble2Str( gapMm ) ) + wxT(
"mm" );
2407 customRules += wxString::Format(
2408 wxT(
"\n(rule \"%s_gap\"\n" )
2409 wxT(
" (condition \"A.NetName == '%s' && B.NetName == '%s'\")\n" )
2410 wxT(
" (constraint clearance (min %s)))\n" ),
2411 ruleName, posNet, negNet, gapStr );
2415 if( customRules.length() > 15 )
2417 wxFile rulesFile( fn.GetFullPath(), wxFile::write );
2419 if( rulesFile.IsOpened() )
2420 rulesFile.Write( customRules );
2430 size_t trackCount = 0;
2431 size_t viaCount = 0;
2441 m_reporter->Report( wxString::Format(
_(
"Imported %zu footprints, %d nets, %zu tracks,"
2442 " %zu vias, %zu zones" ),
2445 trackCount, viaCount,
2452 const std::vector<INPUT_LAYER_DESC>& aInputLayerDescriptionVector )
2454 std::map<wxString, PCB_LAYER_ID> layer_map;
2458 layer_map[layer.Name] = layer.AutoMapLayer;
2468 return static_cast<int>( std::clamp<int64_t>( nm, INT_MIN, INT_MAX ) );
2477 if( aUnits ==
"I" || aUnits ==
"MIL" || aUnits ==
"MILS" )
2480 if( aUnits ==
"M" || aUnits ==
"MM" || aUnits ==
"METRIC" )
2483 if( aUnits ==
"INCH" || aUnits ==
"INCHES" )
2494 long long origin_nm =
static_cast<long long>( std::round( origin *
m_scaleFactor ) );
2495 long long val_nm =
static_cast<long long>( std::round( aVal *
m_scaleFactor ) );
2497 long long result = aIsX ? ( val_nm - origin_nm ) : ( origin_nm - val_nm );
2498 return static_cast<int>( std::clamp<long long>(
result, INT_MIN, INT_MAX ) );
2506 if(
info.padsLayerNum == aPadsLayer )
2523 if( aNetName.empty() )
2554 const std::vector<PADS_IO::ARC_POINT>& aPts )
2560 if( aPts.size() == 1 && aPts[0].is_arc
2561 &&
std::abs( aPts[0].arc.delta_angle ) >= 359.0 )
2567 constexpr int NUM_SEGS = 36;
2569 for(
int i = 0; i < NUM_SEGS; i++ )
2571 double angle = 2.0 *
M_PI * i / NUM_SEGS;
2581 for(
size_t i = 1; i < aPts.size(); i++ )
2583 const auto& pt = aPts[i];
2590 for(
int j = 1; j < arcPoly.
PointCount(); j++ )
2612 std::swap( start,
end );
2634 double dx = aCurr.
x - aPrev.
x;
2635 double dy = aCurr.
y - aPrev.
y;
2640 midX = ( aPrev.
x + aCurr.
x ) / 2.0 - dy / 2.0;
2641 midY = ( aPrev.
y + aCurr.
y ) / 2.0 + dx / 2.0;
2646 midX = ( aPrev.
x + aCurr.
x ) / 2.0 + dy / 2.0;
2647 midY = ( aPrev.
y + aCurr.
y ) / 2.0 - dx / 2.0;
2655 double startAngleRad = atan2( aPrev.
y - aCurr.
arc.
cy, aPrev.
x - aCurr.
arc.
cx );
2672 std::vector<PADS_IO::LAYER_INFO> padsLayerInfos =
m_parser->GetLayerInfos();
2698 for(
const auto& padsInfo : padsLayerInfos )
2701 info.padsLayerNum = padsInfo.number;
2702 info.name = padsInfo.name;
2707 info.type = convertLayerType( padsInfo.layer_type );
2709 std::string lowerName = padsInfo.name;
2710 std::transform( lowerName.begin(), lowerName.end(), lowerName.begin(),
2711 [](
unsigned char c ){ return std::tolower( c ); } );
2713 bool isBottom = lowerName.find(
"bottom" ) != std::string::npos
2714 || lowerName.find(
"bot" ) != std::string::npos;
2726 if( padsInfo.number == 1 )
2728 else if( padsInfo.number ==
m_parser->GetParameters().layer_count )
2737 info.required = padsInfo.required;
2741 std::vector<INPUT_LAYER_DESC> inputDescs =
2747 int copperLayerCount =
m_parser->GetParameters().layer_count;
2749 if( copperLayerCount < 1 )
2750 copperLayerCount = 2;
2752 m_loadBoard->SetCopperLayerCount( copperLayerCount );
2760 switch(
m_parser->GetParameters().units )
2782 const auto& designRules =
m_parser->GetDesignRules();
2805 if( defaultNetclass )
2807 defaultNetclass->SetClearance(
scaleSize( designRules.default_clearance ) );
2808 defaultNetclass->SetTrackWidth(
scaleSize( designRules.default_track_width ) );
2809 defaultNetclass->SetViaDiameter(
scaleSize( designRules.default_via_size ) );
2810 defaultNetclass->SetViaDrill(
scaleSize( designRules.default_via_drill ) );
2813 const auto& viaDefs =
m_parser->GetViaDefs();
2815 if( !viaDefs.empty() )
2819 const std::string& defaultViaName =
m_parser->GetParameters().default_signal_via;
2820 auto defaultIt = viaDefs.find( defaultViaName );
2822 if( defaultIt == viaDefs.end() )
2823 defaultIt = viaDefs.begin();
2825 int viaDia =
scaleSize( defaultIt->second.size );
2826 int viaDrill =
scaleSize( defaultIt->second.drill );
2831 if( defaultNetclass )
2833 defaultNetclass->SetViaDiameter( viaDia );
2834 defaultNetclass->SetViaDrill( viaDrill );
2837 for(
const auto& [
name, def] : viaDefs )
2841 const auto& netClasses =
m_parser->GetNetClasses();
2843 for(
const auto& nc : netClasses )
2845 if( nc.name.empty() )
2848 wxString ncName = wxString::FromUTF8( nc.name );
2849 std::shared_ptr<NETCLASS> netclass = std::make_shared<NETCLASS>( ncName );
2851 if( nc.clearance > 0 )
2852 netclass->SetClearance(
scaleSize( nc.clearance ) );
2854 if( nc.track_width > 0 )
2855 netclass->SetTrackWidth(
scaleSize( nc.track_width ) );
2857 if( nc.via_size > 0 )
2858 netclass->SetViaDiameter(
scaleSize( nc.via_size ) );
2860 if( nc.via_drill > 0 )
2861 netclass->SetViaDrill(
scaleSize( nc.via_drill ) );
2863 if( nc.diff_pair_width > 0 )
2864 netclass->SetDiffPairWidth(
scaleSize( nc.diff_pair_width ) );
2866 if( nc.diff_pair_gap > 0 )
2867 netclass->SetDiffPairGap(
scaleSize( nc.diff_pair_gap ) );
2871 for(
const std::string& netName : nc.net_names )
2878 const auto& diffPairs =
m_parser->GetDiffPairs();
2880 for(
const auto& dp : diffPairs )
2882 if( dp.name.empty() )
2885 wxString dpClassName =
2886 wxString::Format( wxT(
"DiffPair_%s" ), wxString::FromUTF8( dp.name ) );
2887 std::shared_ptr<NETCLASS> dpNetclass = std::make_shared<NETCLASS>( dpClassName );
2890 dpNetclass->SetDiffPairGap(
scaleSize( dp.gap ) );
2894 dpNetclass->SetDiffPairWidth(
scaleSize( dp.width ) );
2895 dpNetclass->SetTrackWidth(
scaleSize( dp.width ) );
2900 if( !dp.positive_net.empty() )
2906 if( !dp.negative_net.empty() )
2916 const auto& boardOutlines =
m_parser->GetBoardOutlines();
2918 if( !boardOutlines.empty() )
2920 double min_x = std::numeric_limits<double>::max();
2921 double max_x = std::numeric_limits<double>::lowest();
2922 double min_y = std::numeric_limits<double>::max();
2923 double max_y = std::numeric_limits<double>::lowest();
2925 for(
const auto& outline : boardOutlines )
2927 for(
const auto& pt : outline.points )
2929 min_x = std::min( min_x, pt.x );
2930 max_x = std::max( max_x, pt.x );
2931 min_y = std::min( min_y, pt.y );
2932 max_y = std::max( max_y, pt.y );
2936 if( min_x < max_x && min_y < max_y )
2945 std::vector<const PADS_IO::LAYER_INFO*> copperLayerInfos;
2947 for(
const auto& li : padsLayerInfos )
2950 copperLayerInfos.push_back( &li );
2953 bool hasStackupData =
false;
2955 for(
const auto* li : copperLayerInfos )
2957 if( li->layer_thickness > 0.0 || li->dielectric_constant > 0.0 )
2959 hasStackupData =
true;
2964 if( hasStackupData )
2971 std::map<PCB_LAYER_ID, const PADS_IO::LAYER_INFO*> copperInfoMap;
2973 for(
const auto* li : copperLayerInfos )
2978 copperInfoMap[kicadLayer] = li;
2988 auto it = copperInfoMap.find( item->GetBrdLayerId() );
2990 if( it != copperInfoMap.end() )
2992 prevCopperInfo = it->second;
2994 if( it->second->copper_thickness > 0.0 )
2995 item->SetThickness(
scaleSize( it->second->copper_thickness ) );
3000 if( prevCopperInfo )
3011 item->SetColor( wxT(
"White" ) );
3015 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 SetStart(const VECTOR2I &aStart)
void SetShape(SHAPE_T aShape)
void SetEnd(const VECTOR2I &aEnd)
void SetWidth(int aWidth)
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
virtual void SetVisible(bool aVisible)
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
void SetKeepUpright(bool aKeepUpright)
virtual void SetText(const wxString &aText)
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
void 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()
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.
void SetOverrideTextEnabled(bool aOverride)
void SetLineThickness(int aWidth)
virtual void SetEnd(const VECTOR2I &aPoint)
virtual void SetStart(const VECTOR2I &aPoint)
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 SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void SetStroke(const STROKE_PARAMS &aStroke) override
virtual void SetPosition(const VECTOR2I &aPos) 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 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