📄 interactiverouter.java
字号:
VerticalRoute vroute = VerticalRoute.newRoute(startPort, endPort); if (!vroute.isSpecificationSucceeded()) return new Route(); // arc width of arcs that will connect to startObj, endObj will determine // valid attachment points of arcs ArcProto startArc = vroute.getStartArc(); ArcProto endArc = vroute.getEndArc(); double startArcWidth = getArcWidthToUse(startObj, startArc); double endArcWidth = (endObj == null) ? startArcWidth : getArcWidthToUse(endObj, endArc); // if extension not supressed, use defaults from arcs if (extendArcHead) extendArcHead = startArc.isExtended() || endArc.isExtended(); if (extendArcTail) extendArcTail = startArc.isExtended() || endArc.isExtended(); // get valid connecting sites for start and end objects based on the objects // themselves, the point the user clicked, and the width of the wire that will // attach to each Poly startPoly = getConnectingSite(startObj, clicked, startArcWidth); Poly endPoly = getConnectingSite(endObj, clicked, endArcWidth); // Now we can figure out where on the start and end objects the connecting // arc(s) should connect Point2D startPoint = new Point2D.Double(0, 0); Point2D endPoint = new Point2D.Double(0,0); getConnectingPoints(startObj, endObj, clicked, startPoint, endPoint, startPoly, endPoly, startArc, endArc); PortInst existingStartPort = null; PortInst existingEndPort = null; // favor contact cuts on arcs boolean contactsOnEndObject = true; // plan start of route if (startObj instanceof PortInst) { // portinst: just wrap in RouteElement existingStartPort = (PortInst)startObj; startRE = RouteElementPort.existingPortInst(existingStartPort, startPoly); } if (startObj instanceof ArcInst) { // arc: figure out where on arc to start startRE = findArcConnectingPoint(route, (ArcInst)startObj, startPoint, stayInside); contactsOnEndObject = false; } if (startRE == null) { if (startObj != badStartObject) System.out.println(" Can't route from "+startObj+", no ports"); badStartObject = startObj; return route; } // plan end of route if (endObj != null) { // we have somewhere to route to if (endObj instanceof PortInst) { // portinst: just wrap in RouteElement existingEndPort = (PortInst)endObj; endRE = RouteElementPort.existingPortInst(existingEndPort, endPoly); } if (endObj instanceof ArcInst) { // arc: figure out where on arc to end // use startRE location when possible if connecting to arc endRE = findArcConnectingPoint(route, (ArcInst)endObj, endPoint, stayInside); contactsOnEndObject = true; } if (endRE == null) { if (endObj != badEndObject) System.out.println(" Can't route to "+endObj+", no ports"); badEndObject = endObj; endObj = null; } } if (endObj == null) { // nowhere to route to, must make new pin to route to // first we need to determine what pin to make based on // start object ArcProto useArc = null; if (startObj instanceof PortInst) { PortInst startPi = (PortInst)startObj; useArc = getArcToUse(startPi.getPortProto(), null); } if (startObj instanceof ArcInst) { ArcInst startAi = (ArcInst)startObj; useArc = startAi.getProto(); } // make new pin to route to PrimitiveNode pn = useArc.findOverridablePinProto(); SizeOffset so = pn.getProtoSizeOffset(); endRE = RouteElementPort.newNode(cell, pn, pn.getPort(0), endPoint, pn.getDefWidth()-so.getHighXOffset()-so.getLowXOffset(), pn.getDefHeight()-so.getHighYOffset()-so.getLowYOffset()); } // favor contact on bisected arc if (startRE.isBisectArcPin()) contactsOnEndObject = false; if (endRE != null && endRE.isBisectArcPin()) contactsOnEndObject = true; // special check: if both are existing port insts and are same port, do nothing if ((existingEndPort != null) && (existingEndPort == existingStartPort)) return new Route(); // add startRE and endRE to route route.add(startRE); route.setStart(startRE); route.setEnd(startRE); //route.add(endRE); route.setEnd(endRE); // Tell Router to route between startRE and endRE if (planRoute(route, cell, endRE, startPoint, endPoint, clicked, stayInside, vroute, contactsOnEndObject, extendArcHead, extendArcTail, contactArea)) { return route; } return new Route(); // error, return empty route } // -------------------- Internal Router Utility Methods -------------------- /** * If routeObj is a NodeInst, first thing we do is get the nearest PortInst * to where the user clicked, and use that instead. * @param routeObj the route object (possibly a NodeInst). * @param clicked where the user clicked * @return the PortInst on the NodeInst closest to where the user clicked, * or just the routeObj back if it is not a NodeInst. */ protected static ElectricObject filterRouteObject(ElectricObject routeObj, Point2D clicked) { if (routeObj instanceof NodeInst) { return ((NodeInst)routeObj).findClosestPortInst(clicked); } if (routeObj instanceof Export) { Export exp = (Export)routeObj; return exp.getOriginalPort(); } return routeObj; } /** * Get the PortProto associated with routeObj (it should be either * a ArcInst or a PortInst, otherwise this will return null). * @param routeObj the route object * @return the PortProto for this route object */ protected static PortProto getRoutePort(ElectricObject routeObj) { assert(!(routeObj instanceof NodeInst)); if (routeObj instanceof ArcInst) { ArcInst ai = (ArcInst)routeObj; PrimitiveNode pn = ai.getProto().findOverridablePinProto(); return pn.getPort(0); } if (routeObj instanceof PortInst) { PortInst pi = (PortInst)routeObj; return pi.getPortProto(); } return null; } protected static double getArcWidthToUse(ElectricObject routeObj, ArcProto ap) { double width = -1; if (routeObj instanceof ArcInst) { ArcInst ai = (ArcInst)routeObj; if (ai.getProto() == ap) return ai.getLambdaBaseWidth(); } if (routeObj instanceof PortInst) { width = Router.getArcWidthToUse((PortInst)routeObj, ap); } return width; } /** * Get the connecting points for the start and end objects of the route. This fills in * the two Point2D's startPoint and endPoint. These will be the end points of an arc that * connects to either startObj or endObj. * @param startObj the start route object * @param endObj the end route object * @param clicked where the user clicked * @param startPoint point inside startPoly on startObj to connect arc to * @param endPoint point inside endPoly on endObj to connect arc to * @param startPoly valid port site on startObj * @param endPoly valid port site on endObj */ protected static void getConnectingPoints(ElectricObject startObj, ElectricObject endObj, Point2D clicked, Point2D startPoint, Point2D endPoint, Poly startPoly, Poly endPoly, ArcProto startArc, ArcProto endArc) {/* Point2D[] points = startPoly.getPoints(); System.out.print("StartPoly: "); for (int i=0; i<points.length; i++) { System.out.print(points[i]+", "); } System.out.println(""); if (endPoly != null) { points = endPoly.getPoints(); System.out.print("EndPoly: "); for (int i=0; i<points.length; i++) { System.out.print(points[i]+", "); } System.out.println(""); }*/ if ((startPoly.getBox() == null && startPoly.getPoints().length != 2) || (endPoly != null && endPoly.getBox() == null && endPoly.getPoints().length != 2)) { // special case: one of the polys is not a rectangle startPoint.setLocation(startPoly.closestPoint(clicked)); if (endPoly == null) { endPoint.setLocation(getClosestOrthogonalPoint(startPoint, clicked)); } else { endPoint.setLocation(endPoly.closestPoint(clicked)); } return; } // just go by bounds for now Rectangle2D startBounds = startPoly.getBounds2D(); // default is center point startPoint.setLocation(startBounds.getCenterX(), startBounds.getCenterY()); if (startObj instanceof ArcInst) { double x, y; // if nothing to connect to, clicked will determine connecting point on startPoly // endPoint will be location of new pin x = getClosestValue(startBounds.getMinX(), startBounds.getMaxX(), clicked.getX()); y = getClosestValue(startBounds.getMinY(), startBounds.getMaxY(), clicked.getY()); startPoint.setLocation(x, y); } if (endPoly == null) { // if arc, find place to connect to. Otherwise use the center point (default) int angleIncrement = endArc.getAngleIncrement(); endPoint.setLocation(getClosestAngledPoint(startPoint, clicked, angleIncrement)); //endPoint.setLocation(getClosestOrthogonalPoint(startPoint, clicked)); // however, if this is an Artwork technology, just put end point at mouse if (startArc.getTechnology() == Artwork.tech()) endPoint.setLocation(clicked); return; } Rectangle2D endBounds = endPoly.getBounds2D(); endPoint.setLocation(endBounds.getCenterX(), endBounds.getCenterY()); if (endObj instanceof ArcInst) { double x, y; // if nothing to connect to, clicked will determine connecting point on startPoly // endPoint will be location of new pin x = getClosestValue(endBounds.getMinX(), endBounds.getMaxX(), clicked.getX()); y = getClosestValue(endBounds.getMinY(), endBounds.getMaxY(), clicked.getY()); endPoint.setLocation(x, y); } // if bounds share x-space, use closest x within that space to clicked point double lowerBoundX = Math.max(startBounds.getMinX(), endBounds.getMinX()); double upperBoundX = Math.min(startBounds.getMaxX(), endBounds.getMaxX()); if (lowerBoundX <= upperBoundX) { double x = getClosestValue(lowerBoundX, upperBoundX, clicked.getX()); startPoint.setLocation(x, startPoint.getY()); endPoint.setLocation(x, endPoint.getY()); } else { // otherwise, use closest point in bounds to the other port // see which one is higher in X...they don't overlap, so any X coord in bounds is comparable if (startBounds.getMinX() > endBounds.getMaxX()) { startPoint.setLocation(startBounds.getMinX(), startPoint.getY()); endPoint.setLocation(endBounds.getMaxX(), endPoint.getY()); } else { startPoint.setLocation(startBounds.getMaxX(), startPoint.getY()); endPoint.setLocation(endBounds.getMinX(), endPoint.getY()); } } // if bounds share y-space, use closest y within that space to clicked point double lowerBoundY = Math.max(startBounds.getMinY(), endBounds.getMinY()); double upperBoundY = Math.min(startBounds.getMaxY(), endBounds.getMaxY()); if (lowerBoundY <= upperBoundY) { double y = getClosestValue(lowerBoundY, upperBoundY, clicked.getY()); startPoint.setLocation(startPoint.getX(), y); endPoint.setLocation(endPoint.getX(), y); } else { // otherwise, use closest point in bounds to the other port // see which one is higher in Y...they don't overlap, so any Y coord in bounds is comparable if (startBounds.getMinY() > endBounds.getMaxY()) { startPoint.setLocation(startPoint.getX(), startBounds.getMinY()); endPoint.setLocation(endPoint.getX(), endBounds.getMaxY()); } else { startPoint.setLocation(startPoint.getX(), startBounds.getMaxY()); endPoint.setLocation(endPoint.getX(), endBounds.getMinY()); } } } /** * Get the connecting site of the electric object. * <ul> * <li>For NodeInsts, this is the nearest portinst to "clicked", which is then subject to: * <li>For PortInsts, this is the nearest site of a multisite port, or just the entire port * <li>For ArcInsts, this is a poly composed of the head location and the tail location * </ul> * See NodeInst.getShapeOfPort() for more details. * @param obj the object to get a connection site for * @param clicked used to find the nearest portinst on a nodeinst, and nearest * site on a multisite port * @param arcWidth contacts port sites are restricted by the size of arcs connecting * to them, such that the arc width does extend beyond the contact edges. * @return a poly describing where something can connect to */ protected static Poly getConnectingSite(ElectricObject obj, Point2D clicked, double arcWidth) { assert(clicked != null); if (obj instanceof NodeInst) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -