56#include <wx/filename.h>
69 const unsigned PROGRESS_DELTA = 250;
89 std::istringstream istr( aStr );
90 istr.imbue( std::locale::classic() );
100 std::istringstream istr( aStr );
101 istr.imbue( std::locale::classic() );
112 std::ifstream ifs( aFile, std::ios::in | std::ios::binary );
120 ifs.ignore( std::numeric_limits<std::streamsize>::max() );
121 std::streamsize length = ifs.gcount();
123 ifs.seekg( 0, std::ios_base::beg );
125 std::string buffer( std::istreambuf_iterator<char>{ ifs }, {} );
127 std::vector < std::string > row;
131 row.reserve( length / 100 );
137 for(
auto& ch : buffer )
143 if( cell.empty() || cell[0] ==
'"' )
152 row.push_back( cell );
164 row.push_back( cell );
167 rows.push_back( row );
176 cell += std::toupper( ch );
181 if( !cell.empty() || !row.empty() )
183 row.push_back( cell );
185 rows.push_back( row );
199 row =
rows.at( aOffset );
201 catch( std::out_of_range& )
209 if( row[0].back() !=
'A' )
212 std::string row1 = row[1];
213 std::string row2 = row[2];
227 if( row1 ==
"REFDES" && row2 ==
"COMPCLASS" )
230 if( row1 ==
"NETNAME" && row2 ==
"REFDES" )
233 if( row1 ==
"CLASS" && row2 ==
"SUBCLASS" && row3.empty() )
236 if( row1 ==
"GRAPHICDATANAME" && row2 ==
"GRAPHICDATANUMBER" )
239 if( row1 ==
"CLASS" && row2 ==
"SUBCLASS" && row3 ==
"GRAPHICDATANAME" )
242 if( row1 ==
"SYMNAME" && row2 ==
"PINNAME" )
245 if( row1 ==
"SYMNAME" && row2 ==
"SYMMIRROR" && row3 ==
"PINNAME" )
248 if( row1 ==
"VIAX" && row2 ==
"VIAY" )
251 if( row1 ==
"SUBCLASS" && row2 ==
"PADSHAPENAME" )
254 if( row1 ==
"PADNAME" )
257 if( row1 ==
"LAYERSORT" )
260 wxLogError(
_(
"Unknown FABMASTER section %s:%s at row %zu." ),
273 if( aRow >=
rows.size() )
276 if(
rows[aRow].size() < 11 )
278 wxLogError(
_(
"Invalid row size in J row %zu. Expecting 11 elements but found %zu." ),
284 for(
int i = 7; i < 10 && retval < 1.0; ++i )
286 std::string units =
rows[aRow][i];
287 std::transform(units.begin(), units.end(),units.begin(), ::toupper);
289 if( units ==
"MILS" )
291 else if( units ==
"MILLIMETERS" )
293 else if( units ==
"MICRONS" )
295 else if( units ==
"INCHES" )
301 wxLogError(
_(
"Could not find units value, defaulting to mils." ) );
311 if( aRow >=
rows.size() )
314 std::vector<std::string> header =
rows[aRow];
316 for(
size_t i = 0; i < header.size(); i++ )
320 alg::delete_if( header[i], [](
const char c ) {
return c ==
'_'; } );
322 if( header[i] == aStr )
326 THROW_IO_ERROR( wxString::Format(
_(
"Could not find column label %s." ), aStr.c_str() ) );
333 const auto& kicad_layer =
layers.find( aLayerName);
335 if( kicad_layer ==
layers.end() )
338 return static_cast<PCB_LAYER_ID>( kicad_layer->second.layerid );
344 size_t rownum = aRow + 2;
346 if( rownum >=
rows.size() )
364 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
368 if( row.size() != header.size() )
370 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
377 auto& pad_name = row[pad_name_col];
378 auto& pad_num = row[pad_num_col];
379 auto& pad_layer = row[pad_lay_col];
380 auto& pad_is_fixed = row[pad_fix_col];
381 auto& pad_is_via = row[pad_via_col];
382 auto& pad_shape = row[pad_shape_col];
383 auto& pad_width = row[pad_width_col];
384 auto& pad_height = row[pad_height_col];
385 auto& pad_xoff = row[pad_xoff_col];
386 auto& pad_yoff = row[pad_yoff_col];
387 auto& pad_flash = row[pad_flash_col];
388 auto& pad_shapename = row[pad_shape_name_col];
391 if( pad_layer ==
"INTERNAL_PAD_DEF" || pad_layer ==
"internal_pad_def" )
395 if( pad_layer[0] ==
'~' )
404 layer.
name = pad_layer;
422 size_t rownum = aRow + 2;
424 if( rownum >=
rows.size() )
430 if( scale_factor <= 0.0 )
446 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
451 if( row.size() != header.size() )
453 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
460 auto& pad_name = row[pad_name_col];
461 auto& pad_num = row[pad_num_col];
462 auto& pad_layer = row[pad_lay_col];
463 auto& pad_is_fixed = row[pad_fix_col];
464 auto& pad_is_via = row[pad_via_col];
465 auto& pad_shape = row[pad_shape_col];
466 auto& pad_width = row[pad_width_col];
467 auto& pad_height = row[pad_height_col];
468 auto& pad_xoff = row[pad_xoff_col];
469 auto& pad_yoff = row[pad_yoff_col];
470 auto& pad_flash = row[pad_flash_col];
471 auto& pad_shapename = row[pad_shape_name_col];
474 if( pad_layer ==
"INTERNAL_PAD_DEF" || pad_layer ==
"internal_pad_def" )
479 auto new_pad =
pads.find( pad_name );
481 if( new_pad !=
pads.end() )
482 pad = &new_pad->second;
487 pad->name = pad_name;
491 if( pad_layer ==
"~DRILL" )
505 wxLogError(
_(
"Expecting drill size value but found %s!%s!%s in row %zu." ),
523 if( drill_x == drill_y )
525 pad->drill_size_x = drill_hit;
526 pad->drill_size_y = drill_hit;
530 pad->drill_size_x = drill_x;
531 pad->drill_size_y = drill_y;
534 if( !pad_shapename.empty() && pad_shapename[0] ==
'P' )
540 if( pad_shape.empty() )
553 wxLogError(
_(
"Expecting pad size values but found %s : %s in row %zu." ),
563 auto layer =
layers.find( pad_layer );
565 if( layer !=
layers.end() )
567 if( layer->second.layerid ==
F_Cu )
569 else if( layer->second.layerid ==
B_Cu )
573 if( w > std::numeric_limits<int>::max() || h > std::numeric_limits<int>::max() )
575 wxLogError(
_(
"Invalid pad size in row %zu." ), rownum );
579 if( pad_layer ==
"~TSM" || pad_layer ==
"~BSM" )
581 if( w > 0.0 && h > 0.0 )
589 if( pad_layer ==
"~TSP" || pad_layer ==
"~BSP" )
591 if( w > 0.0 && h > 0.0 )
600 if( pad_layer[0] ==
'~' )
610 wxLogError(
_(
"Expecting pad offset values but found %s:%s in row %zu." ),
617 if( w > 0.0 && h > 0.0 && recnum == 1 )
621 pad->via = ( std::toupper( pad_is_via[0] ) !=
'V' );
623 if( pad_shape ==
"CIRCLE" )
626 pad->shape = PAD_SHAPE::CIRCLE;
628 else if( pad_shape ==
"RECTANGLE" )
630 pad->shape = PAD_SHAPE::RECTANGLE;
632 else if( pad_shape ==
"ROUNDED_RECT" )
634 pad->shape = PAD_SHAPE::ROUNDRECT;
636 else if( pad_shape ==
"SQUARE" )
638 pad->shape = PAD_SHAPE::RECTANGLE;
641 else if( pad_shape ==
"OBLONG" || pad_shape ==
"OBLONG_X" || pad_shape ==
"OBLONG_Y" )
642 pad->shape = PAD_SHAPE::OVAL;
643 else if( pad_shape ==
"OCTAGON" )
645 pad->shape = PAD_SHAPE::RECTANGLE;
646 pad->is_octogon =
true;
648 else if( pad_shape ==
"SHAPE" )
650 pad->shape = PAD_SHAPE::CUSTOM;
651 pad->custom_name = pad_shapename;
655 wxLogError(
_(
"Unknown pad shape name '%s' on layer '%s' in row %zu." ),
664 return rownum - aRow;
670 size_t rownum = aRow + 2;
672 if( rownum >=
rows.size() )
675 auto& header =
rows[aRow];
678 if( scale_factor <= 0.0 )
684 if( layer_class_col < 0 || layer_subclass_col < 0 )
687 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
691 if( row.size() != header.size() )
693 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
703 layer.
name = row[layer_subclass_col];
707 if( row[layer_class_col] ==
"ANTI ETCH" )
712 else if( row[layer_class_col] ==
"ETCH" )
718 return rownum - aRow;
726 std::string max_layer_name;
728 std::vector<std::pair<std::string, int>> extra_layers
730 {
"ASSEMBLY_TOP",
F_Fab },
731 {
"ASSEMBLY_BOTTOM",
B_Fab },
732 {
"PLACE_BOUND_TOP",
F_CrtYd },
733 {
"PLACE_BOUND_BOTTOM",
B_CrtYd },
736 std::vector<FABMASTER_LAYER*> layer_order;
745 layer_order.push_back( &layer );
747 else if( layer.
name.find(
"SILK" ) != std::string::npos &&
748 layer.
name.find(
"AUTOSILK" ) == std::string::npos )
750 if( layer.
name.find(
"B" ) != std::string::npos )
755 else if( layer.
name.find(
"MASK" ) != std::string::npos ||
756 layer.
name.find(
"MSK" ) != std::string::npos )
758 if( layer.
name.find(
"B" ) != std::string::npos )
763 else if( layer.
name.find(
"PAST" ) != std::string::npos )
765 if( layer.
name.find(
"B" ) != std::string::npos )
770 else if( layer.
name.find(
"NCLEGEND" ) != std::string::npos )
779 for(
auto layer : layer_order )
780 layer->layerid = layernum++;
784 layer_order.back()->layerid =
B_Cu;
786 for(
auto& new_pair : extra_layers )
790 new_layer.
name = new_pair.first;
791 new_layer.
layerid = new_pair.second;
794 auto result =
layers.emplace( new_pair.first, new_layer );
798 result.first->second.layerid = new_pair.second;
799 result.first->second.disable =
false;
814 size_t rownum = aRow + 2;
816 if( rownum >=
rows.size() )
819 auto& header =
rows[aRow];
822 if( scale_factor <= 0.0 )
830 int layer_er_col =
getColFromName( aRow,
"LAYERDIELECTRICCONSTANT" );
831 int layer_rho_col =
getColFromName( aRow,
"LAYERELECTRICALCONDUCTIVITY" );
834 if( layer_sort_col < 0 || layer_subclass_col < 0 || layer_art_col < 0 || layer_use_col < 0
835 || layer_cond_col < 0 || layer_er_col < 0 || layer_rho_col < 0 || layer_mat_col < 0 )
838 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
842 if( row.size() != header.size() )
844 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
851 auto& layer_sort = row[layer_sort_col];
852 auto& layer_subclass = row[layer_subclass_col];
853 auto& layer_art = row[layer_art_col];
854 auto& layer_use = row[layer_use_col];
855 auto& layer_cond = row[layer_cond_col];
856 auto& layer_er = row[layer_er_col];
857 auto& layer_rho = row[layer_rho_col];
858 auto& layer_mat = row[layer_mat_col];
860 if( layer_mat ==
"AIR" )
865 if( layer_subclass.empty() )
867 if( layer_cond !=
"NO" )
868 layer.
name =
"In.Cu" + layer_sort;
870 layer.
name =
"Dielectric" + layer_sort;
873 layer.
positive = ( layer_art !=
"NEGATIVE" );
878 return rownum - aRow;
889 size_t rownum = aRow + 2;
891 if( rownum >=
rows.size() )
894 auto& header =
rows[aRow];
897 if( scale_factor <= 0.0 )
902 int pad_grdata_name_col =
getColFromName( aRow,
"GRAPHICDATANAME" );
903 int pad_grdata_num_col =
getColFromName( aRow,
"GRAPHICDATANUMBER" );
918 if( pad_subclass_col < 0 || pad_shape_name_col < 0 || pad_grdata1_col < 0 || pad_grdata2_col < 0
919 || pad_grdata3_col < 0 || pad_grdata4_col < 0 || pad_grdata5_col < 0
920 || pad_grdata6_col < 0 || pad_grdata7_col < 0 || pad_grdata8_col < 0
921 || pad_grdata9_col < 0 || pad_stack_name_col < 0 || pad_refdes_col < 0
922 || pad_pin_num_col < 0 )
925 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
929 if( row.size() != header.size() )
931 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
939 auto& pad_layer = row[pad_subclass_col];
940 auto pad_shape_name = row[pad_shape_name_col];
941 auto& pad_record_tag = row[pad_record_tag_col];
956 auto& pad_stack_name = row[pad_stack_name_col];
957 auto& pad_refdes = row[pad_refdes_col];
958 auto& pad_pin_num = row[pad_pin_num_col];
962 std::string prefix(
"FIG_SHAPE " );
964 if( pad_shape_name.length() <= prefix.length()
965 || !std::equal( prefix.begin(), prefix.end(), pad_shape_name.begin() ) )
975 if( std::sscanf( pad_record_tag.c_str(),
"%d %d", &
id, &seq ) != 2 )
977 wxLogError(
_(
"Invalid format for id string '%s' in custom pad row %zu." ),
978 pad_record_tag.c_str(),
983 auto name = pad_shape_name.substr( prefix.length() );
984 name +=
"_" + pad_refdes +
"_" + pad_pin_num;
987 auto& custom_pad = ret.first->second;
993 custom_pad.name =
name;
994 custom_pad.padstack = pad_stack_name;
995 custom_pad.pinnum = pad_pin_num;
996 custom_pad.refdes = pad_refdes;
1003 auto gr_item = std::unique_ptr<GRAPHIC_ITEM>(
processGraphic( gr_data, scale_factor ) );
1007 gr_item->layer = pad_layer;
1008 gr_item->refdes = pad_refdes;
1010 gr_item->subseq = 0;
1015 auto retval = pad_it.first->second.insert( std::move(gr_item ) );
1017 if( !retval.second )
1019 wxLogError(
_(
"Could not insert graphical item %d into padstack '%s'." ),
1021 pad_stack_name.c_str() );
1026 wxLogError(
_(
"Unrecognized pad shape primitive '%s' in row %zu." ),
1032 return rownum - aRow;
1082 angle = endangle - startangle;
1114 new_rect->
width = 0;
1140 if( toks.size() < 8 )
1143 wxLogError(
_(
"Invalid token count. Expected 8 but found %zu." ), toks.size() );
1145 new_text->
width = 0;
1146 new_text->
ital =
false;
1206 size_t rownum = aRow + 2;
1208 if( rownum >=
rows.size() )
1214 if( scale_factor <= 0.0 )
1233 if( geo_name_col < 0 || geo_num_col < 0 || geo_grdata1_col < 0 || geo_grdata2_col < 0
1234 || geo_grdata3_col < 0 || geo_grdata4_col < 0 || geo_grdata5_col < 0
1235 || geo_grdata6_col < 0 || geo_grdata7_col < 0 || geo_grdata8_col < 0
1236 || geo_grdata9_col < 0 || geo_subclass_col < 0 || geo_sym_name_col < 0
1237 || geo_refdes_col < 0 )
1240 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
1244 if( row.size() != header.size() )
1246 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
1253 auto& geo_tag = row[geo_tag_col];
1268 auto& geo_refdes = row[geo_refdes_col];
1276 if( std::sscanf( geo_tag.c_str(),
"%d %d %d", &
id, &seq, &subseq ) < 2 )
1278 wxLogError(
_(
"Invalid format for record_tag string '%s' in row %zu." ),
1284 auto gr_item = std::unique_ptr<GRAPHIC_ITEM>(
processGraphic( gr_data, scale_factor ) );
1288 wxLogDebug( wxT(
"Unhandled graphic item '%s' in row %zu." ),
1295 gr_item->layer = row[geo_subclass_col];
1297 gr_item->subseq = subseq;
1299 if( geo_refdes.empty() )
1304 new_gr.
subclass = row[geo_subclass_col];
1305 new_gr.
refdes = row[geo_refdes_col];
1306 new_gr.
name = row[geo_sym_name_col];
1308 new_gr.
elements = std::make_unique<graphic_element>();
1313 graphic.
elements->emplace( std::move( gr_item ) );
1318 std::map<int, GEOM_GRAPHIC>{} );
1319 auto map_it = sym_gr_it.first->second.emplace(
id,
GEOM_GRAPHIC{} );
1320 auto& gr = map_it.first;
1324 gr->second.subclass = row[geo_subclass_col];
1325 gr->second.refdes = row[geo_refdes_col];
1326 gr->second.name = row[geo_sym_name_col];
1328 gr->second.elements = std::make_unique<graphic_element>();
1331 auto result = gr->second.elements->emplace( std::move( gr_item ) );
1335 return rownum - aRow;
1344 size_t rownum = aRow + 2;
1346 if( rownum >=
rows.size() )
1352 if( scale_factor <= 0.0 )
1361 if( viax_col < 0 || viay_col < 0 || padstack_name_col < 0 || net_name_col < 0
1362 || test_point_col < 0 )
1365 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
1369 if( row.size() != header.size() )
1371 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
1378 vias.emplace_back( std::make_unique<FM_VIA>() );
1383 via->padstack = row[padstack_name_col];
1384 via->net = row[net_name_col];
1385 via->test_point = ( row[test_point_col] ==
"YES" );
1388 return rownum - aRow;
1399 size_t rownum = aRow + 2;
1401 if( rownum >=
rows.size() )
1407 if( scale_factor <= 0.0 )
1413 int grdata_num_col =
getColFromName( aRow,
"GRAPHICDATANUMBER" );
1426 if( class_col < 0 || layer_col < 0 || grdata_name_col < 0 || grdata_num_col < 0
1427 || tag_col < 0 || grdata1_col < 0 || grdata2_col < 0 || grdata3_col < 0
1428 || grdata4_col < 0 || grdata5_col < 0 || grdata6_col < 0 || grdata7_col < 0
1429 || grdata8_col < 0 || grdata9_col < 0 || netname_col < 0 )
1432 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
1436 if( row.size() != header.size() )
1438 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
1458 const std::string& geo_tag = row[tag_col];
1465 if( std::sscanf( geo_tag.c_str(),
"%d %d %d", &
id, &seq, &subseq ) < 2 )
1467 wxLogError(
_(
"Invalid format for record_tag string '%s' in row %zu." ),
1473 auto gr_item = std::unique_ptr<GRAPHIC_ITEM>(
processGraphic( gr_data, scale_factor ) );
1477 wxLogTrace(
traceFabmaster,
_(
"Unhandled graphic item '%s' in row %zu." ),
1483 auto new_trace = std::make_unique<TRACE>();
1485 new_trace->layer = row[layer_col];
1486 new_trace->netname = row[netname_col];
1487 new_trace->lclass = row[class_col];
1489 gr_item->layer = row[layer_col];
1491 gr_item->subseq = subseq;
1494 if( new_trace->lclass ==
"REF DES" )
1496 auto result =
refdes.emplace( std::move( new_trace ) );
1497 auto& ref = *result.first;
1498 ref->segment.emplace( std::move( gr_item ) );
1500 else if( gr_item->width == 0 )
1502 auto result =
zones.emplace( std::move( new_trace ) );
1503 auto& zone = *result.first;
1504 auto gr_result = zone->segment.emplace( std::move( gr_item ) );
1506 if( !gr_result.second )
1508 wxLogError(
_(
"Duplicate item for ID %d and sequence %d in row %zu." ),
1517 auto result =
traces.emplace( std::move( new_trace ) );
1518 auto& trace = *result.first;
1519 auto gr_result = trace->segment.emplace( std::move( gr_item ) );
1521 if( !gr_result.second )
1523 wxLogError(
_(
"Duplicate item for ID %d and sequence %d in row %zu." ),
1531 return rownum - aRow;
1537 if( aSymType ==
"PACKAGE" )
1539 else if( aSymType ==
"DRAFTING")
1541 else if( aSymType ==
"MECHANICAL" )
1543 else if( aSymType ==
"FORMAT" )
1552 if( aCmpClass ==
"IO" )
1554 else if( aCmpClass ==
"IC" )
1556 else if( aCmpClass ==
"DISCRETE" )
1569 size_t rownum = aRow + 2;
1571 if( rownum >=
rows.size() )
1577 if( scale_factor <= 0.0 )
1585 int compinscode_col =
getColFromName( aRow,
"COMPINSERTIONCODE" );
1596 if( refdes_col < 0 || compclass_col < 0 || comppartnum_col < 0 || compheight_col < 0
1597 || compdevlabelcol < 0 || compinscode_col < 0 || symtype_col < 0 || symname_col < 0
1598 || symmirror_col < 0 || symrotate_col < 0 || symx_col < 0 || symy_col < 0
1599 || compvalue_col < 0 || comptol_col < 0 || compvolt_col < 0 )
1602 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
1606 if( row.size() != header.size() )
1608 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
1615 auto cmp = std::make_unique<COMPONENT>();
1617 cmp->refdes = row[refdes_col];
1619 cmp->pn = row[comppartnum_col];
1620 cmp->height = row[compheight_col];
1621 cmp->dev_label = row[compdevlabelcol];
1622 cmp->insert_code = row[compinscode_col];
1624 cmp->name = row[symname_col];
1625 cmp->mirror = ( row[symmirror_col] ==
"YES" );
1626 cmp->rotate =
readDouble( row[symrotate_col] );
1629 cmp->value = row[compvalue_col];
1630 cmp->tol = row[comptol_col];
1631 cmp->voltage = row[compvolt_col];
1637 auto retval =
components.insert( std::make_pair( cmp->refdes, std::vector<std::unique_ptr<COMPONENT>>{} ) );
1642 vec->second.push_back( std::move( cmp ) );
1645 return rownum - aRow;
1655 size_t rownum = aRow + 2;
1657 if( rownum >=
rows.size() )
1663 if( scale_factor <= 0.0 )
1677 if( symname_col < 0 ||symmirror_col < 0 || pinname_col < 0 || pinnum_col < 0 || pinx_col < 0
1678 || piny_col < 0 || padstack_col < 0 || refdes_col < 0 || pinrot_col < 0
1679 || testpoint_col < 0 )
1682 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
1686 if( row.size() != header.size() )
1688 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
1695 auto pin = std::make_unique<PIN>();
1697 pin->name = row[symname_col];
1698 pin->mirror = ( row[symmirror_col] ==
"YES" );
1699 pin->pin_name = row[pinname_col];
1700 pin->pin_number = row[pinnum_col];
1703 pin->padstack = row[padstack_col];
1704 pin->refdes = row[refdes_col];
1707 auto map_it =
pins.find(
pin->refdes );
1709 if( map_it ==
pins.end() )
1711 auto retval =
pins.insert( std::make_pair(
pin->refdes, std::set<std::unique_ptr<PIN>,
1713 map_it = retval.first;
1716 map_it->second.insert( std::move(
pin ) );
1719 return rownum - aRow;
1728 size_t rownum = aRow + 2;
1730 if( rownum >=
rows.size() )
1736 if( scale_factor <= 0.0 )
1746 if( netname_col < 0 || refdes_col < 0 || pinnum_col < 0 || pinname_col < 0 || pingnd_col < 0
1750 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
1754 if( row.size() != header.size() )
1756 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
1764 new_net.
name = row[netname_col];
1765 new_net.
refdes = row[refdes_col];
1766 new_net.
pin_num = row[pinnum_col];
1767 new_net.
pin_name = row[pinname_col];
1768 new_net.
pin_gnd = ( row[pingnd_col] ==
"YES" );
1769 new_net.
pin_pwr = ( row[pinpwr_col] ==
"YES" );
1772 netnames.insert( row[netname_col] );
1775 return rownum - aRow;
1782 for(
size_t i = 0; i <
rows.size(); )
1796 i += std::max( retval, 1 );
1804 i += std::max( retval, 1 );
1812 i += std::max( retval, 1 );
1820 i += std::max( retval, 1 );
1828 i += std::max( retval, 1 );
1836 i += std::max( retval, 1 );
1844 i += std::max( retval, 1 );
1852 i += std::max( retval, 1 );
1860 i += std::max( retval, 1 );
1868 i += std::max( retval, 1 );
1885 for(
auto& zone :
zones )
1895 if( zone->layer ==
"OUTLINE" || zone->layer ==
"DESIGN_OUTLINE" )
1916 std::set<ZONE*> zones_to_delete;
1918 for(
auto zone : aBoard->
Zones() )
1921 if( zone->GetNetCode() > 0 )
1923 zones_to_delete.insert( zone );
1927 for(
auto zone1 : aBoard->
Zones() )
1930 if( zone1->GetNetCode() > 0 )
1935 std::vector<std::vector<ZONE*>> possible_deletions( overlaps.size() );
1937 for(
auto zone2 : aBoard->
Zones() )
1939 if( zone2->GetNetCode() <= 0 )
1944 if( zone1->GetLayer() != zone2->GetLayer() )
1950 for(
auto& pt1 : outline1.
CPoints() )
1954 overlaps[ zone2->GetNetCode() ]++;
1957 for(
auto& pt2 : outline2.
CPoints() )
1962 overlaps[ zone2->GetNetCode() ]++;
1967 size_t max_net_id = 0;
1969 for(
size_t el = 1; el < overlaps.size(); ++el )
1971 if( overlaps[el] > max_net )
1973 max_net = overlaps[el];
1979 zone1->SetNetCode( max_net_id );
1982 for(
auto zone : zones_to_delete )
2001 bool has_multiple = mod.second.size() > 1;
2003 for(
int i = 0; i < mod.second.size(); ++i )
2005 auto& src = mod.second[i];
2009 wxString mod_ref = src->name;
2013 mod_ref.Append( wxString::Format( wxT(
"_%d" ), i ) );
2018 wxString key = !lib_ref.empty() ? lib_ref + wxT(
":" ) + mod_ref : mod_ref;
2021 fpID.
Parse( key,
true );
2030 wxString reference = src->refdes;
2032 if( !std::isalpha( src->refdes[0] ) )
2033 reference.Prepend(
"UNK" );
2041 for(
auto& ref :
refdes )
2044 static_cast<const GRAPHIC_TEXT*
>( ( *( ref->segment.begin() ) ).get() );
2046 if( lsrc->
text == src->refdes )
2053 wxLogTrace(
traceFabmaster, wxS(
"The layer %s is not mapped?" ),
2054 ref->layer.c_str() );
2084 fp->
Add( txt, ADD_MODE::APPEND );
2100 for(
auto& gr_ref : gr_it->second )
2102 auto& graphic = gr_ref.second;
2104 for(
auto& seg : *graphic.elements )
2111 STROKE_PARAMS defaultStroke( ds.GetLineThickness( layer ) );
2113 switch( seg->shape )
2137 if( lsrc->
width == 0 )
2140 fp->
Add( line, ADD_MODE::APPEND );
2154 if( lsrc->
width == 0 )
2160 fp->
Add( circle, ADD_MODE::APPEND );
2175 if( lsrc->
width == 0 )
2181 fp->
Add( arc, ADD_MODE::APPEND );
2206 fp->
Add( rect, ADD_MODE::APPEND );
2241 fp->
Add( txt, ADD_MODE::APPEND );
2250 auto pin_it =
pins.find( src->refdes );
2252 if( pin_it !=
pins.end() )
2254 for(
auto&
pin : pin_it->second )
2256 auto pin_net_it =
pin_nets.find( std::make_pair(
pin->refdes,
2257 pin->pin_number ) );
2258 auto padstack =
pads.find(
pin->padstack );
2259 std::string netname =
"";
2262 netname = pin_net_it->second.name;
2264 auto net_it = netinfo.find( netname );
2266 std::unique_ptr<PAD> newpad = std::make_unique<PAD>( fp );
2268 if( net_it != netinfo.end() )
2269 newpad->SetNet( net_it->second );
2271 newpad->SetNetCode( 0 );
2273 newpad->SetX(
pin->pin_x );
2276 newpad->SetY( 2 * src->y -
pin->pin_y );
2278 newpad->SetY(
pin->pin_y );
2280 newpad->SetNumber(
pin->pin_number );
2282 if( padstack ==
pads.end() )
2284 wxLogError(
_(
"Unable to locate padstack %s in file %s\n" ),
2290 auto&
pad = padstack->second;
2292 newpad->SetShape(
pad.shape );
2294 if(
pad.shape == PAD_SHAPE::CUSTOM )
2298 int pad_size = std::min(
pad.width,
pad.height );
2300 newpad->SetSize(
VECTOR2I( pad_size / 2, pad_size / 2 ) );
2302 std::string custom_name =
pad.custom_name +
"_" +
pin->refdes +
"_" +
2304 auto custom_it =
pad_shapes.find( custom_name );
2310 int last_subseq = 0;
2317 for(
const auto& el : (*custom_it).second.elements )
2324 if(
getLayer( ( *( el.second.begin() ) )->layer ) != primary_layer )
2327 for(
const auto& seg : el.second )
2329 if( seg->subseq > 0 || seg->subseq != last_subseq )
2331 poly_outline.
Polygon(0).back().SetClosed(
true );
2339 if( poly_outline.
VertexCount( 0, hole_idx ) == 0 )
2359 wxLogError(
_(
"Invalid custom pad '%s'. Replacing with "
2361 custom_name.c_str() );
2362 newpad->SetShape( PAD_SHAPE::CIRCLE );
2368 poly_outline.
Move( -newpad->GetPosition() );
2372 poly_outline.
Mirror(
false,
true,
2383 newpad->AddPrimitivePoly( poly_outline, 0,
true );
2387 newpad->MergePrimitivesAsPolygon( &mergedPolygon );
2391 wxLogError(
_(
"Invalid custom pad '%s'. Replacing with "
2393 custom_name.c_str() );
2394 newpad->SetShape( PAD_SHAPE::CIRCLE );
2399 wxLogError(
_(
"Could not find custom pad '%s'." ),
2400 custom_name.c_str() );
2412 newpad->SetAttribute( PAD_ATTRIB::PTH );
2417 newpad->SetAttribute( PAD_ATTRIB::NPTH );
2421 if(
pad.drill_size_x ==
pad.drill_size_y )
2422 newpad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
2424 newpad->SetDrillShape( PAD_DRILL_SHAPE::OBLONG );
2426 newpad->SetDrillSize(
VECTOR2I(
pad.drill_size_x,
pad.drill_size_y ) );
2430 newpad->SetAttribute( PAD_ATTRIB::SMD );
2434 else if(
pad.bottom )
2440 newpad->SetOrientation(
EDA_ANGLE( -src->rotate +
pin->rotation,
2443 newpad->SetOrientation(
EDA_ANGLE( src->rotate -
pin->rotation,
2446 if( newpad->GetSizeX() > 0 || newpad->GetSizeY() > 0 )
2448 fp->
Add( newpad.release(), ADD_MODE::APPEND );
2452 wxLogError(
_(
"Invalid zero-sized pad ignored in\nfile: %s" ),
2464 aBoard->
Add( fp, ADD_MODE::APPEND );
2479 for(
auto& layer :
layers )
2484 layer_set.
set( layer.second.layerid );
2489 for(
auto& layer :
layers )
2491 if( layer.second.conductive )
2494 layer.second.name );
2511 auto net_it = netinfo.find(
via->net );
2512 auto padstack =
pads.find(
via->padstack );
2518 if( net_it != netinfo.end() )
2519 new_via->
SetNet( net_it->second );
2521 if( padstack ==
pads.end() )
2525 if( !ds.m_ViasDimensionsList.empty() )
2527 new_via->
SetWidth( ds.m_ViasDimensionsList[0].m_Diameter );
2528 new_via->
SetDrill( ds.m_ViasDimensionsList[0].m_Drill );
2533 new_via->
SetWidth( ds.m_ViasMinSize );
2538 new_via->
SetDrill( padstack->second.drill_size_x );
2539 new_via->
SetWidth( padstack->second.width );
2542 aBoard->
Add( new_via, ADD_MODE::APPEND );
2556 aBoard->
Add( newnet, ADD_MODE::APPEND );
2566 auto net_it = netinfo.find( aLine->netname );
2568 int last_subseq = 0;
2569 ZONE* new_zone =
nullptr;
2571 for(
const auto& seg : aLine->segment )
2588 if( net_it != netinfo.end() )
2589 trk->
SetNet( net_it->second );
2591 aBoard->
Add( trk, ADD_MODE::APPEND );
2601 if( net_it != netinfo.end() )
2602 trk->
SetNet( net_it->second );
2604 aBoard->
Add( trk, ADD_MODE::APPEND );
2616 aBoard->
Add( circle, ADD_MODE::APPEND );
2629 aBoard->
Add( rect, ADD_MODE::APPEND );
2645 aBoard->
Add( txt, ADD_MODE::APPEND );
2650 wxLogError(
_(
"Expecting etch data to be on copper layer. Row found on layer '%s'" ),
2651 seg->layer.c_str() );
2662 int last_subseq = 0;
2667 for(
const auto& seg : aElement )
2669 if( seg->subseq > 0 || seg->subseq != last_subseq )
2676 if( poly_outline.
VertexCount( 0, hole_idx ) == 0 )
2690 return poly_outline;
2696 if( aLine->segment.empty() )
2701 auto new_layer =
getLayer( aLine->layer );
2708 if( aLine->segment.size() < 3 )
2710 for(
const auto& seg : aLine->segment )
2717 STROKE_PARAMS( ( *( aLine->segment.begin() ) )->width, LINE_STYLE::SOLID ) );
2726 new_shape->
SetShape( SHAPE_T::SEGMENT );
2734 new_shape->
SetShape( SHAPE_T::ARC );
2739 aBoard->
Add( new_shape, ADD_MODE::APPEND );
2752 new_poly->
SetShape( SHAPE_T::POLY );
2764 LINE_STYLE::SOLID ) );
2771 aBoard->
Add( new_poly, ADD_MODE::APPEND );
2780 if( aLine->segment.size() < 3 )
2783 int last_subseq = 0;
2786 ZONE* zone =
nullptr;
2789 auto net_it = netinfo.find( aLine->netname );
2791 auto new_layer =
getLayer( aLine->layer );
2796 zone =
new ZONE( aBoard );
2799 if( net_it != netinfo.end() )
2800 zone->
SetNet( net_it->second );
2802 if( aLine->layer ==
"ALL" )
2814 if( aLine->lclass ==
"ROUTE KEEPOUT")
2819 else if( aLine->lclass ==
"VIA KEEPOUT")
2835 for(
const auto& seg : aLine->segment )
2837 if( seg->subseq > 0 && seg->subseq != last_subseq )
2841 if( aLine->lclass ==
"BOUNDARY" )
2845 last_subseq = seg->subseq;
2846 last_subseq = seg->subseq;
2853 if( zone_outline->
VertexCount( 0, hole_idx ) == 0 )
2868 aBoard->
Add( zone, ADD_MODE::APPEND );
2872 delete( zone_outline );
2884 if( aLine->lclass ==
"BOARD GEOMETRY" && aLine->layer !=
"DIMENSION" )
2886 else if( aLine->lclass ==
"DRAWING FORMAT" )
2893 for(
auto& seg : aLine->segment )
2895 switch( seg->shape )
2911 aBoard->
Add( line, ADD_MODE::APPEND );
2925 if( lsrc->
width == 0 )
2928 aBoard->
Add( circle, ADD_MODE::APPEND );
2945 aBoard->
Add( arc, ADD_MODE::APPEND );
2959 aBoard->
Add( rect, ADD_MODE::APPEND );
2976 aBoard->
Add( txt, ADD_MODE::APPEND );
2998 if( geom.subclass ==
"PIN_NUMBER" )
3006 if( !geom.elements->empty() )
3009 if( ( *( geom.elements->begin() ) )->width == 0 )
3026 aBoard->
Add( new_poly, ADD_MODE::APPEND );
3030 for(
auto& seg : *geom.elements )
3032 switch( seg->shape )
3045 aBoard->
Add( line, ADD_MODE::APPEND );
3059 aBoard->
Add( circle, ADD_MODE::APPEND );
3073 aBoard->
Add( arc, ADD_MODE::APPEND );
3087 aBoard->
Add( rect, ADD_MODE::APPEND );
3104 aBoard->
Add( txt, ADD_MODE::APPEND );
3120 std::vector<ZONE*> sortedZones;
3121 std::copy( aBoard->
Zones().begin(), aBoard->
Zones().end(), std::back_inserter( sortedZones ) );
3122 std::sort( sortedZones.begin(), sortedZones.end(),
3123 [&](
const ZONE* a,
const ZONE* b )
3125 if( a->GetLayer() == b->GetLayer() )
3126 return a->GetBoundingBox().GetArea() > b->GetBoundingBox().GetArea();
3128 return a->GetLayer() < b->GetLayer();
3132 unsigned int priority = 0;
3134 for(
ZONE* zone : sortedZones )
3137 if( zone->GetIsRuleArea() )
3140 if( zone->GetLayer() != layer )
3142 layer = zone->GetLayer();
3146 zone->SetAssignedPriority( priority );
3175 for(
auto& track :
traces )
3179 if( track->lclass ==
"ETCH" )
3181 else if( track->layer ==
"OUTLINE" || track->layer ==
"DIMENSION" )
constexpr EDA_IU_SCALE pcbIUScale
BASE_SET & set(size_t pos=std::numeric_limits< size_t >::max(), bool value=true)
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.
const ZONES & Zones() const
bool SetLayerName(PCB_LAYER_ID aLayer, const wxString &aLayerName)
Changes the name of the layer given by aLayer.
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayer) const
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
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.
int GetWidth() const override
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
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 SetLocalClearance(std::optional< int > aClearance)
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 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_0
static constexpr EDA_ANGLE ANGLE_360
static const wxChar traceFabmaster[]
Flag to enable FABMASTER plugin debugging output.
#define THROW_IO_ERROR(msg)
bool IsPcbLayer(int aLayer)
Test whether a layer is a valid layer for Pcbnew.
constexpr PCB_LAYER_ID PCBNEW_LAYER_ID_START
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
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)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
VECTOR2< int32_t > VECTOR2I