~ubuntu-branches/ubuntu/maverick/electric/maverick

« back to all changes in this revision

Viewing changes to com/sun/electric/database/topology/ArcInst.java

  • Committer: Bazaar Package Importer
  • Author(s): Onkar Shinde
  • Date: 2010-01-09 16:26:04 UTC
  • mfrom: (1.1.4 upstream) (3.1.6 sid)
  • Revision ID: james.westby@ubuntu.com-20100109162604-1ypvmy8ijmlc6oq7
Tags: 8.10-1
* New upstream version.
* debian/control
  - Add libjava3d-java and quilt build dependencies.
  - Update standards version to 3.8.3.
  - Add libjava3d-java as recommends to binary package.
* debian/rules
  - Use quilt patch system instead of simple patchsys.
  - Add java3d related jar files to DEB_JARS.
* debian/patches/*
  - Update as per current upstream source. Convert to quilt.
* debian/ant.properties
  - Do not disable 3D plugin anymore.
  - Use new property to disable compilation of OS X related classes.
* debian/wrappers/electric
  - Add java3d related jar files to runtime classpath.
* debian/README.source
  - Change text to the appropriate one for quilt.

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
import com.sun.electric.database.geometry.GenMath;
34
34
import com.sun.electric.database.geometry.Poly;
35
35
import com.sun.electric.database.hierarchy.Cell;
 
36
import com.sun.electric.database.hierarchy.EDatabase;
36
37
import com.sun.electric.database.id.CellId;
37
38
import com.sun.electric.database.id.PrimitivePortId;
38
39
import com.sun.electric.database.prototype.PortProto;
46
47
import com.sun.electric.technology.PrimitivePort;
47
48
import com.sun.electric.technology.TechPool;
48
49
import com.sun.electric.technology.Technology;
 
50
import com.sun.electric.technology.technologies.Schematics;
49
51
import com.sun.electric.tool.Job;
50
52
import com.sun.electric.tool.user.ErrorLogger;
51
53
 
58
60
import java.util.List;
59
61
import java.util.ArrayList;
60
62
import java.util.Iterator;
 
63
import java.util.Comparator;
61
64
 
62
65
/**
63
66
 * An ArcInst is an instance of an ArcProto (a wire type)
82
85
 * <P>
83
86
 * <CENTER><IMG SRC="doc-files/ArcInst-4.gif"></CENTER>
84
87
 */
85
 
public class ArcInst extends Geometric implements Comparable<ArcInst>
86
 
{
87
 
    /** empty array of ArcInsts. */                     public static final ArcInst[] NULL_ARRAY = {};
88
 
 
89
 
        /** The index of the tail of this ArcInst. */           public static final int TAILEND = ImmutableArcInst.TAILEND;
90
 
        /** The index of the head of this ArcInst. */           public static final int HEADEND = ImmutableArcInst.HEADEND;
91
 
        /** Key of the obsolete variable holding arc name.*/public static final Variable.Key ARC_NAME = Variable.newKey("ARC_name");
92
 
 
93
 
        /** Minimal distance of arc end to port polygon. */     static final double MINPORTDISTANCE = DBMath.getEpsilon()*0.71; // sqrt(0.5)
94
 
 
95
 
        // -------------------------- private data ----------------------------------
96
 
 
97
 
    /** Owner of this ArcInst. */                       private final Topology topology;
98
 
    /** persistent data of this ArcInst. */             ImmutableArcInst d;
99
 
        /** bounds after transformation. */                                     private final Rectangle2D.Double visBounds = new Rectangle2D.Double();
100
 
 
101
 
        /** PortInst on tail end of this arc instance */        /*package*/final PortInst tailPortInst;
102
 
        /** PortInst on head end of this arc instance */        /*package*/final PortInst headPortInst;
103
 
 
104
 
        /**
105
 
         * Private constructor of ArcInst.
 
88
public class ArcInst extends Geometric implements Comparable<ArcInst> {
 
89
 
 
90
    /** empty array of ArcInsts. */
 
91
    public static final ArcInst[] NULL_ARRAY = {};
 
92
    /** The index of the tail of this ArcInst. */
 
93
    public static final int TAILEND = ImmutableArcInst.TAILEND;
 
94
    /** The index of the head of this ArcInst. */
 
95
    public static final int HEADEND = ImmutableArcInst.HEADEND;
 
96
    /** Key of the obsolete variable holding arc name.*/
 
97
    public static final Variable.Key ARC_NAME = Variable.newKey("ARC_name");
 
98
    /** Minimal distance of arc end to port polygon. */
 
99
    static final double MINPORTDISTANCE = DBMath.getEpsilon() * 0.71; // sqrt(0.5)
 
100
    // -------------------------- private data ----------------------------------
 
101
    /** Owner of this ArcInst. */
 
102
    private final Topology topology;
 
103
    /** persistent data of this ArcInst. */
 
104
    ImmutableArcInst d;
 
105
    /** bounds after transformation. */
 
106
    private final Rectangle2D.Double visBounds = new Rectangle2D.Double();
 
107
    /** PortInst on tail end of this arc instance */    /*package*/
 
108
 
 
109
    final PortInst tailPortInst;
 
110
    /** PortInst on head end of this arc instance */    /*package*/
 
111
 
 
112
    final PortInst headPortInst;
 
113
 
 
114
//      /** 0-based index of this ArcInst in Cell. */                   private int arcIndex = -1; //scanline
 
115
    /**
 
116
     * Private constructor of ArcInst.
106
117
     * @param topology the Topology of the ArcInst.
107
118
     * @param d persistent data of ArcInst.
108
 
         * @param headPort the head end PortInst.
109
 
         * @param tailPort the tail end PortInst.
110
 
         */
111
 
        public ArcInst(Topology topology, ImmutableArcInst d, PortInst headPort, PortInst tailPort)
112
 
        {
113
 
                super(topology.cell);
 
119
     * @param headPort the head end PortInst.
 
120
     * @param tailPort the tail end PortInst.
 
121
     */
 
122
    public ArcInst(Topology topology, ImmutableArcInst d, PortInst headPort, PortInst tailPort) {
114
123
        this.topology = topology;
115
124
 
116
125
        // initialize this object
117
 
                assert parent == headPort.getNodeInst().getParent();
118
 
        assert parent == tailPort.getNodeInst().getParent();
 
126
        assert topology == headPort.getNodeInst().topology;
 
127
        assert topology == tailPort.getNodeInst().topology;
119
128
        assert d.headNodeId == headPort.getNodeInst().getD().nodeId;
120
129
        assert d.tailNodeId == tailPort.getNodeInst().getD().nodeId;
121
130
        assert d.headPortId == headPort.getPortProto().getId();
123
132
 
124
133
        this.d = d;
125
134
 
126
 
                // create node/arc connections and place them properly
127
 
                tailPortInst = tailPort;
 
135
        // create node/arc connections and place them properly
 
136
        tailPortInst = tailPort;
128
137
//              tailEnd = new TailConnection(this);
129
138
 
130
 
                headPortInst = headPort;
 
139
        headPortInst = headPort;
131
140
//              headEnd = new HeadConnection(this);
132
 
        }
 
141
    }
133
142
 
134
 
    private Object writeReplace() { return new ArcInstKey(this); }
 
143
    private Object writeReplace() {
 
144
        return new ArcInstKey(this);
 
145
    }
135
146
 
136
147
    private static class ArcInstKey extends EObjectInputStream.Key<ArcInst> {
137
 
        public ArcInstKey() {}
138
 
        private ArcInstKey(ArcInst ai) { super(ai); }
 
148
 
 
149
        public ArcInstKey() {
 
150
        }
 
151
 
 
152
        private ArcInstKey(ArcInst ai) {
 
153
            super(ai);
 
154
        }
139
155
 
140
156
        @Override
141
157
        public void writeExternal(EObjectOutputStream out, ArcInst ai) throws IOException {
142
 
            if (ai.getDatabase() != out.getDatabase() || !ai.isLinked())
 
158
            if (ai.getDatabase() != out.getDatabase() || !ai.isLinked()) {
143
159
                throw new NotSerializableException(ai + " not linked");
144
 
            out.writeObject(ai.getParent());
 
160
            }
 
161
            out.writeObject(ai.topology.cell);
145
162
            out.writeInt(ai.getArcId());
146
163
        }
147
164
 
148
165
        @Override
149
166
        public ArcInst readExternal(EObjectInputStream in) throws IOException, ClassNotFoundException {
150
 
            Cell cell = (Cell)in.readObject();
 
167
            Cell cell = (Cell) in.readObject();
151
168
            int arcId = in.readInt();
152
169
            ArcInst ai = cell.getArcById(arcId);
153
 
            if (ai == null)
 
170
            if (ai == null) {
154
171
                throw new InvalidObjectException("ArcInst from " + cell);
 
172
            }
155
173
            return ai;
156
174
        }
157
175
    }
158
176
 
 
177
    /**
 
178
     * Comparator class for sorting ArcInst by their length.
 
179
     */
 
180
    public static class ArcsByLength implements Comparator<ArcInst> {
 
181
 
 
182
        /**
 
183
         * Method to sort ArcInst by their length.
 
184
         */
 
185
        public int compare(ArcInst a1, ArcInst a2) {
 
186
            double len1 = a1.getHeadLocation().distance(a1.getTailLocation());
 
187
            double len2 = a2.getHeadLocation().distance(a2.getTailLocation());
 
188
            if (len1 == len2) {
 
189
                return 0;
 
190
            }
 
191
            if (len1 < len2) {
 
192
                return 1;
 
193
            }
 
194
            return -1;
 
195
        }
 
196
    }
 
197
 
159
198
    /****************************** CREATE, DELETE, MODIFY ******************************/
160
 
 
161
 
        /**
162
 
         * Method to create a new ArcInst with appropriate defaults, connecting two PortInsts.
163
 
         * Since no coordinates are given, the ArcInst connects to the center of the PortInsts.
164
 
         * @param type the prototype of the new ArcInst.
165
 
         * @param head the head end PortInst.
166
 
         * @param tail the tail end PortInst.
167
 
         * @return the newly created ArcInst, or null if there is an error.
168
 
         */
169
 
        public static ArcInst makeInstance(ArcProto type, PortInst head, PortInst tail)
170
 
        {
 
199
    /**
 
200
     * Method to create a new ArcInst with appropriate defaults, connecting two PortInsts.
 
201
     * Since no coordinates are given, the ArcInst connects to the center of the PortInsts.
 
202
     * @param type the prototype of the new ArcInst.
 
203
     * @param head the head end PortInst.
 
204
     * @param tail the tail end PortInst.
 
205
     * @return the newly created ArcInst, or null if there is an error.
 
206
     */
 
207
    public static ArcInst makeInstance(ArcProto type, PortInst head, PortInst tail) {
171
208
        EditingPreferences ep = tail.getEditingPreferences();
172
209
        ImmutableArcInst a = type.getDefaultInst(ep);
173
210
        return newInstanceBase(type, type.getDefaultLambdaBaseWidth(ep), head, tail, null, null, null, 0, a.flags);
174
 
        }
 
211
    }
175
212
 
176
 
        /**
177
 
         * Method to create a new ArcInst with appropriate defaults, connecting two PortInsts.
178
 
         * Since no coordinates are given, the ArcInst connects to the center of the PortInsts.
179
 
         * @param type the prototype of the new ArcInst.
180
 
         * @param baseWidth the base width of the new ArcInst.  The width must be > 0.
181
 
         * @param head the head end PortInst.
182
 
         * @param tail the tail end PortInst.
183
 
         * @return the newly created ArcInst, or null if there is an error.
184
 
         */
185
 
        public static ArcInst makeInstanceBase(ArcProto type, double baseWidth, PortInst head, PortInst tail)
186
 
        {
 
213
    /**
 
214
     * Method to create a new ArcInst with appropriate defaults, connecting two PortInsts.
 
215
     * Since no coordinates are given, the ArcInst connects to the center of the PortInsts.
 
216
     * @param type the prototype of the new ArcInst.
 
217
     * @param baseWidth the base width of the new ArcInst.  The width must be > 0.
 
218
     * @param head the head end PortInst.
 
219
     * @param tail the tail end PortInst.
 
220
     * @return the newly created ArcInst, or null if there is an error.
 
221
     */
 
222
    public static ArcInst makeInstanceBase(ArcProto type, double baseWidth, PortInst head, PortInst tail) {
187
223
        EditingPreferences ep = tail.getEditingPreferences();
188
224
        ImmutableArcInst a = type.getDefaultInst(ep);
189
225
        return newInstanceBase(type, baseWidth, head, tail, null, null, null, 0, a.flags);
190
 
        }
191
 
 
192
 
        /**
193
 
         * Method to create a new ArcInst with appropriate defaults, connecting two PortInsts at specified locations.
194
 
         * This is more general than the version that does not take coordinates.
195
 
         * @param type the prototype of the new ArcInst.
196
 
         * @param head the head end PortInst.
197
 
         * @param tail the tail end PortInst.
198
 
         * @param headPt the coordinate of the head end PortInst.
199
 
         * @param tailPt the coordinate of the tail end PortInst.
200
 
         * @param name the name of the new ArcInst
201
 
         * @return the newly created ArcInst, or null if there is an error.
202
 
         */
203
 
        public static ArcInst makeInstance(ArcProto type, PortInst head, PortInst tail,
204
 
                                           Point2D headPt, Point2D tailPt, String name)
205
 
        {
206
 
        EditingPreferences ep = tail.getEditingPreferences();
207
 
        ImmutableArcInst a = type.getDefaultInst(ep);
208
 
                return newInstanceBase(type, type.getDefaultLambdaBaseWidth(ep), head, tail, headPt, tailPt, name, 0, a.flags);
209
 
        }
210
 
 
211
 
        /**
212
 
         * Method to create a new ArcInst with appropriate defaults, connecting two PortInsts at specified locations.
213
 
         * This is more general than the version that does not take coordinates.
214
 
         * @param type the prototype of the new ArcInst.
215
 
         * @param baseWidth the base width of the new ArcInst.  The width must be > 0.
216
 
         * @param head the head end PortInst.
217
 
         * @param tail the tail end PortInst.
218
 
         * @param headPt the coordinate of the head end PortInst.
219
 
         * @param tailPt the coordinate of the tail end PortInst.
220
 
         * @param name the name of the new ArcInst
221
 
         * @return the newly created ArcInst, or null if there is an error.
222
 
         */
223
 
        public static ArcInst makeInstanceBase(ArcProto type, double baseWidth, PortInst head, PortInst tail,
224
 
                                           Point2D headPt, Point2D tailPt, String name)
225
 
        {
226
 
        EditingPreferences ep = tail.getEditingPreferences();
227
 
        ImmutableArcInst a = type.getDefaultInst(ep);
228
 
                return newInstanceBase(type, baseWidth, head, tail, headPt, tailPt, name, 0, a.flags);
229
 
        }
230
 
 
231
 
    /**
232
 
         * Method to create a new ArcInst connecting two PortInsts.
233
 
         * Since no coordinates are given, the ArcInst connects to the center of the PortInsts.
234
 
         * @param type the prototype of the new ArcInst.
235
 
         * @param baseWidth the base width of the new ArcInst.  The width must be > 0.
236
 
         * @param head the head end PortInst.
237
 
         * @param tail the tail end PortInst.
238
 
         * @return the newly created ArcInst, or null if there is an error.
239
 
         */
240
 
        public static ArcInst newInstanceBase(ArcProto type, double baseWidth, PortInst head, PortInst tail)
241
 
        {
242
 
                return newInstanceBase(type, baseWidth, head, tail, null, null, null, 0, ImmutableArcInst.DEFAULT_FLAGS);
243
 
        }
244
 
 
245
 
        /**
246
 
         * Method to create a new ArcInst connecting two PortInsts at specified locations.
247
 
         * This is more general than the version that does not take coordinates.
248
 
         * @param type the prototype of the new ArcInst.
249
 
         * @param baseWidth the base width of the new ArcInst.  The width must be > 0.
250
 
         * @param head the head end PortInst.
251
 
         * @param tail the tail end PortInst.
252
 
         * @param headPt the coordinate of the head end PortInst.
253
 
         * @param tailPt the coordinate of the tail end PortInst.
254
 
         * @param name the name of the new ArcInst
255
 
         * @param defAngle default angle in case port points coincide
256
 
     * @return the newly created ArcInst, or null if there is an error.
257
 
         */
258
 
        public static ArcInst newInstanceBase(ArcProto type, double baseWidth, PortInst head, PortInst tail,
259
 
                                          Point2D headPt, Point2D tailPt, String name, int defAngle)
260
 
        {
 
226
    }
 
227
 
 
228
    /**
 
229
     * Method to create a new ArcInst with appropriate defaults, connecting two PortInsts at specified locations.
 
230
     * This is more general than the version that does not take coordinates.
 
231
     * @param type the prototype of the new ArcInst.
 
232
     * @param head the head end PortInst.
 
233
     * @param tail the tail end PortInst.
 
234
     * @param headPt the coordinate of the head end PortInst.
 
235
     * @param tailPt the coordinate of the tail end PortInst.
 
236
     * @param name the name of the new ArcInst
 
237
     * @return the newly created ArcInst, or null if there is an error.
 
238
     */
 
239
    public static ArcInst makeInstance(ArcProto type, PortInst head, PortInst tail,
 
240
            Point2D headPt, Point2D tailPt, String name) {
 
241
        EditingPreferences ep = tail.getEditingPreferences();
 
242
        ImmutableArcInst a = type.getDefaultInst(ep);
 
243
        return newInstanceBase(type, type.getDefaultLambdaBaseWidth(ep), head, tail, headPt, tailPt, name, 0, a.flags);
 
244
    }
 
245
 
 
246
    /**
 
247
     * Method to create a new ArcInst with appropriate defaults, connecting two PortInsts at specified locations.
 
248
     * This is more general than the version that does not take coordinates.
 
249
     * @param type the prototype of the new ArcInst.
 
250
     * @param baseWidth the base width of the new ArcInst.  The width must be > 0.
 
251
     * @param head the head end PortInst.
 
252
     * @param tail the tail end PortInst.
 
253
     * @param headPt the coordinate of the head end PortInst.
 
254
     * @param tailPt the coordinate of the tail end PortInst.
 
255
     * @param name the name of the new ArcInst
 
256
     * @return the newly created ArcInst, or null if there is an error.
 
257
     */
 
258
    public static ArcInst makeInstanceBase(ArcProto type, double baseWidth, PortInst head, PortInst tail,
 
259
            Point2D headPt, Point2D tailPt, String name) {
 
260
        EditingPreferences ep = tail.getEditingPreferences();
 
261
        ImmutableArcInst a = type.getDefaultInst(ep);
 
262
        return newInstanceBase(type, baseWidth, head, tail, headPt, tailPt, name, 0, a.flags);
 
263
    }
 
264
 
 
265
    /**
 
266
     * Method to create a new ArcInst connecting two PortInsts.
 
267
     * Since no coordinates are given, the ArcInst connects to the center of the PortInsts.
 
268
     * @param type the prototype of the new ArcInst.
 
269
     * @param baseWidth the base width of the new ArcInst.  The width must be > 0.
 
270
     * @param head the head end PortInst.
 
271
     * @param tail the tail end PortInst.
 
272
     * @return the newly created ArcInst, or null if there is an error.
 
273
     */
 
274
    public static ArcInst newInstanceBase(ArcProto type, double baseWidth, PortInst head, PortInst tail) {
 
275
        return newInstanceBase(type, baseWidth, head, tail, null, null, null, 0, ImmutableArcInst.DEFAULT_FLAGS);
 
276
    }
 
277
 
 
278
    /**
 
279
     * Method to create a new ArcInst connecting two PortInsts at specified locations.
 
280
     * This is more general than the version that does not take coordinates.
 
281
     * @param type the prototype of the new ArcInst.
 
282
     * @param baseWidth the base width of the new ArcInst.  The width must be > 0.
 
283
     * @param head the head end PortInst.
 
284
     * @param tail the tail end PortInst.
 
285
     * @param headPt the coordinate of the head end PortInst.
 
286
     * @param tailPt the coordinate of the tail end PortInst.
 
287
     * @param name the name of the new ArcInst
 
288
     * @param defAngle default angle in case port points coincide
 
289
     * @return the newly created ArcInst, or null if there is an error.
 
290
     */
 
291
    public static ArcInst newInstanceBase(ArcProto type, double baseWidth, PortInst head, PortInst tail,
 
292
            Point2D headPt, Point2D tailPt, String name, int defAngle) {
261
293
        return newInstanceBase(type, baseWidth, head, tail, headPt, tailPt, name, defAngle, ImmutableArcInst.DEFAULT_FLAGS);
262
294
    }
263
295
 
264
 
        /**
265
 
         * Method to create a new ArcInst connecting two PortInsts at specified locations.
266
 
         * This is more general than the version that does not take coordinates.
267
 
         * @param type the prototype of the new ArcInst.
268
 
         * @param baseWidth the base width of the new ArcInst.  The width must be > 0.
269
 
         * @param head the head end PortInst.
270
 
         * @param tail the tail end PortInst.
271
 
         * @param headPt the coordinate of the head end PortInst.
272
 
         * @param tailPt the coordinate of the tail end PortInst.
273
 
         * @param name the name of the new ArcInst
274
 
         * @param defAngle default angle in case port points coincide
 
296
    /**
 
297
     * Method to create a new ArcInst connecting two PortInsts at specified locations.
 
298
     * This is more general than the version that does not take coordinates.
 
299
     * @param type the prototype of the new ArcInst.
 
300
     * @param baseWidth the base width of the new ArcInst.  The width must be > 0.
 
301
     * @param head the head end PortInst.
 
302
     * @param tail the tail end PortInst.
 
303
     * @param headPt the coordinate of the head end PortInst.
 
304
     * @param tailPt the coordinate of the tail end PortInst.
 
305
     * @param name the name of the new ArcInst
 
306
     * @param defAngle default angle in case port points coincide
275
307
     * @param flags flags of thew new ArcInst
276
308
     * @return the newly created ArcInst, or null if there is an error.
277
 
         */
278
 
        public static ArcInst newInstanceBase(ArcProto type, double baseWidth, PortInst head, PortInst tail,
279
 
                                          Point2D headPt, Point2D tailPt, String name, int defAngle, int flags)
280
 
        {
 
309
     */
 
310
    public static ArcInst newInstanceBase(ArcProto type, double baseWidth, PortInst head, PortInst tail,
 
311
            Point2D headPt, Point2D tailPt, String name, int defAngle, int flags) {
281
312
//        if (type.isNotUsed())
282
313
//        {
283
314
////            System.out.println("Cannot create arc instance of " + type + " because prototype is unused");
284
315
////            return null;
285
316
//        }
286
317
 
287
 
        long gridExtendOverMin = DBMath.lambdaToGrid(0.5*baseWidth) - type.getGridBaseExtend();
 
318
        long gridExtendOverMin = DBMath.lambdaToGrid(0.5 * baseWidth) - type.getGridBaseExtend();
288
319
//              if (gridFullWidth < type.getMaxLayerGridOffset())
289
320
//                      gridFullWidth = type.getDefaultGridFullWidth();
290
321
 
291
322
        // if points are null, create them as would newInstance
292
 
                EPoint headP;
293
 
        if (headPt == null)
294
 
        {
 
323
        EPoint headP;
 
324
        if (headPt == null) {
295
325
//            Rectangle2D headBounds = head.getBounds();
296
326
            headP = head.getCenter(); //new EPoint(headBounds.getCenterX(), headBounds.getCenterY());
297
 
        } else
298
 
                {
299
 
                        headP = EPoint.snap(headPt);
300
 
                }
301
 
                EPoint tailP;
302
 
        if (tailPt == null)
303
 
        {
 
327
        } else {
 
328
            headP = EPoint.snap(headPt);
 
329
        }
 
330
        EPoint tailP;
 
331
        if (tailPt == null) {
304
332
//            Rectangle2D tailBounds = tail.getBounds();
305
333
            tailP = tail.getCenter(); // new EPoint(tailBounds.getCenterX(), tailBounds.getCenterY());
306
 
        } else
307
 
                {
308
 
                        tailP = EPoint.snap(tailPt);
309
 
                }
 
334
        } else {
 
335
            tailP = EPoint.snap(tailPt);
 
336
        }
310
337
 
311
 
                // make sure points are valid
312
 
        Cell parent = head.getNodeInst().getParent();
 
338
        // make sure points are valid
 
339
        Cell parent = head.getNodeInst().topology.cell;
313
340
        Poly headPoly = head.getPoly();
314
341
        if (!stillInPoly(headP, headPoly)) {
315
 
                        System.out.println("Error in " + parent + ": head of " + type.getName() +
316
 
                                " arc at (" + headP.getX() + "," + headP.getY() + ") does not fit in " +
317
 
                                head + " which is centered at (" + headPoly.getCenterX() + "," + headPoly.getCenterY() + ")");
318
 
                        return null;
319
 
                }
 
342
            System.out.println("Error in " + parent + ": head of " + type.getName()
 
343
                    + " arc at (" + headP.getX() + "," + headP.getY() + ") does not fit in "
 
344
                    + head + " which is centered at (" + headPoly.getCenterX() + "," + headPoly.getCenterY() + ")");
 
345
            return null;
 
346
        }
320
347
        Poly tailPoly = tail.getPoly();
321
 
                if (!stillInPoly(tailP, tailPoly))
322
 
                {
323
 
                        System.out.println("Error in " + parent + ": tail of " + type.getName() +
324
 
                                " arc at (" + tailP.getX() + "," + tailP.getY() + ") does not fit in " +
325
 
                                tail + " which is centered at (" + tailPoly.getCenterX() + "," + tailPoly.getCenterY() + ")");
326
 
                        return null;
327
 
                }
 
348
        if (!stillInPoly(tailP, tailPoly)) {
 
349
            System.out.println("Error in " + parent + ": tail of " + type.getName()
 
350
                    + " arc at (" + tailP.getX() + "," + tailP.getY() + ") does not fit in "
 
351
                    + tail + " which is centered at (" + tailPoly.getCenterX() + "," + tailPoly.getCenterY() + ")");
 
352
            return null;
 
353
        }
328
354
 
329
355
        TextDescriptor nameDescriptor = TextDescriptor.getArcTextDescriptor();
330
356
        Name nameKey = name != null ? Name.findName(name) : null;
331
 
                if (nameKey != null && !nameKey.isTempname()) {
332
 
                        // adjust the name descriptor for "smart" text placement
333
 
            long gridBaseWidth = 2*(gridExtendOverMin + type.getGridBaseExtend());
334
 
                        nameDescriptor = getSmartTextDescriptor(defAngle, DBMath.gridToLambda(gridBaseWidth), nameDescriptor, parent.getEditingPreferences());
335
 
                }
 
357
        if (nameKey != null && !nameKey.isTempname()) {
 
358
            // adjust the name descriptor for "smart" text placement
 
359
            long gridBaseWidth = 2 * (gridExtendOverMin + type.getGridBaseExtend());
 
360
            nameDescriptor = getSmartTextDescriptor(defAngle, DBMath.gridToLambda(gridBaseWidth), nameDescriptor, parent.getEditingPreferences());
 
361
        }
336
362
        return newInstance(parent, type, name, nameDescriptor, head, tail, headP, tailP, gridExtendOverMin, defAngle, flags);
337
 
        }
 
363
    }
338
364
 
339
 
        /**
 
365
    /**
340
366
     * Method to create a new ArcInst connecting two PortInsts at specified locations.
341
367
     * This is more general than the version that does not take coordinates.
342
368
     * @param parent the parent Cell of this ArcInst
352
378
     * @param flags flag bits.
353
379
     * @return the newly created ArcInst, or null if there is an error.
354
380
     */
355
 
        public static ArcInst newInstance(Cell parent, ArcProto protoType, String name, TextDescriptor nameDescriptor,
356
 
        PortInst headPort, PortInst tailPort, EPoint headPt, EPoint tailPt, long gridExtendOverMin, int angle, int flags)
357
 
        {
 
381
    public static ArcInst newInstance(Cell parent, ArcProto protoType, String name, TextDescriptor nameDescriptor,
 
382
            PortInst headPort, PortInst tailPort, EPoint headPt, EPoint tailPt, long gridExtendOverMin, int angle, int flags) {
358
383
        parent.checkChanging();
359
384
        Topology topology = parent.getTopology();
360
385
 
361
 
                // make sure fields are valid
362
 
                if (protoType == null || headPort == null || tailPort == null || !headPort.isLinked() || !tailPort.isLinked()) return null;
363
 
        if (headPt == null || tailPt == null) return null;
 
386
        // make sure fields are valid
 
387
        if (protoType == null || headPort == null || tailPort == null || !headPort.isLinked() || !tailPort.isLinked()) {
 
388
            return null;
 
389
        }
 
390
        if (headPt == null || tailPt == null) {
 
391
            return null;
 
392
        }
364
393
 
365
 
        if (parent != headPort.getNodeInst().getParent() || parent != tailPort.getNodeInst().getParent())
366
 
                {
367
 
                        System.out.println("ArcProto.newInst: the 2 PortInsts are in different Cells!");
 
394
        if (topology != headPort.getNodeInst().topology || topology != tailPort.getNodeInst().topology) {
 
395
            System.out.println("ArcProto.newInst: the 2 PortInsts are in different Cells!");
368
396
            System.out.println("Cell " + parent.getName());
369
 
            System.out.println("Head " + headPort.getNodeInst().getParent().getName());
370
 
            System.out.println("Tail " + tailPort.getNodeInst().getParent().getName());
 
397
            System.out.println("Head " + headPort.getNodeInst().topology.cell.getName());
 
398
            System.out.println("Tail " + tailPort.getNodeInst().topology.cell.getName());
371
399
            return null;
372
 
                }
 
400
        }
373
401
 
374
402
        // make sure the arc can connect to these ports
375
403
        PortProto headProto = headPort.getPortProto();
376
 
                PrimitivePort headPrimPort = headProto.getBasePort();
377
 
                if (!headPrimPort.connectsTo(protoType))
378
 
                {
379
 
                        System.out.println("Cannot create " + protoType + " from (" + headPt.getX() + "," + headPt.getY() +
380
 
                                ") to (" + tailPt.getX() + "," + tailPt.getY() + ") in " + parent +
381
 
                                " because it cannot connect to port " + headProto.getName() +
382
 
                                " on node " + headPort.getNodeInst().describe(false));
383
 
                        return null;
384
 
                }
385
 
                PortProto tailProto = tailPort.getPortProto();
386
 
                PrimitivePort tailPrimPort = tailProto.getBasePort();
387
 
                if (!tailPrimPort.connectsTo(protoType))
388
 
                {
389
 
                        System.out.println("Cannot create " + protoType + " from (" + headPt.getX() + "," + headPt.getY() +
390
 
                                ") to (" + tailPt.getX() + "," + tailPt.getY() + ") in " + parent +
391
 
                                " because it cannot connect to port " + tailProto.getName() +
392
 
                                " on node " + tailPort.getNodeInst().describe(false));
393
 
                        return null;
394
 
                }
 
404
        PrimitivePort headPrimPort = headProto.getBasePort();
 
405
        if (!headPrimPort.connectsTo(protoType)) {
 
406
            System.out.println("Cannot create " + protoType + " from (" + headPt.getX() + "," + headPt.getY()
 
407
                    + ") to (" + tailPt.getX() + "," + tailPt.getY() + ") in " + parent
 
408
                    + " because it cannot connect to port " + headProto.getName()
 
409
                    + " on node " + headPort.getNodeInst().describe(false));
 
410
            return null;
 
411
        }
 
412
        PortProto tailProto = tailPort.getPortProto();
 
413
        PrimitivePort tailPrimPort = tailProto.getBasePort();
 
414
        if (!tailPrimPort.connectsTo(protoType)) {
 
415
            System.out.println("Cannot create " + protoType + " from (" + headPt.getX() + "," + headPt.getY()
 
416
                    + ") to (" + tailPt.getX() + "," + tailPt.getY() + ") in " + parent
 
417
                    + " because it cannot connect to port " + tailProto.getName()
 
418
                    + " on node " + tailPort.getNodeInst().describe(false));
 
419
            return null;
 
420
        }
395
421
 
396
 
        if (nameDescriptor == null) nameDescriptor = TextDescriptor.getArcTextDescriptor();
 
422
        if (nameDescriptor == null) {
 
423
            nameDescriptor = TextDescriptor.getArcTextDescriptor();
 
424
        }
397
425
        Name nameKey = name != null ? Name.findName(name) : null;
398
 
                if (nameKey == null || checkNameKey(nameKey, topology))
399
 
                {
 
426
        if (nameKey == null || checkNameKey(nameKey, topology)
 
427
                || nameKey.isBus() && protoType != Schematics.tech().bus_arc) {
400
428
            nameKey = topology.getArcAutoname();
401
429
//              } else
402
430
//              {
403
431
//                      // adjust the name descriptor for "smart" text placement
404
432
//            long gridBaseWidth = 2*(gridExtendOverMin + protoType.getGridBaseExtend());
405
433
//                      nameDescriptor = getSmartTextDescriptor(angle, DBMath.gridToLambda(gridBaseWidth), nameDescriptor);
406
 
                }
 
434
        }
407
435
        TechPool techPool = parent.getTechPool();
408
 
        if (!(tailProto.getId() instanceof PrimitivePortId && techPool.getPrimitivePort((PrimitivePortId)tailProto.getId()).isNegatable()))
 
436
        if (!(tailProto.getId() instanceof PrimitivePortId && techPool.getPrimitivePort((PrimitivePortId) tailProto.getId()).isNegatable())) {
409
437
            flags = ImmutableArcInst.TAIL_NEGATED.set(flags, false);
410
 
        if (!(headProto.getId() instanceof PrimitivePortId && techPool.getPrimitivePort((PrimitivePortId)headProto.getId()).isNegatable()))
 
438
        }
 
439
        if (!(headProto.getId() instanceof PrimitivePortId && techPool.getPrimitivePort((PrimitivePortId) headProto.getId()).isNegatable())) {
411
440
            flags = ImmutableArcInst.HEAD_NEGATED.set(flags, false);
 
441
        }
412
442
        if (protoType.getTechnology().isNoNegatedArcs()) {
413
443
            flags = ImmutableArcInst.TAIL_NEGATED.set(flags, false);
414
444
            flags = ImmutableArcInst.HEAD_NEGATED.set(flags, false);
426
456
                gridExtendOverMin, angle, flags);
427
457
        ArcInst ai = new ArcInst(topology, d, headPort, tailPort);
428
458
 
429
 
                // attach this arc to the two nodes it connects
430
 
                headPort.getNodeInst().redoGeometric();
431
 
                tailPort.getNodeInst().redoGeometric();
432
 
 
433
 
                // add this arc to the cell
434
 
                topology.addArc(ai);
435
 
 
436
 
                // handle change control, constraint, and broadcast
437
 
                Constraints.getCurrent().newObject(ai);
438
 
                return ai;
439
 
        }
 
459
        // attach this arc to the two nodes it connects
 
460
        headPort.getNodeInst().redoGeometric();
 
461
        tailPort.getNodeInst().redoGeometric();
 
462
 
 
463
        // add this arc to the cell
 
464
        topology.addArc(ai);
 
465
 
 
466
        // handle change control, constraint, and broadcast
 
467
        Constraints.getCurrent().newObject(ai);
 
468
        return ai;
 
469
    }
440
470
 
441
471
    /**
442
 
         * Method to delete this ArcInst.
443
 
         */
444
 
        public void kill()
445
 
        {
446
 
                if (!isLinked())
447
 
                {
448
 
                        System.out.println("ArcInst already killed");
449
 
                        return;
450
 
                }
 
472
     * Method to delete this ArcInst.
 
473
     */
 
474
    public void kill() {
 
475
        if (!isLinked()) {
 
476
            System.out.println("ArcInst already killed");
 
477
            return;
 
478
        }
451
479
        checkChanging();
452
480
 
453
 
                // remove this arc from the two nodes it connects
454
 
                headPortInst.getNodeInst().redoGeometric();
455
 
                tailPortInst.getNodeInst().redoGeometric();
456
 
 
457
 
                // remove this arc from the cell
458
 
                topology.removeArc(this);
459
 
 
460
 
                // handle change control, constraint, and broadcast
461
 
                Constraints.getCurrent().killObject(this);
462
 
        }
463
 
 
464
 
        /**
465
 
         * Method to change the width and end locations of this ArcInst.
466
 
         * @param dHeadX the change to the X coordinate of the head of this ArcInst.
467
 
         * @param dHeadY the change to the Y coordinate of the head of this ArcInst.
468
 
         * @param dTailX the change to the X coordinate of the tail of this ArcInst.
469
 
         * @param dTailY the change to the Y coordinate of the tail of this ArcInst.
470
 
         */
471
 
        public void modify(double dHeadX, double dHeadY, double dTailX, double dTailY)
472
 
        {
473
 
                // save old arc state
 
481
        // remove this arc from the two nodes it connects
 
482
        headPortInst.getNodeInst().redoGeometric();
 
483
        tailPortInst.getNodeInst().redoGeometric();
 
484
 
 
485
        // remove this arc from the cell
 
486
        topology.removeArc(this);
 
487
 
 
488
        // handle change control, constraint, and broadcast
 
489
        Constraints.getCurrent().killObject(this);
 
490
    }
 
491
 
 
492
    /**
 
493
     * Method to change the width and end locations of this ArcInst.
 
494
     * @param dHeadX the change to the X coordinate of the head of this ArcInst.
 
495
     * @param dHeadY the change to the Y coordinate of the head of this ArcInst.
 
496
     * @param dTailX the change to the X coordinate of the tail of this ArcInst.
 
497
     * @param dTailY the change to the Y coordinate of the tail of this ArcInst.
 
498
     */
 
499
    public void modify(double dHeadX, double dHeadY, double dTailX, double dTailY) {
 
500
        // save old arc state
474
501
        ImmutableArcInst oldD = d;
475
502
 
476
 
                // change the arc
 
503
        // change the arc
477
504
        EPoint tail = d.tailLocation;
478
 
                if (dTailX != 0 || dTailY != 0)
479
 
                        tail = new EPoint(tail.getX() + dTailX, tail.getY() + dTailY);
 
505
        if (dTailX != 0 || dTailY != 0) {
 
506
            tail = new EPoint(tail.getX() + dTailX, tail.getY() + dTailY);
 
507
        }
480
508
        EPoint head = d.headLocation;
481
 
        if (dHeadX != 0 || dHeadY != 0)
 
509
        if (dHeadX != 0 || dHeadY != 0) {
482
510
            head = new EPoint(head.getX() + dHeadX, head.getY() + dHeadY);
483
 
                lowLevelModify(d.withLocations(tail, head));
 
511
        }
 
512
        lowLevelModify(d.withLocations(tail, head));
484
513
 
485
 
                // track the change
 
514
        // track the change
486
515
        Constraints.getCurrent().modifyArcInst(this, oldD);
487
 
        }
 
516
    }
488
517
 
489
 
        /**
490
 
         * Method to change the width this ArcInst.
491
 
         * @param lambdaBaseWidth new base width of the ArcInst in lambda units.
492
 
         */
 
518
    /**
 
519
     * Method to change the width this ArcInst.
 
520
     * @param lambdaBaseWidth new base width of the ArcInst in lambda units.
 
521
     */
493
522
    public void setLambdaBaseWidth(double lambdaBaseWidth) {
494
523
        setGridBaseWidth(DBMath.lambdaToSizeGrid(lambdaBaseWidth));
495
524
    }
496
525
 
497
 
        /**
498
 
         * Method to change the width this ArcInst.
499
 
         * @param gridBaseWidth new base width of the ArcInst in lambda units.
500
 
         */
 
526
    /**
 
527
     * Method to change the width this ArcInst.
 
528
     * @param gridBaseWidth new base width of the ArcInst in lambda units.
 
529
     */
501
530
    public void setGridBaseWidth(long gridBaseWidth) {
502
 
        if (gridBaseWidth == getGridBaseWidth()) return;
 
531
        if (gridBaseWidth == getGridBaseWidth()) {
 
532
            return;
 
533
        }
503
534
 
504
535
        // save old arc state
505
536
        ImmutableArcInst oldD = d;
506
537
 
507
538
        // change the arc
508
 
        lowLevelModify(d.withGridExtendOverMin(gridBaseWidth/2 - getProto().getGridBaseExtend()));
 
539
        lowLevelModify(d.withGridExtendOverMin(gridBaseWidth / 2 - getProto().getGridBaseExtend()));
509
540
 
510
541
        // track the change
511
542
        Constraints.getCurrent().modifyArcInst(this, oldD);
512
543
    }
513
544
 
514
 
        /**
515
 
         * Method to replace this ArcInst with one of another type.
516
 
         * @param ap the new type of arc.
517
 
         * @return the new ArcInst (null on error).
518
 
         */
519
 
        public ArcInst replace(ArcProto ap)
520
 
        {
521
 
                // check for connection allowance
522
 
                if (!headPortInst.getPortProto().connectsTo(ap) || !tailPortInst.getPortProto().connectsTo(ap))
523
 
                {
524
 
                        System.out.println("Cannot replace " + this + " with one of type " + ap.getName() +
525
 
                                " because the nodes cannot connect to it");
526
 
                        return null;
527
 
                }
528
 
 
529
 
                // first create the new nodeinst in place
530
 
                ArcInst newar = ArcInst.newInstanceBase(ap, getLambdaBaseWidth(), headPortInst, tailPortInst, d.headLocation, d.tailLocation, null, 0);
531
 
                if (newar == null)
532
 
                {
533
 
                        System.out.println("Cannot replace " + this + " with one of type " + ap.getName() +
534
 
                                " because the new arc failed to create");
535
 
                        return null;
536
 
                }
537
 
 
538
 
                // copy all variables on the arcinst
539
 
                newar.copyPropertiesFrom(this);
540
 
 
541
 
                // now delete the original nodeinst
542
 
                kill();
543
 
                newar.setName(getName());
544
 
                return newar;
545
 
        }
546
 
 
547
 
        /****************************** LOW-LEVEL IMPLEMENTATION ******************************/
548
 
 
 
545
    /**
 
546
     * Method to replace this ArcInst with one of another type.
 
547
     * @param ap the new type of arc.
 
548
     * @return the new ArcInst (null on error).
 
549
     */
 
550
    public ArcInst replace(ArcProto ap) {
 
551
        // check for connection allowance
 
552
        if (!headPortInst.getPortProto().connectsTo(ap) || !tailPortInst.getPortProto().connectsTo(ap)) {
 
553
            System.out.println("Cannot replace " + this + " with one of type " + ap.getName()
 
554
                    + " because the nodes cannot connect to it");
 
555
            return null;
 
556
        }
 
557
 
 
558
        // first create the new nodeinst in place
 
559
        ArcInst newar = ArcInst.newInstanceBase(ap, getLambdaBaseWidth(), headPortInst, tailPortInst, d.headLocation, d.tailLocation, null, 0);
 
560
        if (newar == null) {
 
561
            System.out.println("Cannot replace " + this + " with one of type " + ap.getName()
 
562
                    + " because the new arc failed to create");
 
563
            return null;
 
564
        }
 
565
 
 
566
        // copy all variables on the arcinst
 
567
        newar.copyPropertiesFrom(this);
 
568
 
 
569
        // now delete the original nodeinst
 
570
        kill();
 
571
        newar.setName(getName());
 
572
        return newar;
 
573
    }
 
574
 
 
575
    /****************************** LOW-LEVEL IMPLEMENTATION ******************************/
549
576
    /**
550
577
     * Returns persistent data of this ArcInst.
551
578
     * @return persistent data of this ArcInst.
552
579
     */
553
580
    @Override
554
 
    public ImmutableArcInst getD() { return d; }
 
581
    public ImmutableArcInst getD() {
 
582
        return d;
 
583
    }
555
584
 
556
585
    /**
557
586
     * Modifies persistend data of this ArcInst.
562
591
    public boolean setD(ImmutableArcInst newD, boolean notify) {
563
592
        checkChanging();
564
593
        ImmutableArcInst oldD = d;
565
 
        if (newD == oldD) return false;
566
 
        parent.setTopologyModified();
 
594
        if (newD == oldD) {
 
595
            return false;
 
596
        }
 
597
        topology.cell.setTopologyModified();
567
598
        d = newD;
568
 
        if (notify)
 
599
        if (notify) {
569
600
            Constraints.getCurrent().modifyArcInst(this, oldD);
 
601
        }
570
602
        return true;
571
603
    }
572
604
 
581
613
     * @param var Variable to add.
582
614
     */
583
615
    public void addVar(Variable var) {
584
 
        if (setD(d.withVariable(var), true))
585
 
        {
 
616
        if (setD(d.withVariable(var), true)) {
586
617
            // check for side-effects of the change
587
618
            checkPossibleVariableEffects(var.getKey());
588
619
        }
589
620
    }
590
621
 
591
 
        /**
592
 
         * Method to handle special case side-effects of setting variables on this NodeInst.
593
 
         * Overrides the general method on ElectricObject.
594
 
         * Currently it handles changes to the number-of-degrees on a circle node.
595
 
         * @param key the Variable key that has changed on this NodeInst.
596
 
         */
597
 
        public void checkPossibleVariableEffects(Variable.Key key)
598
 
        {
 
622
    /**
 
623
     * Method to handle special case side-effects of setting variables on this NodeInst.
 
624
     * Overrides the general method on ElectricObject.
 
625
     * Currently it handles changes to the number-of-degrees on a circle node.
 
626
     * @param key the Variable key that has changed on this NodeInst.
 
627
     */
 
628
    public void checkPossibleVariableEffects(Variable.Key key) {
599
629
        if (key == ImmutableArcInst.ARC_RADIUS) {
600
 
                        lowLevelModify(d);
 
630
            lowLevelModify(d);
601
631
        }
602
 
        }
 
632
    }
603
633
 
604
 
        /**
605
 
         * Method to delete a Variable from this ArcInst.
606
 
         * @param key the key of the Variable to delete.
607
 
         */
608
 
        public void delVar(Variable.Key key)
609
 
        {
 
634
    /**
 
635
     * Method to delete a Variable from this ArcInst.
 
636
     * @param key the key of the Variable to delete.
 
637
     */
 
638
    public void delVar(Variable.Key key) {
610
639
        setD(d.withoutVariable(key), true);
611
 
        }
 
640
    }
612
641
 
613
 
        /**
614
 
         * Low-level method to change the width and end locations of this ArcInst.
 
642
    /**
 
643
     * Low-level method to change the width and end locations of this ArcInst.
615
644
     * New persistent data may differ from old one only by width and end locations
616
 
         * @param d the new persistent data of this ArcInst.
617
 
         */
618
 
        public void lowLevelModify(ImmutableArcInst d)
619
 
        {
620
 
                // first remove from the R-Tree structure
 
645
     * @param d the new persistent data of this ArcInst.
 
646
     */
 
647
    public void lowLevelModify(ImmutableArcInst d) {
 
648
        // first remove from the R-Tree structure
621
649
        boolean renamed = this.d.name != d.name;
622
 
        if (renamed)
 
650
        if (renamed) {
623
651
            topology.removeArc(this);
 
652
        }
624
653
 
625
 
                // now make the change
 
654
        // now make the change
626
655
        setD(d, false);
627
 
        if (renamed)
 
656
        if (renamed) {
628
657
            topology.addArc(this);
629
 
 
630
 
        redoGeometric();
631
 
 
632
 
                // update end shrinkage information ?????????????????????
 
658
        }
 
659
 
 
660
        topology.setArcsDirty();
 
661
 
 
662
        // update end shrinkage information ?????????????????????
633
663
//              headPortInst.getNodeInst().updateShrinkage();
634
664
//              tailPortInst.getNodeInst().updateShrinkage();
635
 
        }
636
 
 
637
 
        /****************************** GRAPHICS ******************************/
638
 
 
639
 
        /**
640
 
         * Method to return the full width of this ArcInst in grid units.
641
 
         * @return the full width of this ArcInst in grid units.
642
 
         */
643
 
        public long getGridFullWidth() { return 2*(d.getGridExtendOverMin() + getProto().getMaxLayerGridExtend()); }
644
 
 
645
 
        /**
646
 
         * Method to return the base width of this ArcInst in lambda units.
647
 
         * @return the base width of this ArcInst in lambda units.
648
 
         */
649
 
        public double getLambdaBaseWidth() { return DBMath.gridToLambda(getGridBaseWidth()); }
650
 
 
651
 
        /**
652
 
         * Method to return the base width of this ArcInst in grid units.
653
 
         * @return the base width of this ArcInst in grid units.
654
 
         */
655
 
        public long getGridBaseWidth() { return 2*(d.getGridExtendOverMin() + getProto().getGridBaseExtend()); }
656
 
 
657
 
        /**
658
 
         * Method to return the length of this ArcInst in lambda units.
659
 
         * @return the length of this ArcInst in lambda units.
660
 
         */
661
 
        public double getLambdaLength() { return d.getLambdaLength(); }
662
 
 
663
 
        /**
664
 
         * Method to return the length of this ArcInst in grid units.
665
 
         * @return the length of this ArcInst in grid units.
666
 
         */
667
 
        public double getGridLength() { return d.getGridLength(); }
 
665
    }
 
666
 
 
667
    /****************************** GRAPHICS ******************************/
 
668
    /**
 
669
     * Method to return the full width of this ArcInst in grid units.
 
670
     * @return the full width of this ArcInst in grid units.
 
671
     */
 
672
    public long getGridFullWidth() {
 
673
        return 2 * (d.getGridExtendOverMin() + getProto().getMaxLayerGridExtend());
 
674
    }
 
675
 
 
676
    /**
 
677
     * Method to return the base width of this ArcInst in lambda units.
 
678
     * @return the base width of this ArcInst in lambda units.
 
679
     */
 
680
    public double getLambdaBaseWidth() {
 
681
        return DBMath.gridToLambda(getGridBaseWidth());
 
682
    }
 
683
 
 
684
    /**
 
685
     * Method to return the base width of this ArcInst in grid units.
 
686
     * @return the base width of this ArcInst in grid units.
 
687
     */
 
688
    public long getGridBaseWidth() {
 
689
        return 2 * (d.getGridExtendOverMin() + getProto().getGridBaseExtend());
 
690
    }
 
691
 
 
692
    /**
 
693
     * Method to return the length of this ArcInst in lambda units.
 
694
     * @return the length of this ArcInst in lambda units.
 
695
     */
 
696
    public double getLambdaLength() {
 
697
        return d.getLambdaLength();
 
698
    }
 
699
 
 
700
    /**
 
701
     * Method to return the length of this ArcInst in grid units.
 
702
     * @return the length of this ArcInst in grid units.
 
703
     */
 
704
    public double getGridLength() {
 
705
        return d.getGridLength();
 
706
    }
668
707
 
669
708
    /**
670
709
     * Returns true if length of this ArcInst is zero.
671
710
     * @return true if length of this ArcInst is zero.
672
711
     */
673
 
    public boolean isZeroLength() { return d.isZeroLength(); }
 
712
    public boolean isZeroLength() {
 
713
        return d.isZeroLength();
 
714
    }
674
715
 
675
 
        /**
676
 
         * Method to return the rotation angle of this ArcInst.
 
716
    /**
 
717
     * Method to return the rotation angle of this ArcInst.
677
718
     * This is an angle of direction from tailLocation to headLocation.
678
 
         * @return the rotation angle of this ArcInst (in tenth-degrees).
679
 
         */
680
 
        public int getAngle() { return d.getAngle(); }
 
719
     * @return the rotation angle of this ArcInst (in tenth-degrees).
 
720
     */
 
721
    public int getAngle() {
 
722
        return d.getAngle();
 
723
    }
681
724
 
682
 
        /**
683
 
         * Method to set the rotation angle of this ArcInst.
684
 
         * @param angle the rotation angle of this ArcInst (in tenth-degrees).
685
 
         * In general, you should not call this method because the
686
 
         * constructors and modification methods update this correctly.
687
 
         * If, however, you have a zero-length arc and want to explicitly set
688
 
         * its angle, then use this method.
689
 
         */
690
 
        public void setAngle(int angle) {
 
725
    /**
 
726
     * Method to set the rotation angle of this ArcInst.
 
727
     * @param angle the rotation angle of this ArcInst (in tenth-degrees).
 
728
     * In general, you should not call this method because the
 
729
     * constructors and modification methods update this correctly.
 
730
     * If, however, you have a zero-length arc and want to explicitly set
 
731
     * its angle, then use this method.
 
732
     */
 
733
    public void setAngle(int angle) {
691
734
        checkChanging();
692
735
        ImmutableArcInst oldD = d;
693
736
        lowLevelModify(d.withAngle(angle));
694
 
        if (parent != null) Constraints.getCurrent().modifyArcInst(this, oldD);
 
737
        assert topology != null;
 
738
        Constraints.getCurrent().modifyArcInst(this, oldD);
695
739
    }
696
740
 
697
741
    /**
701
745
     * These Polys include displayable variables on the ArcInst.
702
746
     */
703
747
    @Override
704
 
    public Iterator<Poly> getShape(Poly.Builder polyBuilder) { return polyBuilder.getShape(this); }
 
748
    public Iterator<Poly> getShape(Poly.Builder polyBuilder) {
 
749
        return polyBuilder.getShape(this);
 
750
    }
705
751
 
706
752
    /**
707
753
     * Method to return the bounds of this ArcInst.
710
756
     */
711
757
    @Override
712
758
    public Rectangle2D getBounds() {
713
 
        if (topology.validArcBounds)
714
 
            return visBounds;
715
 
        topology.computeArcBounds();
 
759
        if (!topology.validArcBounds) {
 
760
            topology.computeArcBounds();
 
761
        }
716
762
        return visBounds;
717
763
    }
718
764
 
726
772
            y = DBMath.gridToLambda(y);
727
773
            w = DBMath.gridToLambda(w);
728
774
            h = DBMath.gridToLambda(h);
729
 
            if (x == visBounds.getX() && y == visBounds.getY() && w == visBounds.getWidth() && h == visBounds.getHeight())
 
775
            if (x == visBounds.getX() && y == visBounds.getY() && w == visBounds.getWidth() && h == visBounds.getHeight()) {
730
776
                return;
 
777
            }
731
778
            visBounds.setRect(x, y, w, h);
732
 
            parent.setDirty();
733
 
       } else {
 
779
//            parent.setDirty();
 
780
        } else {
734
781
            b.clear();
735
782
            b.genShapeOfArc(d);
736
 
            if (b.makeBounds(visBounds))
737
 
                parent.setDirty();
 
783
            b.makeBounds(null, visBounds);
 
784
//            if (b.makeBounds(null, visBounds))
 
785
//                parent.setDirty();
738
786
        }
739
787
    }
740
788
 
741
789
    /**
742
 
     * Method to recalculate the Geometric bounds for this NodeInst.
 
790
     * Method to create a Poly object that describes an ArcInst in lambda units.
 
791
     * The ArcInst is described by its width and style.
 
792
     * @param gridWidth the width of the Poly in grid units.
 
793
     * @param style the style of the ArcInst.
 
794
     * @return a Poly that describes the ArcInst in lambda units.
743
795
     */
744
 
    public void redoGeometric() {
745
 
        if (parent != null)
746
 
            parent.setGeomDirty();
747
 
        topology.validArcBounds = false;
748
 
        topology.unfreshRTree();
749
 
    }
750
 
 
751
 
        /**
752
 
         * Method to create a Poly object that describes an ArcInst in lambda units.
753
 
         * The ArcInst is described by its width and style.
754
 
         * @param gridWidth the width of the Poly in grid units.
755
 
         * @param style the style of the ArcInst.
756
 
         * @return a Poly that describes the ArcInst in lambda units.
757
 
         */
758
796
    public Poly makeLambdaPoly(long gridWidth, Poly.Type style) {
759
797
        Poly.Builder polyBuilder = Poly.threadLocalLambdaBuilder();
760
 
        polyBuilder.setup(parent);
 
798
        polyBuilder.setup(topology.cell);
761
799
        return polyBuilder.makePoly(getD(), gridWidth, style);
762
800
    }
763
801
 
772
810
//        CellBackup.Memoization m = parent != null ? parent.getMemoization() : null;
773
811
//        return getD().makeGridPoly(m, gridWidth, style);
774
812
//    }
775
 
 
776
 
        /**
 
813
    /**
777
814
     * Method to fill polygon "poly" with the outline in lambda units of the curved arc in
778
815
     * this ArcInst whose width in grid units is "gridWidth".  The style of the polygon is set to "style".
779
816
     * If there is no curvature information in the arc, the routine returns null,
781
818
     */
782
819
    public Poly curvedArcLambdaOutline(Poly.Type style, long gridWidth, long gridRadius) {
783
820
        Poly.Builder polyBuilder = Poly.threadLocalLambdaBuilder();
784
 
        polyBuilder.setup(parent);
 
821
        polyBuilder.setup(topology.cell);
785
822
        Variable radius = Variable.newInstance(ImmutableArcInst.ARC_RADIUS, new Double(DBMath.gridToLambda(gridRadius)), TextDescriptor.getArcTextDescriptor());
786
823
        return polyBuilder.makePoly(getD().withVariable(radius), gridWidth, style);
787
824
    }
801
838
//              addDisplayableVariables(getBounds(), polys, 0, wnd, false);
802
839
//              return polys;
803
840
//      }
804
 
 
805
 
        /**
806
 
         * Method to return the number of displayable Variables on this ArcInst.
807
 
         * A displayable Variable is one that will be shown with its object.
808
 
         * @return the number of displayable Variables on this ArcInst.
809
 
         */
810
 
        public int numDisplayableVariables(boolean multipleStrings)
811
 
        {
812
 
                return super.numDisplayableVariables(multipleStrings) + (isUsernamed()?1:0);
813
 
        }
814
 
 
815
 
        /**
816
 
         * Method to add all displayable Variables on this Electric object to an array of Poly objects.
817
 
         * @param rect a rectangle describing the bounds of the object on which the Variables will be displayed.
818
 
         * @param polys an array of Poly objects that will be filled with the displayable Variables.
819
 
         * @param start the starting index in the array of Poly objects to fill with displayable Variables.
820
 
         * @return the number of Variables that were added.
821
 
         */
822
 
        public int addDisplayableVariables(Rectangle2D rect, Poly [] polys, int start, EditWindow0 wnd, boolean multipleStrings)
823
 
        {
824
 
                int numVars = 0;
825
 
                if (isUsernamed())
826
 
                {
827
 
                        double cX = rect.getCenterX();
828
 
                        double cY = rect.getCenterY();
829
 
                        TextDescriptor td = d.nameDescriptor;
830
 
                        double offX = td.getXOff();
831
 
                        double offY = td.getYOff();
832
 
                        TextDescriptor.Position pos = td.getPos();
833
 
                        Poly.Type style = pos.getPolyType();
834
 
 
835
 
                        Point2D [] pointList = null;
836
 
                        if (style == Poly.Type.TEXTBOX)
837
 
                        {
838
 
                                pointList = Poly.makePoints(rect);
839
 
                        } else
840
 
                        {
841
 
                                pointList = new Point2D.Double[1];
842
 
                                pointList[0] = new Point2D.Double(cX+offX, cY+offY);
843
 
                        }
844
 
                        polys[start] = new Poly(pointList);
845
 
                        polys[start].setStyle(style);
846
 
                        polys[start].setString(getNameKey().toString());
847
 
                        polys[start].setTextDescriptor(td);
848
 
                        polys[start].setLayer(null);
849
 
                        polys[start].setDisplayedText(new DisplayedText(this, ARC_NAME));
850
 
                        numVars = 1;
851
 
                }
852
 
                return super.addDisplayableVariables(rect, polys, start+numVars, wnd, multipleStrings) + numVars;
853
 
        }
854
 
 
855
 
        /**
856
 
         * Method to get all displayable Variables on this ArcInst to an array of Poly objects.
857
 
         * @param wnd window in which the Variables will be displayed.
858
 
         * @return an array of Poly objects with displayable variables.
859
 
         */
860
 
        public Poly[] getDisplayableVariables(EditWindow0 wnd) {
 
841
    /**
 
842
     * Method to return the number of displayable Variables on this ArcInst.
 
843
     * A displayable Variable is one that will be shown with its object.
 
844
     * @return the number of displayable Variables on this ArcInst.
 
845
     */
 
846
    public int numDisplayableVariables(boolean multipleStrings) {
 
847
        return super.numDisplayableVariables(multipleStrings) + (isUsernamed() ? 1 : 0);
 
848
    }
 
849
 
 
850
    /**
 
851
     * Method to add all displayable Variables on this Electric object to an array of Poly objects.
 
852
     * @param rect a rectangle describing the bounds of the object on which the Variables will be displayed.
 
853
     * @param polys an array of Poly objects that will be filled with the displayable Variables.
 
854
     * @param start the starting index in the array of Poly objects to fill with displayable Variables.
 
855
     * @return the number of Variables that were added.
 
856
     */
 
857
    public int addDisplayableVariables(Rectangle2D rect, Poly[] polys, int start, EditWindow0 wnd, boolean multipleStrings) {
 
858
        int numVars = 0;
 
859
        if (isUsernamed()) {
 
860
            double cX = rect.getCenterX();
 
861
            double cY = rect.getCenterY();
 
862
            TextDescriptor td = d.nameDescriptor;
 
863
            double offX = td.getXOff();
 
864
            double offY = td.getYOff();
 
865
            TextDescriptor.Position pos = td.getPos();
 
866
            Poly.Type style = pos.getPolyType();
 
867
 
 
868
            Point2D[] pointList = null;
 
869
            if (style == Poly.Type.TEXTBOX) {
 
870
                pointList = Poly.makePoints(rect);
 
871
            } else {
 
872
                pointList = new Point2D.Double[1];
 
873
                pointList[0] = new Point2D.Double(cX + offX, cY + offY);
 
874
            }
 
875
            polys[start] = new Poly(pointList);
 
876
            polys[start].setStyle(style);
 
877
            polys[start].setString(getNameKey().toString());
 
878
            polys[start].setTextDescriptor(td);
 
879
            polys[start].setLayer(null);
 
880
            polys[start].setDisplayedText(new DisplayedText(this, ARC_NAME));
 
881
            numVars = 1;
 
882
        }
 
883
        return super.addDisplayableVariables(rect, polys, start + numVars, wnd, multipleStrings) + numVars;
 
884
    }
 
885
 
 
886
    /**
 
887
     * Method to get all displayable Variables on this ArcInst to an array of Poly objects.
 
888
     * @param wnd window in which the Variables will be displayed.
 
889
     * @return an array of Poly objects with displayable variables.
 
890
     */
 
891
    public Poly[] getDisplayableVariables(EditWindow0 wnd) {
861
892
        return getDisplayableVariables(getBounds(), wnd, true);
862
893
    }
863
894
 
864
 
        /****************************** CONNECTIONS ******************************/
865
 
 
866
 
        /**
867
 
         * Method to return the Connection on the tail end of this ArcInst.
868
 
         * @return the Connection on the tail end of this ArcInst.
869
 
         */
870
 
        public TailConnection getTail() { return new TailConnection(this); }
871
 
 
872
 
        /**
873
 
         * Method to return the Connection on the head end of this ArcInst.
874
 
         * @return the Connection on the head end of this ArcInst.
875
 
         */
876
 
        public HeadConnection getHead() { return new HeadConnection(this); }
877
 
 
878
 
        /**
879
 
         * Method to return the connection at an end of this ArcInst.
880
 
         * @param connIndex TAILEND (0) for the tail of this ArcInst, HEADEND (1) for the head.
881
 
         */
 
895
    /****************************** CONNECTIONS ******************************/
 
896
 
 
897
    /**
 
898
     * Method to return the Connection on the tail end of this ArcInst.
 
899
     * @return the Connection on the tail end of this ArcInst.
 
900
     */
 
901
    public TailConnection getTail() {
 
902
        return new TailConnection(this);
 
903
    }
 
904
 
 
905
    /**
 
906
     * Method to return the Connection on the head end of this ArcInst.
 
907
     * @return the Connection on the head end of this ArcInst.
 
908
     */
 
909
    public HeadConnection getHead() {
 
910
        return new HeadConnection(this);
 
911
    }
 
912
 
 
913
    /**
 
914
     * Method to return the connection at an end of this ArcInst.
 
915
     * @param connIndex TAILEND (0) for the tail of this ArcInst, HEADEND (1) for the head.
 
916
     */
882
917
    public Connection getConnection(int connIndex) {
883
918
        switch (connIndex) {
884
 
            case ImmutableArcInst.TAILEND: return new TailConnection(this);
885
 
            case ImmutableArcInst.HEADEND: return new HeadConnection(this);
886
 
            default: throw new IllegalArgumentException("Bad end " + connIndex);
 
919
            case ImmutableArcInst.TAILEND:
 
920
                return new TailConnection(this);
 
921
            case ImmutableArcInst.HEADEND:
 
922
                return new HeadConnection(this);
 
923
            default:
 
924
                throw new IllegalArgumentException("Bad end " + connIndex);
887
925
        }
888
926
    }
889
927
 
890
 
        /**
891
 
         * Method to return the PortInst on tail of this ArcInst.
892
 
         * @return the PortInst on tail.
893
 
         */
894
 
        public PortInst getTailPortInst() { return tailPortInst; }
 
928
    /**
 
929
     * Method to return the PortInst on tail of this ArcInst.
 
930
     * @return the PortInst on tail.
 
931
     */
 
932
    public PortInst getTailPortInst() {
 
933
        return tailPortInst;
 
934
    }
895
935
 
896
 
        /**
897
 
         * Method to return the PortInst on head of this ArcInst.
898
 
         * @return the PortInst on head.
899
 
         */
900
 
        public PortInst getHeadPortInst() { return headPortInst; }
 
936
    /**
 
937
     * Method to return the PortInst on head of this ArcInst.
 
938
     * @return the PortInst on head.
 
939
     */
 
940
    public PortInst getHeadPortInst() {
 
941
        return headPortInst;
 
942
    }
901
943
 
902
944
    /**
903
945
     * Method to tell whether this ArcInst is connected directly to another
911
953
        return tailPortInst.getNodeInst() == geom || headPortInst.getNodeInst() == geom;
912
954
    }
913
955
 
914
 
        /**
915
 
         * Method to return the PortInst on an end of this ArcInst.
916
 
         * @param connIndex TAILEND (0) for the tail of this ArcInst, HEADEND (1) for the head.
917
 
         * @return the PortInst at an end.
918
 
         */
 
956
    /**
 
957
     * Method to return the PortInst on an end of this ArcInst.
 
958
     * @param connIndex TAILEND (0) for the tail of this ArcInst, HEADEND (1) for the head.
 
959
     * @return the PortInst at an end.
 
960
     */
919
961
    public PortInst getPortInst(int connIndex) {
920
962
        switch (connIndex) {
921
 
            case ImmutableArcInst.TAILEND: return tailPortInst;
922
 
            case ImmutableArcInst.HEADEND: return headPortInst;
923
 
            default: throw new IllegalArgumentException("Bad end " + connIndex);
 
963
            case ImmutableArcInst.TAILEND:
 
964
                return tailPortInst;
 
965
            case ImmutableArcInst.HEADEND:
 
966
                return headPortInst;
 
967
            default:
 
968
                throw new IllegalArgumentException("Bad end " + connIndex);
924
969
        }
925
970
    }
926
971
 
927
 
        /**
928
 
         * Method to return the Location on tail of this ArcInst.
929
 
         * @return the Location on tail.
930
 
         */
931
 
        public EPoint getTailLocation() { return d.tailLocation; }
 
972
    /**
 
973
     * Method to return the Location on tail of this ArcInst.
 
974
     * @return the Location on tail.
 
975
     */
 
976
    public EPoint getTailLocation() {
 
977
        return d.tailLocation;
 
978
    }
932
979
 
933
 
        /**
934
 
         * Method to return the Location on head of this ArcInst.
935
 
         * @return the Location on head.
936
 
         */
937
 
        public EPoint getHeadLocation() { return d.headLocation; }
 
980
    /**
 
981
     * Method to return the Location on head of this ArcInst.
 
982
     * @return the Location on head.
 
983
     */
 
984
    public EPoint getHeadLocation() {
 
985
        return d.headLocation;
 
986
    }
938
987
 
939
988
    /**
940
989
     * Method to return the Location on an end of this ArcInst.
943
992
     */
944
993
    public EPoint getLocation(int connIndex) {
945
994
        switch (connIndex) {
946
 
            case ImmutableArcInst.TAILEND: return d.tailLocation;
947
 
            case ImmutableArcInst.HEADEND: return d.headLocation;
948
 
            default: throw new IllegalArgumentException("Bad end " + connIndex);
 
995
            case ImmutableArcInst.TAILEND:
 
996
                return d.tailLocation;
 
997
            case ImmutableArcInst.HEADEND:
 
998
                return d.headLocation;
 
999
            default:
 
1000
                throw new IllegalArgumentException("Bad end " + connIndex);
949
1001
        }
950
1002
    }
951
1003
 
952
 
        /**
953
 
         * Method to tell whether a tail connection on this ArcInst contains a port location.
954
 
         * @param pt the point in question.
955
 
         * @param reduceForArc if true reduce width by width offset of it proto.
956
 
         * @return true if the point is inside of the port.
957
 
         */
 
1004
    /**
 
1005
     * Method to tell whether a tail connection on this ArcInst contains a port location.
 
1006
     * @param pt the point in question.
 
1007
     * @param reduceForArc if true reduce width by width offset of it proto.
 
1008
     * @return true if the point is inside of the port.
 
1009
     */
958
1010
    public boolean tailStillInPort(Point2D pt, boolean reduceForArc) {
959
1011
        return stillInPort(ImmutableArcInst.TAILEND, pt, reduceForArc);
960
1012
    }
961
1013
 
962
 
        /**
963
 
         * Method to tell whether a head connection on this ArcInst contains a port location.
964
 
         * @param pt the point in question.
965
 
         * @param reduceForArc if true reduce width by width offset of it proto.
966
 
         * @return true if the point is inside of the port.
967
 
         */
 
1014
    /**
 
1015
     * Method to tell whether a head connection on this ArcInst contains a port location.
 
1016
     * @param pt the point in question.
 
1017
     * @param reduceForArc if true reduce width by width offset of it proto.
 
1018
     * @return true if the point is inside of the port.
 
1019
     */
968
1020
    public boolean headStillInPort(Point2D pt, boolean reduceForArc) {
969
1021
        return stillInPort(ImmutableArcInst.HEADEND, pt, reduceForArc);
970
1022
    }
971
1023
 
972
 
        /**
973
 
         * Method to tell whether a connection on this ArcInst contains a port location.
974
 
         * @param connIndex TAILEND (0) for the tail of this ArcInst, HEADEND (1) for the head.
975
 
         * @param pt the point in question.
976
 
         * @param reduceForArc if true reduce width by width offset of it proto.
977
 
         * @return true if the point is inside of the port.
978
 
         */
979
 
        public boolean stillInPort(int connIndex, Point2D pt, boolean reduceForArc)
980
 
        {
981
 
                // determine the area of the nodeinst
982
 
                PortInst pi = getPortInst(connIndex);
983
 
                Poly poly = pi.getPoly();
984
 
                if (reduceForArc)
985
 
                {
986
 
                        double wid = getLambdaBaseWidth();
987
 
                        poly.reducePortPoly(pi, wid, getAngle());
988
 
                }
 
1024
    /**
 
1025
     * Method to tell whether a connection on this ArcInst contains a port location.
 
1026
     * @param connIndex TAILEND (0) for the tail of this ArcInst, HEADEND (1) for the head.
 
1027
     * @param pt the point in question.
 
1028
     * @param reduceForArc if true reduce width by width offset of it proto.
 
1029
     * @return true if the point is inside of the port.
 
1030
     */
 
1031
    public boolean stillInPort(int connIndex, Point2D pt, boolean reduceForArc) {
 
1032
        // determine the area of the nodeinst
 
1033
        PortInst pi = getPortInst(connIndex);
 
1034
        Poly poly = pi.getPoly();
 
1035
        if (reduceForArc) {
 
1036
            double wid = getLambdaBaseWidth();
 
1037
            poly.reducePortPoly(pi, wid, getAngle());
 
1038
        }
989
1039
        return stillInPoly(pt, poly);
990
1040
//              if (poly.isInside(pt)) return true;
991
1041
//              if (poly.polyDistance(pt.getX(), pt.getY()) < MINPORTDISTANCE) return true;
992
1042
//
993
1043
//              // no good
994
1044
//              return false;
995
 
        }
 
1045
    }
996
1046
 
997
 
    private static boolean stillInPoly(Point2D pt, Poly poly) { return poly.isInside(pt) || poly.polyDistance(pt.getX(), pt.getY()) < MINPORTDISTANCE; }
 
1047
    private static boolean stillInPoly(Point2D pt, Poly poly) {
 
1048
        return poly.isInside(pt) || poly.polyDistance(pt.getX(), pt.getY()) < MINPORTDISTANCE;
 
1049
    }
998
1050
 
999
1051
    /****************************** TEXT ******************************/
1000
 
 
1001
 
        /**
1002
 
         * Method to return the name of this ArcInst.
1003
 
         * @return the name of this ArcInst.
1004
 
         */
1005
 
        public String getName() { return d.name.toString(); }
1006
 
 
1007
 
        /**
1008
 
         * Retruns true if this ArcInst was named by user.
1009
 
         * @return true if this ArcInst was named by user.
1010
 
         */
1011
 
        public boolean isUsernamed() { return d.isUsernamed();  }
1012
 
 
1013
 
        /**
1014
 
         * Method to return the name key of this ArcInst.
1015
 
         * @return the name key of this ArcInst, null if there is no name.
1016
 
         */
1017
 
        public Name getNameKey() { return d.name; }
1018
 
 
1019
 
        /**
1020
 
         * Method to rename this ArcInst.
1021
 
         * This ArcInst must be linked to database.
1022
 
         * @param name new name of this geometric.
1023
 
         * @return true on error
1024
 
         */
1025
 
        public boolean setName(String name)
1026
 
        {
1027
 
                assert isLinked();
1028
 
                Name key;
1029
 
                boolean doSmart = false;
1030
 
                if (name != null && name.length() > 0)
1031
 
                {
1032
 
                        if (name.equals(getName())) return false;
1033
 
                        if (!isUsernamed()) doSmart = true;
1034
 
                        key = Name.findName(name);
1035
 
                } else
1036
 
                {
1037
 
                        if (!isUsernamed()) return false;
1038
 
                        key = topology.getArcAutoname();
1039
 
                }
1040
 
                if (checkNameKey(key, topology)) return true;
 
1052
    /**
 
1053
     * Method to return the name of this ArcInst.
 
1054
     * @return the name of this ArcInst.
 
1055
     */
 
1056
    public String getName() {
 
1057
        return d.name.toString();
 
1058
    }
 
1059
 
 
1060
    /**
 
1061
     * Retruns true if this ArcInst was named by user.
 
1062
     * @return true if this ArcInst was named by user.
 
1063
     */
 
1064
    public boolean isUsernamed() {
 
1065
        return d.isUsernamed();
 
1066
    }
 
1067
 
 
1068
    /**
 
1069
     * Method to return the name key of this ArcInst.
 
1070
     * @return the name key of this ArcInst, null if there is no name.
 
1071
     */
 
1072
    public Name getNameKey() {
 
1073
        return d.name;
 
1074
    }
 
1075
 
 
1076
    /**
 
1077
     * Method to rename this ArcInst.
 
1078
     * This ArcInst must be linked to database.
 
1079
     * @param name new name of this geometric.
 
1080
     * @return true on error
 
1081
     */
 
1082
    public boolean setName(String name) {
 
1083
        assert isLinked();
 
1084
        Name key;
 
1085
        boolean doSmart = false;
 
1086
        if (name != null && name.length() > 0) {
 
1087
            if (name.equals(getName())) {
 
1088
                return false;
 
1089
            }
 
1090
            if (!isUsernamed()) {
 
1091
                doSmart = true;
 
1092
            }
 
1093
            key = Name.findName(name);
 
1094
        } else {
 
1095
            if (!isUsernamed()) {
 
1096
                return false;
 
1097
            }
 
1098
            key = topology.getArcAutoname();
 
1099
        }
 
1100
        if (checkNameKey(key, topology) || key.isBus() && getProto() != Schematics.tech().bus_arc) {
 
1101
            return true;
 
1102
        }
1041
1103
        ImmutableArcInst oldD = d;
1042
1104
        lowLevelModify(d.withName(key));
1043
 
        if (doSmart)
1044
 
        {
1045
 
                TextDescriptor td = TextDescriptor.getArcTextDescriptor();
1046
 
                TextDescriptor smartDescriptor = getSmartTextDescriptor(getAngle(), getLambdaBaseWidth(), td, getEditingPreferences());
1047
 
                setTextDescriptor(ARC_NAME, smartDescriptor);
 
1105
        if (doSmart) {
 
1106
            TextDescriptor td = TextDescriptor.getArcTextDescriptor();
 
1107
            TextDescriptor smartDescriptor = getSmartTextDescriptor(getAngle(), getLambdaBaseWidth(), td, getEditingPreferences());
 
1108
            setTextDescriptor(ARC_NAME, smartDescriptor);
1048
1109
        }
1049
1110
 
1050
1111
        // apply constraints
1051
1112
        Constraints.getCurrent().modifyArcInst(this, oldD);
1052
 
                return false;
1053
 
        }
1054
 
 
1055
 
        /**
1056
 
         * Method to return a "smart" text descriptor for an arc.
1057
 
         * @param angle the angle of the arc (in tenths of a degree).
1058
 
         * @param width the width of the arc.
1059
 
         * @param prev the former text descriptor of the arc.
1060
 
         * @return a new text descriptor that handles smart placement.
1061
 
         */
1062
 
        private static TextDescriptor getSmartTextDescriptor(int angle, double width, TextDescriptor prev, EditingPreferences ep)
1063
 
        {
1064
 
                // assigning valid name: do smart text placement
1065
 
                if ((angle%1800) == 0)
1066
 
                {
1067
 
                        // horizontal arc
1068
 
                        int smart = ep.smartHorizontalPlacementArc;
1069
 
                        if (smart == 1)
1070
 
                        {
1071
 
                                // arc text above
1072
 
                                return prev.withPos(TextDescriptor.Position.UP).withOff(0, width/2);
1073
 
                        } else if (smart == 2)
1074
 
                        {
1075
 
                                // arc text below
1076
 
                                return prev.withPos(TextDescriptor.Position.DOWN).withOff(0, -width/2);
1077
 
                        }
1078
 
                } else if ((angle%1800) == 900)
1079
 
                {
1080
 
                        // vertical arc
1081
 
                        int smart = ep.smartVerticalPlacementArc;
1082
 
                        if (smart == 1)
1083
 
                        {
1084
 
                                // arc text to the left
1085
 
                                return prev.withPos(TextDescriptor.Position.LEFT).withOff(-width/2, 0);
1086
 
                        } else if (smart == 2)
1087
 
                        {
1088
 
                                // arc text to the right
1089
 
                                return prev.withPos(TextDescriptor.Position.RIGHT).withOff(width/2, 0);
1090
 
                        }
1091
 
                }
1092
 
                return prev;
1093
 
        }
1094
 
 
1095
 
        /**
1096
 
         * Method to check the new name key of an ArcInst.
1097
 
         * @param name new name key of this ArcInst.
 
1113
        return false;
 
1114
    }
 
1115
 
 
1116
    /**
 
1117
     * Method to return a "smart" text descriptor for an arc.
 
1118
     * @param angle the angle of the arc (in tenths of a degree).
 
1119
     * @param width the width of the arc.
 
1120
     * @param prev the former text descriptor of the arc.
 
1121
     * @return a new text descriptor that handles smart placement.
 
1122
     */
 
1123
    private static TextDescriptor getSmartTextDescriptor(int angle, double width, TextDescriptor prev, EditingPreferences ep) {
 
1124
        // assigning valid name: do smart text placement
 
1125
        if ((angle % 1800) == 0) {
 
1126
            // horizontal arc
 
1127
            int smart = ep.smartHorizontalPlacementArc;
 
1128
            if (smart == 1) {
 
1129
                // arc text above
 
1130
                return prev.withPos(TextDescriptor.Position.UP).withOff(0, width / 2);
 
1131
            } else if (smart == 2) {
 
1132
                // arc text below
 
1133
                return prev.withPos(TextDescriptor.Position.DOWN).withOff(0, -width / 2);
 
1134
            }
 
1135
        } else if ((angle % 1800) == 900) {
 
1136
            // vertical arc
 
1137
            int smart = ep.smartVerticalPlacementArc;
 
1138
            if (smart == 1) {
 
1139
                // arc text to the left
 
1140
                return prev.withPos(TextDescriptor.Position.LEFT).withOff(-width / 2, 0);
 
1141
            } else if (smart == 2) {
 
1142
                // arc text to the right
 
1143
                return prev.withPos(TextDescriptor.Position.RIGHT).withOff(width / 2, 0);
 
1144
            }
 
1145
        }
 
1146
        return prev;
 
1147
    }
 
1148
 
 
1149
    /**
 
1150
     * Method to check the new name key of an ArcInst.
 
1151
     * @param name new name key of this ArcInst.
1098
1152
     * @param parent parent Cell used for error message
1099
 
         * @return true on error.
1100
 
         */
1101
 
        private static boolean checkNameKey(Name name, Topology topology)
1102
 
        {
 
1153
     * @return true on error.
 
1154
     */
 
1155
    private static boolean checkNameKey(Name name, Topology topology) {
1103
1156
        Cell parent = topology.cell;
1104
 
                if (!name.isValid())
1105
 
                {
1106
 
                        System.out.println(parent + ": Invalid name \""+name+"\" wasn't assigned to arc" + " :" + Name.checkName(name.toString()));
1107
 
                        return true;
1108
 
                }
1109
 
                if (name.isTempname() && name.getBasename() != ImmutableArcInst.BASENAME)
1110
 
                {
1111
 
                        System.out.println(parent + ": Temporary arc name \""+name+"\" must have prefix net@");
1112
 
                        return true;
1113
 
                }
1114
 
                if (name.hasEmptySubnames())
1115
 
                {
1116
 
                        if (name.isBus())
1117
 
                                System.out.println(parent + ": Name \""+name+"\" with empty subnames wasn't assigned to arc");
1118
 
                        else
1119
 
                                System.out.println(parent + ": Cannot assign empty name \""+name+"\" to arc");
1120
 
                        return true;
1121
 
                }
1122
 
                if (topology.hasTempArcName(name))
1123
 
                {
1124
 
                        System.out.println(parent + " already has ArcInst with temporary name \""+name+"\"");
1125
 
                        return true;
1126
 
                }
1127
 
                return false;
1128
 
        }
1129
 
 
1130
 
        /**
1131
 
         * Returns the TextDescriptor on this ArcInst selected by variable key.
1132
 
         * This key may be a key of variable on this ArcInst or the
1133
 
         * special keys:
1134
 
         * <code>ArcInst.ARC_NAME</code>
1135
 
         * The TextDescriptor gives information for displaying the Variable.
1136
 
         * @param varKey key of variable or special key.
1137
 
         * @return the TextDescriptor on this ArcInst.
1138
 
         */
1139
 
        public TextDescriptor getTextDescriptor(Variable.Key varKey)
1140
 
        {
1141
 
                if (varKey == ARC_NAME) return d.nameDescriptor;
1142
 
                return super.getTextDescriptor(varKey);
1143
 
        }
1144
 
 
1145
 
        /**
1146
 
         * Updates the TextDescriptor on this ArcInst selected by varKey.
1147
 
         * The varKey may be a key of variable on this ArcInst or
 
1157
        if (!name.isValid()) {
 
1158
            System.out.println(parent + ": Invalid name \"" + name + "\" wasn't assigned to arc" + " :" + Name.checkName(name.toString()));
 
1159
            return true;
 
1160
        }
 
1161
        if (name.isBus()) {
 
1162
            if (name.isTempname()) {
 
1163
                System.out.println(parent + ": Temporary name \"" + name + "\" can't be bus");
 
1164
                return true;
 
1165
            }
 
1166
            if (!parent.busNamesAllowed()) {
 
1167
                System.out.println(parent + ": Bus name \"" + name + "\" can be in icons and schematics only");
 
1168
                return true;
 
1169
            }
 
1170
        }
 
1171
        if (name.isTempname() && name.getBasename() != ImmutableArcInst.BASENAME) {
 
1172
            System.out.println(parent + ": Temporary arc name \"" + name + "\" must have prefix net@");
 
1173
            return true;
 
1174
        }
 
1175
        if (name.hasEmptySubnames()) {
 
1176
            if (name.isBus()) {
 
1177
                System.out.println(parent + ": Name \"" + name + "\" with empty subnames wasn't assigned to arc");
 
1178
            } else {
 
1179
                System.out.println(parent + ": Cannot assign empty name \"" + name + "\" to arc");
 
1180
            }
 
1181
            return true;
 
1182
        }
 
1183
        if (topology.hasTempArcName(name)) {
 
1184
            System.out.println(parent + " already has ArcInst with temporary name \"" + name + "\"");
 
1185
            return true;
 
1186
        }
 
1187
        return false;
 
1188
    }
 
1189
 
 
1190
    /**
 
1191
     * Returns the TextDescriptor on this ArcInst selected by variable key.
 
1192
     * This key may be a key of variable on this ArcInst or the
 
1193
     * special keys:
 
1194
     * <code>ArcInst.ARC_NAME</code>
 
1195
     * The TextDescriptor gives information for displaying the Variable.
 
1196
     * @param varKey key of variable or special key.
 
1197
     * @return the TextDescriptor on this ArcInst.
 
1198
     */
 
1199
    public TextDescriptor getTextDescriptor(Variable.Key varKey) {
 
1200
        if (varKey == ARC_NAME) {
 
1201
            return d.nameDescriptor;
 
1202
        }
 
1203
        return super.getTextDescriptor(varKey);
 
1204
    }
 
1205
 
 
1206
    /**
 
1207
     * Updates the TextDescriptor on this ArcInst selected by varKey.
 
1208
     * The varKey may be a key of variable on this ArcInst or
1148
1209
     * the special key ArcInst.ARC_NAME.
1149
 
         * If varKey doesn't select any text descriptor, no action is performed.
1150
 
         * The TextDescriptor gives information for displaying the Variable.
1151
 
         * @param varKey key of variable or special key.
1152
 
         * @param td new value TextDescriptor
1153
 
         */
 
1210
     * If varKey doesn't select any text descriptor, no action is performed.
 
1211
     * The TextDescriptor gives information for displaying the Variable.
 
1212
     * @param varKey key of variable or special key.
 
1213
     * @param td new value TextDescriptor
 
1214
     */
1154
1215
    @Override
1155
 
        public void setTextDescriptor(Variable.Key varKey, TextDescriptor td)
1156
 
        {
 
1216
    public void setTextDescriptor(Variable.Key varKey, TextDescriptor td) {
1157
1217
        if (varKey == ARC_NAME) {
1158
 
                        setD(d.withNameDescriptor(td), true);
 
1218
            setD(d.withNameDescriptor(td), true);
1159
1219
            return;
1160
1220
        }
1161
1221
        super.setTextDescriptor(varKey, td);
1162
1222
    }
1163
1223
 
1164
 
        /**
1165
 
         * Method to determine whether a variable key on ArcInst is deprecated.
1166
 
         * Deprecated variable keys are those that were used in old versions of Electric,
1167
 
         * but are no longer valid.
1168
 
         * @param key the key of the variable.
1169
 
         * @return true if the variable key is deprecated.
1170
 
         */
1171
 
        public boolean isDeprecatedVariable(Variable.Key key)
1172
 
        {
1173
 
                if (key == ARC_NAME) return true;
1174
 
                return super.isDeprecatedVariable(key);
1175
 
        }
 
1224
    /**
 
1225
     * Method to determine whether a variable key on ArcInst is deprecated.
 
1226
     * Deprecated variable keys are those that were used in old versions of Electric,
 
1227
     * but are no longer valid.
 
1228
     * @param key the key of the variable.
 
1229
     * @return true if the variable key is deprecated.
 
1230
     */
 
1231
    public boolean isDeprecatedVariable(Variable.Key key) {
 
1232
        if (key == ARC_NAME) {
 
1233
            return true;
 
1234
        }
 
1235
        return super.isDeprecatedVariable(key);
 
1236
    }
1176
1237
 
1177
 
        /**
1178
 
         * Method to describe this ArcInst as a string.
 
1238
    /**
 
1239
     * Method to describe this ArcInst as a string.
1179
1240
     * @param withQuotes to wrap description between quotes
1180
 
         * @return a description of this ArcInst.
1181
 
         */
1182
 
        public String describe(boolean withQuotes)
1183
 
        {
1184
 
                String description = getProto().describe();
1185
 
                String name = (withQuotes) ? "'"+getName()+"'" : getName();
1186
 
                if (name != null) description += "[" + name + "]";
1187
 
                return description;
1188
 
        }
 
1241
     * @return a description of this ArcInst.
 
1242
     */
 
1243
    public String describe(boolean withQuotes) {
 
1244
        String description = getProto().describe();
 
1245
        String name = (withQuotes) ? "'" + getName() + "'" : getName();
 
1246
        if (name != null) {
 
1247
            description += "[" + name + "]";
 
1248
        }
 
1249
        return description;
 
1250
    }
1189
1251
 
1190
1252
    /**
1191
1253
     * Compares ArcInsts by their Cells and names.
1192
1254
     * @param that the other ArcInst.
1193
1255
     * @return a comparison between the ArcInsts.
1194
1256
     */
1195
 
        public int compareTo(ArcInst that)
1196
 
        {
1197
 
                int cmp;
1198
 
                if (this.parent != that.parent)
1199
 
                {
1200
 
                        cmp = this.parent.compareTo(that.parent);
1201
 
                        if (cmp != 0) return cmp;
1202
 
                }
1203
 
                cmp = this.getName().compareTo(that.getName());
1204
 
                if (cmp != 0) return cmp;
1205
 
                return this.d.arcId - that.d.arcId;
1206
 
        }
 
1257
    public int compareTo(ArcInst that) {
 
1258
        int cmp;
 
1259
        if (this.topology != that.topology) {
 
1260
            cmp = this.topology.cell.compareTo(that.topology.cell);
 
1261
            if (cmp != 0) {
 
1262
                return cmp;
 
1263
            }
 
1264
        }
 
1265
        cmp = this.getName().compareTo(that.getName());
 
1266
        if (cmp != 0) {
 
1267
            return cmp;
 
1268
        }
 
1269
        return this.d.arcId - that.d.arcId;
 
1270
    }
1207
1271
 
1208
 
        /**
1209
 
         * Returns a printable version of this ArcInst.
1210
 
         * @return a printable version of this ArcInst.
1211
 
         */
1212
 
        public String toString()
1213
 
        {
 
1272
    /**
 
1273
     * Returns a printable version of this ArcInst.
 
1274
     * @return a printable version of this ArcInst.
 
1275
     */
 
1276
    public String toString() {
1214
1277
        return "arc " + describe(true);
1215
 
        }
1216
 
 
1217
 
        /****************************** CONSTRAINTS ******************************/
1218
 
 
 
1278
    }
 
1279
 
 
1280
    /****************************** CONSTRAINTS ******************************/
1219
1281
    private void setFlag(ImmutableArcInst.Flag flag, boolean state) {
1220
1282
        checkChanging();
1221
 
        if (setD(d.withFlag(flag, state), true))
1222
 
            redoGeometric();
1223
 
    }
1224
 
 
1225
 
        /**
1226
 
         * Method to set this ArcInst to be rigid.
1227
 
         * Rigid arcs cannot change length or the angle of their connection to a NodeInst.
1228
 
     * @param state
1229
 
     */
1230
 
        public void setRigid(boolean state) { setFlag(ImmutableArcInst.RIGID, state); }
1231
 
 
1232
 
        /**
1233
 
         * Method to tell whether this ArcInst is rigid.
1234
 
         * Rigid arcs cannot change length or the angle of their connection to a NodeInst.
1235
 
         * @return true if this ArcInst is rigid.
1236
 
         */
1237
 
        public boolean isRigid() { return d.isRigid(); }
1238
 
 
1239
 
        /**
1240
 
         * Method to set this ArcInst to be fixed-angle.
1241
 
         * Fixed-angle arcs cannot change their angle, so if one end moves,
1242
 
         * the other may also adjust to keep the arc angle constant.
1243
 
     * @param state
1244
 
     */
1245
 
        public void setFixedAngle(boolean state) { setFlag(ImmutableArcInst.FIXED_ANGLE, state); }
1246
 
 
1247
 
        /**
1248
 
         * Method to tell whether this ArcInst is fixed-angle.
1249
 
         * Fixed-angle arcs cannot change their angle, so if one end moves,
1250
 
         * the other may also adjust to keep the arc angle constant.
1251
 
         * @return true if this ArcInst is fixed-angle.
1252
 
         */
1253
 
        public boolean isFixedAngle() { return d.isFixedAngle(); }
1254
 
 
1255
 
        /**
1256
 
         * Method to set this ArcInst to be slidable.
1257
 
         * Arcs that slide will not move their connected NodeInsts if the arc's end is still within the port area.
1258
 
         * Arcs that cannot slide will force their NodeInsts to move by the same amount as the arc.
1259
 
         * Rigid arcs cannot slide but nonrigid arcs use this state to make a decision.
1260
 
     * @param state
1261
 
     */
1262
 
        public void setSlidable(boolean state) { setFlag(ImmutableArcInst.SLIDABLE, state); }
1263
 
 
1264
 
        /**
1265
 
         * Method to tell whether this ArcInst is slidable.
1266
 
         * Arcs that slide will not move their connected NodeInsts if the arc's end is still within the port area.
1267
 
         * Arcs that cannot slide will force their NodeInsts to move by the same amount as the arc.
1268
 
         * Rigid arcs cannot slide but nonrigid arcs use this state to make a decision.
1269
 
         * @return true if this ArcInst is slidable.
1270
 
         */
1271
 
        public boolean isSlidable() { return d.isSlidable(); }
1272
 
 
1273
 
        /****************************** PROPERTIES ******************************/
1274
 
 
1275
 
        /**
1276
 
         * Method to determine whether this ArcInst is directional, with an arrow on one end.
1277
 
         * Directional arcs have an arrow drawn on them to indicate flow.
1278
 
         * It is only for documentation purposes and does not affect the circuit.
1279
 
         * @param connIndex TAILEND (0) for the tail of this ArcInst, HEADEND (1) for the head.
1280
 
         * @return true if that end has a directional arrow on it.
1281
 
     */
1282
 
        public boolean isArrowed(int connIndex) { return d.isArrowed(connIndex); }
1283
 
 
1284
 
        /**
1285
 
         * Method to determine whether this ArcInst is directional, with an arrow on the tail.
1286
 
         * Directional arcs have an arrow drawn on them to indicate flow.
1287
 
         * It is only for documentation purposes and does not affect the circuit.
1288
 
         * @return true if the arc's tail has a directional arrow on it.
1289
 
     */
1290
 
        public boolean isTailArrowed() { return d.isTailArrowed(); }
1291
 
 
1292
 
        /**
1293
 
         * Method to determine whether this ArcInst is directional, with an arrow on the head.
1294
 
         * Directional arcs have an arrow drawn on them to indicate flow.
1295
 
         * It is only for documentation purposes and does not affect the circuit.
1296
 
         * @return true if the arc's head has a directional arrow on it.
1297
 
     */
1298
 
        public boolean isHeadArrowed() { return d.isHeadArrowed(); }
1299
 
 
1300
 
        /**
1301
 
         * Method to determine whether this ArcInst is directional, with an arrow line drawn down the center.
1302
 
         * Directional arcs have an arrow drawn on them to indicate flow.
1303
 
         * It is only for documentation purposes and does not affect the circuit.
1304
 
         * The body is typically drawn when one of the ends has an arrow on it, but it may be
1305
 
         * drawin without an arrow head in order to continue an attached arc that has an arrow.
1306
 
         * @return true if the arc's tail has an arrow line on it.
1307
 
     */
1308
 
        public boolean isBodyArrowed() { return d.isBodyArrowed(); }
1309
 
 
1310
 
        /**
1311
 
         * Method to set this ArcInst to be directional, with an arrow on one end.
1312
 
         * Directional arcs have an arrow drawn on them to indicate flow.
1313
 
         * It is only for documentation purposes and does not affect the circuit.
1314
 
         * @param connIndex TAILEND (0) for the tail of this ArcInst, HEADEND (1) for the head.
 
1283
        if (setD(d.withFlag(flag, state), true)) {
 
1284
            topology.setArcsDirty();
 
1285
        }
 
1286
    }
 
1287
 
 
1288
    /**
 
1289
     * Method to set this ArcInst to be rigid.
 
1290
     * Rigid arcs cannot change length or the angle of their connection to a NodeInst.
 
1291
     * @param state
 
1292
     */
 
1293
    public void setRigid(boolean state) {
 
1294
        setFlag(ImmutableArcInst.RIGID, state);
 
1295
    }
 
1296
 
 
1297
    /**
 
1298
     * Method to tell whether this ArcInst is rigid.
 
1299
     * Rigid arcs cannot change length or the angle of their connection to a NodeInst.
 
1300
     * @return true if this ArcInst is rigid.
 
1301
     */
 
1302
    public boolean isRigid() {
 
1303
        return d.isRigid();
 
1304
    }
 
1305
 
 
1306
    /**
 
1307
     * Method to set this ArcInst to be fixed-angle.
 
1308
     * Fixed-angle arcs cannot change their angle, so if one end moves,
 
1309
     * the other may also adjust to keep the arc angle constant.
 
1310
     * @param state
 
1311
     */
 
1312
    public void setFixedAngle(boolean state) {
 
1313
        setFlag(ImmutableArcInst.FIXED_ANGLE, state);
 
1314
    }
 
1315
 
 
1316
    /**
 
1317
     * Method to tell whether this ArcInst is fixed-angle.
 
1318
     * Fixed-angle arcs cannot change their angle, so if one end moves,
 
1319
     * the other may also adjust to keep the arc angle constant.
 
1320
     * @return true if this ArcInst is fixed-angle.
 
1321
     */
 
1322
    public boolean isFixedAngle() {
 
1323
        return d.isFixedAngle();
 
1324
    }
 
1325
 
 
1326
    /**
 
1327
     * Method to set this ArcInst to be slidable.
 
1328
     * Arcs that slide will not move their connected NodeInsts if the arc's end is still within the port area.
 
1329
     * Arcs that cannot slide will force their NodeInsts to move by the same amount as the arc.
 
1330
     * Rigid arcs cannot slide but nonrigid arcs use this state to make a decision.
 
1331
     * @param state
 
1332
     */
 
1333
    public void setSlidable(boolean state) {
 
1334
        setFlag(ImmutableArcInst.SLIDABLE, state);
 
1335
    }
 
1336
 
 
1337
    /**
 
1338
     * Method to tell whether this ArcInst is slidable.
 
1339
     * Arcs that slide will not move their connected NodeInsts if the arc's end is still within the port area.
 
1340
     * Arcs that cannot slide will force their NodeInsts to move by the same amount as the arc.
 
1341
     * Rigid arcs cannot slide but nonrigid arcs use this state to make a decision.
 
1342
     * @return true if this ArcInst is slidable.
 
1343
     */
 
1344
    public boolean isSlidable() {
 
1345
        return d.isSlidable();
 
1346
    }
 
1347
 
 
1348
    /****************************** PROPERTIES ******************************/
 
1349
    /**
 
1350
     * Method to determine whether this ArcInst is directional, with an arrow on one end.
 
1351
     * Directional arcs have an arrow drawn on them to indicate flow.
 
1352
     * It is only for documentation purposes and does not affect the circuit.
 
1353
     * @param connIndex TAILEND (0) for the tail of this ArcInst, HEADEND (1) for the head.
 
1354
     * @return true if that end has a directional arrow on it.
 
1355
     */
 
1356
    public boolean isArrowed(int connIndex) {
 
1357
        return d.isArrowed(connIndex);
 
1358
    }
 
1359
 
 
1360
    /**
 
1361
     * Method to determine whether this ArcInst is directional, with an arrow on the tail.
 
1362
     * Directional arcs have an arrow drawn on them to indicate flow.
 
1363
     * It is only for documentation purposes and does not affect the circuit.
 
1364
     * @return true if the arc's tail has a directional arrow on it.
 
1365
     */
 
1366
    public boolean isTailArrowed() {
 
1367
        return d.isTailArrowed();
 
1368
    }
 
1369
 
 
1370
    /**
 
1371
     * Method to determine whether this ArcInst is directional, with an arrow on the head.
 
1372
     * Directional arcs have an arrow drawn on them to indicate flow.
 
1373
     * It is only for documentation purposes and does not affect the circuit.
 
1374
     * @return true if the arc's head has a directional arrow on it.
 
1375
     */
 
1376
    public boolean isHeadArrowed() {
 
1377
        return d.isHeadArrowed();
 
1378
    }
 
1379
 
 
1380
    /**
 
1381
     * Method to determine whether this ArcInst is directional, with an arrow line drawn down the center.
 
1382
     * Directional arcs have an arrow drawn on them to indicate flow.
 
1383
     * It is only for documentation purposes and does not affect the circuit.
 
1384
     * The body is typically drawn when one of the ends has an arrow on it, but it may be
 
1385
     * drawin without an arrow head in order to continue an attached arc that has an arrow.
 
1386
     * @return true if the arc's tail has an arrow line on it.
 
1387
     */
 
1388
    public boolean isBodyArrowed() {
 
1389
        return d.isBodyArrowed();
 
1390
    }
 
1391
 
 
1392
    /**
 
1393
     * Method to set this ArcInst to be directional, with an arrow on one end.
 
1394
     * Directional arcs have an arrow drawn on them to indicate flow.
 
1395
     * It is only for documentation purposes and does not affect the circuit.
 
1396
     * @param connIndex TAILEND (0) for the tail of this ArcInst, HEADEND (1) for the head.
1315
1397
     * @param state true to show a directional arrow on the specified end.
1316
1398
     */
1317
1399
    public void setArrowed(int connIndex, boolean state) {
1318
1400
        switch (connIndex) {
1319
 
            case ImmutableArcInst.TAILEND: setTailArrowed(state); break;
1320
 
            case ImmutableArcInst.HEADEND: setHeadArrowed(state); break;
1321
 
            default: throw new IllegalArgumentException("Bad end " + connIndex);
 
1401
            case ImmutableArcInst.TAILEND:
 
1402
                setTailArrowed(state);
 
1403
                break;
 
1404
            case ImmutableArcInst.HEADEND:
 
1405
                setHeadArrowed(state);
 
1406
                break;
 
1407
            default:
 
1408
                throw new IllegalArgumentException("Bad end " + connIndex);
1322
1409
        }
1323
1410
    }
1324
1411
 
1325
 
        /**
1326
 
         * Method to set this ArcInst to be directional, with an arrow on the tail.
1327
 
         * Directional arcs have an arrow drawn on them to indicate flow.
1328
 
         * It is only for documentation purposes and does not affect the circuit.
 
1412
    /**
 
1413
     * Method to set this ArcInst to be directional, with an arrow on the tail.
 
1414
     * Directional arcs have an arrow drawn on them to indicate flow.
 
1415
     * It is only for documentation purposes and does not affect the circuit.
1329
1416
     * @param state true to show a directional arrow on the tail.
1330
1417
     */
1331
 
        public void setTailArrowed(boolean state) { setFlag(ImmutableArcInst.TAIL_ARROWED, state); }
 
1418
    public void setTailArrowed(boolean state) {
 
1419
        setFlag(ImmutableArcInst.TAIL_ARROWED, state);
 
1420
    }
1332
1421
 
1333
 
        /**
1334
 
         * Method to set this ArcInst to be directional, with an arrow on the head.
1335
 
         * Directional arcs have an arrow drawn on them to indicate flow.
1336
 
         * It is only for documentation purposes and does not affect the circuit.
 
1422
    /**
 
1423
     * Method to set this ArcInst to be directional, with an arrow on the head.
 
1424
     * Directional arcs have an arrow drawn on them to indicate flow.
 
1425
     * It is only for documentation purposes and does not affect the circuit.
1337
1426
     * @param state true to show a directional arrow on the head.
1338
1427
     */
1339
 
        public void setHeadArrowed(boolean state) { setFlag(ImmutableArcInst.HEAD_ARROWED, state); }
 
1428
    public void setHeadArrowed(boolean state) {
 
1429
        setFlag(ImmutableArcInst.HEAD_ARROWED, state);
 
1430
    }
1340
1431
 
1341
 
        /**
1342
 
         * Method to set this ArcInst to be directional, with an arrow line drawn down the center.
1343
 
         * Directional arcs have an arrow drawn on them to indicate flow.
1344
 
         * It is only for documentation purposes and does not affect the circuit.
1345
 
         * The body is typically drawn when one of the ends has an arrow on it, but it may be
1346
 
         * drawin without an arrow head in order to continue an attached arc that has an arrow.
 
1432
    /**
 
1433
     * Method to set this ArcInst to be directional, with an arrow line drawn down the center.
 
1434
     * Directional arcs have an arrow drawn on them to indicate flow.
 
1435
     * It is only for documentation purposes and does not affect the circuit.
 
1436
     * The body is typically drawn when one of the ends has an arrow on it, but it may be
 
1437
     * drawin without an arrow head in order to continue an attached arc that has an arrow.
1347
1438
     * @param state true to show a directional line on this arc.
1348
1439
     */
1349
 
        public void setBodyArrowed(boolean state) { setFlag(ImmutableArcInst.BODY_ARROWED, state); }
1350
 
 
1351
 
        /**
1352
 
         * Method to tell whether an end of ArcInst has its ends extended.
1353
 
         * Extended arcs continue past their endpoint by half of their width.
1354
 
         * Most layout arcs want this so that they make clean connections to orthogonal arcs.
1355
 
         * @param connIndex TAILEND (0) for the tail of this ArcInst, HEADEND (1) for the head.
1356
 
         * @return true if that end of this ArcInst iss extended.
1357
 
         */
1358
 
        public boolean isExtended(int connIndex) { return d.isExtended(connIndex); }
1359
 
 
1360
 
        /**
1361
 
         * Method to tell whether the tail of this arc is extended.
1362
 
         * Extended arcs continue past their endpoint by half of their width.
1363
 
         * Most layout arcs want this so that they make clean connections to orthogonal arcs.
1364
 
         * @return true if the tail of this arc is extended.
1365
 
         */
1366
 
        public boolean isTailExtended() { return d.isTailExtended(); }
1367
 
 
1368
 
        /**
1369
 
         * Method to tell whether the head of this arc is extended.
1370
 
         * Extended arcs continue past their endpoint by half of their width.
1371
 
         * Most layout arcs want this so that they make clean connections to orthogonal arcs.
1372
 
         * @return true if the head of this arc is extended.
1373
 
         */
1374
 
        public boolean isHeadExtended() { return d.isHeadExtended(); }
1375
 
 
1376
 
        /**
1377
 
         * Method to set whether an end of this arc is extended.
1378
 
         * Extended arcs continue past their endpoint by half of their width.
1379
 
         * Most layout arcs want this so that they make clean connections to orthogonal arcs.
1380
 
         * @param connIndex TAILEND (0) for the tail of this ArcInst, HEADEND (1) for the head.
1381
 
         * @param e true to set that end of this arc to be extended.
1382
 
         */
 
1440
    public void setBodyArrowed(boolean state) {
 
1441
        setFlag(ImmutableArcInst.BODY_ARROWED, state);
 
1442
    }
 
1443
 
 
1444
    /**
 
1445
     * Method to tell whether an end of ArcInst has its ends extended.
 
1446
     * Extended arcs continue past their endpoint by half of their width.
 
1447
     * Most layout arcs want this so that they make clean connections to orthogonal arcs.
 
1448
     * @param connIndex TAILEND (0) for the tail of this ArcInst, HEADEND (1) for the head.
 
1449
     * @return true if that end of this ArcInst iss extended.
 
1450
     */
 
1451
    public boolean isExtended(int connIndex) {
 
1452
        return d.isExtended(connIndex);
 
1453
    }
 
1454
 
 
1455
    /**
 
1456
     * Method to tell whether the tail of this arc is extended.
 
1457
     * Extended arcs continue past their endpoint by half of their width.
 
1458
     * Most layout arcs want this so that they make clean connections to orthogonal arcs.
 
1459
     * @return true if the tail of this arc is extended.
 
1460
     */
 
1461
    public boolean isTailExtended() {
 
1462
        return d.isTailExtended();
 
1463
    }
 
1464
 
 
1465
    /**
 
1466
     * Method to tell whether the head of this arc is extended.
 
1467
     * Extended arcs continue past their endpoint by half of their width.
 
1468
     * Most layout arcs want this so that they make clean connections to orthogonal arcs.
 
1469
     * @return true if the head of this arc is extended.
 
1470
     */
 
1471
    public boolean isHeadExtended() {
 
1472
        return d.isHeadExtended();
 
1473
    }
 
1474
 
 
1475
    /**
 
1476
     * Method to set whether an end of this arc is extended.
 
1477
     * Extended arcs continue past their endpoint by half of their width.
 
1478
     * Most layout arcs want this so that they make clean connections to orthogonal arcs.
 
1479
     * @param connIndex TAILEND (0) for the tail of this ArcInst, HEADEND (1) for the head.
 
1480
     * @param e true to set that end of this arc to be extended.
 
1481
     */
1383
1482
    public void setExtended(int connIndex, boolean e) {
1384
1483
        switch (connIndex) {
1385
 
            case ImmutableArcInst.TAILEND: setTailExtended(e); break;
1386
 
            case ImmutableArcInst.HEADEND: setHeadExtended(e); break;
1387
 
            default: throw new IllegalArgumentException("Bad end " + connIndex);
 
1484
            case ImmutableArcInst.TAILEND:
 
1485
                setTailExtended(e);
 
1486
                break;
 
1487
            case ImmutableArcInst.HEADEND:
 
1488
                setHeadExtended(e);
 
1489
                break;
 
1490
            default:
 
1491
                throw new IllegalArgumentException("Bad end " + connIndex);
1388
1492
        }
1389
1493
    }
1390
1494
 
1391
 
        /**
1392
 
         * Method to set whether the tail of this arc is extended.
1393
 
         * Extended arcs continue past their endpoint by half of their width.
1394
 
         * Most layout arcs want this so that they make clean connections to orthogonal arcs.
1395
 
         * @param e true to set the tail of this arc to be extended.
1396
 
         */
1397
 
        public void setTailExtended(boolean e) {
 
1495
    /**
 
1496
     * Method to set whether the tail of this arc is extended.
 
1497
     * Extended arcs continue past their endpoint by half of their width.
 
1498
     * Most layout arcs want this so that they make clean connections to orthogonal arcs.
 
1499
     * @param e true to set the tail of this arc to be extended.
 
1500
     */
 
1501
    public void setTailExtended(boolean e) {
1398
1502
        setFlag(ImmutableArcInst.TAIL_EXTENDED, e);
1399
1503
//        if (isLinked()) updateGeometric();
1400
1504
    }
1401
1505
 
1402
 
        /**
1403
 
         * Method to set whether the head of this arc is extended.
1404
 
         * Extended arcs continue past their endpoint by half of their width.
1405
 
         * Most layout arcs want this so that they make clean connections to orthogonal arcs.
1406
 
         * @param e true to set the head of this arc to be extended.
1407
 
         */
1408
 
        public void setHeadExtended(boolean e) {
 
1506
    /**
 
1507
     * Method to set whether the head of this arc is extended.
 
1508
     * Extended arcs continue past their endpoint by half of their width.
 
1509
     * Most layout arcs want this so that they make clean connections to orthogonal arcs.
 
1510
     * @param e true to set the head of this arc to be extended.
 
1511
     */
 
1512
    public void setHeadExtended(boolean e) {
1409
1513
        setFlag(ImmutableArcInst.HEAD_EXTENDED, e);
1410
1514
//        if (isLinked()) updateGeometric();
1411
1515
    }
1412
1516
 
1413
 
        /**
1414
 
         * Method to tell whether an end of this arc is negated.
1415
 
         * Negated arc have a negating bubble on them to indicate negation.
1416
 
         * This is only valid in schematics technologies.
1417
 
         * @param connIndex TAILEND (0) for the tail of this ArcInst, HEADEND (1) for the head.
1418
 
         * @return true if set that end of this arc is negated.
1419
 
         */
1420
 
        public boolean isNegated(int connIndex) { return d.isNegated(connIndex); }
1421
 
 
1422
 
        /**
1423
 
         * Method to tell whether the tail of this arc is negated.
1424
 
         * Negated arc have a negating bubble on them to indicate negation.
1425
 
         * This is only valid in schematics technologies.
1426
 
         * @return true if set the tail of this arc is negated.
1427
 
         */
1428
 
        public boolean isTailNegated() { return d.isTailNegated(); }
1429
 
 
1430
 
        /**
1431
 
         * Method to tell whether the head of this arc is negated.
1432
 
         * Negated arc have a negating bubble on them to indicate negation.
1433
 
         * This is only valid in schematics technologies.
1434
 
         * @return true if set the head of this arc is negated.
1435
 
         */
1436
 
        public boolean isHeadNegated() { return d.isHeadNegated(); }
1437
 
 
1438
 
        /**
1439
 
         * Method to set whether an end of this arc is negated.
1440
 
         * Negated arc have a negating bubble on them to indicate negation.
1441
 
         * This is only valid in schematics technologies.
1442
 
         * @param connIndex TAILEND (0) for the tail of this ArcInst, HEADEND (1) for the head.
1443
 
         * @param n true to set that end of this arc to be negated.
1444
 
         */
 
1517
    /**
 
1518
     * Method to tell whether an end of this arc is negated.
 
1519
     * Negated arc have a negating bubble on them to indicate negation.
 
1520
     * This is only valid in schematics technologies.
 
1521
     * @param connIndex TAILEND (0) for the tail of this ArcInst, HEADEND (1) for the head.
 
1522
     * @return true if set that end of this arc is negated.
 
1523
     */
 
1524
    public boolean isNegated(int connIndex) {
 
1525
        return d.isNegated(connIndex);
 
1526
    }
 
1527
 
 
1528
    /**
 
1529
     * Method to tell whether the tail of this arc is negated.
 
1530
     * Negated arc have a negating bubble on them to indicate negation.
 
1531
     * This is only valid in schematics technologies.
 
1532
     * @return true if set the tail of this arc is negated.
 
1533
     */
 
1534
    public boolean isTailNegated() {
 
1535
        return d.isTailNegated();
 
1536
    }
 
1537
 
 
1538
    /**
 
1539
     * Method to tell whether the head of this arc is negated.
 
1540
     * Negated arc have a negating bubble on them to indicate negation.
 
1541
     * This is only valid in schematics technologies.
 
1542
     * @return true if set the head of this arc is negated.
 
1543
     */
 
1544
    public boolean isHeadNegated() {
 
1545
        return d.isHeadNegated();
 
1546
    }
 
1547
 
 
1548
    /**
 
1549
     * Method to set whether an end of this arc is negated.
 
1550
     * Negated arc have a negating bubble on them to indicate negation.
 
1551
     * This is only valid in schematics technologies.
 
1552
     * @param connIndex TAILEND (0) for the tail of this ArcInst, HEADEND (1) for the head.
 
1553
     * @param n true to set that end of this arc to be negated.
 
1554
     */
1445
1555
    public void setNegated(int connIndex, boolean n) {
1446
1556
        switch (connIndex) {
1447
 
            case ImmutableArcInst.TAILEND: setTailNegated(n); break;
1448
 
            case ImmutableArcInst.HEADEND: setHeadNegated(n); break;
1449
 
            default: throw new IllegalArgumentException("Bad end " + connIndex);
 
1557
            case ImmutableArcInst.TAILEND:
 
1558
                setTailNegated(n);
 
1559
                break;
 
1560
            case ImmutableArcInst.HEADEND:
 
1561
                setHeadNegated(n);
 
1562
                break;
 
1563
            default:
 
1564
                throw new IllegalArgumentException("Bad end " + connIndex);
1450
1565
        }
1451
1566
    }
1452
1567
 
1453
 
        /**
1454
 
         * Method to set whether the tail of this arc is negated.
1455
 
         * Negated arc have a negating bubble on them to indicate negation.
1456
 
         * This is only valid in schematics technologies.
1457
 
         * @param n true to set the tail of this arc to be negated.
1458
 
         */
1459
 
        public void setTailNegated(boolean n) {
1460
 
        if (!(d.tailPortId instanceof PrimitivePortId && getTechPool().getPrimitivePort((PrimitivePortId)d.tailPortId).isNegatable()))
1461
 
            n = false;
1462
 
        if (getProto().getTechnology().isNoNegatedArcs())
1463
 
            n = false;
 
1568
    /**
 
1569
     * Method to set whether the tail of this arc is negated.
 
1570
     * Negated arc have a negating bubble on them to indicate negation.
 
1571
     * This is only valid in schematics technologies.
 
1572
     * @param n true to set the tail of this arc to be negated.
 
1573
     */
 
1574
    public void setTailNegated(boolean n) {
 
1575
        if (!(d.tailPortId instanceof PrimitivePortId && getTechPool().getPrimitivePort((PrimitivePortId) d.tailPortId).isNegatable())) {
 
1576
            n = false;
 
1577
        }
 
1578
        if (getProto().getTechnology().isNoNegatedArcs()) {
 
1579
            n = false;
 
1580
        }
1464
1581
        setFlag(ImmutableArcInst.TAIL_NEGATED, n);
1465
 
        }
1466
 
 
1467
 
        /**
1468
 
         * Method to set whether the head of this arc is negated.
1469
 
         * Negated arc have a negating bubble on them to indicate negation.
1470
 
         * This is only valid in schematics technologies.
1471
 
         * @param n true to set the head of this arc to be negated.
1472
 
         */
1473
 
        public void setHeadNegated(boolean n) {
1474
 
        if (!(d.headPortId instanceof PrimitivePortId && getTechPool().getPrimitivePort((PrimitivePortId)d.headPortId).isNegatable()))
1475
 
            n = false;
1476
 
        if (getProto().getTechnology().isNoNegatedArcs())
1477
 
            n = false;
1478
 
        setFlag(ImmutableArcInst.HEAD_NEGATED,  n);
1479
 
        }
1480
 
 
1481
 
        /****************************** MISCELLANEOUS ******************************/
1482
 
 
1483
 
    /**
1484
 
         * Method to check and repair data structure errors in this ArcInst.
1485
 
         */
1486
 
        public int checkAndRepair(boolean repair, List<Geometric> list, ErrorLogger errorLogger)
1487
 
        {
1488
 
                int errorCount = 0;
 
1582
    }
 
1583
 
 
1584
    /**
 
1585
     * Method to set whether the head of this arc is negated.
 
1586
     * Negated arc have a negating bubble on them to indicate negation.
 
1587
     * This is only valid in schematics technologies.
 
1588
     * @param n true to set the head of this arc to be negated.
 
1589
     */
 
1590
    public void setHeadNegated(boolean n) {
 
1591
        if (!(d.headPortId instanceof PrimitivePortId && getTechPool().getPrimitivePort((PrimitivePortId) d.headPortId).isNegatable())) {
 
1592
            n = false;
 
1593
        }
 
1594
        if (getProto().getTechnology().isNoNegatedArcs()) {
 
1595
            n = false;
 
1596
        }
 
1597
        setFlag(ImmutableArcInst.HEAD_NEGATED, n);
 
1598
    }
 
1599
 
 
1600
    /****************************** MISCELLANEOUS ******************************/
 
1601
    /**
 
1602
     * Method to check and repair data structure errors in this ArcInst.
 
1603
     */
 
1604
    public int checkAndRepair(boolean repair, List<Geometric> list, ErrorLogger errorLogger) {
 
1605
        int errorCount = 0;
1489
1606
        ArcProto ap = getProto();
1490
1607
 
1491
 
        if (ap.isNotUsed())
1492
 
        {
 
1608
        Cell parent = topology.cell;
 
1609
        if (ap.isNotUsed()) {
1493
1610
//            if (repair)
1494
 
            if (errorLogger != null)
1495
 
            {
 
1611
            if (errorLogger != null) {
1496
1612
                String msg = "Prototype of arc " + getName() + " is unused";
1497
1613
                if (repair) {
1498
1614
                    // Can't put this arc into error logger because it will be deleted.
1502
1618
                    errorLogger.logError(msg, this, parent, null, 1);
1503
1619
                }
1504
1620
            }
1505
 
            if (repair) list.add(this);
 
1621
            if (repair) {
 
1622
                list.add(this);
 
1623
            }
1506
1624
            // This counts as 1 error, ignoring other errors
1507
1625
            return 1;
1508
1626
        }
1509
1627
 
1510
 
                // see if the ends are in their ports
1511
 
                if (!headStillInPort(d.headLocation, false))
1512
 
                {
1513
 
                        Poly poly = headPortInst.getPoly();
1514
 
                        String msg = parent + ", " + this +
1515
 
                                ": head not in port, is at (" + d.headLocation.getX() + "," + d.headLocation.getY() +
1516
 
                                ") distance to port is " + poly.polyDistance(d.headLocation.getX(), d.headLocation.getY()) +
1517
 
                                " port center is (" + poly.getCenterX() + "," + poly.getCenterY() + ")";
1518
 
                        System.out.println(msg);
1519
 
                        if (errorLogger != null)
1520
 
                        {
 
1628
        // see if the ends are in their ports
 
1629
        if (!headStillInPort(d.headLocation, false)) {
 
1630
            Poly poly = headPortInst.getPoly();
 
1631
            String msg = parent + ", " + this
 
1632
                    + ": head not in port, is at (" + d.headLocation.getX() + "," + d.headLocation.getY()
 
1633
                    + ") distance to port is " + poly.polyDistance(d.headLocation.getX(), d.headLocation.getY())
 
1634
                    + " port center is (" + poly.getCenterX() + "," + poly.getCenterY() + ")";
 
1635
            System.out.println(msg);
 
1636
            if (errorLogger != null) {
1521
1637
                List<Object> errorList = new ArrayList<Object>(2);
1522
1638
                errorList.add(headPortInst.getNodeInst());
1523
1639
                errorList.add(makeLambdaPoly(getGridBaseWidth(), Poly.Type.CLOSED));
1528
1644
                    geomList.add(this);
1529
1645
                    geomList.add(headPortInst.getNodeInst());
1530
1646
                    errorLogger.logMessage(msg, geomList, parent, 1, true);
1531
 
               }
1532
 
                        }
1533
 
                        if (repair)
1534
 
                        {
 
1647
                }
 
1648
            }
 
1649
            if (repair) {
1535
1650
                Constraints.getCurrent().modifyArcInst(this, getD());
1536
1651
//                              setD(d.withLocations(d.tailLocation, new EPoint(poly.getCenterX(), poly.getCenterY())), false);
1537
1652
//                              updateGeometric();
1538
 
                        }
1539
 
                        errorCount++;
1540
 
                }
1541
 
                if (!tailStillInPort(d.tailLocation, false))
1542
 
                {
1543
 
                        Poly poly = tailPortInst.getPoly();
1544
 
                        String msg = parent + ", " + this +
1545
 
                                ": tail not in port, is at (" + d.tailLocation.getX() + "," + d.tailLocation.getY() +
1546
 
                                ") distance to port is " + poly.polyDistance(d.tailLocation.getX(), d.tailLocation.getY()) +
1547
 
                                " port center is (" + poly.getCenterX() + "," + poly.getCenterY() + ")";
1548
 
                        System.out.println(msg);
1549
 
                        if (errorLogger != null)
1550
 
                        {
1551
 
                if (repair)
1552
 
                {
 
1653
            }
 
1654
            errorCount++;
 
1655
        }
 
1656
        if (!tailStillInPort(d.tailLocation, false)) {
 
1657
            Poly poly = tailPortInst.getPoly();
 
1658
            String msg = parent + ", " + this
 
1659
                    + ": tail not in port, is at (" + d.tailLocation.getX() + "," + d.tailLocation.getY()
 
1660
                    + ") distance to port is " + poly.polyDistance(d.tailLocation.getX(), d.tailLocation.getY())
 
1661
                    + " port center is (" + poly.getCenterX() + "," + poly.getCenterY() + ")";
 
1662
            System.out.println(msg);
 
1663
            if (errorLogger != null) {
 
1664
                if (repair) {
1553
1665
                    List<Object> errorList = new ArrayList<Object>(2);
1554
1666
                    errorList.add(tailPortInst.getNodeInst());
1555
1667
                    errorList.add(makeLambdaPoly(getGridBaseWidth(), Poly.Type.CLOSED));
1559
1671
                    geomList.add(this);
1560
1672
                    geomList.add(tailPortInst.getNodeInst());
1561
1673
                    errorLogger.logMessage(msg, geomList, parent, 1, true);
1562
 
               }
1563
 
                        }
1564
 
                        if (repair)
1565
 
                        {
 
1674
                }
 
1675
            }
 
1676
            if (repair) {
1566
1677
                Constraints.getCurrent().modifyArcInst(this, getD());
1567
1678
//                              setD(d.withLocations(new EPoint(poly.getCenterX(), poly.getCenterY()), d.headLocation), false);
1568
1679
//                              updateGeometric();
1569
 
                        }
1570
 
                        errorCount++;
1571
 
                }
1572
 
                return errorCount;
1573
 
        }
 
1680
            }
 
1681
            errorCount++;
 
1682
        }
 
1683
        return errorCount;
 
1684
    }
1574
1685
 
1575
 
        /**
1576
 
         * Method to check invariants in this ArcInst.
1577
 
         * @exception AssertionError if invariants are not valid
1578
 
         */
1579
 
        public void check(Poly.Builder polyBuilder) {
 
1686
    /**
 
1687
     * Method to check invariants in this ArcInst.
 
1688
     * @exception AssertionError if invariants are not valid
 
1689
     */
 
1690
    public void check(Poly.Builder polyBuilder) {
1580
1691
        if (topology.validArcBounds && Job.getDebug()) {
1581
1692
            double minX = Double.POSITIVE_INFINITY, minY = Double.POSITIVE_INFINITY;
1582
1693
            double maxX = Double.NEGATIVE_INFINITY, maxY = Double.NEGATIVE_INFINITY;
1583
 
            for (Iterator<Poly> it = getShape(polyBuilder); it.hasNext(); ) {
 
1694
            for (Iterator<Poly> it = getShape(polyBuilder); it.hasNext();) {
1584
1695
                Poly poly = it.next();
1585
1696
                Rectangle2D bounds = poly.getBounds2D();
1586
1697
                minX = Math.min(minX, bounds.getMinX());
1599
1710
        }
1600
1711
    }
1601
1712
 
1602
 
        /**
1603
 
         * Method to get the arcId of this ArcInst.
 
1713
    /**
 
1714
     * Method to get the arcId of this ArcInst.
1604
1715
     * The arcId is assign to ArcInst in chronological order
1605
 
         * The arcId doesn't relate to alpahnumeric ordering of arcs in the Cell.
1606
 
         * @return the index of this ArcInst.
1607
 
         */
1608
 
        public final int getArcId() { return d.arcId; }
 
1716
     * The arcId doesn't relate to alpahnumeric ordering of arcs in the Cell.
 
1717
     * @return the index of this ArcInst.
 
1718
     */
 
1719
    public final int getArcId() {
 
1720
        return d.arcId;
 
1721
    }
1609
1722
 
 
1723
//
 
1724
//      /**
 
1725
//       * Method to return the index of this arcInst
 
1726
//       * @return the index of this arcInst
 
1727
//       */
 
1728
//      public final int getArcIndex(){
 
1729
//              return arcIndex;
 
1730
//      }
 
1731
//
 
1732
//      /**
 
1733
//       * Method to set the index of this arcInst
 
1734
//       * @param arcIndex index of this arcInst
 
1735
//       */
 
1736
//      public final void setArcIndex( int arcIndex ){
 
1737
//              this.arcIndex = arcIndex;
 
1738
//      }
1610
1739
    /**
1611
1740
     * Returns true if this ArcInst is linked into database.
1612
1741
     * @return true if this ArcInst is linked into database.
1613
1742
     */
1614
 
        public boolean isLinked()
1615
 
        {
1616
 
                try
1617
 
                {
1618
 
                        return parent != null && parent.isLinked() && parent.getArcById(getArcId()) == this;
1619
 
                } catch (IndexOutOfBoundsException e)
1620
 
                {
1621
 
                        return false;
1622
 
                }
1623
 
        }
1624
 
 
1625
 
        /**
1626
 
         * Method to return the prototype of this ArcInst.
1627
 
         * @return the prototype of this ArcInst.
1628
 
         */
1629
 
        public ArcProto getProto() { return getTechPool().getArcProto(d.protoId); }
 
1743
    public boolean isLinked() {
 
1744
        try {
 
1745
            Cell parent = topology.cell;
 
1746
            return parent.isLinked() && parent.getArcById(getArcId()) == this;
 
1747
        } catch (IndexOutOfBoundsException e) {
 
1748
            return false;
 
1749
        }
 
1750
    }
 
1751
 
 
1752
    /**
 
1753
     * Method to return the Cell Topology that contains this ArcInst.
 
1754
     * @return the Topology that contains this ArcInst.
 
1755
     */
 
1756
    @Override
 
1757
    public Topology getTopology() {
 
1758
        return topology;
 
1759
    }
 
1760
 
 
1761
    /**
 
1762
     * Routing to check whether changing of this cell allowed or not.
 
1763
     * By default checks whole database change. Overriden in subclasses.
 
1764
     */
 
1765
    @Override
 
1766
    public void checkChanging() {
 
1767
        topology.cell.checkChanging();
 
1768
    }
 
1769
 
 
1770
    /**
 
1771
     * Method to determine the appropriate Cell associated with this ElectricObject.
 
1772
     * @return the appropriate Cell associated with this ElectricicObject.
 
1773
     */
 
1774
    @Override
 
1775
    public Cell whichCell() {
 
1776
        return topology.cell;
 
1777
    }
 
1778
 
 
1779
    /**
 
1780
     * Returns database to which this ArcInst belongs.
 
1781
     * @return database to which this ArcInst belongs.
 
1782
     */
 
1783
    @Override
 
1784
    public EDatabase getDatabase() {
 
1785
        return topology.cell.getDatabase();
 
1786
    }
 
1787
 
 
1788
    /**
 
1789
     * Method to return the prototype of this ArcInst.
 
1790
     * @return the prototype of this ArcInst.
 
1791
     */
 
1792
    public ArcProto getProto() {
 
1793
        return getTechPool().getArcProto(d.protoId);
 
1794
    }
1630
1795
 
1631
1796
    /**
1632
1797
     * Copies all properties (variables, constraints, and textdescriptor)
1635
1800
     * @param fromAi the arc from which to copy all arc properties
1636
1801
     */
1637
1802
    public void copyPropertiesFrom(ArcInst fromAi) {
1638
 
        if (fromAi == null) return;
 
1803
        if (fromAi == null) {
 
1804
            return;
 
1805
        }
1639
1806
        copyVarsFrom(fromAi);
1640
 
                copyConstraintsFrom(fromAi);
 
1807
        copyConstraintsFrom(fromAi);
1641
1808
        copyTextDescriptorFrom(fromAi, ArcInst.ARC_NAME);
1642
1809
    }
1643
1810
 
1648
1815
     */
1649
1816
    public void copyConstraintsFrom(ArcInst fromAi) {
1650
1817
        checkChanging();
1651
 
        if (fromAi == null) return;
 
1818
        if (fromAi == null) {
 
1819
            return;
 
1820
        }
1652
1821
        ImmutableArcInst oldD = d;
1653
1822
        int flags = fromAi.d.flags;
1654
 
        if (!(d.tailPortId instanceof PrimitivePortId && getTechPool().getPrimitivePort((PrimitivePortId)d.tailPortId).isNegatable()))
 
1823
        if (!(d.tailPortId instanceof PrimitivePortId && getTechPool().getPrimitivePort((PrimitivePortId) d.tailPortId).isNegatable())) {
1655
1824
            flags = ImmutableArcInst.TAIL_NEGATED.set(flags, false);
1656
 
        if (!(d.headPortId instanceof PrimitivePortId && getTechPool().getPrimitivePort((PrimitivePortId)d.headPortId).isNegatable()))
 
1825
        }
 
1826
        if (!(d.headPortId instanceof PrimitivePortId && getTechPool().getPrimitivePort((PrimitivePortId) d.headPortId).isNegatable())) {
1657
1827
            flags = ImmutableArcInst.HEAD_NEGATED.set(flags, false);
 
1828
        }
1658
1829
        if (getProto().getTechnology().isNoNegatedArcs()) {
1659
1830
            flags = ImmutableArcInst.TAIL_NEGATED.set(flags, false);
1660
1831
            flags = ImmutableArcInst.HEAD_NEGATED.set(flags, false);
1661
1832
        }
1662
1833
        lowLevelModify(d.withFlags(flags).withAngle(fromAi.getAngle()));
1663
 
                if (parent != null) Constraints.getCurrent().modifyArcInst(this, oldD);
 
1834
        assert topology != null;
 
1835
        Constraints.getCurrent().modifyArcInst(this, oldD);
1664
1836
    }
1665
1837
 
1666
1838
//      /**
1689
1861
//              this.userBits = userBits & DATABASE_BITS;
1690
1862
//              if (isLinked() && extensionChanged) updateGeometric();
1691
1863
//      }
1692
 
 
1693
1864
//      /**
1694
1865
//       * Method to copy the various state bits from another ArcInst to this ArcInst.
1695
1866
//       * @param ai the other ArcInst to copy.
1696
1867
//       */
1697
1868
//      public void copyStateBits(ArcInst ai) { checkChanging(); this.userBits = ai.userBits; Undo.otherChange(this); }
1698
 
 
1699
1869
//      /**
1700
1870
//       * Method to set default constraint information on this ArcInst.
1701
1871
//       */
1709
1879
//        setHeadArrowed(protoType.isDirectional());
1710
1880
//        setBodyArrowed(protoType.isDirectional());
1711
1881
//      }
1712
 
 
1713
 
        /**
1714
 
         * Method to set this ArcInst to be hard-to-select.
1715
 
         * Hard-to-select ArcInsts cannot be selected by clicking on them.
1716
 
         * Instead, the "special select" command must be given.
 
1882
    /**
 
1883
     * Method to set this ArcInst to be hard-to-select.
 
1884
     * Hard-to-select ArcInsts cannot be selected by clicking on them.
 
1885
     * Instead, the "special select" command must be given.
1717
1886
     * @param state
1718
1887
     */
1719
 
        public void setHardSelect(boolean state) { setFlag(ImmutableArcInst.HARD_SELECT, state); }
 
1888
    public void setHardSelect(boolean state) {
 
1889
        setFlag(ImmutableArcInst.HARD_SELECT, state);
 
1890
    }
1720
1891
 
1721
 
        /**
1722
 
         * Method to tell whether this ArcInst is hard-to-select.
1723
 
         * Hard-to-select ArcInsts cannot be selected by clicking on them.
1724
 
         * Instead, the "special select" command must be given.
1725
 
         * @return true if this ArcInst is hard-to-select.
1726
 
         */
1727
 
        public boolean isHardSelect() { return d.isHardSelect(); }
 
1892
    /**
 
1893
     * Method to tell whether this ArcInst is hard-to-select.
 
1894
     * Hard-to-select ArcInsts cannot be selected by clicking on them.
 
1895
     * Instead, the "special select" command must be given.
 
1896
     * @return true if this ArcInst is hard-to-select.
 
1897
     */
 
1898
    public boolean isHardSelect() {
 
1899
        return d.isHardSelect();
 
1900
    }
1728
1901
 
1729
1902
    /**
1730
1903
     * This function is to compare NodeInst elements. Initiative CrossLibCopy
1732
1905
     * @param buffer To store comparison messages in case of failure
1733
1906
     * @return True if objects represent same ArcInst
1734
1907
     */
1735
 
    public boolean compare(Object obj, StringBuffer buffer)
1736
 
        {
1737
 
                if (this == obj) return (true);
 
1908
    public boolean compare(Object obj, StringBuffer buffer) {
 
1909
        if (this == obj) {
 
1910
            return (true);
 
1911
        }
1738
1912
 
1739
1913
        // Better if compare classes? but it will crash with obj=null
1740
 
        if (obj == null || getClass() != obj.getClass())
 
1914
        if (obj == null || getClass() != obj.getClass()) {
1741
1915
            return (false);
 
1916
        }
1742
1917
 
1743
 
        ArcInst a = (ArcInst)obj;
1744
 
         if (getProto().getClass() != a.getProto().getClass())
 
1918
        ArcInst a = (ArcInst) obj;
 
1919
        if (getProto().getClass() != a.getProto().getClass()) {
1745
1920
            return (false);
 
1921
        }
1746
1922
 
1747
1923
        // Not sure if I should defina myEquals for Geometric
1748
1924
        ArcProto arcType = a.getProto();
1749
 
                Technology tech = arcType.getTechnology();
1750
 
        if (getProto().getTechnology() != tech)
1751
 
        {
1752
 
                if (buffer != null)
1753
 
                        buffer.append("No same technology for arcs " + getName() + " and " + a.getName() + "\n");
 
1925
        Technology tech = arcType.getTechnology();
 
1926
        if (getProto().getTechnology() != tech) {
 
1927
            if (buffer != null) {
 
1928
                buffer.append("No same technology for arcs " + getName() + " and " + a.getName() + "\n");
 
1929
            }
1754
1930
            return (false);
1755
1931
        }
1756
1932
 
1757
 
                Poly[] polyList = getProto().getTechnology().getShapeOfArc(this);
 
1933
        Poly[] polyList = getProto().getTechnology().getShapeOfArc(this);
1758
1934
        Poly[] aPolyList = tech.getShapeOfArc(a);
1759
1935
 
1760
 
         if (polyList.length != aPolyList.length)
1761
 
         {
1762
 
                 if (buffer != null)
1763
 
                         buffer.append("No same number of geometries in " + getName() + " and " + a.getName() + "\n");
1764
 
                 return (false);
1765
 
         }
 
1936
        if (polyList.length != aPolyList.length) {
 
1937
            if (buffer != null) {
 
1938
                buffer.append("No same number of geometries in " + getName() + " and " + a.getName() + "\n");
 
1939
            }
 
1940
            return (false);
 
1941
        }
1766
1942
 
1767
1943
        // Remove noCheckList if equals is implemented
1768
1944
        // Sort them out by a key so comparison won't be O(n2)
1769
1945
        List<Poly> noCheckAgain = new ArrayList<Poly>();
1770
 
        for (int i = 0; i < polyList.length; i++)
1771
 
        {
 
1946
        for (int i = 0; i < polyList.length; i++) {
1772
1947
            boolean found = false;
1773
 
            for (int j = 0; j < aPolyList.length; j++)
1774
 
            {
 
1948
            for (int j = 0; j < aPolyList.length; j++) {
1775
1949
                // Already found
1776
 
                if (noCheckAgain.contains(aPolyList[j])) continue;
1777
 
                if (polyList[i].compare(aPolyList[j], buffer))
1778
 
                {
 
1950
                if (noCheckAgain.contains(aPolyList[j])) {
 
1951
                    continue;
 
1952
                }
 
1953
                if (polyList[i].compare(aPolyList[j], buffer)) {
1779
1954
                    found = true;
1780
1955
                    noCheckAgain.add(aPolyList[j]);
1781
1956
                    break;
1782
1957
                }
1783
1958
            }
1784
1959
            // polyList[i] doesn't match any elem in noPolyList
1785
 
            if (!found)
1786
 
            {
 
1960
            if (!found) {
1787
1961
                // No message otherwise all comparisons are found in buffer
1788
1962
                /*
1789
 
                    if (buffer != null)
1790
 
                            buffer.append("No corresponding geometry in " + getName() + " found in " + a.getName() + "\n");
1791
 
                    */
1792
 
                    return (false);
 
1963
                if (buffer != null)
 
1964
                buffer.append("No corresponding geometry in " + getName() + " found in " + a.getName() + "\n");
 
1965
                 */
 
1966
                return (false);
1793
1967
            }
1794
1968
        }
1795
1969
        return (true);
1796
1970
    }
1797
1971
 
1798
 
        /**
1799
 
         * Method to crop given polygon against a connecting transistor. Function similar to Quick.cropActiveArc
1800
 
         * @param poly
1801
 
         * @return new polygon if was cropped otherwise the original
1802
 
         */
1803
 
        public Poly cropPerLayer(Poly poly)
1804
 
        {
1805
 
                // must be manhattan
1806
 
                Rectangle2D polyBounds = poly.getBox();
1807
 
                if (polyBounds == null) return poly;
1808
 
                polyBounds = new Rectangle2D.Double(polyBounds.getMinX(), polyBounds.getMinY(), polyBounds.getWidth(), polyBounds.getHeight());
1809
 
 
1810
 
                // search for adjoining transistor in the cell
1811
 
                for(int i=0; i<2; i++)
1812
 
                {
1813
 
                        PortInst pi = getPortInst(i);
1814
 
                        NodeInst ni = pi.getNodeInst();
1815
 
                        //if (!ni.isFET()) continue;
1816
 
 
1817
 
                        // crop the arc against this transistor
1818
 
                        AffineTransform trans = ni.rotateOut();
1819
 
                        Technology tech = ni.getProto().getTechnology();
1820
 
                        Poly [] activeCropPolyList = tech.getShapeOfNode(ni);
1821
 
                        int nTot = activeCropPolyList.length;
1822
 
                        for(int k=0; k<nTot; k++)
1823
 
                        {
1824
 
                                Poly nPoly = activeCropPolyList[k];
1825
 
                                if (nPoly.getLayer() != poly.getLayer()) continue;
1826
 
                                nPoly.transform(trans);
1827
 
                                Rectangle2D nPolyBounds = nPoly.getBox();
1828
 
                                if (nPolyBounds == null) continue;
1829
 
                                int result = Poly.cropBoxComplete(polyBounds, nPolyBounds);
1830
 
                                if (result == 1)
1831
 
                                {
1832
 
                                        // Empty polygon
1833
 
                                        return null;
1834
 
                                }
1835
 
                                if (result == -2)
1836
 
                                        System.out.println("When is this case?");
1837
 
                                Poly newPoly = new Poly(polyBounds);
1838
 
                                newPoly.setLayer(poly.getLayer());
1839
 
                                newPoly.setStyle(poly.getStyle());
1840
 
                                return newPoly;
1841
 
                        }
1842
 
                }
1843
 
                return poly;
1844
 
        }
 
1972
    /**
 
1973
     * Method to crop given polygon against a connecting transistor. Function similar to Quick.cropActiveArc
 
1974
     * @param poly
 
1975
     * @return new polygon if was cropped otherwise the original
 
1976
     */
 
1977
    public Poly cropPerLayer(Poly poly) {
 
1978
        // must be manhattan
 
1979
        Rectangle2D polyBounds = poly.getBox();
 
1980
        if (polyBounds == null) {
 
1981
            return poly;
 
1982
        }
 
1983
        polyBounds = new Rectangle2D.Double(polyBounds.getMinX(), polyBounds.getMinY(), polyBounds.getWidth(), polyBounds.getHeight());
 
1984
 
 
1985
        // search for adjoining transistor in the cell
 
1986
        for (int i = 0; i < 2; i++) {
 
1987
            PortInst pi = getPortInst(i);
 
1988
            NodeInst ni = pi.getNodeInst();
 
1989
            //if (!ni.isFET()) continue;
 
1990
 
 
1991
            // crop the arc against this transistor
 
1992
            AffineTransform trans = ni.rotateOut();
 
1993
            Technology tech = ni.getProto().getTechnology();
 
1994
            Poly[] activeCropPolyList = tech.getShapeOfNode(ni);
 
1995
            int nTot = activeCropPolyList.length;
 
1996
            for (int k = 0; k < nTot; k++) {
 
1997
                Poly nPoly = activeCropPolyList[k];
 
1998
                if (nPoly.getLayer() != poly.getLayer()) {
 
1999
                    continue;
 
2000
                }
 
2001
                nPoly.transform(trans);
 
2002
                Rectangle2D nPolyBounds = nPoly.getBox();
 
2003
                if (nPolyBounds == null) {
 
2004
                    continue;
 
2005
                }
 
2006
                int result = Poly.cropBoxComplete(polyBounds, nPolyBounds);
 
2007
                if (result == 1) {
 
2008
                    // Empty polygon
 
2009
                    return null;
 
2010
                }
 
2011
                if (result == -2) {
 
2012
                    System.out.println("When is this case?");
 
2013
                }
 
2014
                Poly newPoly = new Poly(polyBounds);
 
2015
                newPoly.setLayer(poly.getLayer());
 
2016
                newPoly.setStyle(poly.getStyle());
 
2017
                return newPoly;
 
2018
            }
 
2019
        }
 
2020
        return poly;
 
2021
    }
1845
2022
 
1846
2023
    /**
1847
2024
     * Method to determin if arc contains active diffusion
1848
2025
     * @return True if contains active diffusion
1849
2026
     */
1850
 
    public boolean isDiffusionArc()
1851
 
    {
 
2027
    public boolean isDiffusionArc() {
1852
2028
        return getProto().getFunction().isDiffusion();
1853
2029
    }
1854
2030
}