/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: GEM.java * gem technology description * Generated automatically from a library * * Copyright (c) 2004 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.technology.technologies; import com.sun.electric.database.ImmutableArcInst; import com.sun.electric.database.ImmutableNodeInst; import com.sun.electric.database.geometry.DBMath; import com.sun.electric.database.geometry.EGraphics; import com.sun.electric.database.geometry.EPoint; import com.sun.electric.database.geometry.ERectangle; import com.sun.electric.database.geometry.Poly; import com.sun.electric.database.prototype.PortCharacteristic; import com.sun.electric.database.variable.Variable; import com.sun.electric.technology.AbstractShapeBuilder; import com.sun.electric.technology.ArcProto; import com.sun.electric.technology.EdgeH; import com.sun.electric.technology.EdgeV; import com.sun.electric.technology.Foundry; import com.sun.electric.technology.Layer; import com.sun.electric.technology.PrimitiveNode; import com.sun.electric.technology.PrimitivePort; import com.sun.electric.technology.TechFactory; import com.sun.electric.technology.Technology; /** * This is the Temporal Specification Facility (from Lansky) Technology. */ public class GEM extends Technology { /** Variable key for GEM element name. */ public static final Variable.Key ELEMENT_NAME = Variable.newKey("GEM_element"); /** Variable key for GEM event 1. */ public static final Variable.Key EVENT_1 = Variable.newKey("GEM_event1"); /** Variable key for GEM event 2. */ public static final Variable.Key EVENT_2 = Variable.newKey("GEM_event2"); /** Variable key for GEM event 3. */ public static final Variable.Key EVENT_3 = Variable.newKey("GEM_event3"); /** Variable key for GEM event 4. */ public static final Variable.Key EVENT_4 = Variable.newKey("GEM_event4"); private Layer E_lay, GA_lay, TA_lay, CA_lay, PA_lay, NA_lay, FA_lay; private ArcProto generalArc, temporalArc, causalArc, prerequisiteArc, nondeterministicArc, nondeterministicForkArc; private Technology.TechPoint [] box_7; private PrimitiveNode e_node; // -------------------- private and protected methods ------------------------ public GEM(Generic generic, TechFactory techFactory) { super(generic, techFactory); setTechDesc("Temporal Specification Facility (from Lansky)"); setFactoryScale(1000, false); // in nanometers: really 1 microns setNoNegatedArcs(); setStaticTechnology(); setNonStandard(); //**************************************** LAYERS **************************************** /** E layer */ E_lay = Layer.newInstance(this, "Element", new EGraphics(false, false, null, 0, 255,0,0, 0.8,true, new int[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0})); /** GA layer */ GA_lay = Layer.newInstance(this, "General-arc", new EGraphics(false, false, null, 0, 0,0,255, 0.8,true, new int[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0})); /** TA layer */ TA_lay = Layer.newInstance(this, "Temporal-arc", new EGraphics(false, false, null, 0, 0,255,0, 0.8,true, new int[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0})); /** CA layer */ CA_lay = Layer.newInstance(this, "Causal-arc", new EGraphics(false, false, null, 0, 0,0,0, 0.8,true, new int[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0})); /** PA layer */ PA_lay = Layer.newInstance(this, "Prereq-arc", new EGraphics(false, false, null, 0, 255,190,6, 0.8,true, new int[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0})); /** NA layer */ NA_lay = Layer.newInstance(this, "Nondet-arc", new EGraphics(false, false, null, 0, 255,255,0, 0.8,true, new int[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0})); /** FA layer */ FA_lay = Layer.newInstance(this, "Fork-arc", new EGraphics(false, false, null, 0, 186,0,255, 0.8,true, new int[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0})); // The layer functions E_lay.setFunction(Layer.Function.ART, Layer.Function.NONELEC); // Element GA_lay.setFunction(Layer.Function.CONTROL, Layer.Function.NONELEC); // General-arc TA_lay.setFunction(Layer.Function.CONTROL, Layer.Function.NONELEC); // Temporal-arc CA_lay.setFunction(Layer.Function.CONTROL, Layer.Function.NONELEC); // Causal-arc PA_lay.setFunction(Layer.Function.CONTROL, Layer.Function.NONELEC); // Prereq-arc NA_lay.setFunction(Layer.Function.CONTROL, Layer.Function.NONELEC); // Nondet-arc FA_lay.setFunction(Layer.Function.CONTROL, Layer.Function.NONELEC); // Fork-arc //******************** ARCS ******************** /** General arc */ generalArc = newArcProto("General", 0, 0, ArcProto.Function.NONELEC, new Technology.ArcLayer(GA_lay, 0, Poly.Type.FILLED) ); generalArc.setWipable(); generalArc.setFactoryAngleIncrement(0); /** Temporal arc */ temporalArc = newArcProto("Temporal", 0, 0, ArcProto.Function.NONELEC, new Technology.ArcLayer(TA_lay, 0, Poly.Type.FILLED) ); temporalArc.setWipable(); temporalArc.setFactoryAngleIncrement(0); temporalArc.setFactoryDirectional(5); /** Causal arc */ causalArc = newArcProto("Causal", 0, 0, ArcProto.Function.NONELEC, new Technology.ArcLayer(CA_lay, 0, Poly.Type.FILLED) ); causalArc.setWipable(); causalArc.setFactoryAngleIncrement(0); /** Prerequisite arc */ prerequisiteArc = newArcProto("Prerequisite", 0, 0, ArcProto.Function.NONELEC, new Technology.ArcLayer(PA_lay, 0, Poly.Type.FILLED) ); prerequisiteArc.setWipable(); prerequisiteArc.setFactoryAngleIncrement(0); prerequisiteArc.setFactoryDirectional(5); /** Nondeterministic arc */ nondeterministicArc = newArcProto("Nondeterministic", 0, 0, ArcProto.Function.NONELEC, new Technology.ArcLayer(NA_lay, 0, Poly.Type.FILLED) ); nondeterministicArc.setWipable(); nondeterministicArc.setFactoryAngleIncrement(0); nondeterministicArc.setFactoryDirectional(5); /** Nondeterministic-fork arc */ nondeterministicForkArc = newArcProto("Nondeterministic-fork", 0, 0, ArcProto.Function.NONELEC, new Technology.ArcLayer(FA_lay, 0, Poly.Type.FILLED) ); nondeterministicForkArc.setWipable(); nondeterministicForkArc.setFactoryAngleIncrement(0); nondeterministicForkArc.setFactoryDirectional(7); //******************** RECTANGLE DESCRIPTIONS ******************** Technology.TechPoint [] box_6 = new Technology.TechPoint[] { new Technology.TechPoint(EdgeH.makeLeftEdge(), EdgeV.makeBottomEdge()), new Technology.TechPoint(EdgeH.makeRightEdge(), EdgeV.makeTopEdge()), }; box_7 = new Technology.TechPoint[] { new Technology.TechPoint(EdgeH.makeCenter(), EdgeV.makeCenter()), new Technology.TechPoint(EdgeH.makeRightEdge(), EdgeV.makeCenter()), }; //******************** NODES ******************** /** General-Pin */ PrimitiveNode gp_node = PrimitiveNode.newInstance("General-Pin", this, 1, 1, null, new Technology.NodeLayer [] { new Technology.NodeLayer(GA_lay, 0, Poly.Type.DISC, Technology.NodeLayer.POINTS, box_7) }); PrimitivePort pinPort = PrimitivePort.newInstance(this, gp_node, new ArcProto [] {generalArc}, "general", 0,180, 0, PortCharacteristic.UNKNOWN, EdgeH.makeCenter(), EdgeV.makeCenter(), EdgeH.makeCenter(), EdgeV.makeCenter()); gp_node.addPrimitivePortsFixed(new PrimitivePort[] {pinPort}); gp_node.setFunction(PrimitiveNode.Function.PIN); gp_node.setArcsWipe(); gp_node.setArcsShrink(); /** Temporal-Pin */ PrimitiveNode tp_node = PrimitiveNode.newInstance("Temporal-Pin", this, 1, 1, null, new Technology.NodeLayer [] { new Technology.NodeLayer(TA_lay, 0, Poly.Type.DISC, Technology.NodeLayer.POINTS, box_7) }); tp_node.addPrimitivePortsFixed(new PrimitivePort[] { PrimitivePort.newInstance(this, tp_node, new ArcProto [] {temporalArc}, "temporal", 0,180, 0, PortCharacteristic.UNKNOWN, EdgeH.makeCenter(), EdgeV.makeCenter(), EdgeH.makeCenter(), EdgeV.makeCenter()) }); tp_node.setFunction(PrimitiveNode.Function.PIN); tp_node.setArcsWipe(); tp_node.setArcsShrink(); /** Cause-Pin */ PrimitiveNode cp_node = PrimitiveNode.newInstance("Cause-Pin", this, 1, 1, null, new Technology.NodeLayer [] { new Technology.NodeLayer(CA_lay, 0, Poly.Type.DISC, Technology.NodeLayer.POINTS, box_7) }); cp_node.addPrimitivePortsFixed(new PrimitivePort[] { PrimitivePort.newInstance(this, cp_node, new ArcProto [] {causalArc}, "cause", 0,180, 0, PortCharacteristic.UNKNOWN, EdgeH.makeCenter(), EdgeV.makeCenter(), EdgeH.makeCenter(), EdgeV.makeCenter()) }); cp_node.setFunction(PrimitiveNode.Function.PIN); cp_node.setArcsWipe(); cp_node.setArcsShrink(); /** Prereq-Pin */ PrimitiveNode pp_node = PrimitiveNode.newInstance("Prereq-Pin", this, 1, 1, null, new Technology.NodeLayer [] { new Technology.NodeLayer(PA_lay, 0, Poly.Type.DISC, Technology.NodeLayer.POINTS, box_7) }); pp_node.addPrimitivePortsFixed(new PrimitivePort[] { PrimitivePort.newInstance(this, pp_node, new ArcProto [] {prerequisiteArc}, "prereq", 0,180, 0, PortCharacteristic.UNKNOWN, EdgeH.makeCenter(), EdgeV.makeCenter(), EdgeH.makeCenter(), EdgeV.makeCenter()) }); pp_node.setFunction(PrimitiveNode.Function.PIN); pp_node.setArcsWipe(); pp_node.setArcsShrink(); /** Nondet-Pin */ PrimitiveNode np_node = PrimitiveNode.newInstance("Nondet-Pin", this, 1, 1, null, new Technology.NodeLayer [] { new Technology.NodeLayer(NA_lay, 0, Poly.Type.DISC, Technology.NodeLayer.POINTS, box_7) }); np_node.addPrimitivePortsFixed(new PrimitivePort[] { PrimitivePort.newInstance(this, np_node, new ArcProto [] {nondeterministicArc}, "nondet", 0,180, 0, PortCharacteristic.UNKNOWN, EdgeH.makeCenter(), EdgeV.makeCenter(), EdgeH.makeCenter(), EdgeV.makeCenter()) }); np_node.setFunction(PrimitiveNode.Function.PIN); np_node.setArcsWipe(); np_node.setArcsShrink(); /** Fork-Pin */ PrimitiveNode fp_node = PrimitiveNode.newInstance("Fork-Pin", this, 1, 1, null, new Technology.NodeLayer [] { new Technology.NodeLayer(FA_lay, 0, Poly.Type.DISC, Technology.NodeLayer.POINTS, box_7) }); fp_node.addPrimitivePortsFixed(new PrimitivePort[] { PrimitivePort.newInstance(this, fp_node, new ArcProto [] {nondeterministicForkArc}, "fork", 0,180, 0, PortCharacteristic.UNKNOWN, EdgeH.makeCenter(), EdgeV.makeCenter(), EdgeH.makeCenter(), EdgeV.makeCenter()) }); fp_node.setFunction(PrimitiveNode.Function.PIN); fp_node.setArcsWipe(); fp_node.setArcsShrink(); /** Element */ e_node = PrimitiveNode.newInstance("Element", this, 8, 8, null, new Technology.NodeLayer [] { new Technology.NodeLayer(E_lay, 0, Poly.Type.CIRCLE, Technology.NodeLayer.POINTS, box_7) }); e_node.addPrimitivePortsFixed(new PrimitivePort[] { PrimitivePort.newInstance(this, e_node, new ArcProto [] {generalArc, temporalArc, causalArc, prerequisiteArc, nondeterministicArc, nondeterministicForkArc}, "port1", 0,180, 0, PortCharacteristic.UNKNOWN, EdgeH.fromLeft(2), EdgeV.fromCenter(0.5), EdgeH.fromLeft(2), EdgeV.fromCenter(0.5)), PrimitivePort.newInstance(this, e_node, new ArcProto [] {generalArc, temporalArc, causalArc, prerequisiteArc, nondeterministicArc, nondeterministicForkArc}, "port2", 0,180, 0, PortCharacteristic.UNKNOWN, EdgeH.fromLeft(2), EdgeV.fromCenter(-0.5), EdgeH.fromLeft(2), EdgeV.fromCenter(-0.5)), PrimitivePort.newInstance(this, e_node, new ArcProto [] {generalArc, temporalArc, causalArc, prerequisiteArc, nondeterministicArc, nondeterministicForkArc}, "port3", 0,180, 0, PortCharacteristic.UNKNOWN, EdgeH.fromLeft(2), EdgeV.fromCenter(-1.5), EdgeH.fromLeft(2), EdgeV.fromCenter(-1.5)), PrimitivePort.newInstance(this, e_node, new ArcProto [] {generalArc, temporalArc, causalArc, prerequisiteArc, nondeterministicArc, nondeterministicForkArc}, "port4", 0,180, 0, PortCharacteristic.UNKNOWN, EdgeH.fromLeft(2), EdgeV.fromCenter(-2.5), EdgeH.fromLeft(2), EdgeV.fromCenter(-2.5)) }); e_node.setFunction(PrimitiveNode.Function.UNKNOWN); /** Group */ PrimitiveNode g_node = PrimitiveNode.newInstance("Group", this, 10, 10, null, new Technology.NodeLayer [] { new Technology.NodeLayer(E_lay, 0, Poly.Type.CLOSED, Technology.NodeLayer.BOX, box_6) }); g_node.addPrimitivePortsFixed(new PrimitivePort[] { PrimitivePort.newInstance(this, g_node, new ArcProto [] {generalArc, temporalArc, causalArc, prerequisiteArc, nondeterministicArc, nondeterministicForkArc}, "group", 0,180, 0, PortCharacteristic.UNKNOWN, EdgeH.makeLeftEdge(), EdgeV.makeBottomEdge(), EdgeH.makeRightEdge(), EdgeV.makeTopEdge()) }); g_node.setFunction(PrimitiveNode.Function.UNKNOWN); // Building information for palette loadFactoryMenuPalette(GEM.class.getResource("gemMenu.xml")); //Foundry newFoundry(Foundry.Type.NONE, null); }; //**************************************** METHODS **************************************** /** * Puts into shape builder s the polygons that describe node "n", given a set of * NodeLayer objects to use. * This method is overridden by specific Technologys. * @param b shape builder where to put polygons * @param n the ImmutableNodeInst that is being described. * @param pn proto of the ImmutableNodeInst in this Technology * @param primLayers an array of NodeLayer objects to convert to Poly objects. * The prototype of this NodeInst must be a PrimitiveNode and not a Cell. */ @Override protected void genShapeOfNode(AbstractShapeBuilder b, ImmutableNodeInst n, PrimitiveNode pn, Technology.NodeLayer[] primLayers) { if (pn == e_node) { Technology.NodeLayer [] eventLayers = new Technology.NodeLayer[6]; eventLayers[0] = new Technology.NodeLayer(E_lay, 0, Poly.Type.CIRCLE, Technology.NodeLayer.POINTS, box_7); String title = ""; Variable varTitle = n.getVar(ELEMENT_NAME); if (varTitle != null) title = varTitle.getPureValue(-1); eventLayers[1] = new Technology.NodeLayer(E_lay, 0, Poly.Type.TEXTCENT, Technology.NodeLayer.POINTS, new Technology.TechPoint[] { new Technology.TechPoint(EdgeH.makeCenter(), EdgeV.fromTop(1))}); eventLayers[1].setMessage(title); String event1 = ""; Variable varEvent1 = n.getVar(EVENT_1); if (varEvent1 != null) event1 = varEvent1.getPureValue(-1); eventLayers[2] = new Technology.NodeLayer(E_lay, 0, Poly.Type.TEXTLEFT, Technology.NodeLayer.POINTS, new Technology.TechPoint[] { new Technology.TechPoint(EdgeH.fromLeft(2), EdgeV.fromCenter(0.5))}); eventLayers[2].setMessage(event1); String event2 = ""; Variable varEvent2 = n.getVar(EVENT_2); if (varEvent2 != null) event2 = varEvent2.getPureValue(-1); eventLayers[3] = new Technology.NodeLayer(E_lay, 0, Poly.Type.TEXTLEFT, Technology.NodeLayer.POINTS, new Technology.TechPoint[] { new Technology.TechPoint(EdgeH.fromLeft(2), EdgeV.fromCenter(-0.5))}); eventLayers[3].setMessage(event2); String event3 = ""; Variable varEvent3 = n.getVar(EVENT_3); if (varEvent3 != null) event3 = varEvent3.getPureValue(-1); eventLayers[4] = new Technology.NodeLayer(E_lay, 0, Poly.Type.TEXTLEFT, Technology.NodeLayer.POINTS, new Technology.TechPoint[] { new Technology.TechPoint(EdgeH.fromLeft(2), EdgeV.fromCenter(-1.5))}); eventLayers[4].setMessage(event3); String event4 = ""; Variable varEvent4 = n.getVar(EVENT_4); if (varEvent4 != null) event4 = varEvent4.getPureValue(-1); eventLayers[5] = new Technology.NodeLayer(E_lay, 0, Poly.Type.TEXTLEFT, Technology.NodeLayer.POINTS, new Technology.TechPoint[] { new Technology.TechPoint(EdgeH.fromLeft(2), EdgeV.fromCenter(-2.5))}); eventLayers[5].setMessage(event4); primLayers = eventLayers; ERectangle fullRectangle = e_node.getFullRectangle(); EPoint fixupCorrection = EPoint.fromGrid(fullRectangle.getGridWidth(), fullRectangle.getGridHeight()); for (Technology.NodeLayer nodeLayer: eventLayers) nodeLayer.fixup(fixupCorrection); } b.genShapeOfNode(n, pn, primLayers, null); } private final double lambdaArrowSize = 1.0; private final double lambdaPlusSize = 0.75; private final double lambdaPlusGap = 0.5; private final double lambdaZigZagWidth = 0.5; private final double lambdaDoubleArcWidth = 0.5; private final double gridArrowSize = lambdaArrowSize * DBMath.GRID; private final double gridPlusSize = lambdaPlusSize * DBMath.GRID; /** * Fill the polygons that describe arc "a". * @param b AbstractShapeBuilder to fill polygons. * @param a the ImmutableArcInst that is being described. * @param graphicsOverride the graphics to use for all generated polygons (if not null). */ @Override protected void getShapeOfArc(AbstractShapeBuilder b, ImmutableArcInst a, EGraphics graphicsOverride) { ArcProto ap = getArcProto(a.protoId); assert ap.getTechnology() == this; if (ap == generalArc) { Layer layer = GA_lay; if (b.skipLayer(layer)) return; b.pushPoint(a.headLocation); b.pushPoint(a.tailLocation); b.pushPoly(Poly.Type.VECTORS, layer, graphicsOverride, null); return; } if (ap == prerequisiteArc) { Layer layer = PA_lay; if (b.skipLayer(layer)) return; b.pushPoint(a.headLocation); b.pushPoint(a.tailLocation); b.pushPoly(Poly.Type.VECTORS, layer, graphicsOverride, null); if (a.isHeadArrowed()) addHeadArrow(b, a, graphicsOverride, layer, a.headLocation); return; } if (ap == nondeterministicForkArc) { Layer layer = FA_lay; if (b.skipLayer(layer)) return; EPoint newTail = a.tailLocation; if (a.isTailArrowed()) newTail = addTailPlus(b, a, graphicsOverride, layer); b.pushPoint(a.headLocation); b.pushPoint(newTail); b.pushPoly(Poly.Type.VECTORS, layer, graphicsOverride, null); if (a.isHeadArrowed()) addHeadArrow(b, a, graphicsOverride, layer, a.headLocation); return; } if (ap == nondeterministicArc) { Layer layer = NA_lay; if (b.skipLayer(layer)) return; EPoint newHead = a.headLocation; if (a.isHeadArrowed()) { newHead = addHeadPlus(b, a, graphicsOverride, layer); addHeadArrow(b, a, graphicsOverride, layer, newHead); } b.pushPoint(a.tailLocation); b.pushPoint(newHead); b.pushPoly(Poly.Type.VECTORS, layer, graphicsOverride, null); return; } if (ap == temporalArc) { Layer layer = TA_lay; if (b.skipLayer(layer)) return; addDoubleLineArc(b, a, graphicsOverride, layer); return; } if (ap == causalArc) { Layer layer = CA_lay; if (b.skipLayer(layer)) return; addZigZagArc(b, a, graphicsOverride, layer); return; } } /** * Tells if arc can be drawn by simplified algorithm * Arcs with user-specified color or pattern are not easy * @param a arc to test * @param explain if true then print explanation why arc is not easy * @return true if arc can be drawn by simplified algorithm */ @Override public boolean isEasyShape(ImmutableArcInst a, boolean explain) { ArcProto ap = getArcProto(a.protoId); if (ap != generalArc) { if (explain) System.out.println("GEM_ARC_SHAPE"); return false; } return super.isEasyShape(a, explain); } private void addHeadArrow(AbstractShapeBuilder b, ImmutableArcInst a, EGraphics graphicsOverride, Layer layer, EPoint headLoc) { int angle = a.getAngle(); angle = (angle + 1800) % 3600; int angleOfArrow = 300; // 30 degrees int backAngle1 = angle - angleOfArrow; int backAngle2 = angle + angleOfArrow; b.pushPoint(headLoc); b.pushPoint(headLoc, DBMath.cos(backAngle1)*gridArrowSize, DBMath.sin(backAngle1)*gridArrowSize); b.pushPoint(headLoc); b.pushPoint(headLoc, DBMath.cos(backAngle2)*gridArrowSize, DBMath.sin(backAngle2)*gridArrowSize); b.pushPoly(Poly.Type.VECTORS, layer, graphicsOverride, null); } private EPoint addTailPlus(AbstractShapeBuilder b, ImmutableArcInst a, EGraphics graphicsOverride, Layer layer) { int angle = a.getAngle(); int angleOfPlus = 900; // 90 degrees int backAngleLeft = angle - angleOfPlus; int backAngleRight = angle + angleOfPlus; EPoint plusCenter = new EPoint(a.tailLocation.getX() + DBMath.cos(angle)*lambdaPlusSize, a.tailLocation.getY() + DBMath.sin(angle)*lambdaPlusSize); b.pushPoint(plusCenter, DBMath.cos(backAngleLeft)*gridPlusSize, DBMath.sin(backAngleLeft)*gridPlusSize); b.pushPoint(plusCenter, DBMath.cos(backAngleRight)*gridPlusSize, DBMath.sin(backAngleRight)*gridPlusSize); b.pushPoint(a.tailLocation); b.pushPoint(a.tailLocation, DBMath.cos(angle)*gridPlusSize*2, DBMath.sin(angle)*gridPlusSize*2); b.pushPoly(Poly.Type.VECTORS, layer, graphicsOverride, null); EPoint newTail = new EPoint(a.tailLocation.getX() + DBMath.cos(angle)*(lambdaPlusSize*2+lambdaPlusGap), a.tailLocation.getY() + DBMath.sin(angle)*(lambdaPlusSize*2+lambdaPlusGap)); return newTail; } private EPoint addHeadPlus(AbstractShapeBuilder b, ImmutableArcInst a, EGraphics graphicsOverride, Layer layer) { int angle = a.getAngle(); angle = (angle + 1800) % 3600; int angleOfPlus = 900; // 90 degrees int backAngleLeft = angle - angleOfPlus; int backAngleRight = angle + angleOfPlus; EPoint plusCenter = new EPoint(a.headLocation.getX() + DBMath.cos(angle)*lambdaPlusSize, a.headLocation.getY() + DBMath.sin(angle)*lambdaPlusSize); b.pushPoint(plusCenter, DBMath.cos(backAngleLeft)*gridPlusSize, DBMath.sin(backAngleLeft)*gridPlusSize); b.pushPoint(plusCenter, DBMath.cos(backAngleRight)*gridPlusSize, DBMath.sin(backAngleRight)*gridPlusSize); b.pushPoint(a.headLocation); b.pushPoint(a.headLocation, DBMath.cos(angle)*gridPlusSize*2, DBMath.sin(angle)*gridPlusSize*2); b.pushPoly(Poly.Type.VECTORS, layer, graphicsOverride, null); EPoint newHead = new EPoint(a.headLocation.getX() + DBMath.cos(angle)*(lambdaPlusSize*2+lambdaPlusGap), a.headLocation.getY() + DBMath.sin(angle)*(lambdaPlusSize*2+lambdaPlusGap)); return newHead; } private void addDoubleLineArc(AbstractShapeBuilder b, ImmutableArcInst a, EGraphics graphicsOverride, Layer layer) { int angle = a.getAngle(); int angleOfArrow = 900; // 90 degrees angle = (angle + 1800) % 3600; int backAngle1 = angle - angleOfArrow; int backAngle2 = angle + angleOfArrow; double indentHeadX = a.headLocation.getX(); double indentHeadY = a.headLocation.getY(); if (a.isHeadArrowed()) { indentHeadX += DBMath.cos(angle)*lambdaDoubleArcWidth; indentHeadY += DBMath.sin(angle)*lambdaDoubleArcWidth; } EPoint headLeft = new EPoint(indentHeadX + DBMath.cos(backAngle1)*lambdaDoubleArcWidth, indentHeadY + DBMath.sin(backAngle1)*lambdaDoubleArcWidth); EPoint headRight = new EPoint(indentHeadX + DBMath.cos(backAngle2)*lambdaDoubleArcWidth, indentHeadY + DBMath.sin(backAngle2)*lambdaDoubleArcWidth); EPoint tailLeft = new EPoint(a.tailLocation.getX() + DBMath.cos(backAngle1)*lambdaDoubleArcWidth, a.tailLocation.getY() + DBMath.sin(backAngle1)*lambdaDoubleArcWidth); EPoint tailRight = new EPoint(a.tailLocation.getX() + DBMath.cos(backAngle2)*lambdaDoubleArcWidth, a.tailLocation.getY() + DBMath.sin(backAngle2)*lambdaDoubleArcWidth); b.pushPoint(tailLeft); b.pushPoint(headLeft); b.pushPoint(tailRight); b.pushPoint(headRight); if (a.isHeadArrowed()) { angleOfArrow = 450; // 45 degrees backAngle1 = angle - angleOfArrow; backAngle2 = angle + angleOfArrow; EPoint headArrowLeft = new EPoint(a.headLocation.getX() + DBMath.cos(backAngle1)*lambdaDoubleArcWidth*2, a.headLocation.getY() + DBMath.sin(backAngle1)*lambdaDoubleArcWidth*2); EPoint headArrowRight = new EPoint(a.headLocation.getX() + DBMath.cos(backAngle2)*lambdaDoubleArcWidth*2, a.headLocation.getY() + DBMath.sin(backAngle2)*lambdaDoubleArcWidth*2); b.pushPoint(a.headLocation); b.pushPoint(headArrowLeft); b.pushPoint(a.headLocation); b.pushPoint(headArrowRight); } b.pushPoly(Poly.Type.VECTORS, layer, graphicsOverride, null); } private void addZigZagArc(AbstractShapeBuilder b, ImmutableArcInst a, EGraphics graphicsOverride, Layer layer) { int angle = a.getAngle(); int angleOfArrow = 900; // 90 degrees int backAngle1 = angle - angleOfArrow; int backAngle2 = angle + angleOfArrow; double centerX = (a.headLocation.getX() + a.tailLocation.getX()) / 2; double centerY = (a.headLocation.getY() + a.tailLocation.getY()) / 2; EPoint centerLeft = new EPoint(centerX + DBMath.cos(backAngle1)*lambdaZigZagWidth, centerY + DBMath.sin(backAngle1)*lambdaZigZagWidth); EPoint centerRight = new EPoint(centerX + DBMath.cos(backAngle2)*lambdaZigZagWidth, centerY + DBMath.sin(backAngle2)*lambdaZigZagWidth); b.pushPoint(a.headLocation); b.pushPoint(centerLeft); b.pushPoint(centerLeft); b.pushPoint(centerRight); b.pushPoint(centerRight); b.pushPoint(a.tailLocation); b.pushPoly(Poly.Type.VECTORS, layer, graphicsOverride, null); } }