59#include <wx/filename.h>
72 const unsigned PROGRESS_DELTA = 250;
93 wxCHECK_MSG( !aStr.empty(), 0.0,
"Empty string passed to readDouble" );
95 std::istringstream istr( aStr );
96 istr.imbue( std::locale::classic() );
107 wxCHECK_MSG( !aStr.empty(), 0,
"Empty string passed to readInt" );
109 std::istringstream istr( aStr );
110 istr.imbue( std::locale::classic() );
120 std::ifstream ifs( aFile, std::ios::in | std::ios::binary );
128 ifs.ignore( std::numeric_limits<std::streamsize>::max() );
129 std::streamsize length = ifs.gcount();
131 ifs.seekg( 0, std::ios_base::beg );
133 std::string buffer( std::istreambuf_iterator<char>{ ifs }, {} );
135 std::vector < std::string > row;
139 row.reserve( length / 100 );
145 for(
auto& ch : buffer )
151 if( cell.empty() || cell[0] ==
'"' )
160 row.push_back( cell );
172 row.push_back( cell );
175 rows.push_back( row );
184 cell += std::toupper( ch );
189 if( !cell.empty() || !row.empty() )
191 row.push_back( cell );
193 rows.push_back( row );
207 row =
rows.at( aOffset );
209 catch( std::out_of_range& )
217 if( row[0].back() !=
'A' )
220 std::string row1 = row[1];
221 std::string row2 = row[2];
235 if( row1 ==
"REFDES" && row2 ==
"COMPCLASS" )
238 if( row1 ==
"NETNAME" && row2 ==
"REFDES" )
241 if( row1 ==
"CLASS" && row2 ==
"SUBCLASS" && row3.empty() )
244 if( row1 ==
"GRAPHICDATANAME" && row2 ==
"GRAPHICDATANUMBER" )
247 if( row1 ==
"CLASS" && row2 ==
"SUBCLASS" && row3 ==
"GRAPHICDATANAME" )
250 if( row1 ==
"SYMNAME" && row2 ==
"PINNAME" )
253 if( row1 ==
"SYMNAME" && row2 ==
"SYMMIRROR" && row3 ==
"PINNAME" )
256 if( row1 ==
"VIAX" && row2 ==
"VIAY" )
259 if( row1 ==
"SUBCLASS" && row2 ==
"PADSHAPENAME" )
262 if( row1 ==
"PADNAME" )
265 if( row1 ==
"LAYERSORT" )
268 wxLogError(
_(
"Unknown FABMASTER section %s:%s at row %zu." ),
281 if( aRow >=
rows.size() )
284 if(
rows[aRow].size() < 11 )
286 wxLogError(
_(
"Invalid row size in J row %zu. Expecting 11 elements but found %zu." ),
292 for(
int i = 7; i < 10 && retval < 1.0; ++i )
294 std::string units =
rows[aRow][i];
295 std::transform(units.begin(), units.end(),units.begin(), ::toupper);
297 if( units ==
"MILS" )
299 else if( units ==
"MILLIMETERS" )
301 else if( units ==
"MICRONS" )
303 else if( units ==
"INCHES" )
309 wxLogError(
_(
"Could not find units value, defaulting to mils." ) );
319 if( aRow >=
rows.size() )
322 std::vector<std::string> header =
rows[aRow];
324 for(
size_t i = 0; i < header.size(); i++ )
328 alg::delete_if( header[i], [](
const char c ) {
return c ==
'_'; } );
330 if( header[i] == aStr )
334 THROW_IO_ERROR( wxString::Format(
_(
"Could not find column label %s." ), aStr.c_str() ) );
341 const auto& kicad_layer =
layers.find( aLayerName);
343 if( kicad_layer ==
layers.end() )
346 return static_cast<PCB_LAYER_ID>( kicad_layer->second.layerid );
352 size_t rownum = aRow + 2;
354 if( rownum >=
rows.size() )
372 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
376 if( row.size() != header.size() )
378 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
385 auto& pad_name = row[pad_name_col];
386 auto& pad_num = row[pad_num_col];
387 auto& pad_layer = row[pad_lay_col];
388 auto& pad_is_fixed = row[pad_fix_col];
389 auto& pad_is_via = row[pad_via_col];
390 auto& pad_shape = row[pad_shape_col];
391 auto& pad_width = row[pad_width_col];
392 auto& pad_height = row[pad_height_col];
393 auto& pad_xoff = row[pad_xoff_col];
394 auto& pad_yoff = row[pad_yoff_col];
395 auto& pad_flash = row[pad_flash_col];
396 auto& pad_shapename = row[pad_shape_name_col];
399 if( pad_layer ==
"INTERNAL_PAD_DEF" || pad_layer ==
"internal_pad_def" )
403 if( pad_layer[0] ==
'~' )
412 layer.
name = pad_layer;
430 size_t rownum = aRow + 2;
432 if( rownum >=
rows.size() )
438 if( scale_factor <= 0.0 )
454 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
459 if( row.size() != header.size() )
461 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
468 auto& pad_name = row[pad_name_col];
469 auto& pad_num = row[pad_num_col];
470 auto& pad_layer = row[pad_lay_col];
471 auto& pad_is_fixed = row[pad_fix_col];
472 auto& pad_is_via = row[pad_via_col];
473 auto& pad_shape = row[pad_shape_col];
474 auto& pad_width = row[pad_width_col];
475 auto& pad_height = row[pad_height_col];
476 auto& pad_xoff = row[pad_xoff_col];
477 auto& pad_yoff = row[pad_yoff_col];
478 auto& pad_flash = row[pad_flash_col];
479 auto& pad_shapename = row[pad_shape_name_col];
482 if( pad_layer ==
"INTERNAL_PAD_DEF" || pad_layer ==
"internal_pad_def" )
487 auto new_pad =
pads.find( pad_name );
489 if( new_pad !=
pads.end() )
490 pad = &new_pad->second;
495 pad->name = pad_name;
499 if( pad_layer ==
"~DRILL" )
513 wxLogError(
_(
"Expecting drill size value but found %s!%s!%s in row %zu." ),
531 if( drill_x == drill_y )
533 pad->drill_size_x = drill_hit;
534 pad->drill_size_y = drill_hit;
538 pad->drill_size_x = drill_x;
539 pad->drill_size_y = drill_y;
542 if( !pad_shapename.empty() && pad_shapename[0] ==
'P' )
548 if( pad_shape.empty() )
561 wxLogError(
_(
"Expecting pad size values but found %s : %s in row %zu." ),
571 auto layer =
layers.find( pad_layer );
573 if( layer !=
layers.end() )
575 if( layer->second.layerid ==
F_Cu )
577 else if( layer->second.layerid ==
B_Cu )
581 if( w > std::numeric_limits<int>::max() || h > std::numeric_limits<int>::max() )
583 wxLogError(
_(
"Invalid pad size in row %zu." ), rownum );
587 if( pad_layer ==
"~TSM" || pad_layer ==
"~BSM" )
589 if( w > 0.0 && h > 0.0 )
597 if( pad_layer ==
"~TSP" || pad_layer ==
"~BSP" )
599 if( w > 0.0 && h > 0.0 )
608 if( pad_layer[0] ==
'~' )
618 wxLogError(
_(
"Expecting pad offset values but found %s:%s in row %zu." ),
625 if( w > 0.0 && h > 0.0 && recnum == 1 )
629 pad->via = ( std::toupper( pad_is_via[0] ) !=
'V' );
631 if( pad_shape ==
"CIRCLE" )
634 pad->shape = PAD_SHAPE::CIRCLE;
636 else if( pad_shape ==
"RECTANGLE" )
638 pad->shape = PAD_SHAPE::RECTANGLE;
640 else if( pad_shape ==
"ROUNDED_RECT" )
642 pad->shape = PAD_SHAPE::ROUNDRECT;
644 else if( pad_shape ==
"SQUARE" )
646 pad->shape = PAD_SHAPE::RECTANGLE;
649 else if( pad_shape ==
"OBLONG" || pad_shape ==
"OBLONG_X" || pad_shape ==
"OBLONG_Y" )
650 pad->shape = PAD_SHAPE::OVAL;
651 else if( pad_shape ==
"OCTAGON" )
653 pad->shape = PAD_SHAPE::RECTANGLE;
654 pad->is_octogon =
true;
656 else if( pad_shape ==
"SHAPE" )
658 pad->shape = PAD_SHAPE::CUSTOM;
659 pad->custom_name = pad_shapename;
663 wxLogError(
_(
"Unknown pad shape name '%s' on layer '%s' in row %zu." ),
672 return rownum - aRow;
678 size_t rownum = aRow + 2;
680 if( rownum >=
rows.size() )
683 auto& header =
rows[aRow];
686 if( scale_factor <= 0.0 )
692 if( layer_class_col < 0 || layer_subclass_col < 0 )
695 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
699 if( row.size() != header.size() )
701 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
711 layer.
name = row[layer_subclass_col];
715 if( row[layer_class_col] ==
"ANTI ETCH" )
720 else if( row[layer_class_col] ==
"ETCH" )
726 return rownum - aRow;
734 std::string max_layer_name;
736 std::vector<std::pair<std::string, int>> extra_layers
738 {
"ASSEMBLY_TOP",
F_Fab },
739 {
"ASSEMBLY_BOTTOM",
B_Fab },
740 {
"PLACE_BOUND_TOP",
F_CrtYd },
741 {
"PLACE_BOUND_BOTTOM",
B_CrtYd },
744 std::vector<FABMASTER_LAYER*> layer_order;
746 int next_user_layer =
User_1;
755 layer_order.push_back( &layer );
757 else if( ( layer.
name.find(
"SILK" ) != std::string::npos
758 && layer.
name.find(
"AUTOSILK" )
759 == std::string::npos )
760 || layer.
name.find(
"DISPLAY" ) != std::string::npos )
762 if( layer.
name.find(
"B" ) != std::string::npos )
767 else if( layer.
name.find(
"MASK" ) != std::string::npos ||
768 layer.
name.find(
"MSK" ) != std::string::npos )
770 if( layer.
name.find(
"B" ) != std::string::npos )
775 else if( layer.
name.find(
"PAST" ) != std::string::npos )
777 if( layer.
name.find(
"B" ) != std::string::npos )
782 else if( layer.
name.find(
"NCLEGEND" ) != std::string::npos )
791 if( layer.
name.find(
"AUTOSILK" ) == std::string::npos )
793 if( next_user_layer <=
User_9 )
796 layer.
layerid = next_user_layer;
797 next_user_layer += 2;
805 wxLogWarning(
_(
"No user layer to put layer %s" ), layer.
name );
813 for(
size_t layeri = 0; layeri < layer_order.size(); ++layeri )
818 else if( layeri == layer_order.size() - 1 )
821 layer->
layerid = layeri * 2 + 2;
824 for(
auto& new_pair : extra_layers )
828 new_layer.
name = new_pair.first;
829 new_layer.
layerid = new_pair.second;
832 auto result =
layers.emplace( new_pair.first, new_layer );
836 result.first->second.layerid = new_pair.second;
837 result.first->second.disable =
false;
841 for(
const auto& [layer_name, fabmaster_layer] :
layers )
843 wxLogTrace(
traceFabmaster, wxT(
"Layer %s -> KiCad layer %d" ), layer_name,
844 fabmaster_layer.layerid );
858 size_t rownum = aRow + 2;
860 if( rownum >=
rows.size() )
863 auto& header =
rows[aRow];
866 if( scale_factor <= 0.0 )
874 int layer_er_col =
getColFromName( aRow,
"LAYERDIELECTRICCONSTANT" );
875 int layer_rho_col =
getColFromName( aRow,
"LAYERELECTRICALCONDUCTIVITY" );
878 if( layer_sort_col < 0 || layer_subclass_col < 0 || layer_art_col < 0 || layer_use_col < 0
879 || layer_cond_col < 0 || layer_er_col < 0 || layer_rho_col < 0 || layer_mat_col < 0 )
882 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
886 if( row.size() != header.size() )
888 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
895 auto& layer_sort = row[layer_sort_col];
896 auto& layer_subclass = row[layer_subclass_col];
897 auto& layer_art = row[layer_art_col];
898 auto& layer_use = row[layer_use_col];
899 auto& layer_cond = row[layer_cond_col];
900 auto& layer_er = row[layer_er_col];
901 auto& layer_rho = row[layer_rho_col];
902 auto& layer_mat = row[layer_mat_col];
904 if( layer_mat ==
"AIR" )
909 if( layer_subclass.empty() )
911 if( layer_cond !=
"NO" )
912 layer.
name =
"In.Cu" + layer_sort;
914 layer.
name =
"Dielectric" + layer_sort;
917 layer.
positive = ( layer_art !=
"NEGATIVE" );
922 return rownum - aRow;
933 size_t rownum = aRow + 2;
935 if( rownum >=
rows.size() )
938 auto& header =
rows[aRow];
941 if( scale_factor <= 0.0 )
946 int pad_grdata_name_col =
getColFromName( aRow,
"GRAPHICDATANAME" );
947 int pad_grdata_num_col =
getColFromName( aRow,
"GRAPHICDATANUMBER" );
962 if( pad_subclass_col < 0 || pad_shape_name_col < 0 || pad_grdata1_col < 0 || pad_grdata2_col < 0
963 || pad_grdata3_col < 0 || pad_grdata4_col < 0 || pad_grdata5_col < 0
964 || pad_grdata6_col < 0 || pad_grdata7_col < 0 || pad_grdata8_col < 0
965 || pad_grdata9_col < 0 || pad_stack_name_col < 0 || pad_refdes_col < 0
966 || pad_pin_num_col < 0 )
969 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
973 if( row.size() != header.size() )
975 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
983 auto& pad_layer = row[pad_subclass_col];
984 auto pad_shape_name = row[pad_shape_name_col];
985 auto& pad_record_tag = row[pad_record_tag_col];
1000 auto& pad_stack_name = row[pad_stack_name_col];
1001 auto& pad_refdes = row[pad_refdes_col];
1002 auto& pad_pin_num = row[pad_pin_num_col];
1006 std::string prefix(
"FIG_SHAPE " );
1008 if( pad_shape_name.length() <= prefix.length()
1009 || !std::equal( prefix.begin(), prefix.end(), pad_shape_name.begin() ) )
1019 if( std::sscanf( pad_record_tag.c_str(),
"%d %d", &
id, &seq ) != 2 )
1021 wxLogError(
_(
"Invalid format for id string '%s' in custom pad row %zu." ),
1022 pad_record_tag.c_str(),
1027 auto name = pad_shape_name.substr( prefix.length() );
1028 name +=
"_" + pad_refdes +
"_" + pad_pin_num;
1031 auto& custom_pad = ret.first->second;
1037 custom_pad.name =
name;
1038 custom_pad.padstack = pad_stack_name;
1039 custom_pad.pinnum = pad_pin_num;
1040 custom_pad.refdes = pad_refdes;
1047 auto gr_item = std::unique_ptr<GRAPHIC_ITEM>(
processGraphic( gr_data, scale_factor ) );
1051 gr_item->layer = pad_layer;
1052 gr_item->refdes = pad_refdes;
1054 gr_item->subseq = 0;
1059 auto retval = pad_it.first->second.insert( std::move(gr_item ) );
1061 if( !retval.second )
1063 wxLogError(
_(
"Could not insert graphical item %d into padstack '%s'." ),
1065 pad_stack_name.c_str() );
1070 wxLogError(
_(
"Unrecognized pad shape primitive '%s' in row %zu." ),
1076 return rownum - aRow;
1126 angle = endangle - startangle;
1161 std::unique_ptr<GRAPHIC_ARC> new_circle = std::make_unique<GRAPHIC_ARC>();
1172 if( size.x != size.y )
1174 wxLogError(
_(
"Circle with unequal x and y radii (x=%d, y=%d)" ), size.x, size.y );
1180 new_circle->radius = size.x / 2;
1186 new_circle->start_x = start.
x;
1187 new_circle->start_y = start.
y;
1189 new_circle->end_x = start.
x;
1190 new_circle->end_y = start.
y;
1192 new_circle->center_x = center.x;
1193 new_circle->center_y = center.y;
1195 new_circle->clockwise =
true;
1197 new_circle->result =
SHAPE_ARC{ start, mid, start, 0 };
1199 return new_circle.release();
1219 new_rect->
width = 0;
1233 auto new_rect = std::make_unique<GRAPHIC_RECTANGLE>();
1242 new_rect->start_x = center_x - size_x / 2;
1243 new_rect->start_y = center_y + size_y / 2;
1244 new_rect->end_x = center_x + size_x / 2;
1245 new_rect->end_y = center_y - size_y / 2;
1247 new_rect->width = 0;
1249 return new_rect.release();
1274 auto new_oblong = std::make_unique<GRAPHIC_OBLONG>();
1286 return new_oblong.release();
1314 wxLogError(
_(
"Expected x and y to be the same, got x = %f and y = %f " ), s.x, s.y );
1317 auto new_poly = std::make_unique<GRAPHIC_POLYGON>();
1321 int radius = s.x / 2;
1322 bool across_corners =
true;
1356 across_corners =
false;
1362 wxCHECK_MSG(
false,
nullptr,
1363 wxString::Format(
"Unhandled polygon type: %s", aData.
graphic_dataname ) );
1368 return new_poly.release();
1379 auto new_cross = std::make_unique<GRAPHIC_CROSS>();
1388 return new_cross.release();
1412 if( toks.size() < 8 )
1415 wxLogError(
_(
"Invalid token count. Expected 8 but found %zu." ), toks.size() );
1417 new_text->
width = 0;
1418 new_text->
ital =
false;
1492 size_t rownum = aRow + 2;
1494 if( rownum >=
rows.size() )
1500 if( scale_factor <= 0.0 )
1519 if( geo_name_col < 0 || geo_num_col < 0 || geo_grdata1_col < 0 || geo_grdata2_col < 0
1520 || geo_grdata3_col < 0 || geo_grdata4_col < 0 || geo_grdata5_col < 0
1521 || geo_grdata6_col < 0 || geo_grdata7_col < 0 || geo_grdata8_col < 0
1522 || geo_grdata9_col < 0 || geo_subclass_col < 0 || geo_sym_name_col < 0
1523 || geo_refdes_col < 0 )
1526 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
1530 if( row.size() != header.size() )
1532 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
1539 auto& geo_tag = row[geo_tag_col];
1554 auto& geo_refdes = row[geo_refdes_col];
1562 if( std::sscanf( geo_tag.c_str(),
"%d %d %d", &
id, &seq, &subseq ) < 2 )
1564 wxLogError(
_(
"Invalid format for record_tag string '%s' in row %zu." ),
1570 auto gr_item = std::unique_ptr<GRAPHIC_ITEM>(
processGraphic( gr_data, scale_factor ) );
1574 wxLogDebug( wxT(
"Unhandled graphic item '%s' in row %zu." ),
1581 gr_item->layer = row[geo_subclass_col];
1583 gr_item->subseq = subseq;
1585 if( geo_refdes.empty() )
1590 new_gr.
subclass = row[geo_subclass_col];
1591 new_gr.
refdes = row[geo_refdes_col];
1592 new_gr.
name = row[geo_sym_name_col];
1594 new_gr.
elements = std::make_unique<graphic_element>();
1599 graphic.
elements->emplace( std::move( gr_item ) );
1604 std::map<int, GEOM_GRAPHIC>{} );
1605 auto map_it = sym_gr_it.first->second.emplace(
id,
GEOM_GRAPHIC{} );
1606 auto& gr = map_it.first;
1610 gr->second.subclass = row[geo_subclass_col];
1611 gr->second.refdes = row[geo_refdes_col];
1612 gr->second.name = row[geo_sym_name_col];
1614 gr->second.elements = std::make_unique<graphic_element>();
1617 auto result = gr->second.elements->emplace( std::move( gr_item ) );
1621 return rownum - aRow;
1630 size_t rownum = aRow + 2;
1632 if( rownum >=
rows.size() )
1638 if( scale_factor <= 0.0 )
1647 if( viax_col < 0 || viay_col < 0 || padstack_name_col < 0 || net_name_col < 0
1648 || test_point_col < 0 )
1651 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
1655 if( row.size() != header.size() )
1657 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
1664 vias.emplace_back( std::make_unique<FM_VIA>() );
1669 via->padstack = row[padstack_name_col];
1670 via->net = row[net_name_col];
1671 via->test_point = ( row[test_point_col] ==
"YES" );
1674 return rownum - aRow;
1685 size_t rownum = aRow + 2;
1687 if( rownum >=
rows.size() )
1693 if( scale_factor <= 0.0 )
1699 int grdata_num_col =
getColFromName( aRow,
"GRAPHICDATANUMBER" );
1712 if( class_col < 0 || layer_col < 0 || grdata_name_col < 0 || grdata_num_col < 0
1713 || tag_col < 0 || grdata1_col < 0 || grdata2_col < 0 || grdata3_col < 0
1714 || grdata4_col < 0 || grdata5_col < 0 || grdata6_col < 0 || grdata7_col < 0
1715 || grdata8_col < 0 || grdata9_col < 0 || netname_col < 0 )
1718 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
1722 if( row.size() != header.size() )
1724 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
1744 const std::string& geo_tag = row[tag_col];
1751 if( std::sscanf( geo_tag.c_str(),
"%d %d %d", &
id, &seq, &subseq ) < 2 )
1753 wxLogError(
_(
"Invalid format for record_tag string '%s' in row %zu." ),
1759 auto gr_item = std::unique_ptr<GRAPHIC_ITEM>(
processGraphic( gr_data, scale_factor ) );
1763 wxLogTrace(
traceFabmaster,
_(
"Unhandled graphic item '%s' in row %zu." ),
1769 auto new_trace = std::make_unique<TRACE>();
1771 new_trace->layer = row[layer_col];
1772 new_trace->netname = row[netname_col];
1773 new_trace->lclass = row[class_col];
1775 gr_item->layer = row[layer_col];
1777 gr_item->subseq = subseq;
1780 if( new_trace->lclass ==
"REF DES" )
1782 auto result =
refdes.emplace( std::move( new_trace ) );
1783 auto& ref = *result.first;
1784 ref->segment.emplace( std::move( gr_item ) );
1786 else if( new_trace->lclass ==
"DEVICE TYPE" || new_trace->lclass ==
"COMPONENT VALUE"
1787 || new_trace->lclass ==
"TOLERANCE" )
1800 else if( gr_item->width == 0 )
1802 auto result =
zones.emplace( std::move( new_trace ) );
1803 auto& zone = *result.first;
1804 auto gr_result = zone->segment.emplace( std::move( gr_item ) );
1806 if( !gr_result.second )
1808 wxLogError(
_(
"Duplicate item for ID %d and sequence %d in row %zu." ),
1816 auto result =
traces.emplace( std::move( new_trace ) );
1817 auto& trace = *result.first;
1818 auto gr_result = trace->segment.emplace( std::move( gr_item ) );
1820 if( !gr_result.second )
1822 wxLogError(
_(
"Duplicate item for ID %d and sequence %d in row %zu." ),
1830 return rownum - aRow;
1836 if( aSymType ==
"PACKAGE" )
1838 else if( aSymType ==
"DRAFTING")
1840 else if( aSymType ==
"MECHANICAL" )
1842 else if( aSymType ==
"FORMAT" )
1851 if( aCmpClass ==
"IO" )
1853 else if( aCmpClass ==
"IC" )
1855 else if( aCmpClass ==
"DISCRETE" )
1868 size_t rownum = aRow + 2;
1870 if( rownum >=
rows.size() )
1876 if( scale_factor <= 0.0 )
1884 int compinscode_col =
getColFromName( aRow,
"COMPINSERTIONCODE" );
1895 if( refdes_col < 0 || compclass_col < 0 || comppartnum_col < 0 || compheight_col < 0
1896 || compdevlabelcol < 0 || compinscode_col < 0 || symtype_col < 0 || symname_col < 0
1897 || symmirror_col < 0 || symrotate_col < 0 || symx_col < 0 || symy_col < 0
1898 || compvalue_col < 0 || comptol_col < 0 || compvolt_col < 0 )
1901 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
1905 if( row.size() != header.size() )
1907 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
1914 const wxString&
refdes = row[refdes_col];
1916 if( row[symx_col].
empty() || row[symy_col].
empty() || row[symrotate_col].
empty() )
1918 wxLogError(
_(
"Missing X, Y, or rotation data in row %zu for refdes %s. "
1919 "This may be an unplaced component." ),
1924 auto cmp = std::make_unique<COMPONENT>();
1928 cmp->pn = row[comppartnum_col];
1929 cmp->height = row[compheight_col];
1930 cmp->dev_label = row[compdevlabelcol];
1931 cmp->insert_code = row[compinscode_col];
1933 cmp->name = row[symname_col];
1934 cmp->mirror = ( row[symmirror_col] ==
"YES" );
1935 cmp->rotate =
readDouble( row[symrotate_col] );
1938 cmp->value = row[compvalue_col];
1939 cmp->tol = row[comptol_col];
1940 cmp->voltage = row[compvolt_col];
1946 auto retval =
components.insert( std::make_pair( cmp->refdes, std::vector<std::unique_ptr<COMPONENT>>{} ) );
1951 vec->second.push_back( std::move( cmp ) );
1954 return rownum - aRow;
1964 size_t rownum = aRow + 2;
1966 if( rownum >=
rows.size() )
1972 if( scale_factor <= 0.0 )
1986 if( symname_col < 0 ||symmirror_col < 0 || pinname_col < 0 || pinnum_col < 0 || pinx_col < 0
1987 || piny_col < 0 || padstack_col < 0 || refdes_col < 0 || pinrot_col < 0
1988 || testpoint_col < 0 )
1991 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
1995 if( row.size() != header.size() )
1997 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
2004 auto pin = std::make_unique<PIN>();
2006 pin->name = row[symname_col];
2007 pin->mirror = ( row[symmirror_col] ==
"YES" );
2008 pin->pin_name = row[pinname_col];
2009 pin->pin_number = row[pinnum_col];
2012 pin->padstack = row[padstack_col];
2013 pin->refdes = row[refdes_col];
2016 auto map_it =
pins.find(
pin->refdes );
2018 if( map_it ==
pins.end() )
2020 auto retval =
pins.insert( std::make_pair(
pin->refdes, std::set<std::unique_ptr<PIN>,
2022 map_it = retval.first;
2025 map_it->second.insert( std::move(
pin ) );
2028 return rownum - aRow;
2037 size_t rownum = aRow + 2;
2039 if( rownum >=
rows.size() )
2045 if( scale_factor <= 0.0 )
2055 if( netname_col < 0 || refdes_col < 0 || pinnum_col < 0 || pinname_col < 0 || pingnd_col < 0
2059 for( ; rownum <
rows.size() &&
rows[rownum].size() > 0 &&
rows[rownum][0] ==
"S"; ++rownum )
2063 if( row.size() != header.size() )
2065 wxLogError(
_(
"Invalid row size in row %zu. Expecting %zu elements but found %zu." ),
2073 new_net.
name = row[netname_col];
2074 new_net.
refdes = row[refdes_col];
2075 new_net.
pin_num = row[pinnum_col];
2076 new_net.
pin_name = row[pinname_col];
2077 new_net.
pin_gnd = ( row[pingnd_col] ==
"YES" );
2078 new_net.
pin_pwr = ( row[pinpwr_col] ==
"YES" );
2081 netnames.insert( row[netname_col] );
2084 return rownum - aRow;
2091 for(
size_t i = 0; i <
rows.size(); )
2105 i += std::max( retval, 1 );
2113 i += std::max( retval, 1 );
2121 i += std::max( retval, 1 );
2129 i += std::max( retval, 1 );
2137 i += std::max( retval, 1 );
2145 i += std::max( retval, 1 );
2153 i += std::max( retval, 1 );
2161 i += std::max( retval, 1 );
2169 i += std::max( retval, 1 );
2177 i += std::max( retval, 1 );
2194 for(
auto& zone :
zones )
2204 if( zone->layer ==
"OUTLINE" || zone->layer ==
"DESIGN_OUTLINE" )
2225 std::set<ZONE*> zones_to_delete;
2227 for(
auto zone : aBoard->
Zones() )
2230 if( zone->GetNetCode() > 0 )
2232 zones_to_delete.insert( zone );
2236 for(
auto zone1 : aBoard->
Zones() )
2239 if( zone1->GetNetCode() > 0 )
2244 std::vector<std::vector<ZONE*>> possible_deletions( overlaps.size() );
2246 for(
auto zone2 : aBoard->
Zones() )
2248 if( zone2->GetNetCode() <= 0 )
2253 if( zone1->GetLayer() != zone2->GetLayer() )
2259 for(
auto& pt1 : outline1.
CPoints() )
2263 overlaps[ zone2->GetNetCode() ]++;
2266 for(
auto& pt2 : outline2.
CPoints() )
2271 overlaps[ zone2->GetNetCode() ]++;
2276 size_t max_net_id = 0;
2278 for(
size_t el = 1; el < overlaps.size(); ++el )
2280 if( overlaps[el] > max_net )
2282 max_net = overlaps[el];
2288 zone1->SetNetCode( max_net_id );
2291 for(
auto zone : zones_to_delete )
2311 if( aMirrorPoint.has_value() )
2351 bool has_multiple = mod.second.size() > 1;
2353 for(
int i = 0; i < mod.second.size(); ++i )
2355 auto& src = mod.second[i];
2359 wxString mod_ref = src->name;
2363 mod_ref.Append( wxString::Format( wxT(
"_%d" ), i ) );
2368 wxString key = !lib_ref.empty() ? lib_ref + wxT(
":" ) + mod_ref : mod_ref;
2371 fpID.
Parse( key,
true );
2380 wxString reference = src->refdes;
2382 if( !std::isalpha( src->refdes[0] ) )
2383 reference.Prepend(
"UNK" );
2396 for(
auto& ref :
refdes )
2399 static_cast<const GRAPHIC_TEXT&
>( **ref->segment.begin() );
2401 if( lsrc.
text == src->refdes )
2408 wxLogTrace(
traceFabmaster, wxS(
"The layer %s is not mapped?" ),
2409 ref->layer.c_str() );
2425 flip_point =
VECTOR2I( src->x, src->y );
2430 setupText( lsrc, layer, *txt, *aBoard, flip_point );
2433 fp->
Add( txt, ADD_MODE::APPEND );
2449 for(
auto& gr_ref : gr_it->second )
2451 auto& graphic = gr_ref.second;
2453 for(
auto& seg : *graphic.elements )
2460 STROKE_PARAMS defaultStroke( ds.GetLineThickness( layer ) );
2462 switch( seg->shape )
2486 if( lsrc->
width == 0 )
2489 fp->
Add( line, ADD_MODE::APPEND );
2507 circle->
Mirror( fp_orig, FLIP_DIRECTION::TOP_BOTTOM );
2510 if( lsrc.
width == 0 )
2516 if( lsrc.
layer ==
"DISPLAY_TOP" || lsrc.
layer ==
"DISPLAY_BOTTOM" )
2523 circle->
Flip( circle->
GetCenter(), FLIP_DIRECTION::TOP_BOTTOM );
2525 fp->
Add( circle, ADD_MODE::APPEND );
2532 std::unique_ptr<PCB_SHAPE> arc =
2533 std::make_unique<PCB_SHAPE>( fp, SHAPE_T::ARC );
2542 sarc.
Mirror( fp_orig, FLIP_DIRECTION::TOP_BOTTOM );
2546 arc->SetLayer( layer );
2550 if( lsrc->
width == 0 )
2551 arc->SetStroke( defaultStroke );
2554 arc->Flip( arc->GetCenter(), FLIP_DIRECTION::TOP_BOTTOM );
2556 fp->
Add( arc.release(), ADD_MODE::APPEND );
2581 fp->
Add( rect, ADD_MODE::APPEND );
2588 std::unique_ptr<PCB_TEXT> txt = std::make_unique<PCB_TEXT>( fp );
2592 flip_point =
VECTOR2I( src->x, src->y );
2594 setupText( lsrc, layer, *txt, *aBoard, flip_point );
2599 txt->SetVisible(
false );
2601 fp->
Add( txt.release(), ADD_MODE::APPEND );
2610 auto pin_it =
pins.find( src->refdes );
2612 if( pin_it !=
pins.end() )
2614 for(
auto&
pin : pin_it->second )
2616 auto pin_net_it =
pin_nets.find( std::make_pair(
pin->refdes,
2617 pin->pin_number ) );
2618 auto padstack =
pads.find(
pin->padstack );
2619 std::string netname =
"";
2622 netname = pin_net_it->second.name;
2624 auto net_it = netinfo.find( netname );
2626 std::unique_ptr<PAD> newpad = std::make_unique<PAD>( fp );
2628 if( net_it != netinfo.end() )
2629 newpad->SetNet( net_it->second );
2631 newpad->SetNetCode( 0 );
2633 newpad->SetX(
pin->pin_x );
2636 newpad->SetY( 2 * src->y -
pin->pin_y );
2638 newpad->SetY(
pin->pin_y );
2640 newpad->SetNumber(
pin->pin_number );
2642 if( padstack ==
pads.end() )
2644 wxLogError(
_(
"Unable to locate padstack %s in file %s\n" ),
2650 auto&
pad = padstack->second;
2654 if(
pad.shape == PAD_SHAPE::CUSTOM )
2658 int pad_size = std::min(
pad.width,
pad.height );
2661 VECTOR2I( pad_size / 2, pad_size / 2 ) );
2663 std::string custom_name =
pad.custom_name +
"_" +
pin->refdes +
"_" +
2665 auto custom_it =
pad_shapes.find( custom_name );
2671 int last_subseq = 0;
2678 for(
const auto& el : (*custom_it).second.elements )
2685 if(
getLayer( ( *( el.second.begin() ) )->layer ) != primary_layer )
2688 for(
const auto& seg : el.second )
2690 if( seg->subseq > 0 || seg->subseq != last_subseq )
2692 poly_outline.
Polygon(0).back().SetClosed(
true );
2700 if( poly_outline.
VertexCount( 0, hole_idx ) == 0 )
2720 wxLogError(
_(
"Invalid custom pad '%s'. Replacing with "
2722 custom_name.c_str() );
2723 newpad->SetShape(
F_Cu, PAD_SHAPE::CIRCLE );
2729 poly_outline.
Move( -newpad->GetPosition() );
2734 FLIP_DIRECTION::TOP_BOTTOM );
2752 wxLogError(
_(
"Invalid custom pad '%s'. Replacing with "
2754 custom_name.c_str() );
2760 wxLogError(
_(
"Could not find custom pad '%s'." ),
2761 custom_name.c_str() );
2774 newpad->SetAttribute( PAD_ATTRIB::PTH );
2779 newpad->SetAttribute( PAD_ATTRIB::NPTH );
2783 if(
pad.drill_size_x ==
pad.drill_size_y )
2784 newpad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
2786 newpad->SetDrillShape( PAD_DRILL_SHAPE::OBLONG );
2788 newpad->SetDrillSize(
VECTOR2I(
pad.drill_size_x,
pad.drill_size_y ) );
2792 newpad->SetAttribute( PAD_ATTRIB::SMD );
2796 else if(
pad.bottom )
2802 newpad->SetOrientation(
EDA_ANGLE( -src->rotate +
pin->rotation,
2805 newpad->SetOrientation(
EDA_ANGLE( src->rotate -
pin->rotation,
2808 if( newpad->GetSizeX() > 0 || newpad->GetSizeY() > 0 )
2810 fp->
Add( newpad.release(), ADD_MODE::APPEND );
2814 wxLogError(
_(
"Invalid zero-sized pad ignored in\nfile: %s" ),
2826 aBoard->
Add( fp, ADD_MODE::APPEND );
2841 for(
auto& layer :
layers )
2846 layer_set.
set( layer.second.layerid );
2851 for(
auto& layer :
layers )
2853 if( layer.second.conductive )
2856 layer.second.name );
2873 auto net_it = netinfo.find(
via->net );
2874 auto padstack =
pads.find(
via->padstack );
2880 if( net_it != netinfo.end() )
2881 new_via->
SetNet( net_it->second );
2883 if( padstack ==
pads.end() )
2887 if( !ds.m_ViasDimensionsList.empty() )
2890 new_via->
SetDrill( ds.m_ViasDimensionsList[0].m_Drill );
2900 new_via->
SetDrill( padstack->second.drill_size_x );
2904 aBoard->
Add( new_via, ADD_MODE::APPEND );
2918 aBoard->
Add( newnet, ADD_MODE::APPEND );
2928 auto net_it = netinfo.find( aLine->netname );
2930 int last_subseq = 0;
2931 ZONE* new_zone =
nullptr;
2933 for(
const auto& seg : aLine->segment )
2939 switch( seg->shape )
2952 if( net_it != netinfo.end() )
2953 trk->
SetNet( net_it->second );
2955 aBoard->
Add( trk, ADD_MODE::APPEND );
2966 if( net_it != netinfo.end() )
2967 trk->
SetNet( net_it->second );
2969 aBoard->
Add( trk, ADD_MODE::APPEND );
2975 for( std::unique_ptr<BOARD_ITEM>& new_item :
2978 aBoard->
Add( new_item.release(), ADD_MODE::APPEND );
2986 wxLogError(
_(
"Expecting etch data to be on copper layer. Row found on layer '%s'" ),
2987 seg->layer.c_str() );
2998 int last_subseq = 0;
3003 for(
const auto& seg : aElement )
3005 if( seg->subseq > 0 || seg->subseq != last_subseq )
3012 if( poly_outline.
VertexCount( 0, hole_idx ) == 0 )
3026 return poly_outline;
3053 if( aLine.
segment.size() == 0 )
3059 int first_subseq = -1;
3060 bool have_multiple_subseqs =
false;
3062 for(
const std::unique_ptr<GRAPHIC_ITEM>& gr_item : aLine.
segment )
3064 if( first ==
nullptr )
3066 first = gr_item.get();
3067 first_subseq = gr_item->
subseq;
3069 else if( gr_item->subseq == first_subseq )
3071 last = gr_item.get();
3075 have_multiple_subseqs =
true;
3081 wxCHECK( first,
true );
3099 switch( last->
shape )
3119 if( end.has_value() && start == end )
3127std::vector<std::unique_ptr<BOARD_ITEM>>
3130 std::vector<std::unique_ptr<BOARD_ITEM>> new_items;
3135 const auto setShapeParameters = [&](
PCB_SHAPE& aShape )
3139 if( aShape.GetWidth() == 0 )
3140 aShape.SetStroke( defaultStroke );
3143 switch( aGraphic.
shape )
3149 auto new_text = std::make_unique<PCB_TEXT>( &aBoard );
3153 new_text->SetMirrored(
true );
3156 setupText( src, aLayer, *new_text, aBoard, std::nullopt );
3158 new_items.emplace_back( std::move( new_text ) );
3170 for(
const SEG& seg : segs )
3172 auto line = std::make_unique<PCB_SHAPE>( &aBoard );
3173 line->SetShape( SHAPE_T::SEGMENT );
3174 line->SetStart( seg.A );
3175 line->SetEnd( seg.B );
3177 setShapeParameters( *line );
3178 new_items.emplace_back( std::move( line ) );
3185 auto new_shape = std::make_unique<PCB_SHAPE>( &aBoard );
3187 setShapeParameters( *new_shape );
3189 switch( aGraphic.
shape )
3195 new_shape->SetShape( SHAPE_T::SEGMENT );
3205 new_shape->SetShape( SHAPE_T::ARC );
3214 new_shape->SetShape( SHAPE_T::CIRCLE );
3216 new_shape->SetRadius( src.
radius );
3223 new_shape->SetShape( SHAPE_T::RECTANGLE );
3227 new_shape->SetFilled( src.
fill );
3233 new_shape->SetShape( SHAPE_T::POLY );
3234 new_shape->SetPolyPoints( src.
m_pts );
3262 new_shape->SetShape( SHAPE_T::POLY );
3263 new_shape->SetPolyShape( poly );
3268 wxLogError(
_(
"Unhandled shape type %d in polygon on layer %s, seq %d %d" ),
3273 new_items.emplace_back( std::move( new_shape ) );
3277 for( std::unique_ptr<BOARD_ITEM>& new_item : new_items )
3279 new_item->SetLayer( aLayer );
3283 if( new_items.size() > 1 )
3285 auto new_group = std::make_unique<PCB_GROUP>( &aBoard );
3286 for( std::unique_ptr<BOARD_ITEM>& new_item : new_items )
3288 new_group->AddItem( new_item.get() );
3290 new_items.emplace_back( std::move( new_group ) );
3299 if( aLine->segment.empty() )
3313 for(
const auto& seg : aLine->segment )
3315 for( std::unique_ptr<BOARD_ITEM>& new_item :
createBoardItems( *aBoard, layer, *seg ) )
3317 aBoard->
Add( new_item.release(), ADD_MODE::APPEND );
3334 new_poly->
SetShape( SHAPE_T::POLY );
3346 STROKE_PARAMS( ( *( aLine->segment.begin() ) )->width, LINE_STYLE::SOLID ) );
3353 aBoard->
Add( new_poly, ADD_MODE::APPEND );
3362 if( aLine->segment.size() < 3 )
3366 ZONE* zone =
nullptr;
3369 auto net_it = netinfo.find( aLine->netname );
3371 auto new_layer =
getLayer( aLine->layer );
3376 zone =
new ZONE( aBoard );
3379 if( net_it != netinfo.end() )
3380 zone->
SetNet( net_it->second );
3382 if( aLine->layer ==
"ALL" )
3394 if( aLine->lclass ==
"ROUTE KEEPOUT")
3399 else if( aLine->lclass ==
"VIA KEEPOUT")
3414 std::unique_ptr<SHAPE_LINE_CHAIN> pending_hole =
nullptr;
3417 const auto add_hole_if_valid = [&]()
3427 wxLogMessage(
_(
"Invalid hole with %d points in zone on layer %s with net %s" ),
3432 pending_hole.reset();
3436 int last_subseq = 0;
3437 for(
const auto& seg : aLine->segment )
3439 if( seg->subseq > 0 && seg->subseq != last_subseq )
3443 if( aLine->lclass ==
"BOUNDARY" )
3446 add_hole_if_valid();
3447 pending_hole = std::make_unique<SHAPE_LINE_CHAIN>();
3448 active_chain = pending_hole.get();
3449 last_subseq = seg->subseq;
3460 active_chain->
Append( start );
3469 wxLogError(
_(
"Outline seems discontinuous: last point was %s, "
3470 "start point of next segment is %s" ),
3475 active_chain->
Append( end );
3485 wxLogError(
_(
"Invalid shape type %d in zone outline" ), seg->shape );
3490 add_hole_if_valid();
3495 aBoard->
Add( zone, ADD_MODE::APPEND );
3499 delete( zone_outline );
3511 if( aLine->lclass ==
"BOARD GEOMETRY" && aLine->layer !=
"DIMENSION" )
3513 else if( aLine->lclass ==
"DRAWING FORMAT" )
3518 for(
auto& seg : aLine->segment )
3520 for( std::unique_ptr<BOARD_ITEM>& new_item :
createBoardItems( *aBoard, layer, *seg ) )
3522 aBoard->
Add( new_item.release(), ADD_MODE::APPEND );
3540 if( geom.subclass ==
"PIN_NUMBER" )
3548 if( !geom.elements->empty() )
3551 if( ( *( geom.elements->begin() ) )->width == 0 )
3568 aBoard->
Add( new_poly, ADD_MODE::APPEND );
3572 for(
auto& seg : *geom.elements )
3574 for( std::unique_ptr<BOARD_ITEM>& new_item :
createBoardItems( *aBoard, layer, *seg ) )
3576 aBoard->
Add( new_item.release(), ADD_MODE::APPEND );
3588 std::vector<ZONE*> sortedZones;
3589 std::copy( aBoard->
Zones().begin(), aBoard->
Zones().end(), std::back_inserter( sortedZones ) );
3590 std::sort( sortedZones.begin(), sortedZones.end(),
3591 [&](
const ZONE* a,
const ZONE* b )
3593 if( a->GetLayer() == b->GetLayer() )
3594 return a->GetBoundingBox().GetArea() > b->GetBoundingBox().GetArea();
3596 return a->GetLayer() < b->GetLayer();
3600 unsigned int priority = 0;
3602 for(
ZONE* zone : sortedZones )
3605 if( zone->GetIsRuleArea() )
3608 if( zone->GetLayer() != layer )
3610 layer = zone->GetLayer();
3614 zone->SetAssignedPriority( priority );
3643 for(
auto& track :
traces )
3647 if( track->lclass ==
"ETCH" )
3649 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)
wxString GetNetname() const
void SetNet(NETINFO_ITEM *aNetInfo)
Set a NET_INFO object for the item.
Container for design settings for a BOARD object.
int GetLineThickness(PCB_LAYER_ID aLayer) const
Return the default graphic segment thickness from the layer class for the given layer.
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.
wxString GetLayerName() const
Return the name of the PCB layer on which the item 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
EDA_ANGLE Normalized() 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 SetWidth(int aWidth)
void SetTextPos(const VECTOR2I &aPoint)
void SetMirrored(bool isMirrored)
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
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)
void SetKeepUpright(bool aKeepUpright)
virtual void SetText(const wxString &aText)
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
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
GRAPHIC_OBLONG * processOblong(const GRAPHIC_DATA &aData, double aScale)
size_t processGeometry(size_t aRow)
A!GRAPHIC_DATA_NAME!GRAPHIC_DATA_NUMBER!RECORD_TAG!GRAPHIC_DATA_1!GRAPHIC_DATA_2!GRAPHIC_DATA_3!...
static std::vector< std::unique_ptr< BOARD_ITEM > > createBoardItems(BOARD &aBoard, PCB_LAYER_ID aLayer, FABMASTER::GRAPHIC_ITEM &aGraphic)
Convert one Fabmaster graphic item to one or more PCB items.
bool Read(const std::string &aFile)
bool loadNets(BOARD *aBoard)
std::map< std::string, std::map< int, GEOM_GRAPHIC > > comp_graphics
GRAPHIC_CROSS * processCross(const GRAPHIC_DATA &aData, double aScale)
unsigned m_lastProgressCount
SYMTYPE parseSymType(const std::string &aSymType)
GRAPHIC_TEXT * processText(const GRAPHIC_DATA &aData, double aScale)
bool loadLayers(BOARD *aBoard)
static void setupText(const FABMASTER::GRAPHIC_TEXT &aGraphicText, PCB_LAYER_ID aLayer, PCB_TEXT &aText, const BOARD &aBoard, const OPT_VECTOR2I &aMirrorPoint)
Set parameters for graphic text.
PCB_LAYER_ID getLayer(const std::string &aLayerName)
GRAPHIC_RECTANGLE * processSquare(const GRAPHIC_DATA &aData, double aScale)
static bool traceIsOpen(const FABMASTER::TRACE &aLine)
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)
GRAPHIC_ARC * processCircle(const GRAPHIC_DATA &aData, double aScale)
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)
GRAPHIC_RECTANGLE * processFigRectangle(const GRAPHIC_DATA &aData, double aScale)
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
GRAPHIC_POLYGON * processPolygon(const GRAPHIC_DATA &aData, double aScale)
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_OBLONG
!< Actually 360° arcs (for both arcs where start==end and real circles)
@ GR_SHAPE_CROSS
!< X/Y oblongs
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
virtual void Mirror(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Mirror this object relative to a given horizontal axis the layer is not changed.
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
void Mirror(const VECTOR2I &aRef, FLIP_DIRECTION aFlipDirection)
const VECTOR2I & GetP1() const
const VECTOR2I & GetP0() const
const VECTOR2I & GetCenter() 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...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
int PointCount() const
Return the number of points (vertices) in this line chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
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
void TransformToPolygon(SHAPE_POLY_SET &aBuffer, int aError, ERROR_LOC aErrorLoc) const override
Fills a SHAPE_POLY_SET with a polygon representation of this shape.
Simple container to manage line stroke parameters.
const std::string Format() const
Return the vector formatted as a string.
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 bool empty(const wxTextEntryBase *aCtrl)
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_90
static constexpr EDA_ANGLE FULL_CIRCLE
static constexpr EDA_ANGLE ANGLE_360
static constexpr EDA_ANGLE ANGLE_180
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 IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
bool AddHoleIfValid(SHAPE_POLY_SET &aOutline, SHAPE_LINE_CHAIN &&aHole)
Adds a hole to a polygon if it is valid (i.e.
std::vector< VECTOR2I > MakeRegularPolygonPoints(const VECTOR2I &aCenter, size_t aN, const VECTOR2I &aPt0)
Get the corners of a regular polygon from the centre, one point and the number of sides.
std::vector< SEG > MakeCrossSegments(const VECTOR2I &aCenter, const VECTOR2I &aSize, EDA_ANGLE aAngle)
Create the two segments for a cross.
void delete_if(_Container &__c, _Function &&__f)
Deletes all values from __c for which __f returns true.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Class to handle a set of BOARD_ITEMs.
std::optional< VECTOR2I > OPT_VECTOR2I
Utility functions for working with shapes.
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
int size_y
! GRAPHIC_DATA_4
int size_x
! GRAPHIC_DATA_3
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
std::string layer
! SUBCLASS
int subseq
! RECORD_TAG[1]
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 oblong_x
! OBLONG_X (as opposed to OBLONG_Y)
int size_x
! GRAPHIC_DATA_3
int size_y
! GRAPHIC_DATA_4
std::vector< VECTOR2I > m_pts
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
graphic_element segment
! GRAPHIC_DATA (can be either LINE or ARC)
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