/* * hyp2mat - convert hyperlynx files to matlab scripts * Copyright 2012 Koen De Vleeschauwer. * * This file is part of hyp2mat. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include "hypfile.h" using namespace std; using namespace HypFile; /* * Hyperlynx 'POLYGON' subrecord of 'NET' record. * Draws polygonal metal area. */ bool HypFile::Hyp::exec_polygon_begin(parse_param& h) { if (trace_hyp) { cerr << "polygon begin:"; if (h.layer_name_set) cerr << " layer_name = " << h.layer_name; if (h.width_set) cerr << " width = " << h.width; if (h.polygon_type_set) { cerr << " polygon_type = " << h.polygon_type << " "; switch (h.polygon_type) { case POLYGON_TYPE_PLANE: cerr << "POLYGON_TYPE_PLANE"; break; case POLYGON_TYPE_POUR: cerr << "POLYGON_TYPE_POUR"; break; case POLYGON_TYPE_COPPER: cerr << "POLYGON_TYPE_COPPER"; break; default: cerr << "Error"; break; } } if (h.id_set) cerr << " id = " << h.id; cerr << " x = " << h.x << " y = " << h.y << endl; } if (!h.layer_name_set) { error("expected polygon layer L = "); return true; } if (!h.width_set) h.width = 0; if (!h.polygon_type_set) h.polygon_type = POLYGON_TYPE_PLANE; if (!h.id_set) { error("expected polygon id ID = "); return true; } h.width *= unit; h.x *= unit; h.y *= unit; current_polygon.id = h.id; current_polygon.polygon_type = h.polygon_type; current_polygon.width = h.width; current_polygon.positive = true; current_polygon.layer_name = h.layer_name; current_polygon.vertex.clear(); current_polygon.vertex.push_back(Point(h.x, h.y)); return false; } bool HypFile::Hyp::exec_polygon_end(parse_param& h) { if (trace_hyp) cerr << "polygon end" << endl; add_polygon(current_polygon); return false; } /* * Hyperlynx 'POLYVOID' subrecord of 'NET' record. * Creates polygonal hole in metal area. */ bool HypFile::Hyp::exec_polyvoid_begin(parse_param& h) { if (trace_hyp) { cerr << "polyvoid begin:"; if (h.id_set) cerr << " id = " << h.id; cerr << " x = " << h.x << " y = " << h.y << endl; } if (!h.id_set) { error("expected polygon id ID = "); return true; } h.x *= unit; h.y *= unit; current_polygon.id = h.id; current_polygon.positive = false; current_polygon.vertex.clear(); current_polygon.vertex.push_back(Point(h.x, h.y)); /* inherit layer_name and width from parent */ for (PolygonList::iterator i = net.back().metal[h.id].begin(); i != net.back().metal[h.id].end(); ++i) { if (i->positive) { current_polygon.polygon_type = i->polygon_type; current_polygon.width = i->width; current_polygon.layer_name = i->layer_name; return false; } } /* no positive polygon/polyline found with same id */ error("polyvoid does not have parent polygon or polyline with same id"); return true; } bool HypFile::Hyp::exec_polyvoid_end(parse_param& h) { if (trace_hyp) cerr << "polyvoid end" << endl; add_polygon(current_polygon); return false; } /* * Hyperlynx 'POLYLINE' subrecord of 'NET' record. * Draws metal trace. */ bool HypFile::Hyp::exec_polyline_begin(parse_param& h) { if (trace_hyp) { cerr << "polyline begin:"; if (h.layer_name_set) cerr << " layer_name = " << h.layer_name; if (h.width_set) cerr << " width = " << h.width; if (h.polygon_type_set) { cerr << " polygon_type = " << h.polygon_type << " "; switch (h.polygon_type) { case POLYGON_TYPE_PLANE: cerr << "POLYGON_TYPE_PLANE"; break; case POLYGON_TYPE_POUR: cerr << "POLYGON_TYPE_POUR"; break; case POLYGON_TYPE_COPPER: cerr << "POLYGON_TYPE_COPPER"; break; default: cerr << "Error"; break; } } if (h.id_set) cerr << " id = " << h.id; cerr << " x = " << h.x << " y = " << h.y << endl; } if (!h.layer_name_set) { error("expected polygon layer L = "); return true; } if (!h.width_set) { error("expected polygon width W = "); return true; } if (!h.polygon_type_set) h.polygon_type = POLYGON_TYPE_PLANE; if (!h.id_set) { error("expected polygon id ID = "); return true; } h.width *= unit; h.x *= unit; h.y *= unit; current_polygon.id = h.id; current_polygon.polygon_type = h.polygon_type; current_polygon.width = h.width; current_polygon.positive = true; current_polygon.layer_name = h.layer_name; current_polygon.vertex.clear(); current_polygon.vertex.push_back(Point(h.x, h.y)); return false; } bool HypFile::Hyp::exec_polyline_end(parse_param& h) { if (trace_hyp) cerr << "polyline end" << endl; // Draw polyline as sequence of line segments for (PointList::iterator i = current_polygon.vertex.begin(); (i != current_polygon.vertex.end()) && (i != --current_polygon.vertex.end()); ++i) { Polygon line_segment; PointList::iterator j = i + 1; line_segment = segment2poly(i->x, i->y, j->x, j->y, current_polygon.width); line_segment.id = current_polygon.id; line_segment.polygon_type = current_polygon.polygon_type; line_segment.positive = true; line_segment.layer_name = current_polygon.layer_name; line_segment.width = 0; add_polygon(line_segment); } return false; } /* * Hyperlynx 'LINE' subrecord of 'NET' record. * Draws straight metal trace. */ bool HypFile::Hyp::exec_line(parse_param& h) { if (trace_hyp) cerr << "line: x = " << h.x << " y = " << h.y << endl; h.x *= unit; h.y *= unit; /* add point to current polygon */ current_polygon.vertex.push_back(Point(h.x, h.y)); return false; } /* * Hyperlynx 'CURVE' subrecord of 'NET' record. * Draws curved metal trace. */ bool HypFile::Hyp::exec_curve(parse_param& h) { if (trace_hyp) { cerr << "curve: x1 = " << h.x1 << " y1 = " << h.y1 << " x2 = " << h.x2 << " y2 = " << h.y2; cerr << " xc = " << h.xc << " yc = " << h.yc << " r = " << h.r << endl; } h.x1 *= unit; h.y1 *= unit; h.x2 *= unit; h.y2 *= unit; h.xc *= unit; h.yc *= unit; h.r *= unit; h.width *= unit; /* calculate arc */ /* 'CURVE' draws arc counterclockwise */ Polygon arc = arc2poly(h.x1, h.y1, h.x2, h.y2, h.xc, h.yc, h.r, false); /* calculate distance between polygon end vertex and arc begin and arc end */ double endvertex_x = current_polygon.vertex.back().x; double endvertex_y = current_polygon.vertex.back().y; double dist1 = (endvertex_x - h.x1) * (endvertex_x - h.x1) + (endvertex_y - h.y1) * (endvertex_y - h.y1); double dist2 = (endvertex_x - h.x2) * (endvertex_x - h.x2) + (endvertex_y - h.y2) * (endvertex_y - h.y2); /* add arc to current polygon. begin with point closest to end vertex. */ if (dist1 <= dist2) /* add arc from (x1, y1) to (x2, y2) */ current_polygon.vertex.insert(current_polygon.vertex.end(), arc.vertex.begin(), arc.vertex.end()); else /* add arc from (x2, y2) to (x1, y1) */ current_polygon.vertex.insert(current_polygon.vertex.end(), arc.vertex.rbegin(), arc.vertex.rend()); return false; } /* not truncated */