📄 interactiverouter.java
字号:
PortInst pi = ((NodeInst)obj).findClosestPortInst(clicked); if (pi == null) return null; obj = pi; } if (obj instanceof PortInst) { PortInst pi = (PortInst)obj; NodeInst ni = pi.getNodeInst(); PortProto pp = pi.getPortProto(); boolean compressPort = false; if (!ni.isCellInstance()) compressPort = true; Poly poly = ni.getShapeOfPort(pp, clicked, compressPort, arcWidth); // this is for multi-site ports return poly; } if (obj instanceof ArcInst) { // make poly out of possible connecting points on arc ArcInst arc = (ArcInst)obj; Point2D [] points = new Point2D[2]; points[0] = arc.getHeadLocation(); points[1] = arc.getTailLocation(); Poly poly = new Poly(points); return poly; } return null; } /** * If drawing to/from an ArcInst, we may connect to some * point along the arc. This may bisect the arc, in which case * we delete the current arc, add in a pin at the appropriate * place, and create 2 new arcs to the old arc head/tail points. * The bisection point depends on where the user point, but it * is always a point on the arc. * <p> * Note that this method adds the returned RouteElement to the * route, and updates the route if the arc is bisected. * This method should NOT add the returned RouteElement to the route. * @param route the route so far * @param arc the arc to draw from/to * @param point point on or near arc * @param stayInside the area in which to route (null if not applicable). * @return a RouteElement holding the new pin at the bisection * point, or a RouteElement holding an existingPortInst if * drawing from either end of the ArcInst. */ protected RouteElementPort findArcConnectingPoint(Route route, ArcInst arc, Point2D point, PolyMerge stayInside) { EPoint head = arc.getHeadLocation(); EPoint tail = arc.getTailLocation(); RouteElementPort headRE = RouteElementPort.existingPortInst(arc.getHeadPortInst(), head); RouteElementPort tailRE = RouteElementPort.existingPortInst(arc.getTailPortInst(), tail); RouteElementPort startRE = null; // find extents of wire double minX, minY, maxX, maxY; Point2D minXpin = null, minYpin = null; if (head.getX() < tail.getX()) { minX = head.getX(); maxX = tail.getX(); minXpin = head; } else { minX = tail.getX(); maxX = head.getX(); minXpin = tail; } if (head.getY() < tail.getY()) { minY = head.getY(); maxY = tail.getY(); minYpin = head; } else { minY = tail.getY(); maxY = head.getY(); minYpin = tail; } // for efficiency purposes, we are going to assume the arc is // either vertical or horizontal for bisecting the arc if (head.getX() == tail.getX()) { // line is vertical, see if point point bisects if (point.getY() > minY && point.getY() < maxY) { Point2D location = new Point2D.Double(head.getX(), point.getY()); startRE = bisectArc(route, arc, location, stayInside); } // not within Y bounds, choose closest pin else if (point.getY() <= minY) { if (minYpin == head) startRE = headRE; else startRE = tailRE; } else { if (minYpin == head) startRE = tailRE; else startRE = headRE; } } // check if arc is horizontal else if (head.getY() == tail.getY()) { // line is horizontal, see if point bisects if (point.getX() > minX && point.getX() < maxX) { Point2D location = new Point2D.Double(point.getX(), head.getY()); startRE = bisectArc(route, arc, location, stayInside); } // not within X bounds, choose closest pin else if (point.getX() <= minX) { if (minXpin == head) startRE = headRE; else startRE = tailRE; } else { if (minXpin == head) startRE = tailRE; else startRE = headRE; } } // arc is not horizontal or vertical, draw from closest pin else { double headDist = point.distance(head); double tailDist = point.distance(tail); if (headDist < tailDist) startRE = headRE; else startRE = tailRE; } //route.add(startRE); // DON'T ADD!! return startRE; } /** * Splits an arc at bisectPoint and updates the route to reflect the change. * This method should NOT add the returned RouteElement to the route. * * @param route the current route * @param arc the arc to split * @param bisectPoint point on arc from which to split it * @param stayInside the area in which to route (null if not applicable). * @return the RouteElement from which to continue the route */ protected RouteElementPort bisectArc(Route route, ArcInst arc, Point2D bisectPoint, PolyMerge stayInside) { Cell cell = arc.getParent(); EPoint head = arc.getHeadLocation(); EPoint tail = arc.getTailLocation(); // determine pin type to use if bisecting arc PrimitiveNode pn = arc.getProto().findOverridablePinProto(); SizeOffset so = pn.getProtoSizeOffset(); double width = pn.getDefWidth()-so.getHighXOffset()-so.getLowXOffset(); double height = pn.getDefHeight()-so.getHighYOffset()-so.getLowYOffset(); // make new pin RouteElementPort newPinRE = RouteElementPort.newNode(cell, pn, pn.getPort(0), bisectPoint, width, height); newPinRE.setBisectArcPin(true); // make dummy end pins RouteElementPort headRE = RouteElementPort.existingPortInst(arc.getHeadPortInst(), head); RouteElementPort tailRE = RouteElementPort.existingPortInst(arc.getTailPortInst(), tail); headRE.setShowHighlight(false); tailRE.setShowHighlight(false); // put name on longer arc String name1 = null; String name2 = null; if (head.distance(bisectPoint) > tail.distance(bisectPoint)) name1 = arc.getName(); else name2 = arc.getName(); // add two arcs to rebuild old startArc RouteElement newHeadArcRE = RouteElementArc.newArc(cell, arc.getProto(), arc.getLambdaBaseWidth(), headRE, newPinRE, head, bisectPoint, name1, arc.getTextDescriptor(ArcInst.ARC_NAME), arc, true, true, stayInside); RouteElement newTailArcRE = RouteElementArc.newArc(cell, arc.getProto(), arc.getLambdaBaseWidth(), newPinRE, tailRE, bisectPoint, tail, name2, arc.getTextDescriptor(ArcInst.ARC_NAME), arc, true, true, stayInside); newHeadArcRE.setShowHighlight(false); newTailArcRE.setShowHighlight(false); // delete old arc RouteElement deleteArcRE = RouteElementArc.deleteArc(arc); // add new stuff to route route.add(deleteArcRE); //route.add(newPinRE); // DON'T ADD!! route.add(headRE); route.add(tailRE); route.add(newHeadArcRE); route.add(newTailArcRE); return newPinRE; } // ------------------------- Spatial Dimension Calculations ------------------------- /** * Get closest value to clicked within a range from min to max */ protected static double getClosestValue(double min, double max, double clicked) { if (clicked >= max) { return max; } else if (clicked <= min) { return min; } else { return clicked; } } /** * Gets the closest orthogonal point from the startPoint to the clicked point. * This is used when the user clicks in space and the router draws only a single * arc towards the clicked point in one dimension. * @param startPoint start point of the arc * @param clicked where the user clicked * @return an end point to draw to from start point to make a single arc segment. */ protected static Point2D getClosestOrthogonalPoint(Point2D startPoint, Point2D clicked) { Point2D newPoint; if (Math.abs(startPoint.getX() - clicked.getX()) < Math.abs(startPoint.getY() - clicked.getY())) { // draw horizontally newPoint = new Point2D.Double(startPoint.getX(), clicked.getY()); } else { // draw vertically newPoint = new Point2D.Double(clicked.getX(), startPoint.getY()); } return newPoint; } /** * Use to find the closest point to clicked to route a wire from startPoint. * This point will be at an angel from startPoint which is a multiple of * angleIncrement. If stayInside and useArc are not null, then the two possible * closest points will be determined by if they reside inside stayInside, * rather than the closest point. * @param startPoint * @param clicked * @param angleIncrement * @return the closest point to clicked to route a wire. */ protected static Point2D getClosestAngledPoint(Point2D startPoint, Point2D clicked, int angleIncrement) { angleIncrement = Math.abs(angleIncrement); if (angleIncrement == 0) return clicked; // don't really have to call this for angleIncr of 90 as general purpose // code below does right thing, but it's a lot faster if (angleIncrement == 90) return getClosestOrthogonalPoint(startPoint, clicked); double angleInc = angleIncrement * Math.PI / 180; // calculate angle double x = clicked.getX()-startPoint.getX(); double y = clicked.getY()-startPoint.getY(); double angle = Math.atan2(y,x); //System.out.println("angle is "+angle); // find closest two angle increments double nearest1 = (int)(angle / angleInc) * angleInc; double nearest2 = (angle<0) ? nearest1 - angleInc : nearest1 + angleInc; //System.out.println("nearest1, nearest2 are "+nearest1+" and "+ nearest2); Point2D n1, n2; // two points on line are candidates: one uses clicked X, other uses clickedY double tan1 = Math.tan(nearest1); if (tan1 == 0) tan1 = 0.000001; //System.out.println("tan1 is "+tan1); Point2D n1_1 = new Point2D.Double(x, x*tan1); Point2D n1_2 = new Point2D.Double(y/tan1, y); //System.out.println("Point1's: "+n1_1+", "+n1_2); // take whichever is shorter if (n1_1.distance(x,y) < n1_2.distance(x,y)) n1 = n1_1; else n1 = n1_2; // same for second angle double tan2 = Math.tan(nearest2); if (tan2 == 0) tan2 = 0.000001; //System.out.println("tan2 is "+tan2); Point2D n2_1 = new Point2D.Double(x, x*tan2); Point2D n2_2 = new Point2D.Double(y/tan2, y); //System.out.println("Point2's: "+n2_1+", "+n2_2); if (n2_1.distance(x,y) < n2_2.distance(x,y)) n2 = n2_1; else n2 = n2_2; //System.out.println("Point1: "+n1); //System.out.println("Point2: "+n2); double xfinal, yfinal; // of the points on the two angles, take closest to clicked if (n2.distance(x,y) < n1.distance(x,y)) { xfinal = DBMath.round(n2.getX() + startPoint.getX()); yfinal = DBMath.round(n2.getY() + startPoint.getY()); } else { xfinal = DBMath.round(n1.getX() + startPoint.getX()); yfinal = DBMath.round(n1.getY() + startPoint.getY()); } return new Point2D.Double(xfinal, yfinal); } protected boolean withinBounds(double point, double bound1, double bound2) { double min, max; if (bound1 < bound2) { min = bound1; max = bound2; } else { min = bound2; max = bound1; } return ((point >= min) && (point <= max)); } /** * Returns true if point is on the line segment, false otherwise. */ protected boolean onSegment(Point2D point, Line2D line) { double minX, minY, maxX, maxY; Point2D head = line.getP1(); Point2D tail = line.getP2(); if (head.getX() < tail.getX()) { minX = head.getX(); maxX = tail.getX(); } else { minX = tail.getX(); maxX = head.getX(); } if (head.getY() < tail.getY()) { minY = head.getY(); maxY = tail.getY(); } else { minY = tail.getY(); maxY = head.getY(); } if ((point.getX() >= minX) && (point.getX() <= maxX) && (point.getY() >= minY) && (point.getY() <= maxY)) return true; return false; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -