750 NET* current_net =
nullptr;
753 auto parsePinToken = [](
const std::string& token,
NET_PIN&
pin ) ->
bool
755 size_t dot_pos = token.find(
'.' );
757 if( dot_pos == std::string::npos )
760 pin.ref_des = token.substr( 0, dot_pos );
761 pin.pin_name = token.substr( dot_pos + 1 );
767 auto expandShortcutPin = [](
const std::string& token ) -> std::vector<std::string>
769 std::vector<std::string> results;
772 if( token.find(
'{' ) == std::string::npos )
774 results.push_back( token );
785 bool is_range =
false;
788 std::vector<RangePart> parts;
790 std::string current_prefix;
792 while( pos < token.size() )
794 if( token[pos] ==
'{' )
796 size_t close_pos = token.find(
'}', pos );
798 if( close_pos == std::string::npos )
801 results.push_back( token );
805 std::string range_str = token.substr( pos + 1, close_pos - pos - 1 );
806 size_t dash_pos = range_str.find(
'-' );
808 if( dash_pos != std::string::npos )
811 part.prefix = current_prefix;
812 part.is_range =
true;
815 INT_MIN,
"net range" );
817 INT_MIN,
"net range" );
819 if( part.start == INT_MIN || part.end == INT_MIN )
821 results.push_back( token );
825 parts.push_back( part );
826 current_prefix.clear();
831 current_prefix += range_str;
838 current_prefix += token[pos];
844 if( !current_prefix.empty() || parts.empty() )
846 RangePart final_part;
847 final_part.prefix = current_prefix;
848 final_part.is_range =
false;
849 final_part.start = 0;
851 parts.push_back( final_part );
856 results.push_back(
"" );
858 for(
const auto& part : parts )
860 std::vector<std::string> new_results;
864 for(
const auto& base : results )
866 int step = ( part.start <= part.end ) ? 1 : -1;
868 for(
int i = part.start; step > 0 ? i <= part.end : i >= part.end; i += step )
870 new_results.push_back( base + part.prefix + std::to_string( i ) );
876 for(
const auto& base : results )
878 new_results.push_back( base + part.prefix );
882 results = std::move( new_results );
896 std::istringstream iss( line );
900 if( token ==
"SIGNAL" )
905 current_net = &
m_nets.back();
908 std::string pin_token;
910 while( iss >> pin_token )
913 if( pin_token ==
".REUSE." )
916 std::string instance, rsignal;
918 if( ( iss >> instance >> rsignal ) && !current_net->
pins.empty() )
920 current_net->
pins.back().reuse_instance = instance;
921 current_net->
pins.back().reuse_signal = rsignal;
928 for(
const auto& expanded : expandShortcutPin( pin_token ) )
932 if( parsePinToken( expanded,
pin ) )
933 current_net->
pins.push_back(
pin );
945 if( token ==
".REUSE." )
947 std::string instance, rsignal;
949 if( ( iss >> instance >> rsignal ) && !current_net->
pins.empty() )
951 current_net->
pins.back().reuse_instance = instance;
952 current_net->
pins.back().reuse_signal = rsignal;
959 for(
const auto& expanded : expandShortcutPin( token ) )
963 if( parsePinToken( expanded,
pin ) )
964 current_net->
pins.push_back(
pin );
967 }
while( iss >> token );
1218 if( line[0] ==
'*' )
1226 std::stringstream iss( line );
1227 std::string
name, type;
1228 double x = 0.0, y = 0.0;
1229 int pieces = 0, flags = 0;
1231 if( !( iss >>
name >> type >> x >> y >> pieces >> flags ) )
1234 std::string owner, signame;
1235 double hatchgrid = 0.0, hatchrad = 0.0;
1238 if( iss >> owner >> signame )
1240 iss >> hatchgrid >> hatchrad >> priority;
1243 for(
int i = 0; i < pieces; ++i )
1250 std::stringstream iss2( line );
1251 std::string poly_type;
1252 int corners = 0, arcs = 0;
1256 if( !( iss2 >> poly_type >> corners >> arcs >> width >> level ) )
1265 pour.
is_cutout = ( poly_type ==
"POCUT" || poly_type ==
"CUTOUT"
1266 || poly_type ==
"CIRCUT" );
1274 if( type ==
"HATOUT" )
1278 else if( type ==
"VOIDOUT" )
1283 else if( type ==
"PADTHERM" )
1287 else if( type ==
"VIATHERM" )
1293 if( poly_type ==
"CIRCLE" || poly_type ==
"CIRCUT" )
1297 std::vector<std::pair<double, double>> endpoints;
1299 for(
int j = 0; j < corners; ++j )
1304 std::stringstream iss3( line );
1305 double px = 0.0, py = 0.0;
1307 if( iss3 >> px >> py )
1308 endpoints.emplace_back( px, py );
1311 if( endpoints.size() == 2 )
1313 double cx = ( endpoints[0].first + endpoints[1].first ) / 2.0;
1314 double cy = ( endpoints[0].second + endpoints[1].second ) / 2.0;
1315 double radius = std::hypot( endpoints[1].first - endpoints[0].first,
1316 endpoints[1].second - endpoints[0].second ) / 2.0;
1323 arc.start_angle = 0.0;
1324 arc.delta_angle = 360.0;
1325 pour.
points.emplace_back( x + cx +
radius, y + cy, arc );
1328 else if( poly_type ==
"SEG" )
1331 for(
int j = 0; j < corners; ++j )
1336 std::stringstream iss3( line );
1337 double px = 0.0, py = 0.0;
1339 if( iss3 >> px >> py )
1341 pour.
points.emplace_back( x + px, y + py );
1353 int totalLines = corners + arcs;
1354 bool nextIsArcEndpoint =
false;
1357 for(
int j = 0; j < totalLines; ++j )
1362 std::stringstream iss3( line );
1363 double px = 0.0, py = 0.0;
1365 if( !( iss3 >> px >> py ) )
1368 int angle1 = 0, angle2 = 0;
1370 if( iss3 >> angle1 >> angle2 )
1376 pendingArc.
cx = x + px;
1377 pendingArc.cy = y + py;
1378 pendingArc.start_angle = angle1 / 10.0;
1379 pendingArc.delta_angle = angle2 / 10.0;
1381 if( !pour.
points.empty() )
1383 double dx = pour.
points.back().x - pendingArc.cx;
1384 double dy = pour.
points.back().y - pendingArc.cy;
1385 pendingArc.radius = std::sqrt( dx * dx + dy * dy );
1388 nextIsArcEndpoint =
true;
1390 else if( nextIsArcEndpoint )
1392 if( pendingArc.radius == 0.0 )
1394 double dx = ( x + px ) - pendingArc.cx;
1395 double dy = ( y + py ) - pendingArc.cy;
1396 pendingArc.radius = std::sqrt( dx * dx + dy * dy );
1399 pour.
points.emplace_back( x + px, y + py, pendingArc );
1400 nextIsArcEndpoint =
false;
1404 pour.
points.emplace_back( x + px, y + py );
1419 if( line[0] ==
'*' )
1426 std::stringstream iss( line );
1427 std::string
name, units;
1428 double orix = 0.0, oriy = 0.0;
1429 int pieces = 0, terminals = 0, stacks = 0, text_cnt = 0, labels = 0;
1431 if( !( iss >>
name >> units >> orix >> oriy >> pieces >> terminals >> stacks >> text_cnt >> labels ) )
1436 decal.
units = units;
1439 for(
int i = 0; i < pieces; ++i )
1441 if( !
readLine( aStream, line ) )
break;
1444 std::stringstream iss2( line );
1450 if( !( iss2 >> type >> corners >> width ) )
1483 decal.
items.push_back( item );
1489 if( type.find(
"COP" ) == 0 )
1491 std::string remaining;
1492 std::getline( iss2, remaining );
1495 std::istringstream rem_ss( remaining );
1496 int pinnum_val = -1;
1498 if( rem_ss >> pinnum_val )
1499 item.
pinnum = pinnum_val;
1503 if( type.find(
"KPT" ) == 0 )
1505 std::string restrictions;
1507 if( iss2 >> restrictions )
1511 for(
int j = 0; j < corners; ++j )
1516 std::stringstream iss3( line );
1517 double px = 0.0, py = 0.0;
1519 if( !( iss3 >> px >> py ) )
1525 int startAngleTenths = 0, deltaAngleTenths = 0;
1526 double bboxMinX = 0.0, bboxMinY = 0.0, bboxMaxX = 0.0, bboxMaxY = 0.0;
1528 if( iss3 >> startAngleTenths >> deltaAngleTenths
1529 >> bboxMinX >> bboxMinY >> bboxMaxX >> bboxMaxY )
1531 double cx = ( bboxMinX + bboxMaxX ) / 2.0;
1532 double cy = ( bboxMinY + bboxMaxY ) / 2.0;
1533 double radius = ( bboxMaxX - bboxMinX ) / 2.0;
1534 double startAngle = startAngleTenths / 10.0;
1535 double deltaAngle = deltaAngleTenths / 10.0;
1538 double startAngleRad = startAngle *
M_PI / 180.0;
1539 double startX = cx +
radius * std::cos( startAngleRad );
1540 double startY = cy +
radius * std::sin( startAngleRad );
1543 double endAngleRad = ( startAngle + deltaAngle ) *
M_PI / 180.0;
1544 double endX = cx +
radius * std::cos( endAngleRad );
1545 double endY = cy +
radius * std::sin( endAngleRad );
1548 item.
points.emplace_back( startX, startY );
1554 arc.start_angle = startAngle;
1555 arc.delta_angle = deltaAngle;
1558 item.
points.emplace_back( endX, endY, arc );
1562 item.
points.emplace_back( px, py );
1566 decal.
items.push_back( item );
1573 for(
int i = 0; i < text_cnt + labels; ++i )
1575 std::string attrLine, fontLine, nameLine;
1577 if( !
readLine( aStream, attrLine ) )
1582 if( !
readLine( aStream, fontLine ) )
1586 if( !
readLine( aStream, nameLine ) )
1590 std::stringstream ss( attrLine );
1591 std::string type_token;
1594 std::string mirrored_str, right_reading_str;
1599 attr.
visible = ( type_token ==
"VALUE" || type_token ==
"FULL_NAME"
1600 || type_token ==
"NAME" || type_token ==
"FULL_BOTH"
1601 || type_token ==
"BOTH" );
1602 attr.
mirrored = ( mirrored_str ==
"M" );
1603 ss >> right_reading_str;
1604 attr.
right_reading = ( right_reading_str ==
"Y" || right_reading_str ==
"ORTHO" );
1608 attr.
name = nameLine;
1619 for(
int i = 0; i < terminals; ++i )
1621 if( !
readLine( aStream, line ) )
break;
1623 size_t t_pos = line.find(
'T' );
1625 if( t_pos != std::string::npos )
1628 std::stringstream iss_t( line );
1630 double nmx = 0.0, nmy = 0.0;
1632 if( iss_t >> term.
x >> term.
y >> nmx >> nmy )
1636 if( term.
name.empty() )
1637 term.
name = std::to_string( i + 1 );
1647 for(
int i = 0; i < stacks; ++i )
1652 std::stringstream iss_pad( line );
1655 int stack_lines = 0;
1656 iss_pad >> token >> pin_idx >> stack_lines;
1658 if( token !=
"PAD" )
1662 std::string plated_token;
1663 bool default_plated =
true;
1664 double header_drill = 0.0;
1666 if( iss_pad >> plated_token )
1668 if( plated_token ==
"P" )
1669 default_plated =
true;
1670 else if( plated_token ==
"N" )
1671 default_plated =
false;
1679 double header_slot_ori = 0.0;
1680 double header_slot_len = 0.0;
1681 double header_slot_off = 0.0;
1683 if( iss_pad >> header_slot_ori >> header_slot_len >> header_slot_off )
1688 std::vector<PAD_STACK_LAYER> stack;
1690 for(
int j = 0; j < stack_lines; ++j )
1695 std::stringstream line_ss( line );
1701 if( !( line_ss >> layer >> size >> shape ) )
1705 layer_data.
layer = layer;
1706 layer_data.
sizeA = size;
1707 layer_data.
sizeB = size;
1708 layer_data.
shape = shape;
1709 layer_data.
plated = default_plated;
1710 layer_data.
drill = header_drill;
1721 else if( shape ==
"S" )
1725 double corner = 0.0;
1727 if( line_ss >> corner )
1740 else if( shape ==
"RA" || shape ==
"SA" )
1745 else if( shape ==
"A" )
1750 if( line_ss >> intd )
1753 else if( shape ==
"OF" )
1756 double ori = 0.0, length = 0.0, offset = 0.0;
1758 if( line_ss >> ori >> length >> offset )
1761 layer_data.
sizeB = length;
1765 else if( shape ==
"RF" )
1769 double ori = 0.0, length = 0.0, offset = 0.0;
1771 if( line_ss >> ori >> length >> offset )
1774 layer_data.
sizeB = length;
1777 double corner = 0.0;
1779 if( line_ss >> corner )
1793 else if( shape ==
"RT" || shape ==
"ST" )
1796 double ori = 0.0, outsize = 0.0, spkwid = 0.0;
1799 if( line_ss >> ori >> outsize >> spkwid >> spknum )
1807 else if( shape ==
"O" || shape ==
"OC" )
1813 else if( shape ==
"RC" )
1817 double ori = 0.0, length = 0.0, offset = 0.0, corner = 0.0;
1819 if( line_ss >> ori >> length >> offset )
1822 layer_data.
sizeB = length;
1825 if( line_ss >> corner )
1842 std::vector<std::string> remaining;
1843 std::string token_rem;
1845 while( line_ss >> token_rem )
1846 remaining.push_back( token_rem );
1849 if( !remaining.empty() )
1855 -1.0,
"pad layer drill" );
1857 if( drill_val >= 0.0 )
1859 layer_data.
drill = drill_val;
1864 if( idx < remaining.size() )
1866 if( remaining[idx] ==
"P" || remaining[idx] ==
"Y" )
1868 layer_data.
plated =
true;
1871 else if( remaining[idx] ==
"N" )
1873 layer_data.
plated =
false;
1879 if( idx + 2 < remaining.size() )
1890 stack.push_back( layer_data );
1903 ROUTE* current_route =
nullptr;
1904 TRACK current_track;
1905 bool in_track =
false;
1906 bool prev_is_plane_connection =
false;
1908 int last_plane_connection_layer = 0;
1909 double last_plane_connection_width = 0;
1910 bool last_plane_on_copper =
false;
1911 std::string default_via_name;
1912 bool has_pending_arc_center =
false;
1914 std::string pending_arc_dir;
1918 if( line[0] ==
'*' )
1920 if( line.rfind(
"*SIGNAL*", 0 ) == 0 )
1922 if( in_track && current_route )
1924 current_route->
tracks.push_back( current_track );
1925 current_track.
points.clear();
1929 prev_is_plane_connection =
false;
1930 has_pending_arc_center =
false;
1932 std::istringstream iss( line );
1936 std::string net_name;
1940 default_via_name.clear();
1942 while( iss >> token )
1944 if( !token.empty() && token.back() ==
';' )
1948 default_via_name = token;
1953 current_route->
net_name = net_name;
1964 if( !isdigit( line[0] ) && line[0] !=
'-' && line[0] !=
'+' )
1966 if( in_track && current_route )
1968 current_route->
tracks.push_back( current_track );
1969 current_track.
points.clear();
1973 prev_is_plane_connection =
false;
1978 std::istringstream pin_iss( line );
1979 std::string pin_token;
1981 while( pin_iss >> pin_token )
1983 size_t dot_pos = pin_token.find(
'.' );
1985 if( dot_pos != std::string::npos )
1988 pin.ref_des = pin_token.substr( 0, dot_pos );
1989 pin.pin_name = pin_token.substr( dot_pos + 1 );
1994 for(
const auto& existing : current_route->
pins )
1996 if( existing.ref_des ==
pin.ref_des &&
1997 existing.pin_name ==
pin.pin_name )
2005 current_route->
pins.push_back(
pin );
2013 std::istringstream iss( line );
2018 iss >> pt.
x >> pt.
y >> layer >> width >> flags;
2030 std::string via_name;
2031 std::string arc_dir;
2037 bool is_unrouted = ( layer == 0 );
2038 bool is_plane_connection = is_unrouted;
2041 bool has_teardrop =
false;
2042 bool has_jumper =
false;
2043 bool has_power =
false;
2045 while( iss >> token )
2048 if( token ==
"CW" || token ==
"CCW" )
2057 if( token ==
"POWER" )
2067 if( token ==
"THERMAL" )
2078 if( token ==
"TEARDROP" )
2080 has_teardrop =
true;
2081 std::string td_token;
2083 while( iss >> td_token )
2085 if( td_token ==
"P" )
2091 std::streampos pos = iss.tellg();
2094 if( iss >> td_flags )
2104 else if( td_token ==
"N" )
2109 std::streampos pos = iss.tellg();
2112 if( iss >> td_flags )
2126 if( td_token ==
"CW" || td_token ==
"CCW" )
2128 else if( td_token ==
"POWER" )
2133 via_name = td_token;
2135 else if( td_token ==
"THERMAL" )
2138 via_name = td_token;
2149 std::streampos pos = iss.tellg();
2150 std::string jumper_flag;
2152 if( iss >> jumper_flag )
2154 if( jumper_flag ==
"S" || jumper_flag ==
"E" )
2157 jumper.
name = token;
2158 jumper.
is_start = ( jumper_flag ==
"S" );
2177 if( token ==
"REUSE" || token ==
".REUSE." )
2180 std::string instance;
2190 if( !arc_dir.empty() )
2192 pending_arc_center = pt;
2193 pending_arc_dir = arc_dir;
2194 has_pending_arc_center =
true;
2198 if( has_pending_arc_center )
2200 has_pending_arc_center =
false;
2202 if( in_track && !current_track.
points.empty() )
2205 double dx0 = arc_start.
x - pending_arc_center.
x;
2206 double dy0 = arc_start.
y - pending_arc_center.
y;
2207 double start_angle = std::atan2( dy0, dx0 );
2209 std::atan2( pt.
y - pending_arc_center.
y, pt.
x - pending_arc_center.
x );
2210 double sweep = end_angle - start_angle;
2214 if( pending_arc_dir ==
"CCW" )
2216 while( sweep <= 0.0 )
2217 sweep += 2.0 *
M_PI;
2221 while( sweep >= 0.0 )
2222 sweep -= 2.0 *
M_PI;
2226 pt.
arc.
cx = pending_arc_center.
x;
2227 pt.
arc.
cy = pending_arc_center.
y;
2228 pt.
arc.
radius = std::sqrt( dx0 * dx0 + dy0 * dy0 );
2238 int effective_layer = layer;
2239 bool is_pad_connection = ( layer == 65 );
2243 if( is_unrouted && in_track )
2244 effective_layer = current_track.
layer;
2249 if( !via_name.empty() && current_route )
2252 via.name = via_name;
2253 via.location = { pt.
x, pt.
y };
2254 current_route->
vias.push_back(
via );
2262 if( has_power && via_name.empty() && !is_unrouted && !is_pad_connection && current_route )
2266 if( !default_via_name.empty() )
2267 implicit_via.
name = default_via_name;
2272 current_route->
vias.push_back( implicit_via );
2276 if( has_teardrop && current_route )
2278 current_route->
teardrops.push_back( teardrop );
2282 if( has_jumper && current_route )
2284 current_route->
jumpers.push_back( jumper );
2290 if( is_plane_connection && prev_is_plane_connection )
2299 last_plane_connection_pt = pt;
2300 last_plane_connection_layer = effective_layer;
2301 last_plane_connection_width = width;
2302 last_plane_on_copper =
true;
2305 prev_is_plane_connection =
true;
2309 if( is_plane_connection && !prev_is_plane_connection )
2315 current_track.
points.push_back( pt );
2317 if( current_route && current_track.
points.size() > 1 )
2318 current_route->
tracks.push_back( current_track );
2320 current_track.
points.clear();
2327 last_plane_on_copper = !is_unrouted;
2329 if( last_plane_on_copper )
2331 last_plane_connection_pt = pt;
2332 last_plane_connection_layer = effective_layer;
2333 last_plane_connection_width = width;
2336 prev_is_plane_connection =
true;
2340 if( !is_plane_connection && prev_is_plane_connection )
2344 if( in_track && current_route && current_track.
points.size() > 1 )
2345 current_route->
tracks.push_back( current_track );
2347 prev_is_plane_connection =
false;
2349 if( is_pad_connection )
2355 current_track.
points.clear();
2357 if( last_plane_on_copper && last_plane_connection_layer == effective_layer )
2359 current_track.
layer = effective_layer;
2360 current_track.
width = std::max( width, last_plane_connection_width );
2361 current_track.
points.push_back( last_plane_connection_pt );
2362 current_track.
points.push_back( pt );
2368 if( !has_power && via_name.empty() && current_route && last_plane_on_copper &&
2369 std::abs( pt.
x - last_plane_connection_pt.
x ) < 0.001 &&
2370 std::abs( pt.
y - last_plane_connection_pt.
y ) < 0.001 )
2374 if( !default_via_name.empty() )
2375 implicit_via.
name = default_via_name;
2380 current_route->
vias.push_back( implicit_via );
2383 current_track.
layer = effective_layer;
2384 current_track.
width = width;
2385 current_track.
points.push_back( pt );
2388 last_plane_on_copper =
false;
2395 if( is_pad_connection )
2397 if( in_track && !current_track.
points.empty() )
2399 current_track.
points.push_back( pt );
2401 if( current_route && current_track.
points.size() > 1 )
2402 current_route->
tracks.push_back( current_track );
2404 current_track.
points.clear();
2412 prev_is_plane_connection =
false;
2416 current_track.
layer = effective_layer;
2417 current_track.
width = width;
2418 current_track.
points.clear();
2419 current_track.
points.push_back( pt );
2424 bool layer_changed = ( effective_layer != current_track.
layer );
2425 bool width_changed = (
std::abs( width - current_track.
width ) > 0.001 );
2427 if( layer_changed || width_changed )
2430 bool connect =
true;
2432 if( layer_changed && via_name.empty() )
2434 bool same_location =
2435 ( pt.
x == current_track.
points.back().x &&
2436 pt.
y == current_track.
points.back().y );
2442 if( !has_power && current_route )
2446 default_via_name.empty() ?
"STANDARDVIA" : default_via_name;
2448 current_route->
vias.push_back( implicit_via );
2451 else if( !has_power )
2461 current_track.
points.push_back( pt );
2465 current_route->
tracks.push_back( current_track );
2470 current_track.
layer = effective_layer;
2471 current_track.
width = width;
2472 current_track.
points.clear();
2473 current_track.
points.push_back( prev_pt );
2477 current_track.
points.push_back( pt );
2482 if( in_track && current_route )
2484 current_route->
tracks.push_back( current_track );
2628 if( line[0] ==
'*' )
2634 std::istringstream iss( line );
2635 std::string
name, type;
2636 double xloc = 0.0, yloc = 0.0;
2638 iss >>
name >> type >> xloc >> yloc >> pieces;
2641 for(
int i = 0; i < pieces; ++i )
2646 if( line[0] ==
'*' )
2652 std::istringstream piss( line );
2653 std::string shape_type;
2656 int linestyle = 0, level = 0;
2657 piss >> shape_type >> corners >> width >> linestyle >> level;
2660 if( shape_type ==
"CLOSED" || shape_type ==
"OPEN" || shape_type ==
"BRDCLS" )
2664 polyline.
width = width;
2665 polyline.
closed = ( shape_type ==
"CLOSED" || shape_type ==
"BRDCLS" );
2667 for(
int j = 0; j < corners; ++j )
2672 if( line[0] ==
'*' )
2678 std::istringstream ciss( line );
2679 double dx = 0.0, dy = 0.0;
2684 int startAngleTenths = 0, deltaAngleTenths = 0;
2685 double bboxMinX = 0.0, bboxMinY = 0.0, bboxMaxX = 0.0, bboxMaxY = 0.0;
2687 if( ciss >> startAngleTenths >> deltaAngleTenths
2688 >> bboxMinX >> bboxMinY >> bboxMaxX >> bboxMaxY )
2690 double cx = ( bboxMinX + bboxMaxX ) / 2.0;
2691 double cy = ( bboxMinY + bboxMaxY ) / 2.0;
2692 double radius = ( bboxMaxX - bboxMinX ) / 2.0;
2693 double startAngle = startAngleTenths / 10.0;
2694 double deltaAngle = deltaAngleTenths / 10.0;
2696 double startAngleRad = startAngle *
M_PI / 180.0;
2697 double startX = cx +
radius * std::cos( startAngleRad );
2698 double startY = cy +
radius * std::sin( startAngleRad );
2700 double endAngleRad = ( startAngle + deltaAngle ) *
M_PI / 180.0;
2701 double endX = cx +
radius * std::cos( endAngleRad );
2702 double endY = cy +
radius * std::sin( endAngleRad );
2704 polyline.
points.emplace_back( xloc + startX, yloc + startY );
2710 arc.start_angle = startAngle;
2711 arc.delta_angle = deltaAngle;
2713 polyline.
points.emplace_back( xloc + endX, yloc + endY, arc );
2717 polyline.
points.emplace_back( xloc + dx, yloc + dy );
2721 if( !polyline.
points.empty() )
2724 else if( shape_type ==
"CIRCLE" || shape_type ==
"BRDCIR" )
2729 polyline.
width = width;
2732 double x1 = 0.0, y1 = 0.0, x2 = 0.0, y2 = 0.0;
2736 std::istringstream c1( line );
2740 if( corners >= 2 &&
readLine( aStream, line ) )
2742 std::istringstream c2( line );
2747 double cx = xloc + ( x1 + x2 ) / 2.0;
2748 double cy = yloc + ( y1 + y2 ) / 2.0;
2749 double radius = std::sqrt( ( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ) ) / 2.0;
2756 arc.start_angle = 0.0;
2757 arc.delta_angle = 360.0;
2761 if( !polyline.
points.empty() )
2767 for(
int j = 0; j < corners; ++j )
2772 if( line[0] ==
'*' )
2789 if( line[0] ==
'*' )
2799 std::istringstream iss( line );
2800 std::string
name, type;
2801 double xloc = 0.0, yloc = 0.0;
2802 int pieces = 0, flags = 0, textCount = 0;
2803 std::string seventhToken, eighthToken;
2804 std::string signame;
2806 iss >>
name >> type >> xloc >> yloc >> pieces >> flags >> seventhToken >> eighthToken;
2808 if( !eighthToken.empty() )
2812 signame = eighthToken;
2814 std::istringstream tiss( seventhToken );
2817 else if( !seventhToken.empty() )
2825 if( std::all_of( seventhToken.begin(), seventhToken.end(),
2828 return std::isdigit( c );
2831 std::istringstream tiss( seventhToken );
2836 signame = seventhToken;
2841 std::string reuse_instance, reuse_signal;
2845 if( line.find(
".REUSE." ) != std::string::npos )
2847 std::istringstream riss( line );
2848 std::string reuse_keyword;
2849 riss >> reuse_keyword >> reuse_instance >> reuse_signal;
2857 if( type ==
"BOARD" )
2859 for(
int i=0; i<pieces; ++i )
2861 if( !
readLine( aStream, line ) )
break;
2864 std::istringstream piss( line );
2865 std::string shape_type;
2868 int piece_flags = 0;
2870 piss >> shape_type >> corners >> width >> piece_flags >> level;
2872 if( shape_type ==
"CLOSED" || shape_type ==
"OPEN" || shape_type ==
"BRDCLS" )
2876 polyline.
width = width;
2877 polyline.
closed = ( shape_type ==
"CLOSED" || shape_type ==
"BRDCLS" );
2879 for(
int j = 0; j < corners; ++j )
2884 if( line[0] ==
'*' )
2890 std::istringstream ciss( line );
2891 double dx = 0.0, dy = 0.0;
2896 int startAngleTenths = 0, deltaAngleTenths = 0;
2897 double bboxMinX = 0.0, bboxMinY = 0.0, bboxMaxX = 0.0, bboxMaxY = 0.0;
2899 if( ciss >> startAngleTenths >> deltaAngleTenths
2900 >> bboxMinX >> bboxMinY >> bboxMaxX >> bboxMaxY )
2902 double cx = ( bboxMinX + bboxMaxX ) / 2.0;
2903 double cy = ( bboxMinY + bboxMaxY ) / 2.0;
2904 double radius = ( bboxMaxX - bboxMinX ) / 2.0;
2905 double startAngle = startAngleTenths / 10.0;
2906 double deltaAngle = deltaAngleTenths / 10.0;
2908 double startAngleRad = startAngle *
M_PI / 180.0;
2909 double startX = cx +
radius * std::cos( startAngleRad );
2910 double startY = cy +
radius * std::sin( startAngleRad );
2912 double endAngleRad = ( startAngle + deltaAngle ) *
M_PI / 180.0;
2913 double endX = cx +
radius * std::cos( endAngleRad );
2914 double endY = cy +
radius * std::sin( endAngleRad );
2916 polyline.
points.emplace_back( xloc + startX, yloc + startY );
2922 arc.start_angle = startAngle;
2923 arc.delta_angle = deltaAngle;
2925 polyline.
points.emplace_back( xloc + endX, yloc + endY, arc );
2929 polyline.
points.emplace_back( xloc + dx, yloc + dy );
2933 if( !polyline.
points.empty() )
2936 else if( shape_type ==
"CIRCLE" || shape_type ==
"BRDCIR" )
2939 double x1 = 0.0, y1 = 0.0, x2 = 0.0, y2 = 0.0;
2943 std::istringstream c1( line );
2947 if( corners >= 2 &&
readLine( aStream, line ) )
2949 std::istringstream c2( line );
2953 double cx = xloc + ( x1 + x2 ) / 2.0;
2954 double cy = yloc + ( y1 + y2 ) / 2.0;
2955 double radius = std::sqrt( ( x2 - x1 ) * ( x2 - x1 ) +
2956 ( y2 - y1 ) * ( y2 - y1 ) ) / 2.0;
2960 polyline.
width = width;
2967 arc.start_angle = 0.0;
2968 arc.delta_angle = 360.0;
2972 if( !polyline.
points.empty() )
2977 for(
int j=0; j<corners; ++j )
2979 if( !
readLine( aStream, line ) )
break;
2985 else if(
name.rfind(
"DIM", 0 ) == 0 && type ==
"LINES" )
3005 double baspnt1_x = 0, baspnt1_y = 0;
3006 double baspnt2_x = 0, baspnt2_y = 0;
3007 double arwln_x = 0, arwln_y = 0;
3008 int baspnt_count = 0;
3009 bool hasArwln =
false;
3011 for(
int i = 0; i < pieces; ++i )
3016 if( line[0] ==
'*' )
3022 std::istringstream piss( line );
3023 std::string shape_type;
3026 int piece_flags = 0;
3028 piss >> shape_type >> corners >> width >> piece_flags >> level;
3032 for(
int j = 0; j < corners; ++j )
3037 if( line[0] ==
'*' )
3043 std::istringstream ciss( line );
3044 double dx = 0.0, dy = 0.0;
3049 if( shape_type ==
"BASPNT" && j == 0 )
3051 if( baspnt_count == 0 )
3053 baspnt1_x = xloc + dx;
3054 baspnt1_y = yloc + dy;
3056 else if( baspnt_count == 1 )
3058 baspnt2_x = xloc + dx;
3059 baspnt2_y = yloc + dy;
3066 if( shape_type ==
"ARWLN1" && j == 0 )
3068 arwln_x = xloc + dx;
3069 arwln_y = yloc + dy;
3076 if( baspnt_count >= 2 )
3080 double dx =
std::abs( baspnt2_x - baspnt1_x );
3081 double dy =
std::abs( baspnt2_y - baspnt1_y );
3082 bool isHorizontal = dx > dy;
3101 dim.
points.push_back( pt1 );
3102 dim.
points.push_back( pt2 );
3107 for(
int t = 0; t < textCount; ++t )
3112 if( line[0] ==
'*' )
3118 std::istringstream tiss( line );
3119 double tx = 0.0, ty = 0.0;
3126 for(
int s = 0; s < skipLines; ++s )
3134 double theight = 0.0, twidth = 0.0;
3135 tiss >> trot >> tlayer >> theight >> twidth;
3158 if( !dim.
points.empty() )
3161 else if( type ==
"KEEPOUT" || type ==
"RESTRICTVIA" || type ==
"RESTRICTROUTE"
3162 || type ==
"RESTRICTAREA" || type ==
"PLACEMENT_KEEPOUT" )
3168 if( type ==
"KEEPOUT" || type ==
"RESTRICTAREA" )
3175 else if( type ==
"RESTRICTVIA" )
3182 else if( type ==
"RESTRICTROUTE" )
3189 else if( type ==
"PLACEMENT_KEEPOUT" )
3198 for(
int i = 0; i < pieces; ++i )
3203 if( line[0] ==
'*' )
3211 std::istringstream piss( line );
3212 std::string shape_type;
3215 int piece_flags = 0;
3217 std::string restrictions;
3218 piss >> shape_type >> corners >> width >> piece_flags >> level >> restrictions;
3221 keepout.
layers.push_back( level );
3227 if( !restrictions.empty() )
3230 bool has_restriction_codes =
false;
3232 for(
char c : restrictions )
3234 if( std::isalpha( c ) )
3236 has_restriction_codes =
true;
3241 if( has_restriction_codes )
3252 for(
char c : restrictions )
3293 if( shape_type ==
"KPTCIR" )
3296 double x1 = 0.0, y1 = 0.0, x2 = 0.0, y2 = 0.0;
3300 std::istringstream c1( line );
3304 if( corners >= 2 &&
readLine( aStream, line ) )
3306 std::istringstream c2( line );
3311 double cx = xloc + ( x1 + x2 ) / 2.0;
3312 double cy = yloc + ( y1 + y2 ) / 2.0;
3313 double radius = std::sqrt( ( x2 - x1 ) * ( x2 - x1 ) +
3314 ( y2 - y1 ) * ( y2 - y1 ) ) / 2.0;
3321 arc.start_angle = 0.0;
3322 arc.delta_angle = 360.0;
3329 for(
int j = 0; j < corners; ++j )
3334 if( line[0] ==
'*' )
3340 std::istringstream ciss( line );
3341 double dx = 0.0, dy = 0.0;
3346 int startAngleTenths = 0, deltaAngleTenths = 0;
3347 double bboxMinX = 0.0, bboxMinY = 0.0, bboxMaxX = 0.0, bboxMaxY = 0.0;
3349 if( ciss >> startAngleTenths >> deltaAngleTenths
3350 >> bboxMinX >> bboxMinY >> bboxMaxX >> bboxMaxY )
3352 double cx = ( bboxMinX + bboxMaxX ) / 2.0;
3353 double cy = ( bboxMinY + bboxMaxY ) / 2.0;
3354 double radius = ( bboxMaxX - bboxMinX ) / 2.0;
3355 double startAngle = startAngleTenths / 10.0;
3356 double deltaAngle = deltaAngleTenths / 10.0;
3358 double startAngleRad = startAngle *
M_PI / 180.0;
3359 double startX = cx +
radius * std::cos( startAngleRad );
3360 double startY = cy +
radius * std::sin( startAngleRad );
3362 double endAngleRad = ( startAngle + deltaAngle ) *
M_PI / 180.0;
3363 double endX = cx +
radius * std::cos( endAngleRad );
3364 double endY = cy +
radius * std::sin( endAngleRad );
3366 keepout.
outline.emplace_back( xloc + startX, yloc + startY );
3372 arc.start_angle = startAngle;
3373 arc.delta_angle = deltaAngle;
3375 keepout.
outline.emplace_back( xloc + endX, yloc + endY, arc );
3379 keepout.
outline.emplace_back( xloc + dx, yloc + dy );
3385 if( !keepout.
outline.empty() )
3388 else if( type ==
"COPPER" || type ==
"COPCUT" )
3394 for(
int i = 0; i < pieces; ++i )
3399 if( line[0] ==
'*' )
3408 std::istringstream piss( line );
3409 std::string shape_type;
3412 int piece_flags = 0;
3414 piss >> shape_type >> corners >> width >> piece_flags >> level;
3418 copper.
layer = level;
3419 copper.
width = width;
3422 copper.
filled = ( shape_type ==
"COPCLS" || shape_type ==
"COPCIR" );
3423 copper.
is_cutout = ( shape_type ==
"COPCUT" || shape_type ==
"COPCCO" ||
3424 shape_type ==
"CIRCUR" || type ==
"COPCUT" );
3427 if( shape_type ==
"COPCIR" || shape_type ==
"COPCCO" || shape_type ==
"CIRCUR" )
3430 double x1 = 0.0, y1 = 0.0, x2 = 0.0, y2 = 0.0;
3434 std::istringstream c1( line );
3438 if( corners >= 2 &&
readLine( aStream, line ) )
3440 std::istringstream c2( line );
3444 double cx = xloc + ( x1 + x2 ) / 2.0;
3445 double cy = yloc + ( y1 + y2 ) / 2.0;
3446 double radius = std::sqrt( ( x2 - x1 ) * ( x2 - x1 ) +
3447 ( y2 - y1 ) * ( y2 - y1 ) ) / 2.0;
3453 arc.start_angle = 0.0;
3454 arc.delta_angle = 360.0;
3461 for(
int j = 0; j < corners; ++j )
3466 if( line[0] ==
'*' )
3472 std::istringstream ciss( line );
3473 double dx = 0.0, dy = 0.0;
3478 int startAngleTenths = 0, deltaAngleTenths = 0;
3479 double bboxMinX = 0.0, bboxMinY = 0.0, bboxMaxX = 0.0, bboxMaxY = 0.0;
3481 if( ciss >> startAngleTenths >> deltaAngleTenths
3482 >> bboxMinX >> bboxMinY >> bboxMaxX >> bboxMaxY )
3484 double cx = ( bboxMinX + bboxMaxX ) / 2.0;
3485 double cy = ( bboxMinY + bboxMaxY ) / 2.0;
3486 double radius = ( bboxMaxX - bboxMinX ) / 2.0;
3487 double startAngle = startAngleTenths / 10.0;
3488 double deltaAngle = deltaAngleTenths / 10.0;
3490 double startAngleRad = startAngle *
M_PI / 180.0;
3491 double startX = cx +
radius * std::cos( startAngleRad );
3492 double startY = cy +
radius * std::sin( startAngleRad );
3494 double endAngleRad = ( startAngle + deltaAngle ) *
M_PI / 180.0;
3495 double endX = cx +
radius * std::cos( endAngleRad );
3496 double endY = cy +
radius * std::sin( endAngleRad );
3498 copper.
outline.emplace_back( xloc + startX, yloc + startY );
3504 arc.start_angle = startAngle;
3505 arc.delta_angle = deltaAngle;
3507 copper.
outline.emplace_back( xloc + endX, yloc + endY, arc );
3511 copper.
outline.emplace_back( xloc + dx, yloc + dy );
3520 else if( type ==
"LINES" )
3523 for(
int i = 0; i < pieces; ++i )
3528 if( line[0] ==
'*' )
3535 std::istringstream piss( line );
3536 std::string shape_type;
3539 int piece_flags = 0;
3541 piss >> shape_type >> corners >> width >> piece_flags >> level;
3545 graphic.
layer = level;
3546 graphic.
width = width;
3550 graphic.
closed = ( shape_type ==
"CLOSED" || shape_type ==
"CIRCLE" );
3552 if( shape_type ==
"CIRCLE" )
3555 double x1 = 0.0, y1 = 0.0, x2 = 0.0, y2 = 0.0;
3559 std::istringstream c1( line );
3563 if( corners >= 2 &&
readLine( aStream, line ) )
3565 std::istringstream c2( line );
3569 double cx = xloc + ( x1 + x2 ) / 2.0;
3570 double cy = yloc + ( y1 + y2 ) / 2.0;
3571 double radius = std::sqrt( ( x2 - x1 ) * ( x2 - x1 ) +
3572 ( y2 - y1 ) * ( y2 - y1 ) ) / 2.0;
3578 arc.start_angle = 0.0;
3579 arc.delta_angle = 360.0;
3586 for(
int j = 0; j < corners; ++j )
3591 if( line[0] ==
'*' )
3597 std::istringstream ciss( line );
3598 double dx = 0.0, dy = 0.0;
3602 int startAngleTenths = 0, deltaAngleTenths = 0;
3603 double bboxMinX = 0.0, bboxMinY = 0.0, bboxMaxX = 0.0, bboxMaxY = 0.0;
3605 if( ciss >> startAngleTenths >> deltaAngleTenths
3606 >> bboxMinX >> bboxMinY >> bboxMaxX >> bboxMaxY )
3608 double cx = ( bboxMinX + bboxMaxX ) / 2.0;
3609 double cy = ( bboxMinY + bboxMaxY ) / 2.0;
3610 double radius = ( bboxMaxX - bboxMinX ) / 2.0;
3611 double startAngle = startAngleTenths / 10.0;
3612 double deltaAngle = deltaAngleTenths / 10.0;
3614 double startAngleRad = startAngle *
M_PI / 180.0;
3615 double startX = cx +
radius * std::cos( startAngleRad );
3616 double startY = cy +
radius * std::sin( startAngleRad );
3618 double endAngleRad = ( startAngle + deltaAngle ) *
M_PI / 180.0;
3619 double endX = cx +
radius * std::cos( endAngleRad );
3620 double endY = cy +
radius * std::sin( endAngleRad );
3622 graphic.
points.emplace_back( xloc + startX, yloc + startY );
3628 arc.start_angle = startAngle;
3629 arc.delta_angle = deltaAngle;
3631 graphic.
points.emplace_back( xloc + endX, yloc + endY, arc );
3635 graphic.
points.emplace_back( xloc + dx, yloc + dy );
3640 if( !graphic.
points.empty() )
3647 for(
int i = 0; i < pieces; ++i )
3652 if( line[0] ==
'*' )
3658 std::istringstream piss( line );
3659 std::string shape_type;
3661 piss >> shape_type >> corners;
3663 for(
int j = 0; j < corners; ++j )
3668 if( line[0] ==
'*' )
3680 for(
int t = 0; t < textCount; ++t )
3685 if( line[0] ==
'*' )
3691 std::istringstream tiss( line );
3701 for(
int s = 0; s < skipLines; ++s )
3707 text.location.x += xloc;
3708 text.location.y += yloc;
3710 std::string mirrored;
3712 text.mirrored = ( mirrored ==
"M" );
3720 if( line[0] ==
'*' )
3726 size_t bracket_start = line.find(
'<' );
3727 size_t bracket_end = line.find(
'>' );
3729 if( bracket_start != std::string::npos && bracket_end != std::string::npos )
3732 line.substr( bracket_start + 1, bracket_end - bracket_start - 1 );
3735 std::istringstream fiss( line );
3736 std::string font_style_part;
3737 fiss >> font_style_part;
3739 size_t colon_pos = font_style_part.find(
':' );
3741 if( colon_pos != std::string::npos )
3742 text.font_style = font_style_part.substr( 0, colon_pos );
3744 text.font_style = font_style_part;
3751 if( line[0] ==
'*' )
3757 text.content = line;
3771 int pendingGates = 0;
3772 int pendingGatePins = 0;
3773 int pendingSigPins = 0;
3774 int pendingUnusedPins = 0;
3792 auto isInteger = [](
const std::string& aToken ) ->
bool
3794 return !aToken.empty() && aToken.find_first_not_of(
"0123456789" ) == std::string::npos;
3797 auto tokenize = [](
const std::string& aLine ) -> std::vector<std::string>
3799 std::istringstream lss( aLine );
3800 std::vector<std::string> tokens;
3803 while( lss >> token )
3804 tokens.push_back( token );
3811 if( line[0] ==
'*' )
3818 if( line[0] ==
'{' && currentPartType )
3822 if( line[0] ==
'}' )
3825 if( line[0] ==
'*' )
3831 std::string attrName, attrValue;
3833 if( line[0] ==
'"' )
3835 size_t endQuote = line.find(
'"', 1 );
3837 if( endQuote != std::string::npos )
3839 attrName = line.substr( 1, endQuote - 1 );
3840 attrValue = line.substr( endQuote + 1 );
3845 std::istringstream attrSS( line );
3847 std::getline( attrSS >> std::ws, attrValue );
3850 if( !attrValue.empty() && attrValue[0] ==
' ' )
3851 attrValue = attrValue.substr( 1 );
3853 if( !attrName.empty() && !attrValue.empty() )
3854 currentPartType->
attributes[attrName] = attrValue;
3860 if( line[0] ==
'{' || line[0] ==
'}' )
3863 std::vector<std::string> tokens = tokenize( line );
3865 if( tokens.empty() )
3869 if( pendingGatePins > 0 )
3871 for(
const std::string& token : tokens )
3873 if( pendingGatePins == 0 )
3879 std::vector<std::string> parts;
3883 while( ( pos = token.find(
'.', start ) ) != std::string::npos )
3885 parts.push_back( token.substr( start, pos - start ) );
3889 parts.push_back( token.substr( start ) );
3891 if( parts.size() < 3 )
3897 bool isNumericSecond = isInteger( parts[1] );
3899 if( currentGate && parts[2].size() == 1 && !isNumericSecond )
3905 if( !parts[2].
empty() )
3906 gpin.
elec_type = parsePinElecType( parts[2][0] );
3908 if( parts.size() >= 4 )
3911 currentGate->
pins.push_back( gpin );
3913 else if( isNumericSecond )
3927 if( pendingGates == 0 && pendingSigPins == 0 && pendingUnusedPins > 0 )
3929 pendingUnusedPins -= std::min<int>( pendingUnusedPins, tokens.size() );
3934 if( currentPartType && tokens.size() >= 3 && tokens[0] ==
"G" && isInteger( tokens[1] )
3935 && isInteger( tokens[2] ) )
3939 currentPartType->
gates.push_back( gate );
3940 currentGate = ¤tPartType->
gates.back();
3944 if( pendingGates > 0 )
3951 if( currentPartType && tokens[0] ==
"SIGPIN" )
3953 std::istringstream sss( line );
3954 std::string keyword;
3962 if( pendingSigPins > 0 )
3971 pt.
name = tokens[0];
3973 if( tokens.size() > 1 )
3978 currentGate =
nullptr;
3981 pendingGatePins = 0;
3983 pendingUnusedPins = 0;
3985 for(
size_t ii = 2; ii < tokens.size(); ++ii )
3987 if( !isInteger( tokens[ii] ) )
3992 if( ii + 1 < tokens.size() && isInteger( tokens[ii + 1] ) )
3995 if( ii + 2 < tokens.size() && isInteger( tokens[ii + 2] ) )
4644 bool inDifPair =
false;
4645 bool inNetClassData =
false;
4646 bool inNetClass =
false;
4647 bool inRuleSet =
false;
4648 bool inRuleSetFor =
false;
4649 bool inClearanceRule =
false;
4650 int netClassDataDepth = -1;
4651 int netClassDepth = -1;
4652 int ruleSetDepth = -1;
4653 int clearanceRuleDepth = -1;
4654 bool foundDefaultRules =
false;
4655 bool isDefaultRuleSet =
false;
4656 std::string ruleSetNetClass;
4666 if( line[0] ==
'*' && braceDepth == 0 )
4673 for(
char c : line )
4681 if( braceDepth == 0 && inDifPair )
4684 if( !currentDiffPair.
name.empty() )
4691 if( inNetClass && braceDepth <= netClassDepth )
4693 if( !currentNetClass.
name.empty() )
4700 if( inNetClassData && braceDepth <= netClassDataDepth )
4702 inNetClassData =
false;
4705 if( inClearanceRule && braceDepth < clearanceRuleDepth )
4707 inClearanceRule =
false;
4709 if( isDefaultRuleSet )
4712 == std::numeric_limits<double>::max() )
4721 == std::numeric_limits<double>::max() )
4727 foundDefaultRules =
true;
4731 if( inRuleSetFor && braceDepth < ruleSetDepth + 1 )
4732 inRuleSetFor =
false;
4734 if( inRuleSet && braceDepth < ruleSetDepth )
4737 isDefaultRuleSet =
false;
4738 ruleSetNetClass.clear();
4743 std::istringstream iss( line );
4749 if( token ==
"LAYER" )
4751 std::string secondToken;
4754 if( secondToken ==
"DATA" )
4761 if( token ==
"NET_CLASS" )
4763 std::string secondToken;
4766 if( secondToken ==
"DATA" )
4768 inNetClassData =
true;
4769 netClassDataDepth = braceDepth;
4771 else if( inNetClassData && !secondToken.empty() )
4773 if( inNetClass && !currentNetClass.
name.empty() )
4777 currentNetClass.
name = secondToken;
4779 netClassDepth = braceDepth;
4781 else if( inRuleSetFor && !secondToken.empty() )
4783 ruleSetNetClass = secondToken;
4786 else if( inNetClass && token ==
"NET" )
4788 std::string netName;
4791 if( !netName.empty() )
4792 currentNetClass.
net_names.push_back( netName );
4794 else if( token ==
"RULE_SET" )
4796 std::string ruleNum;
4800 ruleSetDepth = braceDepth;
4801 ruleSetNetClass.clear();
4802 isDefaultRuleSet = ( ruleNum ==
"(1)" && !foundDefaultRules );
4804 else if( inRuleSet && !inClearanceRule && token ==
"FOR" )
4806 inRuleSetFor =
true;
4808 else if( inRuleSet && token ==
"CLEARANCE_RULE" )
4810 inClearanceRule =
true;
4811 clearanceRuleDepth = braceDepth;
4813 if( isDefaultRuleSet )
4815 m_design_rules.default_clearance = std::numeric_limits<double>::max();
4816 m_design_rules.copper_edge_clearance = std::numeric_limits<double>::max();
4819 else if( inClearanceRule )
4824 if( !iss.fail() && val > 0.0 )
4826 if( isDefaultRuleSet )
4828 if( token ==
"MIN_TRACK_WIDTH" )
4832 else if( token ==
"REC_TRACK_WIDTH" )
4836 else if( token ==
"DRILL_TO_DRILL" )
4840 else if( token ==
"OUTLINE_TO_TRACK" || token ==
"OUTLINE_TO_VIA"
4841 || token ==
"OUTLINE_TO_PAD" || token ==
"OUTLINE_TO_COPPER"
4842 || token ==
"OUTLINE_TO_SMD" )
4847 else if( token.rfind(
"SAME_NET_", 0 ) == 0 || token ==
"BODY_TO_BODY"
4848 || token ==
"MAX_TRACK_WIDTH"
4849 || token.rfind(
"TEXT_TO_", 0 ) == 0
4850 || token.rfind(
"COPPER_TO_", 0 ) == 0 )
4856 else if( token ==
"TRACK_TO_TRACK" || token.rfind(
"VIA_TO_", 0 ) == 0
4857 || token.rfind(
"PAD_TO_", 0 ) == 0
4858 || token.rfind(
"SMD_TO_", 0 ) == 0
4859 || token.rfind(
"DRILL_TO_", 0 ) == 0 )
4865 else if( !ruleSetNetClass.empty() )
4869 if( nc.name == ruleSetNetClass )
4871 if( token ==
"REC_TRACK_WIDTH" )
4872 nc.track_width = val;
4873 else if( token ==
"TRACK_TO_TRACK" )
4882 else if( token ==
"DIF_PAIR" )
4885 if( inDifPair && !currentDiffPair.
name.empty() )
4889 iss >> currentDiffPair.
name;
4892 else if( inDifPair )
4894 if( token ==
"NET" )
4896 std::string netName;
4905 else if( token ==
"GAP" )
4907 iss >> currentDiffPair.
gap;
4909 else if( token ==
"WIDTH" )
4911 iss >> currentDiffPair.
width;
4913 else if( token ==
"CONNECTION" )
4919 else if( token ==
"ASSOCIATED" )
4922 std::string keyword, netName;
4923 iss >> keyword >> netName;
4925 if( keyword ==
"NET" )
4937 if( token ==
"PART" && !inDifPair && !inNetClass )
4939 std::string partName;
4942 if( !partName.empty() )
4945 int savedDepth = braceDepth;
4953 if( line[0] ==
'}' )
4956 if( line[0] ==
'{' )
4959 if( line[0] ==
'*' )
4966 std::string attrName, attrValue;
4968 if( line[0] ==
'"' )
4970 size_t endQuote = line.find(
'"', 1 );
4972 if( endQuote != std::string::npos )
4974 attrName = line.substr( 1, endQuote - 1 );
4975 attrValue = line.substr( endQuote + 1 );
4980 std::istringstream attrSS( line );
4982 std::getline( attrSS >> std::ws, attrValue );
4985 if( !attrValue.empty() && attrValue[0] ==
' ' )
4986 attrValue = attrValue.substr( 1 );
4988 if( !attrName.empty() && !attrValue.empty() )
4989 attrs[attrName] = attrValue;
4993 braceDepth = savedDepth;