📄 libtotech.java
字号:
if (ns.layer == Generic.tech().cellCenterNode) continue; AffineTransform trans = ns.node.rotateOut(); Rectangle2D nodeBounds = getBoundingBox(ns.node); // determine the layer LayerInfo giLayer = null; if (ns.layer != null && ns.layer != Generic.tech().portNode) { String desiredLayer = ns.layer.getName().substring(6); for(int i=0; i<lis.length; i++) { if (desiredLayer.equals(lis[i].name)) { giLayer = lis[i]; break; } } if (giLayer == null) { System.out.println("Cannot find layer " + desiredLayer); return null; } } // look at other examples and find samples associated with this firstEx.studySample = ns; NodeInfo.LayerDetails multiRule = null; for(int n=1; n<neList.size(); n++) { Example ne = neList.get(n); // count number of samples associated with the main sample int total = 0; for(Sample nso : ne.samples) { if (nso.assoc == ns) { ne.studySample = nso; total++; } } if (total == 0) { error.markError(ns.node, np, "Still unassociated sample (shouldn't happen)"); return null; } // if there are multiple associations, it must be a contact cut if (total > 1) { // make sure the layer is real geometry, not highlight or a port if (ns.layer == null || ns.layer == Generic.tech().portNode) { error.markError(ns.node, np, "Only contact layers may be iterated in examples"); return null; } // add the rule multiRule = getMultiCutRule(ns, neList, np); if (multiRule != null) break; } } if (multiRule != null) { multiRule.layer = giLayer; nodeLayers[count] = multiRule; count++; continue; } // associations done for this sample, now analyze them Point2D [] pointList = null; int [] pointFactor = null; Point2D [] points = null; if (ns.node.getProto() == Artwork.tech().filledPolygonNode || ns.node.getProto() == Artwork.tech().closedPolygonNode || ns.node.getProto() == Artwork.tech().openedPolygonNode || ns.node.getProto() == Artwork.tech().openedDottedPolygonNode || ns.node.getProto() == Artwork.tech().openedDashedPolygonNode || ns.node.getProto() == Artwork.tech().openedThickerPolygonNode) { points = ns.node.getTrace(); } int trueCount = 0; int minFactor = 0; if (points != null) { // make sure the arrays hold "count" points pointList = new Point2D[points.length]; pointFactor = new int[points.length]; for(int i=0; i<points.length; i++) { pointList[i] = new Point2D.Double(nodeBounds.getCenterX() + points[i].getX(), nodeBounds.getCenterY() + points[i].getY()); trans.transform(pointList[i], pointList[i]); } trueCount = points.length; } else { double [] angles = null; if (ns.node.getProto() == Artwork.tech().circleNode || ns.node.getProto() == Artwork.tech().thickCircleNode) { angles = ns.node.getArcDegrees(); if (angles[0] == 0 && angles[1] == 0) angles = null; }// if (angles == null)// {// Variable var2 = ns.node.getVar(Info.MINSIZEBOX_KEY);// if (var2 != null) minFactor = 2;// } // set sample description if (angles != null) { // handle circular arc sample pointList = new Point2D[3]; pointFactor = new int[3]; pointList[0] = new Point2D.Double(nodeBounds.getCenterX(), nodeBounds.getCenterY()); double dist = nodeBounds.getMaxX() - nodeBounds.getCenterX(); pointList[1] = new Point2D.Double(nodeBounds.getCenterX() + dist * Math.cos(angles[0]), nodeBounds.getCenterY() + dist * Math.sin(angles[0])); trans.transform(pointList[1], pointList[1]); trueCount = 3; } else if (ns.node.getProto() == Artwork.tech().circleNode || ns.node.getProto() == Artwork.tech().thickCircleNode || ns.node.getProto() == Artwork.tech().filledCircleNode) { // handle circular sample pointList = new Point2D[2+minFactor]; pointFactor = new int[2+minFactor]; pointList[0] = new Point2D.Double(nodeBounds.getCenterX(), nodeBounds.getCenterY()); pointList[1] = new Point2D.Double(nodeBounds.getMaxX(), nodeBounds.getCenterY()); trueCount = 2; } else { // rectangular sample: get the bounding box in (pointListx, pointListy) pointList = new Point2D[2+minFactor]; pointFactor = new int[2+minFactor]; pointList[0] = new Point2D.Double(nodeBounds.getMinX(), nodeBounds.getMinY()); pointList[1] = new Point2D.Double(nodeBounds.getMaxX(), nodeBounds.getMaxY()); trueCount = 2; }// if (minFactor > 1)// {// pointList[2] = new Point2D.Double(pointList[0].getX(),pointList[0].getY());// pointList[3] = new Point2D.Double(pointList[1].getX(),pointList[1].getY());// } } double [] pointLeftDist = new double[pointFactor.length]; double [] pointRightDist = new double[pointFactor.length]; double [] pointBottomDist = new double[pointFactor.length]; double [] pointTopDist = new double[pointFactor.length]; double [] centerXDist = new double[pointFactor.length]; double [] centerYDist = new double[pointFactor.length]; double [] pointXRatio = new double[pointFactor.length]; double [] pointYRatio = new double[pointFactor.length]; for(int i=0; i<pointFactor.length; i++) { pointLeftDist[i] = pointList[i].getX() - firstEx.lx; pointRightDist[i] = firstEx.hx - pointList[i].getX(); pointBottomDist[i] = pointList[i].getY() - firstEx.ly; pointTopDist[i] = firstEx.hy - pointList[i].getY(); centerXDist[i] = pointList[i].getX() - (firstEx.lx+firstEx.hx)/2; centerYDist[i] = pointList[i].getY() - (firstEx.ly+firstEx.hy)/2; if (firstEx.hx == firstEx.lx) pointXRatio[i] = 0; else pointXRatio[i] = (pointList[i].getX() - (firstEx.lx+firstEx.hx)/2) / (firstEx.hx-firstEx.lx); if (firstEx.hy == firstEx.ly) pointYRatio[i] = 0; else pointYRatio[i] = (pointList[i].getY() - (firstEx.ly+firstEx.hy)/2) / (firstEx.hy-firstEx.ly); if (i < trueCount) pointFactor[i] = TOEDGELEFT | TOEDGERIGHT | TOEDGETOP | TOEDGEBOT | FROMCENTX | FROMCENTY | RATIOCENTX | RATIOCENTY; else pointFactor[i] = FROMCENTX | FROMCENTY; } Point2D [] pointCoords = new Point2D[pointFactor.length]; for(int n = 1; n<neList.size(); n++) { Example ne = neList.get(n); NodeInst ni = ne.studySample.node; AffineTransform oTrans = ni.rotateOut(); Rectangle2D oNodeBounds = getBoundingBox(ni); Point2D [] oPoints = null; if (ni.getProto() == Artwork.tech().filledPolygonNode || ni.getProto() == Artwork.tech().closedPolygonNode || ni.getProto() == Artwork.tech().openedPolygonNode || ni.getProto() == Artwork.tech().openedDottedPolygonNode || ni.getProto() == Artwork.tech().openedDashedPolygonNode || ni.getProto() == Artwork.tech().openedThickerPolygonNode) { oPoints = ni.getTrace(); } int newCount = 2; if (oPoints != null) { newCount = oPoints.length; int numPoints = Math.min(trueCount, newCount); int bestOffset = 0; double bestDist = Double.MAX_VALUE; for(int offset = 0; offset < numPoints; offset++) { // determine total distance between points double dist = 0; for(int i=0; i<numPoints; i++) { double dX = points[i].getX() - oPoints[(i+offset)%numPoints].getX(); double dY = points[i].getY() - oPoints[(i+offset)%numPoints].getY(); dist += Math.hypot(dX, dY); } if (dist < bestDist) { bestDist = dist; bestOffset = offset; } } for(int i=0; i<numPoints; i++) { pointCoords[i] = new Point2D.Double(oNodeBounds.getCenterX() + oPoints[(i+bestOffset)%numPoints].getX(), oNodeBounds.getCenterY() + oPoints[(i+bestOffset)%numPoints].getY()); oTrans.transform(pointCoords[i], pointCoords[i]); } } else { double [] angles = null; if (ni.getProto() == Artwork.tech().circleNode || ni.getProto() == Artwork.tech().thickCircleNode) { angles = ni.getArcDegrees(); if (angles[0] == 0 && angles[1] == 0) angles = null; } if (angles != null) { pointCoords[0] = new Point2D.Double(oNodeBounds.getCenterX(), oNodeBounds.getCenterY()); double dist = oNodeBounds.getMaxX() - oNodeBounds.getCenterX(); pointCoords[1] = new Point2D.Double(oNodeBounds.getCenterX() + dist * Math.cos(angles[0]), oNodeBounds.getCenterY() + dist * Math.sin(angles[0])); oTrans.transform(pointCoords[1], pointCoords[1]); } else if (ni.getProto() == Artwork.tech().circleNode || ni.getProto() == Artwork.tech().thickCircleNode || ni.getProto() == Artwork.tech().filledCircleNode) { pointCoords[0] = new Point2D.Double(oNodeBounds.getCenterX(), oNodeBounds.getCenterY()); pointCoords[1] = new Point2D.Double(oNodeBounds.getMaxX(), oNodeBounds.getCenterY()); } else { pointCoords[0] = new Point2D.Double(oNodeBounds.getMinX(), oNodeBounds.getMinY()); pointCoords[1] = new Point2D.Double(oNodeBounds.getMaxX(), oNodeBounds.getMaxY()); } } if (newCount != trueCount) { error.markError(ni, np, "Main example of layer " + Info.getSampleName(ne.studySample.layer) + " has " + trueCount + " points but this has " + newCount); return null; } for(int i=0; i<trueCount; i++) { // see if edges are fixed distance from example edge if (!DBMath.areEquals(pointLeftDist[i], pointCoords[i].getX() - ne.lx)) pointFactor[i] &= ~TOEDGELEFT; if (!DBMath.areEquals(pointRightDist[i], ne.hx - pointCoords[i].getX())) pointFactor[i] &= ~TOEDGERIGHT; if (!DBMath.areEquals(pointBottomDist[i], pointCoords[i].getY() - ne.ly)) pointFactor[i] &= ~TOEDGEBOT; if (!DBMath.areEquals(pointTopDist[i], ne.hy - pointCoords[i].getY())) pointFactor[i] &= ~TOEDGETOP; // see if edges are fixed distance from example center if (!DBMath.areEquals(centerXDist[i], pointCoords[i].getX() - (ne.lx+ne.hx)/2)) pointFactor[i] &= ~FROMCENTX; if (!DBMath.areEquals(centerYDist[i], pointCoords[i].getY() - (ne.ly+ne.hy)/2)) pointFactor[i] &= ~FROMCENTY; // see if edges are fixed ratio from example center double r = 0; if (ne.hx != ne.lx) r = (pointCoords[i].getX() - (ne.lx+ne.hx)/2) / (ne.hx-ne.lx); if (!DBMath.areEquals(r, pointXRatio[i])) pointFactor[i] &= ~RATIOCENTX; if (ne.hy == ne.ly) r = 0; else r = (pointCoords[i].getY() - (ne.ly+ne.hy)/2) / (ne.hy-ne.ly); if (!DBMath.areEquals(r, pointYRatio[i])) pointFactor[i] &= ~RATIOCENTY; } // make sure port information is on the primary example if (ns.layer != Generic.tech().portNode) continue; // check port angle Variable var = ns.node.getVar(Info.PORTANGLE_KEY); Variable var2 = ni.getVar(Info.PORTANGLE_KEY); if (var == null && var2 != null) { System.out.println("Warning: moving port angle to main example of " + np); ns.node.newVar(Info.PORTANGLE_KEY, var2.getObject()); } // check port range var = ns.node.getVar(Info.PORTRANGE_KEY); var2 = ni.getVar(Info.PORTRANGE_KEY); if (var == null && var2 != null) { System.out.println("Warning: moving port range to main example of " + np); ns.node.newVar(Info.PORTRANGE_KEY, var2.getObject()); } // check connectivity var = ns.node.getVar(Info.CONNECTION_KEY); var2 = ni.getVar(Info.CONNECTION_KEY); if (var == null && var2 != null) { System.out.println("Warning: moving port connections to main example of " + np); ns.node.newVar(Info.CONNECTION_KEY, var2.getObject()); } } // error check for the highlight layer if (ns.layer == null) { for(int i=0; i<trueCount; i++) if ((pointFactor[i]&(TOEDGELEFT|TOEDGERIGHT)) == 0 || (pointFactor[i]&(TOEDGETOP|TOEDGEBOT)) == 0) { error.markError(ns.node, np, "Highlight must be constant distance from edge"); return null; } } // finally, make a rule for this sample Technology.TechPoint [] newRule = stretchPoints(pointList, pointFactor, ns, np, neList); if (newRule == null) return null; // add the rule to the global list ns.msg = Info.getValueOnNode(ns.node); if (ns.msg != null && ns.msg.length() == 0) ns.msg = null; ns.values = newRule; // stop now if a highlight or port object if (ns.layer == null || ns.layer == Generic.tech().portNode) continue; nodeLayers[count] = new NodeInfo.LayerDetails(); nodeLayers[count].layer = giLayer; nodeLayers[count].ns = ns; nodeLayers[count].style = getStyle(ns.node); nodeLayers[count].representation = Technology.NodeLayer.POINTS; nodeLayers[count].values = fixValues(np, ns.values); if (nodeLayers[count].values.length == 2) { if (nodeLayers[count].style == Poly.Type.CROSSED || nodeLayers[count].style == Poly.Type.FILLED || nodeLayers[count].style == Poly.Type.CLOSED) { nodeLayers[count].representation = Technology.NodeLayer.BOX;// if (minFactor != 0)// nodeLayers[count].representation = Technology.NodeLayer.MINBOX; } } count++; } if (count != nodeLayers.length) System.out.println("Warning: Generated only " + count + " of " + nodeLayers.length + " layers for " + np); return nodeLayers; } private NodeInfo.LayerDetails [] makeNodeScaledUniformly(List<Example> neList, Cell np, LayerInfo [] lis) { Example firstEx = neList.get(0); // count
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -