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 )
2158 circle->
Flip( circle->
GetCenter(), FLIP_DIRECTION::TOP_BOTTOM );
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;
2294 if(
pad.shape == PAD_SHAPE::CUSTOM )
2298 int pad_size = std::min(
pad.width,
pad.height );
2301 VECTOR2I( pad_size / 2, pad_size / 2 ) );
2303 std::string custom_name =
pad.custom_name +
"_" +
pin->refdes +
"_" +
2305 auto custom_it =
pad_shapes.find( custom_name );
2311 int last_subseq = 0;
2318 for(
const auto& el : (*custom_it).second.elements )
2325 if(
getLayer( ( *( el.second.begin() ) )->layer ) != primary_layer )
2328 for(
const auto& seg : el.second )
2330 if( seg->subseq > 0 || seg->subseq != last_subseq )
2332 poly_outline.
Polygon(0).back().SetClosed(
true );
2340 if( poly_outline.
VertexCount( 0, hole_idx ) == 0 )
2360 wxLogError(
_(
"Invalid custom pad '%s'. Replacing with "
2362 custom_name.c_str() );
2363 newpad->SetShape(
F_Cu, PAD_SHAPE::CIRCLE );
2369 poly_outline.
Move( -newpad->GetPosition() );
2374 FLIP_DIRECTION::TOP_BOTTOM );
2392 wxLogError(
_(
"Invalid custom pad '%s'. Replacing with "
2394 custom_name.c_str() );
2400 wxLogError(
_(
"Could not find custom pad '%s'." ),
2401 custom_name.c_str() );
2414 newpad->SetAttribute( PAD_ATTRIB::PTH );
2419 newpad->SetAttribute( PAD_ATTRIB::NPTH );
2423 if(
pad.drill_size_x ==
pad.drill_size_y )
2424 newpad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
2426 newpad->SetDrillShape( PAD_DRILL_SHAPE::OBLONG );
2428 newpad->SetDrillSize(
VECTOR2I(
pad.drill_size_x,
pad.drill_size_y ) );
2432 newpad->SetAttribute( PAD_ATTRIB::SMD );
2436 else if(
pad.bottom )
2442 newpad->SetOrientation(
EDA_ANGLE( -src->rotate +
pin->rotation,
2445 newpad->SetOrientation(
EDA_ANGLE( src->rotate -
pin->rotation,
2448 if( newpad->GetSizeX() > 0 || newpad->GetSizeY() > 0 )
2450 fp->
Add( newpad.release(), ADD_MODE::APPEND );
2454 wxLogError(
_(
"Invalid zero-sized pad ignored in\nfile: %s" ),
2466 aBoard->
Add( fp, ADD_MODE::APPEND );
2481 for(
auto& layer :
layers )
2486 layer_set.
set( layer.second.layerid );
2491 for(
auto& layer :
layers )
2493 if( layer.second.conductive )
2496 layer.second.name );
2513 auto net_it = netinfo.find(
via->net );
2514 auto padstack =
pads.find(
via->padstack );
2520 if( net_it != netinfo.end() )
2521 new_via->
SetNet( net_it->second );
2523 if( padstack ==
pads.end() )
2527 if( !ds.m_ViasDimensionsList.empty() )
2530 new_via->
SetDrill( ds.m_ViasDimensionsList[0].m_Drill );
2540 new_via->
SetDrill( padstack->second.drill_size_x );
2544 aBoard->
Add( new_via, ADD_MODE::APPEND );
2558 aBoard->
Add( newnet, ADD_MODE::APPEND );
2568 auto net_it = netinfo.find( aLine->netname );
2570 int last_subseq = 0;
2571 ZONE* new_zone =
nullptr;
2573 for(
const auto& seg : aLine->segment )
2590 if( net_it != netinfo.end() )
2591 trk->
SetNet( net_it->second );
2593 aBoard->
Add( trk, ADD_MODE::APPEND );
2603 if( net_it != netinfo.end() )
2604 trk->
SetNet( net_it->second );
2606 aBoard->
Add( trk, ADD_MODE::APPEND );
2618 aBoard->
Add( circle, ADD_MODE::APPEND );
2631 aBoard->
Add( rect, ADD_MODE::APPEND );
2647 aBoard->
Add( txt, ADD_MODE::APPEND );
2652 wxLogError(
_(
"Expecting etch data to be on copper layer. Row found on layer '%s'" ),
2653 seg->layer.c_str() );
2664 int last_subseq = 0;
2669 for(
const auto& seg : aElement )
2671 if( seg->subseq > 0 || seg->subseq != last_subseq )
2678 if( poly_outline.
VertexCount( 0, hole_idx ) == 0 )
2692 return poly_outline;
2698 if( aLine->segment.empty() )
2703 auto new_layer =
getLayer( aLine->layer );
2710 if( aLine->segment.size() < 3 )
2712 for(
const auto& seg : aLine->segment )
2719 STROKE_PARAMS( ( *( aLine->segment.begin() ) )->width, LINE_STYLE::SOLID ) );
2728 new_shape->
SetShape( SHAPE_T::SEGMENT );
2736 new_shape->
SetShape( SHAPE_T::ARC );
2741 aBoard->
Add( new_shape, ADD_MODE::APPEND );
2754 new_poly->
SetShape( SHAPE_T::POLY );
2766 LINE_STYLE::SOLID ) );
2773 aBoard->
Add( new_poly, ADD_MODE::APPEND );
2782 if( aLine->segment.size() < 3 )
2785 int last_subseq = 0;
2788 ZONE* zone =
nullptr;
2791 auto net_it = netinfo.find( aLine->netname );
2793 auto new_layer =
getLayer( aLine->layer );
2798 zone =
new ZONE( aBoard );
2801 if( net_it != netinfo.end() )
2802 zone->
SetNet( net_it->second );
2804 if( aLine->layer ==
"ALL" )
2816 if( aLine->lclass ==
"ROUTE KEEPOUT")
2821 else if( aLine->lclass ==
"VIA KEEPOUT")
2837 for(
const auto& seg : aLine->segment )
2839 if( seg->subseq > 0 && seg->subseq != last_subseq )
2843 if( aLine->lclass ==
"BOUNDARY" )
2847 last_subseq = seg->subseq;
2848 last_subseq = seg->subseq;
2855 if( zone_outline->
VertexCount( 0, hole_idx ) == 0 )
2870 aBoard->
Add( zone, ADD_MODE::APPEND );
2874 delete( zone_outline );
2886 if( aLine->lclass ==
"BOARD GEOMETRY" && aLine->layer !=
"DIMENSION" )
2888 else if( aLine->lclass ==
"DRAWING FORMAT" )
2895 for(
auto& seg : aLine->segment )
2897 switch( seg->shape )
2913 aBoard->
Add( line, ADD_MODE::APPEND );
2927 if( lsrc->
width == 0 )
2930 aBoard->
Add( circle, ADD_MODE::APPEND );
2947 aBoard->
Add( arc, ADD_MODE::APPEND );
2961 aBoard->
Add( rect, ADD_MODE::APPEND );
2978 aBoard->
Add( txt, ADD_MODE::APPEND );
3000 if( geom.subclass ==
"PIN_NUMBER" )
3008 if( !geom.elements->empty() )
3011 if( ( *( geom.elements->begin() ) )->width == 0 )
3028 aBoard->
Add( new_poly, ADD_MODE::APPEND );
3032 for(
auto& seg : *geom.elements )
3034 switch( seg->shape )
3047 aBoard->
Add( line, ADD_MODE::APPEND );
3061 aBoard->
Add( circle, ADD_MODE::APPEND );
3075 aBoard->
Add( arc, ADD_MODE::APPEND );
3089 aBoard->
Add( rect, ADD_MODE::APPEND );
3106 aBoard->
Add( txt, ADD_MODE::APPEND );
3122 std::vector<ZONE*> sortedZones;
3123 std::copy( aBoard->
Zones().begin(), aBoard->
Zones().end(), std::back_inserter( sortedZones ) );
3124 std::sort( sortedZones.begin(), sortedZones.end(),
3125 [&](
const ZONE* a,
const ZONE* b )
3127 if( a->GetLayer() == b->GetLayer() )
3128 return a->GetBoundingBox().GetArea() > b->GetBoundingBox().GetArea();
3130 return a->GetLayer() < b->GetLayer();
3134 unsigned int priority = 0;
3136 for(
ZONE* zone : sortedZones )
3139 if( zone->GetIsRuleArea() )
3142 if( zone->GetLayer() != layer )
3144 layer = zone->GetLayer();
3148 zone->SetAssignedPriority( priority );
3177 for(
auto& track :
traces )
3181 if( track->lclass ==
"ETCH" )
3183 else if( track->layer ==
"OUTLINE" || track->layer ==
"DIMENSION" )
constexpr EDA_IU_SCALE pcbIUScale
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
BASE_SET & set(size_t pos)
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.
constexpr 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)
Set the text to be italic - this will also update the font if needed.
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 constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
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
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
int GetWidth() const override
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
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 SetEnd(const VECTOR2I &aEnd)
void SetStart(const VECTOR2I &aStart)
virtual void SetWidth(int aWidth)
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
void SetWidth(int aWidth) 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.
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.
void Mirror(const VECTOR2I &aRef, FLIP_DIRECTION aFlipDirection)
Mirror the line points about y or x (or both)
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 SetLayerSet(const LSET &aLayerSet) override
void SetDoNotAllowVias(bool aEnable)
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.
VECTOR2< int32_t > VECTOR2I