📄 abstractshapebuilder.java
字号:
long pureGridRadius = Math.abs(gridRadius); double gridLength = a.getGridLength(); // see if the lambdaRadius can work with these arc ends if (pureGridRadius*2 < gridLength) return false; // determine the center of the circle Point2D [] centers = DBMath.findCenters(pureGridRadius, a.headLocation.gridMutable(), a.tailLocation.gridMutable()); if (centers == null) return false; Point2D centerPt = centers[1]; if (gridRadius < 0) { centerPt = centers[0]; } double centerX = centerPt.getX(); double centerY = centerPt.getY(); // determine the base and range of angles int angleBase = DBMath.figureAngle(a.headLocation.getGridX() - centerX, a.headLocation.getGridY() - centerY); int angleRange = DBMath.figureAngle(a.tailLocation.getGridX() - centerX, a.tailLocation.getGridY() - centerY); angleRange -= angleBase; if (angleRange < 0) angleRange += 3600; // force the curvature to be the smaller part of a circle (used to determine this by the reverse-ends bit) if (angleRange > 1800) { angleBase += angleRange; if (angleBase < 0) angleBase += 3600; angleRange = 3600 - angleRange; } // determine the number of intervals to use for the arc int pieces = angleRange; while (pieces > MAXARCPIECES) pieces /= 2; if (pieces == 0) return false; // get the inner and outer radii of the arc double outerRadius = pureGridRadius + gridWidth / 2; double innerRadius = outerRadius - gridWidth; // fill the polygon for(int i=0; i<=pieces; i++) { int angle = (angleBase + i * angleRange / pieces) % 3600; pushPoint(DBMath.cos(angle) * innerRadius + centerX, DBMath.sin(angle) * innerRadius + centerY); } for(int i=pieces; i>=0; i--) { int angle = (angleBase + i * angleRange / pieces) % 3600; pushPoint(DBMath.cos(angle) * outerRadius + centerX, DBMath.sin(angle) * outerRadius + centerY); } return true; } /** * Generate shape of this ImmutableArcInst in easy case. * @param a the arc information. * @return true if shape was generated. */ public boolean genShapeEasy(ImmutableArcInst a) { if (m.isHardArc(a.arcId)) return false; ArcProto protoType = techPool.getArcProto(a.protoId); int gridExtendOverMin = (int)a.getGridExtendOverMin(); int minLayerExtend = gridExtendOverMin + protoType.getMinLayerGridExtend(); if (minLayerExtend == 0) { assert protoType.getNumArcLayers() == 1; Technology.ArcLayer primLayer = protoType.getArcLayer(0); Layer layer = primLayer.getLayer(); if (onlyTheseLayers != null && !onlyTheseLayers.contains(layer.getFunction(), layer.getFunctionExtras())) return true; Poly.Type style = primLayer.getStyle(); if (style == Poly.Type.FILLED) style = Poly.Type.OPENED; intCoords[0] = (int)a.tailLocation.getGridX(); intCoords[1] = (int)a.tailLocation.getGridY(); intCoords[2] = (int)a.headLocation.getGridX(); intCoords[3] = (int)a.headLocation.getGridY(); addIntLine(intCoords, style, primLayer.getLayer()); return true; } boolean tailExtended = false; if (a.isTailExtended()) { short shrinkT = shrinkage.get(a.tailNodeId); if (shrinkT == Shrinkage.EXTEND_90) tailExtended = true; else if (shrinkT != Shrinkage.EXTEND_0) return false; } boolean headExtended = false; if (a.isHeadExtended()) { short shrinkH = shrinkage.get(a.headNodeId); if (shrinkH == Shrinkage.EXTEND_90) headExtended = true; else if (shrinkH != Shrinkage.EXTEND_0) return false; } for (int i = 0, n = protoType.getNumArcLayers(); i < n; i++) { Technology.ArcLayer primLayer = protoType.getArcLayer(i); Layer layer = primLayer.getLayer(); assert primLayer.getStyle() == Poly.Type.FILLED; if (onlyTheseLayers != null && !onlyTheseLayers.contains(layer.getFunction(), layer.getFunctionExtras())) continue; a.makeGridBoxInt(intCoords, tailExtended, headExtended, gridExtendOverMin + protoType.getLayerGridExtend(i)); addIntBox(intCoords, layer); } return true; } public void pushPoint(EPoint p, double gridX, double gridY) { pushPointLow(p.getGridX() + DBMath.roundShapeCoord(gridX), p.getGridY() + DBMath.roundShapeCoord(gridY)); } public void pushPoint(double gridX, double gridY) { pushPointLow(DBMath.roundShapeCoord(gridX), DBMath.roundShapeCoord(gridY)); } public void pushPoint(EPoint p) { pushPointLow(p.getGridX(), p.getGridY()); } private void pushPointLow(double gridX, double gridY) { if (pointCount*2 >= doubleCoords.length) resize(); doubleCoords[pointCount*2] = gridX; doubleCoords[pointCount*2 + 1] = gridY; pointCount++; } private void resize() { double[] newDoubleCoords = new double[doubleCoords.length*2]; System.arraycopy(doubleCoords, 0, newDoubleCoords, 0, doubleCoords.length); doubleCoords = newDoubleCoords; } public void pushPoly(Poly.Type style, Layer layer) { addDoublePoly(pointCount, style, layer); pointCount = 0; } public void pushBox(int minX, int minY, int maxX, int maxY, Layer layer) { intCoords[0] = minX; intCoords[1] = minY; intCoords[2] = maxX; intCoords[3] = maxY; addIntBox(intCoords, layer); } public abstract void addDoublePoly(int numPoints, Poly.Type style, Layer layer); public abstract void addIntLine(int[] coords, Poly.Type style, Layer layer); public abstract void addIntBox(int[] coords, Layer layer); public static class Shrinkage { public static final short EXTEND_90 = 0; public static final short EXTEND_0 = 1; private static final short EXTEND_ANY = 2; private static final int ANGLE_SHIFT = 12; private static final int ANGLE_MASK = (1 << ANGLE_SHIFT) - 1; private static final int ANGLE_DIAGONAL_MASK = 1 << (ANGLE_SHIFT*2); private static final int ANGLE_COUNT_SHIFT = ANGLE_SHIFT*2 + 1; private final short[] shrink; public Shrinkage() { shrink = new short[0]; } public Shrinkage(CellBackup cellBackup) { CellRevision cellRevision = cellBackup.cellRevision; TechPool techPool = cellBackup.techPool; int maxNodeId = -1; for (int nodeIndex = 0; nodeIndex < cellRevision.nodes.size(); nodeIndex++) maxNodeId = Math.max(maxNodeId, cellRevision.nodes.get(nodeIndex).nodeId); int[] angles = new int[maxNodeId+1]; for (ImmutableArcInst a: cellRevision.arcs) { ArcProto ap = techPool.getArcProto(a.protoId); if (a.getGridExtendOverMin() + ap.getMaxLayerGridExtend() == 0) continue; if (a.tailNodeId == a.headNodeId && a.tailPortId == a.headPortId) { // Fake register for full shrinkage registerArcEnd(angles, a.tailNodeId, 0, false, false); continue; } boolean is90 = a.isManhattan(); registerArcEnd(angles, a.tailNodeId, a.getOppositeAngle(), is90, a.isTailExtended()); registerArcEnd(angles, a.headNodeId, a.getAngle(), is90, a.isHeadExtended()); } short[] shrink = new short[maxNodeId + 1]; for (int nodeIndex = 0; nodeIndex < cellRevision.nodes.size(); nodeIndex++) { ImmutableNodeInst n = cellRevision.nodes.get(nodeIndex); NodeProtoId np = n.protoId; if (np instanceof PrimitiveNodeId && techPool.getPrimitiveNode((PrimitiveNodeId)np).isArcsShrink()) shrink[n.nodeId] = computeShrink(angles[n.nodeId]); } this.shrink = shrink; } /** * Method to tell the "end shrink" factors on all arcs on a specified ImmutableNodeInst. * EXTEND_90 indicates no shortening (extend the arc by half its width). * EXTEND_0 indicates no extend. * EXTEND_ANY + [0..3600) is a sum of arc angles modulo 3600 * if this ImmutableNodeInst is a pin which can "isArcsShrink" and this pin connects * exactly two arcs whit extended ends and angle between arcs is accute. * @param nodeId nodeId of specified ImmutableNodeInst * @return shrink factor of specified ImmutableNodeInst is wiped. */ public short get(int nodeId) { return nodeId < shrink.length ? shrink[nodeId] : 0; } private void registerArcEnd(int[] angles, int nodeId, int angle, boolean is90, boolean extended) { assert angle >= 0 && angle < 3600; int ang = angles[nodeId]; if (extended) { int count = ang >>> ANGLE_COUNT_SHIFT; switch (count) { case 0: ang |= angle; ang += (1 << ANGLE_COUNT_SHIFT); break; case 1: ang |= (angle << ANGLE_SHIFT); ang += (1 << ANGLE_COUNT_SHIFT); break; case 2: ang += (1 << ANGLE_COUNT_SHIFT); break; } if (!is90) ang |= ANGLE_DIAGONAL_MASK; } else { ang |= (3 << ANGLE_COUNT_SHIFT); } angles[nodeId] = ang; } static short computeShrink(int angs) { boolean hasAny = (angs&ANGLE_DIAGONAL_MASK) != 0; int count = angs >>> ANGLE_COUNT_SHIFT; if (hasAny && count == 2) { int ang0 = angs & ANGLE_MASK; int ang1 = (angs >> ANGLE_SHIFT) & ANGLE_MASK; int da = ang0 > ang1 ? ang0 - ang1 : ang1 - ang0; if (da == 900 || da == 2700) return EXTEND_90; if (da == 1800) return EXTEND_0; if (900 < da && da < 2700) { int a = ang0 + ang1; if (a >= 3600) a -= 3600; return (short)(EXTEND_ANY + a); } } return EXTEND_90; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -