📄 layoutcell.java
字号:
// figure out the new location of the other nodeinst Point2D ptD = new Point2D.Double(); trans.transform(ono.getAnchorCenter(), ptD); dx = ptD.getX(); dy = ptD.getY(); dx = dx - ono.getAnchorCenterX() - othX; dy = dy - ono.getAnchorCenterY() - othY; // ignore null motion on nodes that have already been examined if (dx != 0 || dy != 0 || !dOrient.equals(Orientation.IDENT)) { rigidModified.add(ai); if (Layout.DEBUG) System.out.println(" Moving "+ono+" at other end by ("+dx+","+dy+")"); alterNodeInst(ono, dx, dy, dOrient); } } // move the arcinst if (Layout.DEBUG) System.out.println(" Altering arc, head moves to "+newPts[ArcInst.HEADEND]+" tail moves to "+newPts[ArcInst.TAILEND]); doMoveArcInst(ai, newPts[ArcInst.HEADEND], newPts[ArcInst.TAILEND], AI_RIGID); } // re-scan rigid arcs and recursively modify arcs on other nodes for(Connection thisEnd : rigidArcs) { ArcInst ai = thisEnd.getArc(); if (!ai.isLinked()) continue; // only want arcinst that was just explored if (!rigidModified.contains(ai)) continue; // get the other nodeinst NodeInst ono = ai.getPortInst(1 - thisEnd.getEndIndex()).getNodeInst(); if (Layout.DEBUG) System.out.println(" " + ni + " re-examining " + ai + " to other "+ono); modNodeArcs(ono, dOrient); } } /** * Method to modify the flexible arcs connected to a NodeInst. * @param ni the NodeInst being examined. * @param dOrient the change in the node Orientation. * @return true if any nodes that have exports move. * This indicates that instances of the current cell must be examined for ArcInst motion. */ private void modFlex(NodeInst ni, Orientation dOrient) { // build a list of the flexible arcs on this nodeinst List<Connection> flexArcs = new ArrayList<Connection>(); for(Iterator<Connection> it = getConnections(ni); it.hasNext(); )// for(Iterator<Connection> it = ni.getConnections(); it.hasNext(); ) { Connection con = it.next(); ArcInst ai = con.getArc(); // ignore if arcinst is not flexible// if (getChangeClock(ai) == AI_RIGID.intValue()) continue; if (Layout.isRigid(ai)) continue; // ignore arcs that connect two ports on the same node if (ai.getHeadPortInst().getNodeInst() == ai.getTailPortInst().getNodeInst()) continue; // include in the list to be considered here flexArcs.add(con); } if (flexArcs.size() == 0) return; // look at all of the flexible arcs on this nodeinst// long startTime = System.currentTimeMillis(); for(Connection thisEnd : flexArcs) { ArcInst ai = thisEnd.getArc(); if (!ai.isLinked()) continue; if (Layout.DEBUG) System.out.println(" Modifying fixed-angle "+ai); // if flexible arcinst has been changed, verify its connectivity if (arcMoved(ai))// if (getChangeClock(ai) >= AI_FLEX.intValue()) { if (Layout.DEBUG) System.out.println(" Arc already changed"); ensureArcInst(ai, AI_FLEX); continue; } // figure where each end of the arcinst is int thisEndIndex = thisEnd.getEndIndex(); int thatEndIndex = 1 - thisEndIndex; EPoint thisLocation = thisEnd.getLocation(); EPoint thatLocation = ai.getLocation(thatEndIndex); // if nodeinst motion stays within port area, ignore the arcinst if (ai.isSlidable() && ai.stillInPort(thisEndIndex, thisLocation, true)) continue; // create the two points that will be the new ends of this arc Point2D [] newPts = new Point2D.Double[2]; for (int i = 0; i < 2; i++) { newPts[i] = new Point2D.Double(); AffineTransform trans = transformByPort(ai.getPortInst(i)); trans.transform(ai.getLocation(i), newPts[i]); newPts[i].setLocation(DBMath.round(newPts[i].getX()), DBMath.round(newPts[i].getY())); } // make sure the arc end is still in the port Poly poly = thisEnd.getPortInst().getPoly(); if (!poly.isInside(newPts[thisEndIndex])) { Rectangle2D bbox = poly.getBounds2D(); if (newPts[thisEndIndex].getY() >= bbox.getMinY() && newPts[thisEndIndex].getY() <= bbox.getMaxY()) { // extend arc horizontally to fit in port if (newPts[thisEndIndex].getX() < bbox.getMinX()) { newPts[thisEndIndex].setLocation(bbox.getMinX(), newPts[thisEndIndex].getY()); } else if (newPts[thisEndIndex].getX() > bbox.getMaxX()) { newPts[thisEndIndex].setLocation(bbox.getMaxX(), newPts[thisEndIndex].getY()); } } else if (newPts[thisEndIndex].getX() >= bbox.getMinX() && newPts[thisEndIndex].getX() <= bbox.getMaxX()) { // extend arc vertically to fit in port if (newPts[thisEndIndex].getY() < bbox.getMinY()) { newPts[thisEndIndex].setLocation(newPts[thisEndIndex].getX(), bbox.getMinY()); } else if (newPts[thisEndIndex].getY() > bbox.getMaxY()) { newPts[thisEndIndex].setLocation(newPts[thisEndIndex].getX(), bbox.getMaxY()); } } else { // extend arc arbitrarily to fit in port Point2D pt = poly.closestPoint(newPts[thisEndIndex]); newPts[thisEndIndex].setLocation(pt); } } // get other end of arcinst and its position NodeInst ono = ai.getPortInst(thatEndIndex).getNodeInst();// newPts[thatEndIndex].setLocation(thatLocation); // see if other nodeinst has changed boolean mangle = true; if (movedNodes.contains(ono)) mangle = false; if (!ai.isFixedAngle()) mangle = false; else { if (ono.isLocked()) mangle = false; else { if (ono.isCellInstance()) { if (ono.getParent().isInstancesLocked()) mangle = false; } else { if (User.isDisallowModificationLockedPrims() && ((PrimitiveNode)ono.getProto()).isLockedPrim()) mangle = false; } } } if (mangle) { // other nodeinst untouched, mangle it double dx = newPts[thisEndIndex].getX() - thisLocation.getX(); double dy = newPts[thisEndIndex].getY() - thisLocation.getY(); double odx = newPts[thatEndIndex].getX() - thatLocation.getX(); double ody = newPts[thatEndIndex].getY() - thatLocation.getY(); if (DBMath.doublesEqual(thisLocation.getX(), thatLocation.getX())) { // null arcinst must not be explicitly horizontal if (!DBMath.doublesEqual(thisLocation.getY(), thatLocation.getY()) || ai.getAngle() == 900 || ai.getAngle() == 2700) { // vertical arcinst: see if it really moved in X if (dx == odx) dx = odx = 0; // move horizontal, shrink vertical newPts[thatEndIndex].setLocation(newPts[thatEndIndex].getX() + dx-odx, newPts[thatEndIndex].getY()); // see if next nodeinst need not be moved if (!DBMath.doublesEqual(dx, odx) && ai.isSlidable() && ai.stillInPort(thatEndIndex, newPts[thatEndIndex], true)) dx = odx = 0; // if other node already moved, don't move it any more if (movedNodes.contains(ono)) dx = odx = 0; if (dx != odx) { double xAmount = DBMath.round(dx-odx); if (Layout.DEBUG) System.out.println(" Moving "+ono+" by ("+xAmount+",0)"); alterNodeInst(ono, xAmount, 0, Orientation.IDENT); } if (Layout.DEBUG) System.out.println(" Moving vertical arc so head=("+newPts[ArcInst.HEADEND].getX()+","+newPts[ArcInst.HEADEND].getY()+ ") and tail=("+newPts[ArcInst.TAILEND].getX()+","+newPts[ArcInst.TAILEND].getY()+")"); doMoveArcInst(ai, newPts[ArcInst.HEADEND], newPts[ArcInst.TAILEND], AI_FLEX); if (!DBMath.doublesEqual(dx, odx)) modNodeArcs(ono, Orientation.IDENT); continue; } } if (DBMath.doublesEqual(thisLocation.getY(), thatLocation.getY())) { // horizontal arcinst: see if it really moved in Y if (DBMath.doublesEqual(dy, ody)) dy = ody = 0; // shrink horizontal, move vertical newPts[thatEndIndex].setLocation(newPts[thatEndIndex].getX(), newPts[thatEndIndex].getY() + dy-ody); // see if next nodeinst need not be moved if (!DBMath.doublesEqual(dy, ody) && ai.isSlidable() && ai.stillInPort(thatEndIndex, newPts[thatEndIndex], true)) dy = ody = 0; // if other node already moved, don't move it any more if (movedNodes.contains(ono)) dx = odx = 0; if (!DBMath.doublesEqual(dy, ody)) { if (Layout.DEBUG) System.out.println(" Moving "+ono+" by (0,"+(dy-ody)+")"); alterNodeInst(ono, 0, dy-ody, Orientation.IDENT); } if (Layout.DEBUG) System.out.println(" Moving horizontal arc so head=("+newPts[ArcInst.HEADEND].getX()+","+newPts[ArcInst.HEADEND].getY()+ ") and tail=("+newPts[ArcInst.TAILEND].getX()+","+newPts[ArcInst.TAILEND].getY()+")"); doMoveArcInst(ai, newPts[ArcInst.HEADEND], newPts[ArcInst.TAILEND], AI_FLEX); if (!DBMath.doublesEqual(dy, ody)) { modNodeArcs(ono, Orientation.IDENT); } continue; } /***** THIS CODE HANDLES ALL-ANGLE RIGIDITY WITH THE FIXED-ANGLE CONSTRAINT *****/ // special code to handle nonorthogonal fixed-angles nonOrthogFixAng(ai, thisEnd, thisEndIndex, thatEndIndex, ono, newPts); dx = newPts[thatEndIndex].getX() - thatLocation.getX(); dy = newPts[thatEndIndex].getY() - thatLocation.getY(); // change the arc updateArc(ai, newPts[ArcInst.HEADEND], newPts[ArcInst.TAILEND], AI_FLEX); // if other node already moved, don't move it any more if (movedNodes.contains(ono)) dx = dy = 0; if (dx != 0 || dy != 0) { if (Layout.DEBUG) System.out.println(" Moving "+ono+" by ("+dx+","+dy+")"); alterNodeInst(ono, dx, dy, Orientation.IDENT); modNodeArcs(ono, Orientation.IDENT); } continue; } // other node has changed or arc is funny, just use its position if (Layout.DEBUG) System.out.println(" Moving nonmanhattan arc so head=("+newPts[ArcInst.HEADEND].getX()+","+newPts[ArcInst.HEADEND].getY()+ ") and tail=("+newPts[ArcInst.TAILEND].getX()+","+newPts[ArcInst.TAILEND].getY()+")"); doMoveArcInst(ai, newPts[ArcInst.HEADEND], newPts[ArcInst.TAILEND], AI_FLEX); }// long stopTime = System.currentTimeMillis();// System.out.println("Moving in modFlex took " + (stopTime - startTime)); } /** * Method to determine the motion of a nonorthogonal ArcInst given that one end has moved. * The end that is "thisEnd" has moved to (ax[thisEndIndex],ay[thisEndIndex]), so this method * must determine the coordinates of the other end and set (ax[thatEndIndex],ay[thatEndIndex]). * @param ai the nonorthogonal ArcInst that is adjusting. * @param thisEnd the Connection at one end of the ArcInst. * @param thisEndIndex the index (0 or 1) of "thisEnd" of the ArcInst. * @param thatEnd the Connection at the other end of the ArcInst. * @param thatEndIndex the index (0 or 1) of "thatEnd" of the ArcInst. * @param ono the node at the other end ("thatEnd"). * @param newPts an array of 2 points that defines the coordinates of the two ends (0: head, 1: tail). */ private void nonOrthogFixAng(ArcInst ai, Connection thisEnd, int thisEndIndex, int thatEndIndex, NodeInst ono, Point2D [] newPts) { // look for longest other arc on "ono" to determine proper end position double bestDist = Double.NEGATIVE_INFINITY; ArcInst bestAI = null; for(Iterator<Connection> it = getConnections(ai.getPortInst(thatEndIndex)); it.hasNext(); )// for(Iterator<Connection> it = ai.getPortInst(thatEndIndex).getConnections(); it.hasNext(); ) { Connection con = it.next(); ArcInst oai = con.getArc(); if (oai == ai) continue; double length = oai.getGridLength(); if (length <= bestDist) continue; bestDist = length; bestAI = oai; } // if no other arcs, allow that end to move the same as this end if (bestAI == null) { newPts[thatEndIndex].setLocation( newPts[thatEndIndex].getX() + newPts[thisEndIndex].getX() - thisEnd.getLocation().getX(), newPts[thatEndIndex].getY() + newPts[thisEndIndex].getY() - thisEnd.getLocation().getY()); return; } // compute intersection of arc "bestai" with new moved arc "ai" Point2D inter = DBMath.intersect(newPts[thisEndIndex], ai.getAngle(), bestAI.getHeadLocation(), bestAI.getAngle()); if (inter == null) { newPts[thatEndIndex].setLocation( newPts[thatEndIndex].getX() + newPts[thisEndIndex].getX() - thisEnd.getLocation().getX(), newPts[thatEndIndex].getY() + newPts[thisEndIndex].getY() - thisEnd.getLocation().getY()); return; } newPts[thatEndIndex].setLocation(inter); } /** * Method to ensure that an ArcInst is still connected properly at each end. * If it is not, the ArcInst must be jogged or adjusted. * @param ai the ArcInst to check. * @param arctyp the nature of the arc: 0 for rigid, 1 for flexible. */ private void ensureArcInst(ArcInst ai, Integer arctyp) { // if nothing is outside port, quit Point2D headPoint = ai.getHeadLocation(); boolean inside0 = ai.headStillInPort(headPoint, true); Point2D tailPoint = ai.getTailLocation(); boolean inside1 = ai.tailStillInPort(tailPoint, true); if (inside0 && inside1) return; // get area of the ports Poly headPoly = ai.getHeadPortInst().getPoly(); Poly tailPoly = ai.getTailPortInst().getPoly(); // if arcinst is not fixed-angle, run it directly to the port centers if (!ai.isFixedAngle()) { double fx = headPoly.getCenterX(); double fy = headPoly.getCenterY(); double tx = tailPoly.getCenterX(); double ty = tailPoly.getCenterY(); doMoveArcInst(ai, new Point2D.Double(fx, fy), new Point2D.Double(tx, ty), arctyp); return; } // get bounding boxes of polygons Rectangle2D headBounds = headPoly.getBounds2D(); Rectangle2D tailBounds = tailPoly.getBounds2D(); double lx0 = headBounds.getMinX(); double hx0 = headBounds.getMaxX(); double ly0 = headBounds.getMinY(); double hy0 = headBounds.getMaxY(); double lx1 = tailBounds.getMinX(); double hx1 = tailBounds.getMaxX(); double ly1 = tailBounds.getMinY(); double hy1 = tailBounds.getMaxY(); // if manhattan path runs between the ports, adjust the arcinst if (lx0 <= hx1 && lx1 <= hx0) { // arcinst runs vertically double tx = (Math.max(lx0,lx1) + Math.min(hx0,hx1)) / 2; double fx = tx; double fy = (ly0+hy0) / 2; double ty = (ly1+hy1) / 2; Point2D fPt = headPoly.closestPoint(new Point2D.Double(fx, fy)); Point2D tPt = tailPoly.closestPoint(new Point2D.Double(tx, ty)); doMoveArcInst(ai, fPt, tPt, arctyp); return; } if (ly0 <= hy1 && ly1 <= hy0) { // arcinst runs horizontally double ty = (Math.max(ly0,ly1) + Math.min(hy0,hy1)) / 2; double fy = ty; double fx = (lx0+hx0) / 2; double tx = (lx1+hx1) / 2; Point2D fPt = headPoly.closestPoint(new Point2D.Double(fx, fy)); Point2D tPt = tailPoly.closestPoint(new Point2D.Double(tx, ty)); doMoveArcInst(ai, fPt, tPt, arctyp); return; } // give up and jog the arcinst double fx = headPoly.getCenterX(); double fy = headPoly.getCenterY(); double tx = tailPoly.getCenterX(); double ty = tailPoly.getCenterY(); doMoveArcInst(ai, new Point2D.Double(fx, fy), new Point2D.Double(tx, ty), arctyp); } /** * Method to update the coordinates of the ends of an ArcInst. * @param ai the ArcInst to adjust * @param headPt the new coordinates of the head of the ArcInst. * @param tailPt the new coordinates of the tail of the ArcInst. * @param arctyp the nature of the arc: 0 for rigid, 1 for flexible. */ private void updateArc(ArcInst ai, Point2D headPt, Point2D tailPt, Integer arctyp) { // set the proper arcinst position// Point2D oldHeadPt = ai.getHeadLocation();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -