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 );
599 pad->SetOffset( kicad_layer, pad_offset );
602 else if( shape ==
"OF" )
605 pad->SetSize( kicad_layer, size );
612 pad->SetOffset( kicad_layer, pad_offset );
615 else if( shape ==
"RC" || shape ==
"OC" )
618 pad->SetSize( kicad_layer, size );
622 double min_dim = std::min( size.
x, size.
y );
624 double ratio = ( min_dim > 0 ) ? (
radius / min_dim ) : 0.25;
625 ratio = std::min( ratio, 0.5 );
626 pad->SetRoundRectRadiusRatio( kicad_layer, ratio );
630 pad->SetRoundRectRadiusRatio( kicad_layer, 0.25 );
638 pad->SetOffset( kicad_layer, pad_offset );
652 for(
size_t term_idx = 0; term_idx < decal.
terminals.size(); ++term_idx )
654 const auto& term = decal.
terminals[term_idx];
658 pad->SetNumber( term.name );
660 VECTOR2I pad_pos( decalScaler( term.x ), -decalScaler( term.y ) );
666 int pin_num =
static_cast<int>( term_idx + 1 );
668 auto stack_it = decal.
pad_stacks.find( pin_num );
673 if( stack_it != decal.
pad_stacks.end() && !stack_it->second.empty() )
675 const std::vector<PADS_IO::PAD_STACK_LAYER>& stack = stack_it->second;
679 double slot_length = 0.0;
680 double slot_orientation = 0.0;
681 double pad_rotation = 0.0;
683 for(
const auto& layer_def : stack )
685 if( layer_def.
drill > 0 )
687 drill = layer_def.
drill;
688 plated = layer_def.
plated;
698 auto mapPadsLayer = [&](
int pads_layer ) ->
PCB_LAYER_ID {
699 if( pads_layer == -2 || pads_layer == 1 )
701 else if( pads_layer == -1
702 || pads_layer ==
m_parser->GetParameters().layer_count )
704 else if( pads_layer > 1
705 && pads_layer < m_parser->GetParameters().layer_count )
707 int inner_idx = pads_layer - 2;
709 if( inner_idx >= 0 && inner_idx < 30 )
716 bool has_explicit_layers =
false;
718 for(
const auto& layer_def : stack )
720 if( layer_def.
layer == -2 || layer_def.
layer == -1
721 || layer_def.
layer == 1
722 || layer_def.
layer ==
m_parser->GetParameters().layer_count )
724 has_explicit_layers =
true;
732 LSET explicitly_seen_tech;
734 for(
const auto& layer_def : stack )
736 if( layer_def.
layer > 0 )
743 explicitly_seen_tech.
set( check );
755 if( has_explicit_layers )
757 std::string front_shape;
758 std::string back_shape;
759 double front_sizeA = 0;
760 double back_sizeA = 0;
761 double front_sizeB = 0;
762 double back_sizeB = 0;
764 for(
const auto& layer_def : stack )
766 if( layer_def.
sizeA <= 0 )
769 if( layer_def.
shape ==
"RT" || layer_def.
shape ==
"ST"
770 || layer_def.
shape ==
"RA" || layer_def.
shape ==
"SA" )
777 if( mapped ==
F_Cu && front_shape.empty() )
779 front_shape = layer_def.
shape;
780 front_sizeA = layer_def.
sizeA;
781 front_sizeB = layer_def.
sizeB;
783 else if( mapped ==
B_Cu && back_shape.empty() )
785 back_shape = layer_def.
shape;
786 back_sizeA = layer_def.
sizeA;
787 back_sizeB = layer_def.
sizeB;
791 if( !front_shape.empty() && !back_shape.empty()
792 && ( front_shape != back_shape
793 || front_sizeA != back_sizeA
794 || front_sizeB != back_sizeB ) )
800 for(
const auto& layer_def : stack )
802 if( layer_def.
layer == 0 )
804 if( !has_explicit_layers )
808 convertPadShape( layer_def,
pad,
F_Cu, part_orient );
823 if( layer_def.
sizeA <= 0 )
832 if( layer_def.
shape ==
"RT" || layer_def.
shape ==
"ST" )
838 pad->SetLocalThermalSpokeWidthOverride(
844 pad->SetThermalSpokeAngleDegrees(
851 if( layer_def.
shape ==
"RA" || layer_def.
shape ==
"SA" )
870 layer_set.
set( tech_layer );
875 layer_set.
set( kicad_layer );
876 convertPadShape( layer_def,
pad, kicad_layer, part_orient );
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();
1223 for(
const auto&
tp : test_points )
1229 footprint->
SetValue( wxString::FromUTF8(
tp.symbol_name ) );
1242 pad->SetNumber( wxT(
"1" ) );
1243 pad->SetPosition( pos );
1250 if( !
tp.net_name.empty() )
1265 tpField->
SetText( wxString::FromUTF8(
tp.type ) );
1266 footprint->
Add( tpField );
1275 const auto& texts =
m_parser->GetTexts();
1277 for(
const auto& pads_text : texts )
1286 _(
"Text on unmapped layer %d assigned to Comments layer" ),
1293 text->SetText( pads_text.content );
1297 int scaledSize =
scaleSize( pads_text.height );
1302 text->SetTextSize(
VECTOR2I( charWidth, charHeight ) );
1304 if( pads_text.width > 0 )
1308 text->SetTextAngle( textAngle );
1316 text->SetPosition( pos + textShift );
1318 if( pads_text.hjust ==
"LEFT" )
1320 else if( pads_text.hjust ==
"RIGHT" )
1325 if( pads_text.vjust ==
"UP" )
1327 else if( pads_text.vjust ==
"DOWN" )
1332 text->SetKeepUpright(
false );
1333 text->SetLayer( textLayer );
1341 const auto& routes =
m_parser->GetRoutes();
1342 std::set<std::pair<int, int>> placedThroughVias;
1344 for(
const auto& route : routes )
1351 for(
const auto& track_def : route.tracks )
1353 if( track_def.points.size() < 2 )
1363 _(
"Skipping track on non-copper layer %d" ), track_def.layer ),
1371 for(
size_t i = 0; i < track_def.points.size() - 1; ++i )
1382 if( ( start -
end ).EuclideanNorm() < 1000 )
1408 for(
const auto& via_def : route.vias )
1414 auto it =
m_parser->GetViaDefs().find( via_def.name );
1416 if( it !=
m_parser->GetViaDefs().end() )
1418 switch( it->second.via_type )
1431 auto key = std::make_pair( pos.
x, pos.
y );
1433 if( placedThroughVias.count( key ) )
1436 placedThroughVias.insert( key );
1441 via->SetPosition( pos );
1443 if( it !=
m_parser->GetViaDefs().end() )
1459 via->SetLayerPair( startLayer, endLayer );
1460 via->SetViaType( viaType );
1491 const auto& copperShapes =
m_parser->GetCopperShapes();
1497 return cs.outline.size() == 2 && !cs.outline[1].is_arc
1498 && !cs.filled && !cs.is_cutout;
1504 auto tryFormRectangle = [&](
size_t idx,
VECTOR2I& minCorner,
VECTOR2I& maxCorner ) ->
bool
1506 if( idx + 3 >= copperShapes.size() )
1509 const auto& c0 = copperShapes[idx];
1510 const auto& c1 = copperShapes[idx + 1];
1511 const auto& c2 = copperShapes[idx + 2];
1512 const auto& c3 = copperShapes[idx + 3];
1514 if( !isRectCandidate( c0 ) || !isRectCandidate( c1 )
1515 || !isRectCandidate( c2 ) || !isRectCandidate( c3 ) )
1520 if( c1.net_name != c0.net_name || c2.net_name != c0.net_name
1521 || c3.net_name != c0.net_name )
1526 if( c1.layer != c0.layer || c2.layer != c0.layer || c3.layer != c0.layer )
1533 for(
int i = 0; i < 4; ++i )
1536 scaleCoord( segs[i]->outline[0].y,
false ) );
1538 scaleCoord( segs[i]->outline[1].y,
false ) );
1542 for(
int i = 0; i < 4; ++i )
1547 if( s.
x != e.
x && s.
y != e.
y )
1552 for(
int i = 0; i < 3; ++i )
1554 if( pts[i * 2 + 1] != pts[( i + 1 ) * 2] )
1559 if( pts[7] != pts[0] )
1563 int minX = pts[0].
x, maxX = pts[0].
x;
1564 int minY = pts[0].
y, maxY = pts[0].
y;
1566 for(
int i = 0; i < 8; ++i )
1568 minX = std::min( minX, pts[i].x );
1569 maxX = std::max( maxX, pts[i].x );
1570 minY = std::min( minY, pts[i].y );
1571 maxY = std::max( maxY, pts[i].y );
1574 minCorner =
VECTOR2I( minX, minY );
1575 maxCorner =
VECTOR2I( maxX, maxY );
1579 for(
size_t idx = 0; idx < copperShapes.size(); ++idx )
1581 const auto& copper = copperShapes[idx];
1583 if( copper.outline.size() < 2 )
1586 if( copper.is_cutout )
1596 _(
"COPPER item on unmapped layer %d defaulting to F.Cu" ),
1611 if( tryFormRectangle( idx, minCorner, maxCorner ) )
1616 rect->
SetEnd( maxCorner );
1628 for(
size_t i = 0; i < copper.outline.size() - 1; ++i )
1630 const auto& p1 = copper.outline[i];
1631 const auto& p2 = copper.outline[i + 1];
1636 if( ( start -
end ).EuclideanNorm() < 1000 )
1662 if( !copper.net_name.empty() )
1667 if( copper.outline.size() < 3 )
1687 for(
size_t i = 0; i < copper.outline.size() - 1; ++i )
1689 const auto& p1 = copper.outline[i];
1690 const auto& p2 = copper.outline[i + 1];
1695 if( ( start -
end ).EuclideanNorm() < 1000 )
1732 const auto& clusters =
m_parser->GetClusters();
1734 if( clusters.empty() )
1737 std::map<std::string, const PADS_IO::CLUSTER*> netToClusterMap;
1739 for(
const auto& cluster : clusters )
1741 for(
const std::string& netName : cluster.net_names )
1744 netToClusterMap[converted] = &cluster;
1748 std::map<int, PCB_GROUP*> clusterGroups;
1750 for(
const auto& cluster : clusters )
1753 group->SetName( wxString::FromUTF8( cluster.name ) );
1755 clusterGroups[cluster.id] =
group;
1764 std::string netName = net->
GetNetname().ToStdString();
1765 auto clusterIt = netToClusterMap.find( netName );
1767 if( clusterIt != netToClusterMap.end() )
1769 int clusterId = clusterIt->second->id;
1770 auto groupIt = clusterGroups.find( clusterId );
1772 if( groupIt != clusterGroups.end() )
1774 groupIt->second->AddItem( track );
1784 const auto& pours =
m_parser->GetPours();
1785 const auto& params =
m_parser->GetParameters();
1789 auto isValidPoly = [](
const std::vector<PADS_IO::ARC_POINT>& pts )
1791 if( pts.size() >= 3 )
1794 if( pts.size() == 1 && pts[0].is_arc
1795 &&
std::abs( pts[0].arc.delta_angle ) >= 359.0 )
1805 int maxPriority = 0;
1807 for(
const auto& pour_def : pours )
1809 if( pour_def.priority > maxPriority )
1810 maxPriority = pour_def.priority;
1814 std::map<std::string, ZONE*> pourZoneMap;
1817 std::map<std::string, std::string> hatoutToParent;
1820 for(
const auto& pour_def : pours )
1824 hatoutToParent[pour_def.name] = pour_def.owner_pour;
1834 if( pour_def.points.size() < 3 )
1844 _(
"Skipping pour on unmapped layer %d" ), pour_def.layer ),
1858 if( pour_def.is_cutout )
1866 zone->
SetZoneName( wxString::Format( wxT(
"Cutout_%s" ), pour_def.owner_pour ) );
1876 int kicadPriority = maxPriority - pour_def.priority + 1;
1886 pourZoneMap[pour_def.name] = zone;
1891 for(
const auto& pour_def : pours )
1896 if( !isValidPoly( pour_def.points ) )
1899 auto zoneIt = pourZoneMap.find( pour_def.owner_pour );
1901 if( zoneIt == pourZoneMap.end() )
1904 ZONE* zone = zoneIt->second;
1931 for(
const auto& void_def : pours )
1936 if( !isValidPoly( void_def.points ) )
1941 auto parentIt = hatoutToParent.find( void_def.owner_pour );
1943 if( parentIt == hatoutToParent.end() )
1946 if( parentIt->second != pour_def.owner_pour )
1954 allVoids.
Append( voidPoly );
1970 const auto& pts = polyline.points;
1972 if( pts.size() < 2 )
1975 for(
size_t i = 0; i < pts.size() - 1; ++i )
2005 if( polyline.closed && pts.size() > 2 )
2010 bool needsClosing = (
std::abs( pLast.
x - pFirst.
x ) > 0.001
2041 const auto& dimensions =
m_parser->GetDimensions();
2043 for(
const auto& dim : dimensions )
2045 if( dim.points.size() < 2 )
2059 if( dim.is_horizontal )
2069 if( dim.is_horizontal )
2071 double heightOffset = dim.crossbar_pos - dim.points[0].y;
2072 int height = -
scaleSize( heightOffset );
2077 double heightOffset = dim.crossbar_pos - dim.points[0].x;
2091 if( dim.text_height > 0 )
2093 int scaledSize =
scaleSize( dim.text_height );
2100 if( dim.text_width > 0 )
2104 if( !dim.text.empty() )
2112 if( dim.rotation != 0.0 )
2123 const auto& keepouts =
m_parser->GetKeepouts();
2124 int keepoutIndex = 0;
2126 for(
const auto& ko : keepouts )
2128 if( ko.outline.size() < 3 )
2134 if( ko.layers.empty() )
2138 else if( ko.layers.size() == 1 )
2147 _(
"Skipping keepout on unmapped layer %d" ), ko.layers[0] ),
2160 for(
int layer : ko.layers )
2165 layerSet.
set( mappedLayer );
2168 if( layerSet.none() )
2196 zone->
SetZoneName( wxString::Format( wxT(
"%s_%d" ), typeName, ++keepoutIndex ) );
2202 if( ko.outline.size() > 2 )
2204 const auto& first = ko.outline.front();
2205 const auto& last = ko.outline.back();
2207 if(
std::abs( first.x - last.x ) > 0.001 ||
std::abs( first.y - last.y ) > 0.001 )
2224 const auto& pts = graphic.points;
2231 if( pts.size() == 1 && pts[0].is_arc
2232 &&
std::abs( pts[0].arc.delta_angle - 360.0 ) < 0.1 )
2247 if( pts.size() < 2 )
2250 for(
size_t i = 0; i < pts.size() - 1; ++i )
2278 if( graphic.closed && pts.size() > 2 )
2283 bool needsClosing = (
std::abs( pLast.
x - pFirst.
x ) > 0.001
2314 wxFileName fn( aFileName );
2315 fn.SetExt( wxT(
"kicad_dru" ) );
2317 wxString customRules = wxT(
"(version 1)\n" );
2319 const auto& diffPairs =
m_parser->GetDiffPairs();
2321 for(
const auto& dp : diffPairs )
2323 if( dp.name.empty() || ( dp.gap <= 0 && dp.width <= 0 ) )
2326 wxString ruleName = wxString::Format( wxT(
"DiffPair_%s" ), wxString::FromUTF8( dp.name ) );
2328 if( dp.gap > 0 && !dp.positive_net.empty() && !dp.negative_net.empty() )
2333 wxString gapStr = wxString::FromUTF8(
FormatDouble2Str( gapMm ) ) + wxT(
"mm" );
2335 customRules += wxString::Format(
2336 wxT(
"\n(rule \"%s_gap\"\n" )
2337 wxT(
" (condition \"A.NetName == '%s' && B.NetName == '%s'\")\n" )
2338 wxT(
" (constraint clearance (min %s)))\n" ),
2339 ruleName, posNet, negNet, gapStr );
2343 if( customRules.length() > 15 )
2345 wxFile rulesFile( fn.GetFullPath(), wxFile::write );
2347 if( rulesFile.IsOpened() )
2348 rulesFile.Write( customRules );
2358 size_t trackCount = 0;
2359 size_t viaCount = 0;
2369 m_reporter->Report( wxString::Format(
_(
"Imported %zu footprints, %d nets, %zu tracks,"
2370 " %zu vias, %zu zones" ),
2373 trackCount, viaCount,
2380 const std::vector<INPUT_LAYER_DESC>& aInputLayerDescriptionVector )
2382 std::map<wxString, PCB_LAYER_ID> layer_map;
2386 layer_map[layer.Name] = layer.AutoMapLayer;
2396 return static_cast<int>( std::clamp<int64_t>( nm, INT_MIN, INT_MAX ) );
2405 if( aUnits ==
"I" || aUnits ==
"MIL" || aUnits ==
"MILS" )
2408 if( aUnits ==
"M" || aUnits ==
"MM" || aUnits ==
"METRIC" )
2411 if( aUnits ==
"INCH" || aUnits ==
"INCHES" )
2422 long long origin_nm =
static_cast<long long>( std::round( origin *
m_scaleFactor ) );
2423 long long val_nm =
static_cast<long long>( std::round( aVal *
m_scaleFactor ) );
2425 long long result = aIsX ? ( val_nm - origin_nm ) : ( origin_nm - val_nm );
2426 return static_cast<int>( std::clamp<long long>(
result, INT_MIN, INT_MAX ) );
2434 if(
info.padsLayerNum == aPadsLayer )
2451 if( aNetName.empty() )
2482 const std::vector<PADS_IO::ARC_POINT>& aPts )
2488 if( aPts.size() == 1 && aPts[0].is_arc
2489 &&
std::abs( aPts[0].arc.delta_angle ) >= 359.0 )
2495 constexpr int NUM_SEGS = 36;
2497 for(
int i = 0; i < NUM_SEGS; i++ )
2499 double angle = 2.0 *
M_PI * i / NUM_SEGS;
2509 for(
size_t i = 1; i < aPts.size(); i++ )
2511 const auto& pt = aPts[i];
2518 for(
int j = 1; j < arcPoly.
PointCount(); j++ )
2540 std::swap( start,
end );
2562 double dx = aCurr.
x - aPrev.
x;
2563 double dy = aCurr.
y - aPrev.
y;
2568 midX = ( aPrev.
x + aCurr.
x ) / 2.0 - dy / 2.0;
2569 midY = ( aPrev.
y + aCurr.
y ) / 2.0 + dx / 2.0;
2574 midX = ( aPrev.
x + aCurr.
x ) / 2.0 + dy / 2.0;
2575 midY = ( aPrev.
y + aCurr.
y ) / 2.0 - dx / 2.0;
2583 double startAngleRad = atan2( aPrev.
y - aCurr.
arc.
cy, aPrev.
x - aCurr.
arc.
cx );
2600 std::vector<PADS_IO::LAYER_INFO> padsLayerInfos =
m_parser->GetLayerInfos();
2626 for(
const auto& padsInfo : padsLayerInfos )
2629 info.padsLayerNum = padsInfo.number;
2630 info.name = padsInfo.name;
2635 info.type = convertLayerType( padsInfo.layer_type );
2637 std::string lowerName = padsInfo.name;
2638 std::transform( lowerName.begin(), lowerName.end(), lowerName.begin(),
2639 [](
unsigned char c ){ return std::tolower( c ); } );
2641 bool isBottom = lowerName.find(
"bottom" ) != std::string::npos
2642 || lowerName.find(
"bot" ) != std::string::npos;
2654 if( padsInfo.number == 1 )
2656 else if( padsInfo.number ==
m_parser->GetParameters().layer_count )
2665 info.required = padsInfo.required;
2669 std::vector<INPUT_LAYER_DESC> inputDescs =
2675 int copperLayerCount =
m_parser->GetParameters().layer_count;
2677 if( copperLayerCount < 1 )
2678 copperLayerCount = 2;
2680 m_loadBoard->SetCopperLayerCount( copperLayerCount );
2688 switch(
m_parser->GetParameters().units )
2710 const auto& designRules =
m_parser->GetDesignRules();
2733 if( defaultNetclass )
2735 defaultNetclass->SetClearance(
scaleSize( designRules.default_clearance ) );
2736 defaultNetclass->SetTrackWidth(
scaleSize( designRules.default_track_width ) );
2737 defaultNetclass->SetViaDiameter(
scaleSize( designRules.default_via_size ) );
2738 defaultNetclass->SetViaDrill(
scaleSize( designRules.default_via_drill ) );
2741 const auto& viaDefs =
m_parser->GetViaDefs();
2743 if( !viaDefs.empty() )
2747 const std::string& defaultViaName =
m_parser->GetParameters().default_signal_via;
2748 auto defaultIt = viaDefs.find( defaultViaName );
2750 if( defaultIt == viaDefs.end() )
2751 defaultIt = viaDefs.begin();
2753 int viaDia =
scaleSize( defaultIt->second.size );
2754 int viaDrill =
scaleSize( defaultIt->second.drill );
2759 if( defaultNetclass )
2761 defaultNetclass->SetViaDiameter( viaDia );
2762 defaultNetclass->SetViaDrill( viaDrill );
2765 for(
const auto& [
name, def] : viaDefs )
2769 const auto& netClasses =
m_parser->GetNetClasses();
2771 for(
const auto& nc : netClasses )
2773 if( nc.name.empty() )
2776 wxString ncName = wxString::FromUTF8( nc.name );
2777 std::shared_ptr<NETCLASS> netclass = std::make_shared<NETCLASS>( ncName );
2779 if( nc.clearance > 0 )
2780 netclass->SetClearance(
scaleSize( nc.clearance ) );
2782 if( nc.track_width > 0 )
2783 netclass->SetTrackWidth(
scaleSize( nc.track_width ) );
2785 if( nc.via_size > 0 )
2786 netclass->SetViaDiameter(
scaleSize( nc.via_size ) );
2788 if( nc.via_drill > 0 )
2789 netclass->SetViaDrill(
scaleSize( nc.via_drill ) );
2791 if( nc.diff_pair_width > 0 )
2792 netclass->SetDiffPairWidth(
scaleSize( nc.diff_pair_width ) );
2794 if( nc.diff_pair_gap > 0 )
2795 netclass->SetDiffPairGap(
scaleSize( nc.diff_pair_gap ) );
2799 for(
const std::string& netName : nc.net_names )
2806 const auto& diffPairs =
m_parser->GetDiffPairs();
2808 for(
const auto& dp : diffPairs )
2810 if( dp.name.empty() )
2813 wxString dpClassName =
2814 wxString::Format( wxT(
"DiffPair_%s" ), wxString::FromUTF8( dp.name ) );
2815 std::shared_ptr<NETCLASS> dpNetclass = std::make_shared<NETCLASS>( dpClassName );
2818 dpNetclass->SetDiffPairGap(
scaleSize( dp.gap ) );
2822 dpNetclass->SetDiffPairWidth(
scaleSize( dp.width ) );
2823 dpNetclass->SetTrackWidth(
scaleSize( dp.width ) );
2828 if( !dp.positive_net.empty() )
2834 if( !dp.negative_net.empty() )
2844 const auto& boardOutlines =
m_parser->GetBoardOutlines();
2846 if( !boardOutlines.empty() )
2848 double min_x = std::numeric_limits<double>::max();
2849 double max_x = std::numeric_limits<double>::lowest();
2850 double min_y = std::numeric_limits<double>::max();
2851 double max_y = std::numeric_limits<double>::lowest();
2853 for(
const auto& outline : boardOutlines )
2855 for(
const auto& pt : outline.points )
2857 min_x = std::min( min_x, pt.x );
2858 max_x = std::max( max_x, pt.x );
2859 min_y = std::min( min_y, pt.y );
2860 max_y = std::max( max_y, pt.y );
2864 if( min_x < max_x && min_y < max_y )
2873 std::vector<const PADS_IO::LAYER_INFO*> copperLayerInfos;
2875 for(
const auto& li : padsLayerInfos )
2878 copperLayerInfos.push_back( &li );
2881 bool hasStackupData =
false;
2883 for(
const auto* li : copperLayerInfos )
2885 if( li->layer_thickness > 0.0 || li->dielectric_constant > 0.0 )
2887 hasStackupData =
true;
2892 if( hasStackupData )
2899 std::map<PCB_LAYER_ID, const PADS_IO::LAYER_INFO*> copperInfoMap;
2901 for(
const auto* li : copperLayerInfos )
2906 copperInfoMap[kicadLayer] = li;
2916 auto it = copperInfoMap.find( item->GetBrdLayerId() );
2918 if( it != copperInfoMap.end() )
2920 prevCopperInfo = it->second;
2922 if( it->second->copper_thickness > 0.0 )
2923 item->SetThickness(
scaleSize( it->second->copper_thickness ) );
2928 if( prevCopperInfo )
2939 item->SetColor( wxT(
"White" ) );
2943 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 ...
@ 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.
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.
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