56#include <wx/filename.h>
61 const unsigned PROGRESS_DELTA = 250;
81 std::istringstream istr( aStr );
82 istr.imbue( std::locale::classic() );
92 std::istringstream istr( aStr );
93 istr.imbue( std::locale::classic() );
104 std::ifstream ifs( aFile, std::ios::in | std::ios::binary );
112 ifs.ignore( std::numeric_limits<std::streamsize>::max() );
113 std::streamsize length = ifs.gcount();
115 ifs.seekg( 0, std::ios_base::beg );
117 std::string buffer( std::istreambuf_iterator<char>{ ifs }, {} );
119 std::vector < std::string > row;
123 row.reserve( length / 100 );
129 for(
auto& ch : buffer )
135 if( cell.empty() || cell[0] ==
'"' )
144 row.push_back( cell );
156 row.push_back( cell );
159 rows.push_back( row );
168 cell += std::toupper( ch );
173 if( !cell.empty() || !row.empty() )
175 row.push_back( cell );
177 rows.push_back( row );
189 row =
rows.at( aOffset );
191 catch( std::out_of_range& )
199 if( row[0].back() !=
'A' )
202 std::string row1 = row[1];
203 std::string row2 = row[2];
216 if( row1 ==
"REFDES" && row2 ==
"COMPCLASS" )
219 if( row1 ==
"NETNAME" && row2 ==
"REFDES" )
222 if( row1 ==
"CLASS" && row2 ==
"SUBCLASS" && row3.empty() )
225 if( row1 ==
"GRAPHICDATANAME" && row2 ==
"GRAPHICDATANUMBER" )
228 if( row1 ==
"CLASS" && row2 ==
"SUBCLASS" && row3 ==
"GRAPHICDATANAME" )
231 if( row1 ==
"SYMNAME" && row2 ==
"PINNAME" )
234 if( row1 ==
"SYMNAME" && row2 ==
"SYMMIRROR" && row3 ==
"PINNAME" )
237 if( row1 ==
"VIAX" && row2 ==
"VIAY" )
240 if( row1 ==
"SUBCLASS" && row2 ==
"PADSHAPENAME" )
243 if( row1 ==
"PADNAME" )
246 if( row1 ==
"LAYERSORT" )
249 wxLogError(
_(
"Unknown FABMASTER section %s:%s at row %zu." ),
261 if( aRow >=
rows.size() )
264 if(
rows[aRow].size() < 11 )
266 wxLogError(
_(
"Invalid row size in J row %zu. Expecting 11 elements but found %zu." ),
272 for(
int i = 7; i < 10 && retval < 1.0; ++i )
274 std::string units =
rows[aRow][i];
275 std::transform(units.begin(), units.end(),units.begin(), ::toupper);
277 if( units ==
"MILS" )
279 else if( units ==
"MILLIMETERS" )
281 else if( units ==
"MICRONS" )
283 else if( units ==
"INCHES" )
289 wxLogError(
_(
"Could not find units value, defaulting to mils." ) );
298 if( aRow >=
rows.size() )
301 std::vector<std::string> header =
rows[aRow];
303 for(
size_t i = 0; i < header.size(); i++ )
307 alg::delete_if( header[i], [](
const char c ) {
return c ==
'_'; } );
309 if( header[i] == aStr )
313 THROW_IO_ERROR( wxString::Format(
_(
"Could not find column label %s." ), aStr.c_str() ) );
320 const auto& kicad_layer =
layers.find( aLayerName);
322 if( kicad_layer ==
layers.end() )
325 return static_cast<PCB_LAYER_ID>( kicad_layer->second.layerid );
331 size_t rownum = aRow + 2;
333 if( rownum >=
rows.size() )
351 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
355 if( row.size() != header.size() )
357 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
364 auto pad_name = row[pad_name_col];
365 auto pad_num = row[pad_num_col];
366 auto pad_layer = row[pad_lay_col];
367 auto pad_is_fixed = row[pad_fix_col];
368 auto pad_is_via = row[pad_via_col];
369 auto pad_shape = row[pad_shape_col];
370 auto pad_width = row[pad_width_col];
371 auto pad_height = row[pad_height_col];
372 auto pad_xoff = row[pad_xoff_col];
373 auto pad_yoff = row[pad_yoff_col];
374 auto pad_flash = row[pad_flash_col];
375 auto pad_shapename = row[pad_shape_name_col];
378 if( pad_layer ==
"INTERNAL_PAD_DEF" || pad_layer ==
"internal_pad_def" )
382 if( pad_layer[0] ==
'~' )
391 layer.
name = pad_layer;
409 size_t rownum = aRow + 2;
411 if( rownum >=
rows.size() )
417 if( scale_factor <= 0.0 )
433 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
438 if( row.size() != header.size() )
440 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
447 auto pad_name = row[pad_name_col];
448 auto pad_num = row[pad_num_col];
449 auto pad_layer = row[pad_lay_col];
450 auto pad_is_fixed = row[pad_fix_col];
451 auto pad_is_via = row[pad_via_col];
452 auto pad_shape = row[pad_shape_col];
453 auto pad_width = row[pad_width_col];
454 auto pad_height = row[pad_height_col];
455 auto pad_xoff = row[pad_xoff_col];
456 auto pad_yoff = row[pad_yoff_col];
457 auto pad_flash = row[pad_flash_col];
458 auto pad_shapename = row[pad_shape_name_col];
461 if( pad_layer ==
"INTERNAL_PAD_DEF" || pad_layer ==
"internal_pad_def" )
466 auto new_pad =
pads.find( pad_name );
468 if( new_pad !=
pads.end() )
469 pad = &new_pad->second;
474 pad->name = pad_name;
478 if( pad_layer ==
"~DRILL" )
492 wxLogError(
_(
"Expecting drill size value but found %s!%s!%s in row %zu." ),
510 if( drill_x == drill_y )
512 pad->drill_size_x = drill_hit;
513 pad->drill_size_y = drill_hit;
517 pad->drill_size_x = drill_x;
518 pad->drill_size_y = drill_y;
521 if( !pad_shapename.empty() && pad_shapename[0] ==
'P' )
527 if( pad_shape.empty() )
540 wxLogError(
_(
"Expecting pad size values but found %s : %s in row %zu." ),
550 auto layer =
layers.find( pad_layer );
552 if( layer !=
layers.end() )
554 if( layer->second.layerid ==
F_Cu )
556 else if( layer->second.layerid ==
B_Cu )
560 if( w > std::numeric_limits<int>::max() || h > std::numeric_limits<int>::max() )
562 wxLogError(
_(
"Invalid pad size in row %zu." ), rownum );
566 if( pad_layer ==
"~TSM" || pad_layer ==
"~BSM" )
568 if( w > 0.0 && h > 0.0 )
576 if( pad_layer ==
"~TSP" || pad_layer ==
"~BSP" )
578 if( w > 0.0 && h > 0.0 )
587 if( pad_layer[0] ==
'~' )
597 wxLogError(
_(
"Expecting pad offset values but found %s:%s in row %zu." ),
604 if( w > 0.0 && h > 0.0 && recnum == 1 )
608 pad->via = ( std::toupper( pad_is_via[0] ) !=
'V' );
610 if( pad_shape ==
"CIRCLE" )
613 pad->shape = PAD_SHAPE::CIRCLE;
615 else if( pad_shape ==
"RECTANGLE" )
617 pad->shape = PAD_SHAPE::RECTANGLE;
619 else if( pad_shape ==
"ROUNDED_RECT" )
621 pad->shape = PAD_SHAPE::ROUNDRECT;
623 else if( pad_shape ==
"SQUARE" )
625 pad->shape = PAD_SHAPE::RECTANGLE;
628 else if( pad_shape ==
"OBLONG" || pad_shape ==
"OBLONG_X" || pad_shape ==
"OBLONG_Y" )
629 pad->shape = PAD_SHAPE::OVAL;
630 else if( pad_shape ==
"OCTAGON" )
632 pad->shape = PAD_SHAPE::RECTANGLE;
633 pad->is_octogon =
true;
635 else if( pad_shape ==
"SHAPE" )
637 pad->shape = PAD_SHAPE::CUSTOM;
638 pad->custom_name = pad_shapename;
642 wxLogError(
_(
"Unknown pad shape name '%s' on layer '%s' in row %zu." ),
651 return rownum - aRow;
657 size_t rownum = aRow + 2;
659 if( rownum >=
rows.size() )
662 auto header =
rows[aRow];
665 if( scale_factor <= 0.0 )
671 if( layer_class_col < 0 || layer_subclass_col < 0 )
674 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
678 if( row.size() != header.size() )
680 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
690 layer.
name = row[layer_subclass_col];
694 if( row[layer_class_col] ==
"ANTI ETCH" )
699 else if( row[layer_class_col] ==
"ETCH" )
705 return rownum - aRow;
713 std::string max_layer_name;
715 std::vector<std::pair<std::string, int>> extra_layers
717 {
"ASSEMBLY_TOP",
F_Fab },
718 {
"ASSEMBLY_BOTTOM",
B_Fab },
719 {
"PLACE_BOUND_TOP",
F_CrtYd },
720 {
"PLACE_BOUND_BOTTOM",
B_CrtYd },
723 std::vector<FABMASTER_LAYER*> layer_order;
732 layer_order.push_back( &layer );
734 else if( layer.
name.find(
"SILK" ) != std::string::npos &&
735 layer.
name.find(
"AUTOSILK" ) == std::string::npos )
737 if( layer.
name.find(
"B" ) != std::string::npos )
742 else if( layer.
name.find(
"MASK" ) != std::string::npos ||
743 layer.
name.find(
"MSK" ) != std::string::npos )
745 if( layer.
name.find(
"B" ) != std::string::npos )
750 else if( layer.
name.find(
"PAST" ) != std::string::npos )
752 if( layer.
name.find(
"B" ) != std::string::npos )
757 else if( layer.
name.find(
"NCLEGEND" ) != std::string::npos )
766 for(
auto layer : layer_order )
767 layer->layerid = layernum++;
771 layer_order.back()->layerid =
B_Cu;
773 for(
auto& new_pair : extra_layers )
777 new_layer.
name = new_pair.first;
778 new_layer.
layerid = new_pair.second;
781 auto result =
layers.emplace( new_pair.first, new_layer );
785 result.first->second.layerid = new_pair.second;
786 result.first->second.disable =
false;
801 size_t rownum = aRow + 2;
803 if( rownum >=
rows.size() )
806 auto header =
rows[aRow];
809 if( scale_factor <= 0.0 )
817 int layer_er_col =
getColFromName( aRow,
"LAYERDIELECTRICCONSTANT" );
818 int layer_rho_col =
getColFromName( aRow,
"LAYERELECTRICALCONDUCTIVITY" );
821 if( layer_sort_col < 0 || layer_subclass_col < 0 || layer_art_col < 0 || layer_use_col < 0
822 || layer_cond_col < 0 || layer_er_col < 0 || layer_rho_col < 0 || layer_mat_col < 0 )
825 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
829 if( row.size() != header.size() )
831 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
838 auto layer_sort = row[layer_sort_col];
839 auto layer_subclass = row[layer_subclass_col];
840 auto layer_art = row[layer_art_col];
841 auto layer_use = row[layer_use_col];
842 auto layer_cond = row[layer_cond_col];
843 auto layer_er = row[layer_er_col];
844 auto layer_rho = row[layer_rho_col];
845 auto layer_mat = row[layer_mat_col];
847 if( layer_mat ==
"AIR" )
852 if( layer_subclass.empty() )
854 if( layer_cond !=
"NO" )
855 layer.
name =
"In.Cu" + layer_sort;
857 layer.
name =
"Dielectric" + layer_sort;
860 layer.
positive = ( layer_art !=
"NEGATIVE" );
865 return rownum - aRow;
876 size_t rownum = aRow + 2;
878 if( rownum >=
rows.size() )
881 auto header =
rows[aRow];
884 if( scale_factor <= 0.0 )
889 int pad_grdata_name_col =
getColFromName( aRow,
"GRAPHICDATANAME" );
890 int pad_grdata_num_col =
getColFromName( aRow,
"GRAPHICDATANUMBER" );
905 if( pad_subclass_col < 0 || pad_shape_name_col < 0 || pad_grdata1_col < 0 || pad_grdata2_col < 0
906 || pad_grdata3_col < 0 || pad_grdata4_col < 0 || pad_grdata5_col < 0
907 || pad_grdata6_col < 0 || pad_grdata7_col < 0 || pad_grdata8_col < 0
908 || pad_grdata9_col < 0 || pad_stack_name_col < 0 || pad_refdes_col < 0
909 || pad_pin_num_col < 0 )
912 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
916 if( row.size() != header.size() )
918 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
926 auto pad_layer = row[pad_subclass_col];
927 auto pad_shape_name = row[pad_shape_name_col];
928 auto pad_record_tag = row[pad_record_tag_col];
943 auto pad_stack_name = row[pad_stack_name_col];
944 auto pad_refdes = row[pad_refdes_col];
945 auto pad_pin_num = row[pad_pin_num_col];
949 std::string prefix(
"FIG_SHAPE " );
951 if( pad_shape_name.length() <= prefix.length()
952 || !std::equal( prefix.begin(), prefix.end(), pad_shape_name.begin() ) )
962 if( std::sscanf( pad_record_tag.c_str(),
"%d %d", &
id, &seq ) != 2 )
964 wxLogError(
_(
"Invalid format for id string '%s' in custom pad row %zu." ),
965 pad_record_tag.c_str(),
970 auto name = pad_shape_name.substr( prefix.length() );
971 name +=
"_" + pad_refdes +
"_" + pad_pin_num;
974 auto& custom_pad = ret.first->second;
980 custom_pad.name =
name;
981 custom_pad.padstack = pad_stack_name;
982 custom_pad.pinnum = pad_pin_num;
983 custom_pad.refdes = pad_refdes;
990 auto gr_item = std::unique_ptr<GRAPHIC_ITEM>(
processGraphic( gr_data, scale_factor ) );
994 gr_item->layer = pad_layer;
995 gr_item->refdes = pad_refdes;
1001 auto retval = pad_it.first->second.insert( std::move(gr_item ) );
1003 if( !retval.second )
1005 wxLogError(
_(
"Could not insert graphical item %d into padstack '%s'." ),
1007 pad_stack_name.c_str() );
1012 wxLogError(
_(
"Unrecognized pad shape primitive '%s' in row %zu." ),
1018 return rownum - aRow;
1066 angle = endangle - startangle;
1096 new_rect->
width = 0;
1120 if( toks.size() < 8 )
1123 wxLogError(
_(
"Invalid token count. Expected 8 but found %zu." ), toks.size() );
1125 new_text->
width = 0;
1126 new_text->
ital =
false;
1186 size_t rownum = aRow + 2;
1188 if( rownum >=
rows.size() )
1194 if( scale_factor <= 0.0 )
1213 if( geo_name_col < 0 || geo_num_col < 0 || geo_grdata1_col < 0 || geo_grdata2_col < 0
1214 || geo_grdata3_col < 0 || geo_grdata4_col < 0 || geo_grdata5_col < 0
1215 || geo_grdata6_col < 0 || geo_grdata7_col < 0 || geo_grdata8_col < 0
1216 || geo_grdata9_col < 0 || geo_subclass_col < 0 || geo_sym_name_col < 0
1217 || geo_refdes_col < 0 )
1220 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
1224 if( row.size() != header.size() )
1226 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
1233 auto geo_tag = row[geo_tag_col];
1248 auto geo_refdes = row[geo_refdes_col];
1256 if( std::sscanf( geo_tag.c_str(),
"%d %d %d", &
id, &seq, &subseq ) < 2 )
1258 wxLogError(
_(
"Invalid format for record_tag string '%s' in row %zu." ),
1264 auto gr_item = std::unique_ptr<GRAPHIC_ITEM>(
processGraphic( gr_data, scale_factor ) );
1268 wxLogDebug( wxT(
"Unhandled graphic item '%s' in row %zu." ),
1275 gr_item->layer = row[geo_subclass_col];
1277 gr_item->subseq = subseq;
1279 if( geo_refdes.empty() )
1284 new_gr.
subclass = row[geo_subclass_col];
1285 new_gr.
refdes = row[geo_refdes_col];
1286 new_gr.
name = row[geo_sym_name_col];
1288 new_gr.
elements = std::make_unique<graphic_element>();
1293 graphic.
elements->emplace( std::move( gr_item ) );
1298 std::map<int, GEOM_GRAPHIC>{} );
1299 auto map_it = sym_gr_it.first->second.emplace(
id,
GEOM_GRAPHIC{} );
1300 auto& gr = map_it.first;
1304 gr->second.subclass = row[geo_subclass_col];
1305 gr->second.refdes = row[geo_refdes_col];
1306 gr->second.name = row[geo_sym_name_col];
1308 gr->second.elements = std::make_unique<graphic_element>();
1311 auto result = gr->second.elements->emplace( std::move( gr_item ) );
1315 return rownum - aRow;
1324 size_t rownum = aRow + 2;
1326 if( rownum >=
rows.size() )
1332 if( scale_factor <= 0.0 )
1341 if( viax_col < 0 || viay_col < 0 || padstack_name_col < 0 || net_name_col < 0
1342 || test_point_col < 0 )
1345 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
1349 if( row.size() != header.size() )
1351 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
1358 vias.emplace_back( std::make_unique<FM_VIA>() );
1363 via->padstack = row[padstack_name_col];
1364 via->net = row[net_name_col];
1365 via->test_point = ( row[test_point_col] ==
"YES" );
1368 return rownum - aRow;
1379 size_t rownum = aRow + 2;
1381 if( rownum >=
rows.size() )
1387 if( scale_factor <= 0.0 )
1393 int grdata_num_col =
getColFromName( aRow,
"GRAPHICDATANUMBER" );
1406 if( class_col < 0 || layer_col < 0 || grdata_name_col < 0 || grdata_num_col < 0
1407 || tag_col < 0 || grdata1_col < 0 || grdata2_col < 0 || grdata3_col < 0
1408 || grdata4_col < 0 || grdata5_col < 0 || grdata6_col < 0 || grdata7_col < 0
1409 || grdata8_col < 0 || grdata9_col < 0 || netname_col < 0 )
1412 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
1416 if( row.size() != header.size() )
1418 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
1438 const std::string& geo_tag = row[tag_col];
1445 if( std::sscanf( geo_tag.c_str(),
"%d %d %d", &
id, &seq, &subseq ) < 2 )
1447 wxLogError(
_(
"Invalid format for record_tag string '%s' in row %zu." ),
1453 auto gr_item = std::unique_ptr<GRAPHIC_ITEM>(
processGraphic( gr_data, scale_factor ) );
1457 wxLogDebug(
_(
"Unhandled graphic item '%s' in row %zu." ),
1463 auto new_trace = std::make_unique<TRACE>();
1465 new_trace->layer = row[layer_col];
1466 new_trace->netname = row[netname_col];
1467 new_trace->lclass = row[class_col];
1469 gr_item->layer = row[layer_col];
1471 gr_item->subseq = subseq;
1474 if( new_trace->lclass ==
"REF DES" )
1476 auto result =
refdes.emplace( std::move( new_trace ) );
1477 auto& ref = *result.first;
1478 ref->segment.emplace( std::move( gr_item ) );
1480 else if( gr_item->width == 0 )
1482 auto result =
zones.emplace( std::move( new_trace ) );
1483 auto& zone = *result.first;
1484 auto gr_result = zone->segment.emplace( std::move( gr_item ) );
1486 if( !gr_result.second )
1488 wxLogError(
_(
"Duplicate item for ID %d and sequence %d in row %zu." ),
1497 auto result =
traces.emplace( std::move( new_trace ) );
1498 auto& trace = *result.first;
1499 auto gr_result = trace->segment.emplace( std::move( gr_item ) );
1501 if( !gr_result.second )
1503 wxLogError(
_(
"Duplicate item for ID %d and sequence %d in row %zu." ),
1511 return rownum - aRow;
1517 if( aSymType ==
"PACKAGE" )
1519 else if( aSymType ==
"DRAFTING")
1521 else if( aSymType ==
"MECHANICAL" )
1523 else if( aSymType ==
"FORMAT" )
1532 if( aCmpClass ==
"IO" )
1534 else if( aCmpClass ==
"IC" )
1536 else if( aCmpClass ==
"DISCRETE" )
1548 size_t rownum = aRow + 2;
1550 if( rownum >=
rows.size() )
1556 if( scale_factor <= 0.0 )
1564 int compinscode_col =
getColFromName( aRow,
"COMPINSERTIONCODE" );
1575 if( refdes_col < 0 || compclass_col < 0 || comppartnum_col < 0 || compheight_col < 0
1576 || compdevlabelcol < 0 || compinscode_col < 0 || symtype_col < 0 || symname_col < 0
1577 || symmirror_col < 0 || symrotate_col < 0 || symx_col < 0 || symy_col < 0
1578 || compvalue_col < 0 || comptol_col < 0 || compvolt_col < 0 )
1581 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
1585 if( row.size() != header.size() )
1587 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
1594 auto cmp = std::make_unique<COMPONENT>();
1596 cmp->refdes = row[refdes_col];
1598 cmp->pn = row[comppartnum_col];
1599 cmp->height = row[compheight_col];
1600 cmp->dev_label = row[compdevlabelcol];
1601 cmp->insert_code = row[compinscode_col];
1603 cmp->name = row[symname_col];
1604 cmp->mirror = ( row[symmirror_col] ==
"YES" );
1605 cmp->rotate =
readDouble( row[symrotate_col] );
1608 cmp->value = row[compvalue_col];
1609 cmp->tol = row[comptol_col];
1610 cmp->voltage = row[compvolt_col];
1616 auto retval =
components.insert( std::make_pair( cmp->refdes, std::vector<std::unique_ptr<COMPONENT>>{} ) );
1621 vec->second.push_back( std::move( cmp ) );
1624 return rownum - aRow;
1633 size_t rownum = aRow + 2;
1635 if( rownum >=
rows.size() )
1641 if( scale_factor <= 0.0 )
1655 if( symname_col < 0 ||symmirror_col < 0 || pinname_col < 0 || pinnum_col < 0 || pinx_col < 0
1656 || piny_col < 0 || padstack_col < 0 || refdes_col < 0 || pinrot_col < 0
1657 || testpoint_col < 0 )
1660 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
1664 if( row.size() != header.size() )
1666 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
1673 auto pin = std::make_unique<PIN>();
1675 pin->name = row[symname_col];
1676 pin->mirror = ( row[symmirror_col] ==
"YES" );
1677 pin->pin_name = row[pinname_col];
1678 pin->pin_number = row[pinnum_col];
1681 pin->padstack = row[padstack_col];
1682 pin->refdes = row[refdes_col];
1685 auto map_it =
pins.find(
pin->refdes );
1687 if( map_it ==
pins.end() )
1689 auto retval =
pins.insert( std::make_pair(
pin->refdes, std::set<std::unique_ptr<PIN>,
PIN::BY_NUM>{} ) );
1690 map_it = retval.first;
1693 map_it->second.insert( std::move(
pin ) );
1696 return rownum - aRow;
1705 size_t rownum = aRow + 2;
1707 if( rownum >=
rows.size() )
1713 if( scale_factor <= 0.0 )
1723 if( netname_col < 0 || refdes_col < 0 || pinnum_col < 0 || pinname_col < 0 || pingnd_col < 0
1727 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
1731 if( row.size() != header.size() )
1733 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
1741 new_net.
name = row[netname_col];
1742 new_net.
refdes = row[refdes_col];
1743 new_net.
pin_num = row[pinnum_col];
1744 new_net.
pin_name = row[pinname_col];
1745 new_net.
pin_gnd = ( row[pingnd_col] ==
"YES" );
1746 new_net.
pin_pwr = ( row[pinpwr_col] ==
"YES" );
1749 netnames.insert( row[netname_col] );
1752 return rownum - aRow;
1759 for(
size_t i = 0; i <
rows.size(); )
1773 i += std::max( retval, 1 );
1781 i += std::max( retval, 1 );
1789 i += std::max( retval, 1 );
1797 i += std::max( retval, 1 );
1805 i += std::max( retval, 1 );
1813 i += std::max( retval, 1 );
1821 i += std::max( retval, 1 );
1829 i += std::max( retval, 1 );
1837 i += std::max( retval, 1 );
1845 i += std::max( retval, 1 );
1862 for(
auto& zone :
zones )
1872 if( zone->layer ==
"OUTLINE" || zone->layer ==
"DESIGN_OUTLINE" )
1893 std::set<ZONE*> zones_to_delete;
1895 for(
auto zone : aBoard->
Zones() )
1898 if( zone->GetNetCode() > 0 )
1900 zones_to_delete.insert( zone );
1904 for(
auto zone1 : aBoard->
Zones() )
1907 if( zone1->GetNetCode() > 0 )
1912 std::vector<std::vector<ZONE*>> possible_deletions( overlaps.size() );
1914 for(
auto zone2 : aBoard->
Zones() )
1916 if( zone2->GetNetCode() <= 0 )
1921 if( zone1->GetLayer() != zone2->GetLayer() )
1927 for(
auto& pt1 : outline1.
CPoints() )
1931 overlaps[ zone2->GetNetCode() ]++;
1934 for(
auto& pt2 : outline2.
CPoints() )
1939 overlaps[ zone2->GetNetCode() ]++;
1944 size_t max_net_id = 0;
1946 for(
size_t el = 1; el < overlaps.size(); ++el )
1948 if( overlaps[el] > max_net )
1950 max_net = overlaps[el];
1956 zone1->SetNetCode( max_net_id );
1959 for(
auto zone : zones_to_delete )
1978 bool has_multiple = mod.second.size() > 1;
1980 for(
int i = 0; i < mod.second.size(); ++i )
1982 auto& src = mod.second[i];
1986 wxString mod_ref = src->name;
1990 mod_ref.Append( wxString::Format( wxT(
"_%d" ), i ) );
1995 wxString key = !lib_ref.empty() ? lib_ref + wxT(
":" ) + mod_ref : mod_ref;
1998 fpID.
Parse( key,
true );
2006 wxString reference = src->refdes;
2008 if( !std::isalpha( src->refdes[0] ) )
2009 reference.Prepend(
"UNK" );
2017 for(
auto& ref :
refdes )
2020 static_cast<const GRAPHIC_TEXT*
>( ( *( ref->segment.begin() ) ).get() );
2022 if( lsrc->
text == src->refdes )
2029 wxLogDebug(
"The layer %s is not mapped?\n", ref->layer.c_str() );
2057 fp->
Add( txt, ADD_MODE::APPEND );
2073 for(
auto& gr_ref : gr_it->second )
2075 auto& graphic = gr_ref.second;
2077 for(
auto& seg : *graphic.elements )
2084 STROKE_PARAMS defaultStroke( ds.GetLineThickness( layer ) );
2086 switch( seg->shape )
2113 if( lsrc->
width == 0 )
2116 fp->
Add( line, ADD_MODE::APPEND );
2133 if( lsrc->
width == 0 )
2139 fp->
Add( circle, ADD_MODE::APPEND );
2157 if( lsrc->
width == 0 )
2163 fp->
Add( arc, ADD_MODE::APPEND );
2191 fp->
Add( rect, ADD_MODE::APPEND );
2224 fp->
Add( txt, ADD_MODE::APPEND );
2233 auto pin_it =
pins.find( src->refdes );
2235 if( pin_it !=
pins.end() )
2237 for(
auto&
pin : pin_it->second )
2239 auto pin_net_it =
pin_nets.find( std::make_pair(
pin->refdes,
pin->pin_number ) );
2240 auto padstack =
pads.find(
pin->padstack );
2241 std::string netname =
"";
2244 netname = pin_net_it->second.name;
2246 auto net_it = netinfo.find( netname );
2248 std::unique_ptr<PAD> newpad = std::make_unique<PAD>( fp );
2250 if( net_it != netinfo.end() )
2251 newpad->SetNet( net_it->second );
2253 newpad->SetNetCode( 0 );
2255 newpad->SetX(
pin->pin_x );
2258 newpad->SetY( 2 * src->y -
pin->pin_y );
2260 newpad->SetY(
pin->pin_y );
2262 newpad->SetNumber(
pin->pin_number );
2264 if( padstack ==
pads.end() )
2266 wxLogError(
_(
"Unable to locate padstack %s in file %s\n" ),
2272 auto&
pad = padstack->second;
2274 newpad->SetShape(
pad.shape );
2276 if(
pad.shape == PAD_SHAPE::CUSTOM )
2280 int pad_size = std::min(
pad.width,
pad.height );
2282 newpad->SetSize(
VECTOR2I( pad_size / 2, pad_size / 2 ) );
2284 std::string custom_name =
pad.custom_name +
"_" +
pin->refdes +
"_" +
pin->pin_number;
2285 auto custom_it =
pad_shapes.find( custom_name );
2291 int last_subseq = 0;
2298 for(
const auto& el : (*custom_it).second.elements )
2304 if(
getLayer( ( *( el.second.begin() ) )->layer ) != primary_layer )
2307 for(
const auto& seg : el.second )
2309 if( seg->subseq > 0 || seg->subseq != last_subseq )
2311 poly_outline.
Polygon(0).back().SetClosed(
true );
2319 if( poly_outline.
VertexCount( 0, hole_idx ) == 0 )
2337 wxLogError(
_(
"Invalid custom pad '%s'. Replacing with "
2339 custom_name.c_str() );
2340 newpad->SetShape( PAD_SHAPE::CIRCLE );
2346 poly_outline.
Move( -newpad->GetPosition() );
2358 newpad->AddPrimitivePoly( poly_outline, 0,
true );
2362 newpad->MergePrimitivesAsPolygon( &mergedPolygon );
2366 wxLogError(
_(
"Invalid custom pad '%s'. Replacing with "
2368 custom_name.c_str() );
2369 newpad->SetShape( PAD_SHAPE::CIRCLE );
2374 wxLogError(
_(
"Could not find custom pad '%s'." ),
2375 custom_name.c_str() );
2385 newpad->SetAttribute( PAD_ATTRIB::PTH );
2390 newpad->SetAttribute( PAD_ATTRIB::NPTH );
2394 if(
pad.drill_size_x ==
pad.drill_size_y )
2399 newpad->SetDrillSize(
VECTOR2I(
pad.drill_size_x,
pad.drill_size_y ) );
2403 newpad->SetAttribute( PAD_ATTRIB::SMD );
2407 else if(
pad.bottom )
2417 if( newpad->GetSizeX() > 0 || newpad->GetSizeY() > 0 )
2419 fp->
Add( newpad.release(), ADD_MODE::APPEND );
2423 wxLogError(
_(
"Invalid zero-sized pad ignored in\nfile: %s" ),
2435 aBoard->
Add( fp, ADD_MODE::APPEND );
2450 for(
auto& layer :
layers )
2455 layer_set.set( layer.second.layerid );
2460 for(
auto& layer :
layers )
2462 if( layer.second.conductive )
2465 layer.second.name );
2482 auto net_it = netinfo.find(
via->net );
2483 auto padstack =
pads.find(
via->padstack );
2489 if( net_it != netinfo.end() )
2490 new_via->
SetNet( net_it->second );
2492 if( padstack ==
pads.end() )
2496 if( !ds.m_ViasDimensionsList.empty() )
2498 new_via->
SetWidth( ds.m_ViasDimensionsList[0].m_Diameter );
2499 new_via->
SetDrill( ds.m_ViasDimensionsList[0].m_Drill );
2504 new_via->
SetWidth( ds.m_ViasMinSize );
2509 new_via->
SetDrill( padstack->second.drill_size_x );
2510 new_via->
SetWidth( padstack->second.width );
2513 aBoard->
Add( new_via, ADD_MODE::APPEND );
2527 aBoard->
Add( newnet, ADD_MODE::APPEND );
2537 auto net_it = netinfo.find( aLine->netname );
2539 int last_subseq = 0;
2540 ZONE* new_zone =
nullptr;
2542 for(
const auto& seg : aLine->segment )
2559 if( net_it != netinfo.end() )
2560 trk->
SetNet( net_it->second );
2562 aBoard->
Add( trk, ADD_MODE::APPEND );
2572 if( net_it != netinfo.end() )
2573 trk->
SetNet( net_it->second );
2575 aBoard->
Add( trk, ADD_MODE::APPEND );
2580 wxLogError(
_(
"Expecting etch data to be on copper layer. Row found on layer '%s'" ),
2581 seg->layer.c_str() );
2592 int last_subseq = 0;
2597 for(
const auto& seg : aElement )
2599 if( seg->subseq > 0 || seg->subseq != last_subseq )
2606 if( poly_outline.
VertexCount( 0, hole_idx ) == 0 )
2621 return poly_outline;
2627 if( aLine->segment.size() < 3 )
2632 auto new_layer =
getLayer( aLine->layer );
2645 new_poly->
SetShape( SHAPE_T::POLY );
2657 PLOT_DASH_TYPE::SOLID ) );
2664 aBoard->
Add( new_poly, ADD_MODE::APPEND );
2673 if( aLine->segment.size() < 3 )
2676 int last_subseq = 0;
2679 ZONE* zone =
nullptr;
2682 auto net_it = netinfo.find( aLine->netname );
2684 auto new_layer =
getLayer( aLine->layer );
2689 zone =
new ZONE( aBoard );
2692 if( net_it != netinfo.end() )
2693 zone->
SetNet( net_it->second );
2695 if( aLine->layer ==
"ALL" )
2707 if( aLine->lclass ==
"ROUTE KEEPOUT")
2712 else if( aLine->lclass ==
"VIA KEEPOUT")
2728 for(
const auto& seg : aLine->segment )
2730 if( seg->subseq > 0 && seg->subseq != last_subseq )
2733 if( aLine->lclass ==
"BOUNDARY" )
2737 last_subseq = seg->subseq;
2738 last_subseq = seg->subseq;
2745 if( zone_outline->
VertexCount( 0, hole_idx ) == 0 )
2760 aBoard->
Add( zone, ADD_MODE::APPEND );
2764 delete( zone_outline );
2776 if( aLine->lclass ==
"BOARD GEOMETRY" )
2778 else if( aLine->lclass ==
"DRAWING FORMAT" )
2785 for(
auto& seg : aLine->segment )
2787 switch( seg->shape )
2803 aBoard->
Add( line, ADD_MODE::APPEND );
2817 if( lsrc->
width == 0 )
2820 aBoard->
Add( circle, ADD_MODE::APPEND );
2837 aBoard->
Add( arc, ADD_MODE::APPEND );
2851 aBoard->
Add( rect, ADD_MODE::APPEND );
2868 aBoard->
Add( txt, ADD_MODE::APPEND );
2890 if( geom.subclass ==
"PIN_NUMBER" )
2898 if( !geom.elements->empty() )
2901 if( ( *( geom.elements->begin() ) )->width == 0 )
2916 aBoard->
Add( new_poly, ADD_MODE::APPEND );
2920 for(
auto& seg : *geom.elements )
2922 switch( seg->shape )
2935 aBoard->
Add( line, ADD_MODE::APPEND );
2949 aBoard->
Add( circle, ADD_MODE::APPEND );
2963 aBoard->
Add( arc, ADD_MODE::APPEND );
2977 aBoard->
Add( rect, ADD_MODE::APPEND );
2994 aBoard->
Add( txt, ADD_MODE::APPEND );
3010 std::sort( aBoard->
Zones().begin(), aBoard->
Zones().end(),
3011 [&](
const ZONE* a,
const ZONE* b )
3013 if( a->GetLayer() == b->GetLayer() )
3014 return a->GetBoundingBox().GetArea() > b->GetBoundingBox().GetArea();
3016 return a->GetLayer() < b->GetLayer();
3020 unsigned int priority = 0;
3025 if( zone->GetIsRuleArea() )
3028 if( zone->GetLayer() != layer )
3030 layer = zone->GetLayer();
3034 zone->SetAssignedPriority( priority );
3063 for(
auto& track :
traces )
3067 if( track->lclass ==
"ETCH" )
3069 else if( track->layer ==
"OUTLINE" )
constexpr EDA_IU_SCALE pcbIUScale
void SetNet(NETINFO_ITEM *aNetInfo)
Set a NET_INFO object for the item.
int GetLineThickness(PCB_LAYER_ID aLayer) const
Return the default graphic segment thickness from the layer class for the given layer.
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Information pertinent to a Pcbnew printed circuit board.
const NETINFO_LIST & GetNetInfo() const
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
void SetFileName(const wxString &aFileName)
void SetEnabledLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings.
bool SetLayerName(PCB_LAYER_ID aLayer, const wxString &aLayerName)
Changes the name of the layer given by aLayer.
const wxString & GetFileName() const
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
void Remove(BOARD_ITEM *aBoardItem, REMOVE_MODE aMode=REMOVE_MODE::NORMAL) override
Removes an item from the container.
bool Intersects(const BOX2< Vec > &aRect) const
void SetCenter(const VECTOR2I &aCenter)
void SetFilled(bool aFlag)
void SetPolyShape(const SHAPE_POLY_SET &aShape)
void SetStart(const VECTOR2I &aStart)
void SetShape(SHAPE_T aShape)
void SetEnd(const VECTOR2I &aEnd)
void SetArcGeometry(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Set the three controlling points for an arc.
void SetWidth(int aWidth)
void SetTextPos(const VECTOR2I &aPoint)
void SetTextWidth(int aWidth)
virtual void SetVisible(bool aVisible)
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
void SetTextHeight(int aHeight)
virtual void SetText(const wxString &aText)
void SetItalic(bool aItalic)
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
size_t processFootprints(size_t aRow)
A!REFDES!COMP_CLASS!COMP_PART_NUMBER!COMP_HEIGHT!COMP_DEVICE_LABEL!COMP_INSERTION_CODE!...
size_t processPins(size_t aRow)
A!SYM_NAME!SYM_MIRROR!PIN_NAME!PIN_NUMBER!PIN_X!PIN_Y!PAD_STACK_NAME!REFDES!PIN_ROTATION!...
int readInt(const std::string &aStr) const
size_t processGeometry(size_t aRow)
A!GRAPHIC_DATA_NAME!GRAPHIC_DATA_NUMBER!RECORD_TAG!GRAPHIC_DATA_1!GRAPHIC_DATA_2!GRAPHIC_DATA_3!...
bool Read(const std::string &aFile)
bool loadNets(BOARD *aBoard)
std::map< std::string, std::map< int, GEOM_GRAPHIC > > comp_graphics
unsigned m_lastProgressCount
SYMTYPE parseSymType(const std::string &aSymType)
GRAPHIC_TEXT * processText(const GRAPHIC_DATA &aData, double aScale)
bool loadLayers(BOARD *aBoard)
PCB_LAYER_ID getLayer(const std::string &aLayerName)
bool loadZones(BOARD *aBoard)
Loads sections of the database into the board.
GRAPHIC_RECTANGLE * processRectangle(const GRAPHIC_DATA &aData, double aScale)
std::vector< std::string > single_row
size_t processSimpleLayers(size_t aRow)
PROGRESS_REPORTER * m_progressReporter
optional; may be nullptr
bool loadFootprints(BOARD *aBoard)
std::unordered_map< std::string, FM_PAD > pads
int getColFromName(size_t aRow, const std::string &aStr)
bool loadVias(BOARD *aBoard)
size_t processLayers(size_t aRow)
A!LAYER_SORT!LAYER_SUBCLASS!LAYER_ARTWORK!LAYER_USE!LAYER_CONDUCTOR!LAYER_DIELECTRIC_CONSTANT!...
std::map< std::string, FABMASTER_LAYER > layers
COMPCLASS parseCompClass(const std::string &aCompClass)
bool loadEtch(BOARD *aBoard, const std::unique_ptr< TRACE > &aLine)
std::map< std::string, std::set< std::unique_ptr< PIN >, PIN::BY_NUM > > pins
std::set< std::unique_ptr< GRAPHIC_ITEM >, GRAPHIC_ITEM::SEQ_CMP > graphic_element
std::map< std::pair< std::string, std::string >, NETNAME > pin_nets
GRAPHIC_ITEM * processGraphic(const GRAPHIC_DATA &aData, double aScale)
Specialty functions for processing graphical data rows into the internal database.
std::deque< single_row > rows
bool loadOutline(BOARD *aBoard, const std::unique_ptr< TRACE > &aLine)
size_t processPadStacks(size_t aRow)
A!PADNAME!RECNUMBER!LAYER!FIXFLAG!VIAFLAG!PADSHAPE1!PADWIDTH!PADHGHT! PADXOFF!PADYOFF!...
std::vector< GEOM_GRAPHIC > board_graphics
section_type detectType(size_t aOffset)
double readDouble(const std::string &aStr) const
Reads the double/integer value from a std string independent of the user locale.
bool loadZone(BOARD *aBoard, const std::unique_ptr< FABMASTER::TRACE > &aLine)
GRAPHIC_ARC * processArc(const GRAPHIC_DATA &aData, double aScale)
SHAPE_POLY_SET loadShapePolySet(const graphic_element &aLine)
bool loadGraphics(BOARD *aBoard)
std::unordered_map< std::string, FABMASTER_PAD_SHAPE > pad_shapes
bool LoadBoard(BOARD *aBoard, PROGRESS_REPORTER *aProgressReporter)
std::vector< std::unique_ptr< FM_VIA > > vias
std::set< std::unique_ptr< TRACE >, TRACE::BY_ID > traces
std::set< std::unique_ptr< TRACE >, TRACE::BY_ID > zones
std::map< std::string, std::vector< std::unique_ptr< COMPONENT > > > components
bool loadPolygon(BOARD *aBoard, const std::unique_ptr< FABMASTER::TRACE > &aLine)
std::set< std::unique_ptr< TRACE >, TRACE::BY_ID > refdes
@ GR_SHAPE_CIRCLE
! Not actually in Fabmaster but we use for 360° arcs
size_t processPadStackLayers(size_t aRow)
std::set< std::string > netnames
size_t processTraces(size_t aRow)
A!CLASS!SUBCLASS!GRAPHIC_DATA_NAME!GRAPHIC_DATA_NUMBER!RECORD_TAG!GRAPHIC_DATA_1!GRAPHIC_DATA_2!...
size_t processNets(size_t aRow)
A!NET_NAME!REFDES!PIN_NUMBER!PIN_NAME!PIN_GROUND!PIN_POWER!
bool orderZones(BOARD *aBoard)
Sets zone priorities based on zone BB size.
double processScaleFactor(size_t aRow)
Processes data from text vectors into internal database for further ordering.
size_t processVias(size_t aRow)
A!VIA_X!VIA_Y!PAD_STACK_NAME!NET_NAME!TEST_POINT!
unsigned m_totalCount
for progress reporting
size_t processCustomPads(size_t aRow)
A!SUBCLASS!PAD_SHAPE_NAME!GRAPHIC_DATA_NAME!GRAPHIC_DATA_NUMBER!RECORD_TAG!GRAPHIC_DATA_1!...
GRAPHIC_LINE * processLine(const GRAPHIC_DATA &aData, double aScale)
A logical library item identifier and consists of various portions much like a URI.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
LSET is a set of PCB_LAYER_IDs.
static LSET AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Handle the data for a net.
unsigned GetNetCount() const
const NETNAMES_MAP & NetsByName() const
Return the name map, at least for python.
static LSET PTHMask()
layer set for a through hole pad
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
static LSET SMDMask()
layer set for a SMD pad on Front layer
virtual void Flip(const VECTOR2I &aCentre, bool aFlipLeftRight) override
Flip this object, i.e.
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
virtual void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
int GetWidth() const override
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
virtual void Move(const VECTOR2I &aMoveVector) override
Move this object.
void SetStroke(const STROKE_PARAMS &aStroke) override
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
void SetWidth(int aWidth)
void SetEnd(const VECTOR2I &aEnd)
void SetStart(const VECTOR2I &aStart)
void SetDrillDefault()
Set the drill value for vias to the default value UNDEFINED_DRILL_DIAMETER.
void SetDrill(int aDrill)
Set the drill value for vias.
void SetPosition(const VECTOR2I &aPoint) override
A progress reporter interface for use in multi-threaded environments.
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).
const VECTOR2I & GetArcMid() const
const VECTOR2I & GetP1() const
const VECTOR2I & GetP0() const
bool PointOnEdge(const VECTOR2I &aP, int aAccuracy=0) const
Check if point aP lies on an edge or vertex of the line chain.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
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 std::vector< VECTOR2I > & CPoints() const
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
Represent a set of closed polygons.
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
void Fracture(POLYGON_MODE aFastMode)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
int VertexCount(int aOutline=-1, int aHole=-1) const
Return the number of vertices in a given outline/hole.
POLYGON & Polygon(int aIndex)
Return the aIndex-th subpolygon in the set.
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)
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Adds a new hole to the given outline (default: last) and returns its index.
void Mirror(bool aX=true, bool aY=false, const VECTOR2I &aRef={ 0, 0 })
Mirror the line points about y or x (or both)
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
SHAPE_LINE_CHAIN & Hole(int aOutline, int aHole)
Return the reference to aHole-th hole in the aIndex-th outline.
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 Move(const VECTOR2I &aVector) override
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
Simple container to manage line stroke parameters.
Handle a list of polygons defining a copper zone.
void SetDoNotAllowPads(bool aEnable)
void SetDoNotAllowCopperPour(bool aEnable)
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void SetIsRuleArea(bool aEnable)
void SetDoNotAllowTracks(bool aEnable)
void SetDoNotAllowVias(bool aEnable)
void SetLocalClearance(int aClearance)
void SetLayerSet(LSET aLayerSet) override
void SetDoNotAllowFootprints(bool aEnable)
void SetAssignedPriority(unsigned aPriority)
void SetPadConnection(ZONE_CONNECTION aPadConnection)
void SetOutline(SHAPE_POLY_SET *aOutline)
static constexpr EDA_ANGLE & ANGLE_360
static constexpr EDA_ANGLE & ANGLE_0
#define THROW_IO_ERROR(msg)
bool IsPcbLayer(int aLayer)
Test whether a layer is a valid layer for Pcbnew.
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
LSET FlipLayerMask(LSET aMask, int aCopperLayersCount)
Calculate the mask layer when flipping a footprint.
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
void delete_if(_Container &__c, _Function &&__f)
Deletes all values from __c for which __f returns true.
bool ReplaceIllegalFileNameChars(std::string *aName, int aReplaceChar)
Checks aName for illegal file name characters.
static std::vector< std::string > split(const std::string &aStr, const std::string &aDelim)
Split the input string into a vector of output strings.
A!LAYER_SORT!LAYER_SUBCLASS!LAYER_ARTWORK!LAYER_USE!LAYER_CONDUCTOR!LAYER_DIELECTRIC_CONSTANT !...
bool disable
! if true, prevent the layer elements from being used
std::string name
! LAYER_SUBCLASS
int layerid
! pcbnew layer (assigned)
bool conductive
! LAYER_CONDUCTOR
bool positive
! LAYER_ARTWORK (either POSITIVE or NEGATIVE)
A!SUBCLASS!PAD_SHAPE_NAME!GRAPHIC_DATA_NAME!GRAPHIC_DATA_NUMBER!RECORD_TAG!GRAPHIC_DATA_1!...
std::string name
! SYM_NAME
std::string refdes
! REFDES
std::string subclass
! SUBCLASS
std::unique_ptr< graphic_element > elements
int end_x
! GRAPHIC_DATA_3
SHAPE_ARC result
! KiCad-style arc representation
int radius
! GRAPHIC_DATA_7 ! width is GRAPHIC_DATA_8
int center_x
! GRAPHIC_DATA_5
bool clockwise
! GRAPHIC_DATA_9
int center_y
! GRAPHIC_DATA_6
int end_y
! GRAPHIC_DATA_4
std::string graphic_data8
std::string graphic_data1
std::string graphic_dataname
std::string graphic_data6
std::string graphic_data7
std::string graphic_data2
std::string graphic_data3
std::string graphic_data10
std::string graphic_datanum
std::string graphic_data4
std::string graphic_data5
std::string graphic_data9
int width
! Various sections depending on type
GRAPHIC_SHAPE shape
! Shape of the graphic_item
int start_y
! GRAPHIC_DATA_2
int start_x
! GRAPHIC_DATA_1
GRAPHIC_TYPE type
! Type of graphic item
int end_x
! GRAPHIC_DATA_3
int end_y
! GRAPHIC_DATA_4 ! width is GRAPHIC_DATA_5
bool fill
! GRAPHIC_DATA_5
int end_y
! GRAPHIC_DATA_4
int end_x
! GRAPHIC_DATA_3
double rotation
! GRAPHIC_DATA_3
std::string text
! GRAPHIC_DATA_7
int height
! GRAPHIC_DATA_6[2]
int thickness
! GRAPHIC_DATA_6[6]
GR_TEXT_H_ALIGN_T orient
! GRAPHIC_DATA_5
bool ital
! GRAPHIC_DATA_6[4] != 0.0
bool mirror
! GRAPHIC_DATA_4
std::string refdes
!< NET_NAME
std::string pin_num
!< REFDES
std::string pin_name
!< PIN_NUMBER
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".