📄 interactiverouter.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: InteractiveRouter.java * * Copyright (c) 2003 Sun Microsystems and Static Free Software * * Electric(tm) is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Electric(tm) is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Electric(tm); see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, Mass 02111-1307, USA. */package com.sun.electric.tool.routing;import com.sun.electric.database.geometry.DBMath;import com.sun.electric.database.geometry.EPoint;import com.sun.electric.database.geometry.Poly;import com.sun.electric.database.geometry.PolyMerge;import com.sun.electric.database.hierarchy.Cell;import com.sun.electric.database.hierarchy.Export;import com.sun.electric.database.prototype.PortProto;import com.sun.electric.database.topology.ArcInst;import com.sun.electric.database.topology.NodeInst;import com.sun.electric.database.topology.PortInst;import com.sun.electric.database.variable.ElectricObject;import com.sun.electric.technology.ArcProto;import com.sun.electric.technology.PrimitiveNode;import com.sun.electric.technology.SizeOffset;import com.sun.electric.technology.technologies.Artwork;import com.sun.electric.tool.JobException;import com.sun.electric.tool.user.CircuitChangeJobs;import com.sun.electric.tool.user.Highlight2;import com.sun.electric.tool.user.Highlighter;import com.sun.electric.tool.user.ui.EditWindow;import java.awt.geom.Line2D;import java.awt.geom.Point2D;import java.awt.geom.Rectangle2D;import java.util.ArrayList;import java.util.List;/** * An Interactive Router has several methods that build on Router * methods to provide interactive control to user. It also * provides methods for highlighting routes to provide visual * feedback to the user. Finally, non-interactive routing is done only * from PortInst to PortInst, whereas interactive routing can start and * end on any arc, and can end in space. * <p> * Note: 'Interactive' is somewhat of a misnomer, as it would imply * the route can be incremently built or changed by the user. In * reality, it is expected that the route simply be rebuilt whenever * the user input changes, until the user decides that the route is acceptable, * at which point the route can be made. * <p> * User: gainsley * Date: Feb 24, 2004 * Time: 4:58:24 PM */public abstract class InteractiveRouter extends Router { /** for highlighting the start of the route */ private List<Highlight2> startRouteHighlights = new ArrayList<Highlight2>(); /** if start has been called */ private boolean started; /** EditWindow we are routing in */ private EditWindow wnd; /** last bad object routed from: prevent too many error messages */ private ElectricObject badStartObject; /** last bad object routing to: prevent too many error messages */ private ElectricObject badEndObject; public InteractiveRouter() { verbose = true; started = false; badStartObject = badEndObject = null; wnd = null; tool = Routing.getRoutingTool(); } public String toString() { return "Interactive Router"; } protected abstract boolean planRoute(Route route, Cell cell, RouteElementPort endRE, Point2D startLoc, Point2D endLoc, Point2D clicked, PolyMerge stayInside, VerticalRoute vroute, boolean contactsOnEndObject, boolean extendArcHead, boolean extendArcTail, Rectangle2D contactArea); // ----------------------- Interactive Route Control -------------------------- /** * This stores the currently highlighted objects to highlight * in addition to route highlighting. If routing it cancelled, * it also restores the original highlighting. */ public void startInteractiveRoute(EditWindow wnd) { this.wnd = wnd; // copy current highlights startRouteHighlights.clear(); for (Highlight2 h : wnd.getHighlighter().getHighlights()) { startRouteHighlights.add(h); } wnd.clearHighlighting(); started = true; } /** * Cancels interative routing and restores original highlights */ public void cancelInteractiveRoute() { // restore original highlights Highlighter highlighter = wnd.getHighlighter(); highlighter.clear(); highlighter.setHighlightList(startRouteHighlights); highlighter.finished(); wnd = null; started = false; } /** * Make a route between startObj and endObj in the EditWindow_ wnd. * Uses the point where the user clicked as a parameter to set the route. * @param wnd the EditWindow_ the user is editing * @param cell the cell in which to create the route * @param startObj a PortInst or ArcInst from which to start the route * @param endObj a PortInst or ArcInst to end the route on. May be null * if the user is drawing to empty space. * @param clicked the point where the user clicked */ public void makeRoute(EditWindow wnd, Cell cell, ElectricObject startObj, ElectricObject endObj, Point2D clicked) { if (!started) startInteractiveRoute(wnd); // plan the route Route route = planRoute(cell, startObj, endObj, clicked, null, true, true); // restore highlights at start of planning, so that // they will correctly show up if this job is undone. wnd.clearHighlighting(); wnd.getHighlighter().setHighlightList(startRouteHighlights); // create route createRoute(route, cell); started = false; } /** * Make a vertical route. Will add in contacts in startPort's technology * to be able to connect to endPort. The added contacts will be placed on * top of startPort. The final contact will be able to connect to <i>arc</i>. * @param wnd the EditWindow_ the user is editing * @param startPort the start of the route * @param arc the arc type that the last contact will be able to connect to * @return true on sucess */ public boolean makeVerticalRoute(EditWindow wnd, PortInst startPort, ArcProto arc) { // do nothing if startPort can already connect to arc if (startPort.getPortProto().connectsTo(arc)) return true; if (!started) startInteractiveRoute(wnd); Point2D startLoc = new Point2D.Double(startPort.getPoly().getCenterX(), startPort.getPoly().getCenterY()); Poly poly = getConnectingSite(startPort, startLoc, -1); RouteElementPort startRE = RouteElementPort.existingPortInst(startPort, poly); Route route = new Route(); route.add(startRE); route.setStart(startRE); VerticalRoute vroute = VerticalRoute.newRoute(startPort.getPortProto(), arc); if (!vroute.isSpecificationSucceeded()) { cancelInteractiveRoute(); return false; } vroute.buildRoute(route, startRE.getCell(), startRE, null, startLoc, startLoc, startLoc, null); // restore highlights at start of planning, so that // they will correctly show up if this job is undone. wnd.finishedHighlighting(); wnd.getHighlighter().setHighlightList(startRouteHighlights); new MakeVerticalRouteJob(this, route, startPort.getNodeInst().getParent(), true); started = false; return true; } private static class MakeVerticalRouteJob extends Router.CreateRouteJob { protected MakeVerticalRouteJob(Router router, Route route, Cell cell, boolean verbose) { super(router.toString(), route, cell, verbose, Routing.getRoutingTool()); } /** Implemented doIt() method to perform Job */ public boolean doIt() throws JobException { if (!super.doIt()) return false; RouteElementPort startRE = route.getStart(); if (startRE.getAction() == RouteElement.RouteElementAction.existingPortInst) { // if this is a pin, replace it with the first contact in vertical route PortInst pi = startRE.getPortInst(); NodeInst ni = pi.getNodeInst(); if (ni.getProto().getFunction() == PrimitiveNode.Function.PIN) { CircuitChangeJobs.Reconnect re = CircuitChangeJobs.Reconnect.erasePassThru(ni, false, true); if (re != null) re.reconnectArcs(); if (!ni.hasExports()) ni.kill(); } } return true; } } // -------------------------- Highlight Route Methods ------------------------- /** * Make a route and highlight it in the window. * @param cell the cell in which to create the route * @param startObj a PortInst or ArcInst from which to start the route * @param endObj a PortInst or ArcInst to end the route on. May be null * if the user is drawing to empty space. * @param clicked the point where the user clicked */ public void highlightRoute(EditWindow wnd, Cell cell, ElectricObject startObj, ElectricObject endObj, Point2D clicked) { if (!started) startInteractiveRoute(wnd); // highlight route Route route = planRoute(cell, startObj, endObj, clicked, null, true, true); highlightRoute(wnd, route, cell); } /** * Highlight a route in the window * @param route the route to be highlighted */ public void highlightRoute(EditWindow wnd, Route route, Cell cell) { if (!started) startInteractiveRoute(wnd); wnd.clearHighlighting(); //wnd.getHighlighter().setHighlightList(startRouteHighlights); for (RouteElement e : route) { e.addHighlightArea(wnd.getHighlighter()); } wnd.finishedHighlighting(); } // -------------------- Internal Router Wrapper of Router --------------------- /** * Plan a route from startObj to endObj, taking into account * where the user clicked in the cell. * @param cell the cell in which to create the arc * @param startObj a PortInst or ArcInst from which to start the route * @param endObj a PortInst or ArcInst to end the route on. May be null * if the user is drawing to empty space. * @param clicked the point where the user clicked * @param stayInside the area in which to route (null if not applicable). * @param extendArcHead true to use default arc extension; false to force no arc extension. * @param extendArcTail true to use default arc extension; false to force no arc extension. * @return a List of RouteElements denoting route */ public Route planRoute(Cell cell, ElectricObject startObj, ElectricObject endObj, Point2D clicked, PolyMerge stayInside, boolean extendArcHead, boolean extendArcTail) { return planRoute(cell, startObj, endObj, clicked, stayInside, extendArcHead, extendArcTail, null); } /** * Plan a route from startObj to endObj, taking into account * where the user clicked in the cell. * @param cell the cell in which to create the arc * @param startObj a PortInst or ArcInst from which to start the route * @param endObj a PortInst or ArcInst to end the route on. May be null * if the user is drawing to empty space. * @param clicked the point where the user clicked * @param stayInside the area in which to route (null if not applicable). * @param extendArcHead true to use default arc extension; false to force no arc extension. * @param extendArcTail true to use default arc extension; false to force no arc extension. * @return a List of RouteElements denoting route */ public Route planRoute(Cell cell, ElectricObject startObj, ElectricObject endObj, Point2D clicked, PolyMerge stayInside, boolean extendArcHead, boolean extendArcTail, Rectangle2D contactArea) { Route route = new Route(); // hold the route if (cell == null) return route; RouteElementPort startRE = null; // denote start of route RouteElementPort endRE = null; // denote end of route // first, convert NodeInsts to PortInsts, if it is one. // Now we don't have to worry about NodeInsts. startObj = filterRouteObject(startObj, clicked); endObj = filterRouteObject(endObj, clicked); // get the port types at each end so we can build electrical route PortProto startPort = getRoutePort(startObj); if (startPort == null) return route; // start cannot be null PortProto endPort; if (endObj == null) { // end object is null, we are routing to a pin. Figure out what arc to use ArcProto useArc = getArcToUse(startPort, null); if (useArc == null) return route; PrimitiveNode pn = useArc.findOverridablePinProto(); endPort = pn.getPort(0); } else { endPort = getRoutePort(endObj); } // now determine the electrical route. We need to know what // arcs will be used (and their widths, eventually) to determine // the Port Poly size for contacts
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -