0001: /**
0002: *
0003: */package net.refractions.udig.tools.edit.support;
0004:
0005: import java.awt.geom.AffineTransform;
0006: import java.util.ArrayList;
0007: import java.util.Collection;
0008: import java.util.Collections;
0009: import java.util.HashMap;
0010: import java.util.HashSet;
0011: import java.util.Iterator;
0012: import java.util.LinkedList;
0013: import java.util.List;
0014: import java.util.ListIterator;
0015: import java.util.Map;
0016: import java.util.Set;
0017:
0018: import net.refractions.udig.core.WeakHashSet;
0019: import net.refractions.udig.tools.edit.EditPlugin;
0020: import net.refractions.udig.tools.edit.preferences.PreferenceUtil;
0021: import net.refractions.udig.tools.edit.support.EditBlackboardEvent.EventType;
0022: import net.refractions.udig.tools.edit.support.PrimitiveShape.Mutator;
0023:
0024: import org.opengis.referencing.operation.MathTransform;
0025:
0026: import com.vividsolutions.jts.geom.Coordinate;
0027: import com.vividsolutions.jts.geom.Envelope;
0028: import com.vividsolutions.jts.geom.Geometry;
0029: import com.vividsolutions.jts.geom.GeometryCollection;
0030: import com.vividsolutions.jts.geom.Polygon;
0031:
0032: /**
0033: * Maps between each pixel to a list of coordinates. Also provides convenience methods to move all
0034: * coordinates at a location
0035: *
0036: * @author jeichar
0037: */
0038: public class EditBlackboard {
0039:
0040: protected Map<Point, List<LazyCoord>> coordMapping;
0041: Map<Point, Set<EditGeom>> geomMapping;
0042: private final List<EditGeom> geometries;
0043: private Set<EditBlackboardListener> listeners = Collections
0044: .synchronizedSet(new WeakHashSet<EditBlackboardListener>());
0045: private Selection selection = new Selection(this );
0046: private volatile int height;
0047: private volatile int width;
0048: private boolean collapseVertices;
0049: PointCoordCalculator pointCoordCalculator;
0050: private volatile int batchingEvents = 0;
0051: private List<EditBlackboardEvent> batchedEvents = new LinkedList<EditBlackboardEvent>();
0052:
0053: /**
0054: * Creates a PixelCoordMap. A default GeomShape will be created and can be obtained by
0055: * {@link #getGeoms()}.get(0)
0056: *
0057: * @param width width of the current ViewportPane
0058: * @param height height of the current ViewportPane
0059: * @param toScreen transform to take the coordinates to a screen location.
0060: * @param layerToMap transform to transform coordinates from a layer's CRS to the map's CRS
0061: * @param coords coordinates that need to be mapped.
0062: */
0063: public EditBlackboard(int width, int height,
0064: AffineTransform toScreen, MathTransform layerToMap) {
0065: collapseVertices = true;
0066: this .width = width;
0067: this .height = height;
0068: coordMapping = new HashMap<Point, List<LazyCoord>>();
0069: geomMapping = new HashMap<Point, Set<EditGeom>>();
0070: pointCoordCalculator = new PointCoordCalculator(toScreen,
0071: layerToMap);
0072: geometries = new ArrayList<EditGeom>();
0073:
0074: geometries.add(new EditGeom(this , null));
0075: }
0076:
0077: /**
0078: * Returns the list of Listeners so that listeners can be added and removed. This is thread
0079: * safe. Each Listener can only be added once.
0080: *
0081: * @return Returns the listeners.
0082: */
0083: public Set<EditBlackboardListener> getListeners() {
0084: return listeners;
0085: }
0086:
0087: /**
0088: * Adds a Geometry to the contained geometries. If the Geometry is a MultiGeometry it will not
0089: * be in the mapping only the sub geometries will be in the geometry.
0090: *
0091: * @param geom the geometry that will be added.
0092: * @param featureId The id of the feature the geometry was part of. Maybe null.
0093: */
0094: public Map<Geometry, EditGeom> setGeometries(Geometry geom,
0095: String featureId) {
0096: Map<Geometry, EditGeom> mapping = null;
0097: ArrayList<EditGeom> old = new ArrayList<EditGeom>(geometries);
0098: synchronized (this ) {
0099: geometries.clear();
0100: coordMapping.clear();
0101: geomMapping.clear();
0102: mapping = new HashMap<Geometry, EditGeom>();
0103: doAddGeometry(geom, mapping, featureId);
0104: if (EditPlugin.isDebugging(EditPlugin.RUN_ASSERTIONS)) {
0105: for (EditGeom geom2 : mapping.values()) {
0106: geom2.assertValid();
0107: }
0108: }
0109: }
0110: if (mapping != null && !mapping.isEmpty())
0111: notify(new EditBlackboardEvent(this , this ,
0112: EventType.SET_GEOMS, old, new ArrayList<EditGeom>(
0113: geometries)));
0114: return mapping;
0115:
0116: }
0117:
0118: /**
0119: * Adds a Geometry to the contained geometries. If the Geometry is a MultiGeometry it will not
0120: * be in the mapping only the sub geometries will be in the geometry.
0121: *
0122: * @param geom the geometry that will be added.
0123: * @param featureID The id of the feature the geometry was part of. Maybe null.
0124: */
0125: public Map<Geometry, EditGeom> addGeometry(Geometry geom,
0126: String featureID) {
0127: List<EditGeom> unmodifiableList = null;
0128: Map<Geometry, EditGeom> mapping = null;
0129: synchronized (this ) {
0130: mapping = new HashMap<Geometry, EditGeom>();
0131: doAddGeometry(geom, mapping, featureID);
0132: unmodifiableList = Collections
0133: .unmodifiableList(new ArrayList<EditGeom>(mapping
0134: .values()));
0135: if (EditPlugin.isDebugging(EditPlugin.RUN_ASSERTIONS)) {
0136: for (EditGeom geom2 : mapping.values()) {
0137: geom2.assertValid();
0138: }
0139: }
0140: }
0141: if (unmodifiableList != null && !unmodifiableList.isEmpty())
0142: notify(new EditBlackboardEvent(this , this ,
0143: EditBlackboardEvent.EventType.ADD_GEOMS, null,
0144: unmodifiableList));
0145: return mapping;
0146: }
0147:
0148: /**
0149: * Adds a Coordinate the nearest edge .
0150: * <p>
0151: * If two edges are equidistant the first edge in the geometry will be targeted edge
0152: * </p>
0153: *
0154: * @param x the x screen location to place the new coordinate
0155: * @param y the x screen location to place the new coordinate
0156: * @param geom the geometry to append the point to.
0157: * @param treatUnknownAsPolygon declares whether to treat geometries of type UNKNOWN as a polygon
0158: * @returns The edge that the point was added to.
0159: */
0160: public ClosestEdge addToNearestEdge(int x, int y, EditGeom geom,
0161: boolean treatUnknownAsPolygon)
0162: throws IllegalArgumentException {
0163: EditBlackboardEvent editBlackboardEvent = null;
0164: ClosestEdge geomClosest = null;
0165: synchronized (this ) {
0166: if (!geometries.contains(geom))
0167: throw new IllegalArgumentException(
0168: "EditBlackboard does not contain EditGeom " + geom); //$NON-NLS-1$
0169: Point p = Point.valueOf(x, y);
0170: geomClosest = geom.getClosestEdge(p, treatUnknownAsPolygon);
0171: Coordinate toCoord = toCoord(p);
0172: LazyCoord lazyCoord = doInsertCoord(p, toCoord,
0173: geomClosest.indexOfPrevious + 1, geomClosest.part);
0174:
0175: geom.assertValid();
0176: editBlackboardEvent = new EditBlackboardEvent(this ,
0177: geomClosest.part, EventType.ADD_POINT, null, p);
0178: editBlackboardEvent.privateData = lazyCoord;
0179: }
0180: if (editBlackboardEvent != null)
0181: notify(editBlackboardEvent);
0182: return geomClosest;
0183: }
0184:
0185: /**
0186: * Adds a Coordinate the nearest edge .
0187: * <p>
0188: * If two edges of the same geometry are equidistant the first edge in the geometry will be
0189: * targeted edge
0190: * </p>
0191: * <p>
0192: * If two edges of different geometries are equidistant both will have a vertex added.
0193: * </p>
0194: * <p>
0195: * If the vertex would end up being added to the same location as an existing vertex then no
0196: * vertext is added
0197: * </p>
0198: *
0199: * @param x the x screen location to place the new coordinate
0200: * @param y the x screen location to place the new coordinate
0201: * @param treatUnknownAsPolygon declares whether to treat geometries of type UNKNOWN as a polygon
0202: * @return the list of GeomShapes that had the coordinate added to.
0203: */
0204: public List<ClosestEdge> addToNearestEdge(int x, int y,
0205: boolean treatUnknownAsPolygon)
0206: throws IllegalArgumentException {
0207: EditBlackboardEvent editBlackboardEvent;
0208: List<ClosestEdge> candidates;
0209: synchronized (this ) {
0210: candidates = getCandidates(x, y, treatUnknownAsPolygon);
0211: Point p = Point.valueOf(x, y);
0212: Coordinate toCoord = toCoord(p);
0213: if (candidates.size() == 0) {
0214: EditGeom editGeom = getGeoms().get(0);
0215: LazyCoord lazyCoord = doAddCoord(p, toCoord, editGeom
0216: .getShell());
0217: editGeom.getShell().assertValid();
0218: editBlackboardEvent = new EditBlackboardEvent(this ,
0219: editGeom.getShell(), EventType.ADD_POINT, null,
0220: p);
0221: editBlackboardEvent.privateData = lazyCoord;
0222: } else {
0223: Map<EditGeom, PrimitiveShape> changed = new HashMap<EditGeom, PrimitiveShape>();
0224: for (ClosestEdge edge : candidates) {
0225: EditGeom geom = edge.shape;
0226:
0227: doInsertCoord(p, toCoord, edge.indexOfPrevious + 1,
0228: edge.part);
0229: changed.put(geom, edge.part);
0230:
0231: edge.part.assertValid();
0232: }
0233: editBlackboardEvent = new EditBlackboardEvent(this ,
0234: changed.values(), EventType.ADD_POINT_TO_MANY,
0235: null, p);
0236: }
0237: }
0238: if (editBlackboardEvent != null)
0239: notify(editBlackboardEvent);
0240: return candidates;
0241: }
0242:
0243: /**
0244: * Adds a Coordinate at the x,y location on the screen to the end of the geomtry. Closure of the
0245: * hole is not enforced.
0246: *
0247: * @param x the x screen location to place the new coordinate
0248: * @param y the x screen location to place the new coordinate
0249: * @param holeIndex the hole to append to.
0250: * @return
0251: * @return added coordinate. <b>Do not modify coordinate otherwise the state of this class will
0252: * be wrong and bugs will occur in the code.</b>
0253: */
0254: public Coordinate addPoint(int x, int y, PrimitiveShape shape)
0255: throws IllegalArgumentException {
0256: LazyCoord lazyCoord = null;
0257: EditBlackboardEvent editBlackboardEvent = null;
0258: synchronized (this ) {
0259: if (!geometries.contains(shape.getEditGeom()))
0260: throw new IllegalArgumentException(
0261: "Blackboard does not contain shape:" + shape); //$NON-NLS-1$
0262:
0263: Point point = Point.valueOf(x, y);
0264: Coordinate coord = toCoord(point);
0265: lazyCoord = doAddCoord(point, coord, shape);
0266: shape.assertValid();
0267: editBlackboardEvent = new EditBlackboardEvent(this , shape,
0268: EventType.ADD_POINT, null, point);
0269: editBlackboardEvent.privateData = lazyCoord;
0270: }
0271: if (editBlackboardEvent != null)
0272: notify(editBlackboardEvent);
0273: return lazyCoord;
0274: }
0275:
0276: public Point addCoordinate(Coordinate coord, PrimitiveShape shape) {
0277: return insertCoordinate(coord, shape.getNumPoints(), shape);
0278: }
0279:
0280: public Point insertCoordinate(Coordinate coord, int index,
0281: PrimitiveShape shape) {
0282: EditBlackboardEvent editBlackboardEvent = null;
0283: Point p = null;
0284: synchronized (this ) {
0285: if (!geometries.contains(shape.getEditGeom()))
0286: throw new IllegalArgumentException(
0287: "Blackboard does not contain shape:" + shape); //$NON-NLS-1$
0288: p = toPoint(coord);
0289: LazyCoord lazyCoord = doInsertCoord(p, coord, index, shape);
0290: shape.assertValid();
0291: editBlackboardEvent = new EditBlackboardEvent(this , shape,
0292: EventType.ADD_POINT, null, p);
0293: editBlackboardEvent.privateData = lazyCoord;
0294: }
0295: if (editBlackboardEvent != null)
0296: notify(editBlackboardEvent);
0297:
0298: return p;
0299: }
0300:
0301: /**
0302: * Adds a Coordinate at the index indicated.
0303: * <p>
0304: * The index is the position in the coordinate list in the shell of the geometry.
0305: * </p>
0306: *
0307: * @param x the x screen location to place the new coordinate
0308: * @param y the x screen location to place the new coordinate
0309: * @param pointIndex the index in terms of points in the shape to add the coordinate.
0310: * @param geom the geometry to append the point to.
0311: * @return added coordinate. <b>Do not modify coordinate otherwise the state of this class will
0312: * be wrong and bugs will occur in the code.</b>
0313: */
0314: public Coordinate insertCoord(int x, int y, int pointIndex,
0315: PrimitiveShape shape) throws IllegalArgumentException {
0316: EditBlackboardEvent editBlackboardEvent = null;
0317: Coordinate coord = null;
0318: synchronized (this ) {
0319: if (!geometries.contains(shape.getEditGeom()))
0320: throw new IllegalArgumentException(
0321: "Blackboard does not contain shape:" + shape); //$NON-NLS-1$
0322: Point point = Point.valueOf(x, y);
0323: coord = toCoord(point);
0324: LazyCoord lazyCoord = doInsertCoord(point, coord,
0325: pointIndex, shape);
0326: shape.assertValid();
0327: editBlackboardEvent = new EditBlackboardEvent(this , shape,
0328: EventType.ADD_POINT, null, point);
0329: editBlackboardEvent.privateData = lazyCoord;
0330: }
0331: if (editBlackboardEvent != null)
0332: notify(editBlackboardEvent);
0333: return coord;
0334: }
0335:
0336: /**
0337: * Inserts the list of coordinates into the shape at the index indicated.
0338: *
0339: * @param pointIndex the location that the coordinates will be inserted.
0340: * @param coords coords that will inserted.insertCoords
0341: * @param shape the shape that will have the coords inserted.
0342: */
0343: public void insertCoords(int pointIndex, Point p,
0344: List<Coordinate> coords, PrimitiveShape shape) {
0345: List<LazyCoord> lazyCoords = null;
0346: synchronized (this ) {
0347: if (!geometries.contains(shape.getEditGeom()))
0348: throw new IllegalArgumentException(
0349: "Blackboard does not contain shape:" + shape); //$NON-NLS-1$
0350: if (coords.isEmpty())
0351: throw new IllegalArgumentException(
0352: "Coordinates cannot be empty"); //$NON-NLS-1$
0353: lazyCoords = shape.getMutator().addPoint(pointIndex, p,
0354: coords);
0355: List<LazyCoord> mappedCoords = coordMapping.get(p);
0356: if (mappedCoords == null) {
0357: mappedCoords = new ArrayList<LazyCoord>();
0358: coordMapping.put(p, mappedCoords);
0359: }
0360: mappedCoords.addAll(lazyCoords);
0361: Set<EditGeom> geoms = geomMapping.get(p);
0362: if (geoms == null) {
0363: geoms = new HashSet<EditGeom>();
0364: geomMapping.put(p, geoms);
0365: }
0366: if (!geoms.contains(shape.getEditGeom()))
0367: geoms.add(shape.getEditGeom());
0368:
0369: if (EditPlugin.isDebugging(EditPlugin.RUN_ASSERTIONS)) {
0370: for (EditGeom geom : geoms) {
0371: geom.assertValid();
0372: }
0373: }
0374:
0375: }
0376: EditBlackboardEvent editBlackboardEvent = new EditBlackboardEvent(
0377: this , shape, EventType.ADD_POINT, null, p);
0378:
0379: editBlackboardEvent.privateData = lazyCoords;
0380: if (lazyCoords != null && !lazyCoords.isEmpty())
0381: notify(editBlackboardEvent);
0382: }
0383:
0384: /**
0385: * Returns the GeomShapes that will have the coordinate added if
0386: * {@linkplain #addToNearestEdge(int, int)} is called.
0387: *
0388: * @param x the x screen location to place the new coordinate
0389: * @param y the x screen location to place the new coordinate
0390: * @param treatUnknownAsPolygon declares whether to treat geometries of type UNKNOWN as a polygon
0391: * @return the GeomShapes that will have the coordinate added if
0392: * {@linkplain #addToNearestEdge(int, int)} is called.
0393: */
0394: public synchronized List<ClosestEdge> getCandidates(int x, int y,
0395: boolean treatUnknownAsPolygon) {
0396: Point p = Point.valueOf(x, y);
0397: List<EditGeom> geoms = getGeoms();
0398: List<ClosestEdge> candidates = new ArrayList<ClosestEdge>();
0399: int closest = Integer.MAX_VALUE;
0400: List<ClosestEdge> closestDistances = new ArrayList<ClosestEdge>();
0401:
0402: for (int i = 0; i < geoms.size(); i++) {
0403: ClosestEdge geomClosest = geoms.get(i).getClosestEdge(p,
0404: treatUnknownAsPolygon);
0405: if (geomClosest == null)
0406: continue;
0407: if (geomClosest.distanceToEdge < closest)
0408: closest = (int) geomClosest.distanceToEdge;
0409: closestDistances.add(geomClosest);
0410: }
0411:
0412: for (ClosestEdge edge : closestDistances) {
0413: if (((int) edge.distanceToEdge) == closest
0414: && !edge.part.getMutator().hasPoint(
0415: edge.pointOnLine)) {
0416: candidates.add(edge);
0417: }
0418: }
0419:
0420: return candidates;
0421: }
0422:
0423: /**
0424: * returns the list of coordinates at location:(x,y) <b>TREAT COORDINATES AS IMMUTABLE!!</b>
0425: * <p>
0426: * This is a dangerous method because the coordinates are mutable but if they are modified
0427: * outside of this class then the model is messed up and crazy bugs will happen. The weakness is
0428: * permitted for performance reasons. I'm trusting people to not be stupid.
0429: * </p>
0430: *
0431: * @return the list of coordinates at location:(x,y). <b>TREAT COORDINATES AS IMMUTABLE!!</b>
0432: */
0433: public synchronized List<Coordinate> getCoords(int x, int y) {
0434: Point point = Point.valueOf(x, y);
0435: List<LazyCoord> list = coordMapping.get(point);
0436: if (list == null)
0437: return Collections.<Coordinate> emptyList();
0438: return new CoordResolvingList(list, point);
0439: }
0440:
0441: /**
0442: * The list of geometries mapped.
0443: *
0444: * @return list of geometries mapped.
0445: */
0446: public synchronized List<EditGeom> getGeoms() {
0447: return Collections.unmodifiableList(new ArrayList<EditGeom>(
0448: geometries));
0449: }
0450:
0451: /**
0452: * Returns a list of the geometries with vertices at the position (x,y). Edges are not
0453: * calculated.
0454: *
0455: * @param x x coordinate of point
0456: * @param y x coordinate of point
0457: * @return
0458: * @return a list of the geometries at the position (x,y)
0459: */
0460: public synchronized List<EditGeom> getGeoms(int x, int y) {
0461: Set<EditGeom> geoms = geomMapping.get(Point.valueOf(x, y));
0462: if (geoms == null)
0463: return Collections.<EditGeom> emptyList();
0464: return new ArrayList<EditGeom>(geoms);
0465: }
0466:
0467: /**
0468: * Moves all the coordinates at location by an offset of (deltaX, deltaY).
0469: *
0470: * @param x x coordinate of coords to move
0471: * @param y y coordinate of coords to move
0472: * @param deltaX the number of pixels to move coords in the positive x direction(Screen space)
0473: * @param deltaY the number of pixels to move coords in the positive y direction(Screen space)
0474: */
0475: public List<Coordinate> moveCoords(int x, int y, int endX, int endY) {
0476:
0477: Set<PrimitiveShape> changed = new HashSet<PrimitiveShape>();
0478: List<LazyCoord> coords = null;
0479: Point start = Point.valueOf(x, y);
0480: Point end = Point.valueOf(endX, endY);
0481: synchronized (this ) {
0482:
0483: if (start.equals(end))
0484: return Collections.<Coordinate> emptyList();
0485:
0486: coords = coordMapping.remove(start);
0487: if (coords == null || coords.size() == 0)
0488: return Collections.<Coordinate> emptyList();
0489:
0490: List<LazyCoord> endCoords = coordMapping.get(end);
0491:
0492: if (endCoords != null) {
0493: endCoords.addAll(coords);
0494: } else {
0495: coordMapping.put(end, coords);
0496: }
0497:
0498: Set<EditGeom> startGeoms = geomMapping.get(start);
0499: Set<EditGeom> endGeoms = geomMapping.get(end);
0500:
0501: endGeoms = endGeoms == null ? new HashSet<EditGeom>()
0502: : endGeoms;
0503: for (EditGeom geom : startGeoms) {
0504: geom.setChanged(true);
0505: if (!endGeoms.contains(geom))
0506: endGeoms.add(geom);
0507: for (PrimitiveShape hole : geom) {
0508: for (ListIterator<Point> iter = hole.getMutator()
0509: .iterator(); iter.hasNext();) {
0510: Point p = iter.next();
0511: if (p.equals(start)) {
0512: changed.add(hole);
0513: for (LazyCoord coord : coords) {
0514: if (hole.hasVertex(p, coord)) {
0515: iter.set(end);
0516: break;
0517: }
0518:
0519: }
0520: }
0521: }
0522: }
0523: }
0524:
0525: geomMapping.put(end, endGeoms);
0526: geomMapping.remove(start);
0527: if (EditPlugin.isDebugging(EditPlugin.RUN_ASSERTIONS))
0528: for (PrimitiveShape shape : changed) {
0529: shape.assertValid();
0530: }
0531: }
0532: if (!changed.isEmpty())
0533: notify(new EditBlackboardEvent(this , changed,
0534: EventType.MOVE_POINT, start, end));
0535: return new CoordResolvingList(coords, end);
0536: }
0537:
0538: /**
0539: * Moves the selection
0540: *
0541: * @param diffX the distance to move the geometry in the x direction. The delta is in pixels.
0542: * @param diffY the distance to move the geometry in the y direction. The delta is in pixels.
0543: * @param selection the selection to move.
0544: */
0545: public void moveSelection(int diffX, int diffY, Selection selection) {
0546:
0547: if (selection instanceof EditGeomSelection) {
0548: moveGeom(diffX, diffY, ((EditGeomSelection) selection)
0549: .getGeom());
0550: } else {
0551: doMoveSelection(diffX, diffY, selection);
0552: }
0553: }
0554:
0555: private void doMoveSelection(int diffX, int diffY,
0556: Selection selection2) {
0557: if (diffX == 0 && diffY == 0)
0558: return;
0559:
0560: if (selection.size() == 0)
0561: return;
0562:
0563: startBatchingEvents();
0564: synchronized (this ) {
0565: for (Point start : selection) {
0566: Collection<LazyCoord> coords = selection
0567: .getLazyCoordinates(start);
0568: Point end = Point.valueOf(start.getX() + diffX, start
0569: .getY()
0570: + diffY);
0571: List<LazyCoord> endCoords = coordMapping.get(end);
0572:
0573: coordMapping.get(start).removeAll(coords);
0574: if (endCoords != null) {
0575: endCoords.addAll(coords);
0576: } else {
0577: coordMapping.put(end, new LinkedList<LazyCoord>(
0578: coords));
0579: }
0580:
0581: Set<EditGeom> startGeoms = geomMapping.get(start);
0582: Set<EditGeom> endGeoms = geomMapping.get(end);
0583: Set<PrimitiveShape> changed = new HashSet<PrimitiveShape>();
0584:
0585: if (startGeoms == null)
0586: continue;
0587:
0588: endGeoms = endGeoms == null ? new HashSet<EditGeom>()
0589: : endGeoms;
0590: Set<EditGeom> toRemove = new HashSet<EditGeom>();
0591: Set<EditGeom> toAdd = new HashSet<EditGeom>();
0592: for (Iterator<EditGeom> geomIter = startGeoms
0593: .iterator(); geomIter.hasNext();) {
0594: EditGeom geom = geomIter.next();
0595: geom.setChanged(true);
0596:
0597: for (PrimitiveShape shape : geom) {
0598:
0599: for (Iterator<Point> shapeIter = shape
0600: .getMutator().getCopyIterator(); shapeIter
0601: .hasNext();) {
0602: Point p = shapeIter.next();
0603: if (p.equals(start)) {
0604: toAdd.add(geom);
0605: for (LazyCoord coord : coords) {
0606: if (shape.hasVertex(p, coord)) {
0607: changed.add(shape);
0608: shape.getMutator().move(start,
0609: end, coord);
0610: }
0611:
0612: }
0613: }
0614: }
0615: if (shape.getMutator().getLazyCoordsAt(start)
0616: .isEmpty())
0617: toRemove.add(geom);
0618: }
0619:
0620: if (!changed.isEmpty())
0621: notify(new EditBlackboardEvent(this , changed,
0622: EventType.MOVE_POINT, start, end));
0623: }
0624: endGeoms.addAll(toAdd);
0625: startGeoms.removeAll(toRemove);
0626: geomMapping.put(end, endGeoms);
0627: if (EditPlugin.isDebugging(EditPlugin.RUN_ASSERTIONS))
0628: for (EditGeom geom : endGeoms) {
0629: geom.assertValid();
0630: }
0631:
0632: }
0633: }
0634: fireBatchedEvents();
0635:
0636: }
0637:
0638: /**
0639: * Moves a geometry deltaX, deltaY pixels.
0640: *
0641: * @param deltaX the distance to move the geometry in the x direction. The delta is in pixels.
0642: * @param deltaY the distance to move the geometry in the y direction. The delta is in pixels.
0643: * @param geom the geometry to move.
0644: */
0645: private void moveGeom(int deltaX, int deltaY, EditGeom geom) {
0646: if (!geometries.contains(geom))
0647: throw new IllegalArgumentException(
0648: "Blackboard does not contain EditGeom:" + geom); //$NON-NLS-1$
0649:
0650: if (deltaX == 0 && deltaY == 0)
0651: return;
0652: synchronized (this ) {
0653: Set<Point> moved = new HashSet<Point>();
0654: Map<Point, List<LazyCoord>> newCoordMapping = new HashMap<Point, List<LazyCoord>>();
0655:
0656: startBatchingEvents();
0657: for (PrimitiveShape shape : geom) {
0658: for (Point point : shape) {
0659: if (moved.contains(point))
0660: continue;
0661:
0662: moved.add(point);
0663: Point destPoint = Point.valueOf(point.getX()
0664: + deltaX, point.getY() + deltaY);
0665:
0666: List<LazyCoord> coords = shape.getMutator()
0667: .getLazyCoordsAt(point);
0668: coordMapping.get(point).removeAll(coords);
0669:
0670: newCoordMapping.put(destPoint, coords);
0671:
0672: geomMapping.get(point).remove(geom);
0673:
0674: notify(new EditBlackboardEvent(this , Collections
0675: .singleton(shape), EventType.MOVE_POINT,
0676: point, destPoint));
0677: }
0678: }
0679:
0680: for (PrimitiveShape shape : geom) {
0681: shape.getMutator().move(deltaX, deltaY);
0682: }
0683:
0684: for (Map.Entry<Point, List<LazyCoord>> entry : newCoordMapping
0685: .entrySet()) {
0686: List<LazyCoord> destCoords = coordMapping.get(entry
0687: .getKey());
0688: if (destCoords == null) {
0689: destCoords = new ArrayList<LazyCoord>();
0690: coordMapping.put(entry.getKey(), destCoords);
0691: }
0692: destCoords.addAll(entry.getValue());
0693:
0694: Set<EditGeom> destGeoms = geomMapping.get(entry
0695: .getKey());
0696: if (destGeoms == null) {
0697: destGeoms = new HashSet<EditGeom>();
0698: destGeoms.add(geom);
0699: geomMapping.put(entry.getKey(), destGeoms);
0700: } else {
0701: if (!destGeoms.contains(geom))
0702: destGeoms.add(geom);
0703: }
0704: }
0705:
0706: geom.assertValid();
0707: geom.setChanged(true);
0708: }
0709: fireBatchedEvents();
0710: }
0711:
0712: /**
0713: * Deletes all the coordinates at a location <b>TREAT COORDINATES AS IMMUTABLE!!</b>
0714: *
0715: * @return the deleted coordinates. <b>TREAT COORDINATES AS IMMUTABLE!!</b>
0716: */
0717: public List<Coordinate> removeCoordsAtPoint(int x, int y) {
0718: Point p = Point.valueOf(x, y);
0719: HashSet<PrimitiveShape> changed = new HashSet<PrimitiveShape>();
0720: List<Coordinate> result = null;
0721: synchronized (this ) {
0722:
0723: List<LazyCoord> coords = coordMapping.remove(p);
0724:
0725: result = coords == null ? Collections
0726: .<Coordinate> emptyList() : new CoordResolvingList(
0727: coords, p);
0728:
0729: Set<EditGeom> geoms = geomMapping.remove(p);
0730: if (geoms == null)
0731: return Collections.<Coordinate> emptyList();
0732: for (EditGeom geom : geoms) {
0733:
0734: for (PrimitiveShape part : geom) {
0735: Mutator mutator = part.getMutator();
0736: if (mutator.remove(p))
0737: changed.add(part);
0738: while (mutator.remove(p))
0739: ;
0740: }
0741: }
0742:
0743: if (EditPlugin.isDebugging(EditPlugin.RUN_ASSERTIONS)) {
0744: for (PrimitiveShape shape : changed) {
0745: shape.assertValid();
0746: }
0747: }
0748: }
0749: if (!changed.isEmpty())
0750: notify(new EditBlackboardEvent(this , changed,
0751: EventType.REMOVE_POINT, p, null));
0752: return result;
0753: }
0754:
0755: /**
0756: * Deletes the coordinates at the provided point in the provided shape.
0757: *
0758: * @param x x coordinate in screen coords
0759: * @param y y coordinate in screen coords
0760: * @param shape shape to delete from.
0761: */
0762: public void removeCoords(int x, int y, PrimitiveShape shape) {
0763: Point p = Point.valueOf(x, y);
0764: synchronized (this ) {
0765: shape.getMutator().remove(p);
0766: Set<EditGeom> geoms = geomMapping.get(p);
0767: if (geoms.isEmpty()) {
0768: throw new IllegalStateException(
0769: "for some reason there was no shape at the location"); //$NON-NLS-1$
0770: }
0771: boolean noMoreReferences = true;
0772:
0773: for (PrimitiveShape shape2 : shape.getEditGeom()) {
0774: if (!shape2.getMutator().getLazyCoordsAt(p).isEmpty()) {
0775: noMoreReferences = false;
0776: break;
0777: }
0778: }
0779:
0780: if (noMoreReferences) {
0781: geoms.remove(shape.getEditGeom());
0782: }
0783: shape.assertValid();
0784: }
0785: notify(new EditBlackboardEvent(this , Collections
0786: .singleton(shape), EventType.REMOVE_POINT, p, null));
0787: }
0788:
0789: /**
0790: * Removes a coordinate from the shape. The index indicates which point to remove, the Point
0791: * parameter is a check to ensure that the correct point is indicated, and the coord is the
0792: * coordinate that will be removed
0793: *
0794: * @param pointIndex index of point in shape
0795: * @param coord coordinate to remove
0796: * @param shape shape to remove from
0797: */
0798: public void removeCoordinate(int pointIndex, Coordinate coord,
0799: PrimitiveShape shape) {
0800:
0801: if (!geometries.contains(shape.getEditGeom()))
0802: throw new IllegalArgumentException(
0803: "Blackboard does not contain shape:" + shape); //$NON-NLS-1$
0804:
0805: Point toRemove = null;
0806: synchronized (this ) {
0807: toRemove = shape.getPoint(pointIndex);
0808:
0809: Mutator mutator = shape.getMutator();
0810: LazyCoord removed = mutator.removePoint(pointIndex, coord);
0811:
0812: boolean occupiesPoint = false;
0813:
0814: for (Point point : mutator) {
0815: if (point.equals(toRemove))
0816: occupiesPoint = true;
0817: }
0818:
0819: List<LazyCoord> coords = coordMapping.get(toRemove);
0820: for (Iterator<LazyCoord> iter = coords.iterator(); iter
0821: .hasNext();) {
0822: if (iter.next() == removed)
0823: iter.remove();
0824: }
0825: if (coords.isEmpty()) {
0826: coordMapping.remove(toRemove);
0827: }
0828:
0829: if (!occupiesPoint) {
0830: Set<EditGeom> geoms = geomMapping.get(toRemove);
0831: geoms.remove(shape.getEditGeom());
0832: if (geoms.isEmpty())
0833: geomMapping.remove(toRemove);
0834: }
0835:
0836: shape.assertValid();
0837: }
0838: if (toRemove != null)
0839: notify(new EditBlackboardEvent(this , Collections
0840: .singleton(shape), EventType.REMOVE_POINT,
0841: toRemove, null));
0842: }
0843:
0844: public synchronized Coordinate toCoord(Point point) {
0845: return pointCoordCalculator.toCoord(point);
0846: }
0847:
0848: /**
0849: * Transforms a Coordinate into the point location it would occupy on the screen.
0850: *
0851: * @param coord coordinate object
0852: * @return point coordinate would occupy on the screen.
0853: */
0854: public synchronized Point toPoint(Coordinate coord) {
0855: return pointCoordCalculator.toPoint(coord);
0856: }
0857:
0858: /**
0859: * Modifies the mapping of points to coordinates so that the transform passed in as a parameter
0860: * is the new toScreen transform.
0861: *
0862: * @param transform new transform
0863: */
0864: public void setToScreenTransform(AffineTransform newToScreen) {
0865: AffineTransform oldToScreen = null;
0866: Map<Point, List<Point>> map = new HashMap<Point, List<Point>>();
0867: synchronized (this ) {
0868: if (newToScreen.equals(pointCoordCalculator.toScreen))
0869: return;
0870:
0871: oldToScreen = new AffineTransform(
0872: pointCoordCalculator.toScreen);
0873: AffineTransform oldToWorld = new AffineTransform(
0874: pointCoordCalculator.toWorld);
0875:
0876: geomMapping.clear();
0877: coordMapping.clear();
0878: PointCoordCalculator calculator = new PointCoordCalculator(
0879: newToScreen, pointCoordCalculator.layerToMap);
0880: for (EditGeom geom : geometries) {
0881: for (PrimitiveShape shape : geom) {
0882: map.putAll(shape.getMutator().transform(
0883: oldToScreen, oldToWorld, calculator));
0884: }
0885: }
0886:
0887: pointCoordCalculator.toScreen.setTransform(newToScreen);
0888: pointCoordCalculator.toWorld
0889: .setTransform(calculator.toWorld);
0890:
0891: if (EditPlugin.isDebugging(EditPlugin.RUN_ASSERTIONS))
0892: for (EditGeom geom : geometries) {
0893: geom.assertValid();
0894: }
0895: }
0896: notify(new EditBlackboardEvent(this , this ,
0897: EventType.TRANFORMATION, new AffineTransform(
0898: oldToScreen), map));
0899: }
0900:
0901: public Selection getSelection() {
0902: return selection;
0903: }
0904:
0905: /**
0906: * Removes all EditGeometries from blackboard and places an empty one on the black board.
0907: */
0908: public void clear() {
0909: EditBlackboardEvent event = null;
0910: synchronized (this ) {
0911: event = new EditBlackboardEvent(this , this ,
0912: EventType.REMOVE_GEOMS, new ArrayList<EditGeom>(
0913: geometries), null);
0914: coordMapping.clear();
0915: geometries.clear();
0916: geomMapping.clear();
0917: geometries.add(new EditGeom(this , null));
0918: selection.doClear();
0919: }
0920: notify(event);
0921: }
0922:
0923: /**
0924: * Removes all the geometries in the list from the blackboard and all the coordinates in the
0925: * geometries
0926: *
0927: * @param geomsToRemove the list of geometries to remove.
0928: */
0929: public List<EditGeom> removeGeometries(
0930: Collection<EditGeom> geomsToRemove) {
0931: ArrayList<EditGeom> removed = new ArrayList<EditGeom>();
0932: synchronized (this ) {
0933: for (EditGeom geom : geomsToRemove) {
0934: if (!geometries.contains(geom)) {
0935: continue;
0936: }
0937: removed.add(geom);
0938: for (PrimitiveShape shape : geom) {
0939: for (int i = 0; i < shape.getNumPoints(); i++) {
0940: Point point = shape.getPoint(i);
0941: List<LazyCoord> coords = shape.getMutator()
0942: .getLazyCoordsAt(i);
0943: coordMapping.get(point).removeAll(coords);
0944: geomMapping.get(point).remove(geom);
0945: }
0946: }
0947: }
0948: geometries.removeAll(geomsToRemove);
0949: }
0950: notify(new EditBlackboardEvent(this , this ,
0951: EventType.REMOVE_GEOMS, removed, null));
0952: return removed;
0953: }
0954:
0955: /**
0956: * Creates a new EditGeom in the map. If there is only one geometry on the bb and it has no
0957: * points and has not been editted it will be removed.
0958: *
0959: * @param featureId The id of the feature the geometry was part of. Maybe null.
0960: * @param type the type of geometry to create if null then the type will be unknown
0961: * @return the created geometry
0962: */
0963: public EditGeom newGeom(String featureId, ShapeType type) {
0964: EditGeom editGeom = new EditGeom(this , featureId);
0965: if (type != null)
0966: editGeom.setShapeType(type);
0967: synchronized (this ) {
0968: if (!geometries.isEmpty() && !geometries.get(0).isChanged()
0969: && geometries.get(0).getShell().getNumPoints() == 0)
0970: geometries.clear();
0971: geometries.add(editGeom);
0972: }
0973: notify(new EditBlackboardEvent(this , this , EventType.ADD_GEOMS,
0974: null, Collections.singletonList(editGeom)));
0975: return editGeom;
0976: }
0977:
0978: /**
0979: * @return Returns the height.
0980: */
0981: public synchronized int getHeight() {
0982: return height;
0983: }
0984:
0985: /**
0986: * @param height The height to set.
0987: */
0988: public synchronized void setHeight(int height) {
0989: this .height = height;
0990: }
0991:
0992: /**
0993: * @return Returns the width.
0994: */
0995: public synchronized int getWidth() {
0996: return width;
0997: }
0998:
0999: /**
1000: * @param width The width to set.
1001: */
1002: public synchronized void setWidth(int width) {
1003: this .width = width;
1004: }
1005:
1006: /**
1007: * @return Returns the collapseVertices.
1008: */
1009: public synchronized boolean isCollapseVertices() {
1010: return this .collapseVertices;
1011: }
1012:
1013: /**
1014: * @param collapseVertices The collapseVertices to set.
1015: */
1016: public synchronized void setCollapseVertices(
1017: boolean collapseVertices) {
1018: this .collapseVertices = collapseVertices;
1019: }
1020:
1021: /**
1022: * Returns the point closest to location. The search is a square of height and width radius + 1.
1023: *
1024: * @param location the locations to start searching from.
1025: * @param radius the distance away from location to search.
1026: * @return the point closest to location or null if no point exists.
1027: */
1028: public Point overVertex(Point location, int radius) {
1029: return overVertex(location, radius, false);
1030: }
1031:
1032: /**
1033: * Returns the point closest to location. If ignore is true the point at locations will not be
1034: * returned. The search is a square of height and width radius + 1.
1035: *
1036: * @param location the locations to start searching from.
1037: * @param radius radius the distance away from location to search.
1038: * @param ignore true if the vertex at location is ignored
1039: * @return the point closest to location or null if no point exists.
1040: */
1041: public synchronized Point overVertex(Point location, int radius,
1042: boolean ignore) {
1043: if (!ignore
1044: && getCoords(location.getX(), location.getY()).size() != 0)
1045: return location;
1046: for (int i = 1; i <= radius; i++) {
1047: Point result = findVertex(location, i);
1048: if (result != null)
1049: return result;
1050: }
1051: return null;
1052: }
1053:
1054: /**
1055: * Changes the behaviour of the EditBlackboard so that events are not fired but batched together
1056: * until {@linkplain #fireBatchedEvents()} is called.
1057: */
1058: public synchronized void startBatchingEvents() {
1059: batchingEvents++;
1060: }
1061:
1062: /**
1063: * Fires all the batched events and resets the EditBlackboard so that it no longer batches
1064: * events.
1065: */
1066: public void fireBatchedEvents() {
1067: List<EditBlackboardEvent> events;
1068: synchronized (this ) {
1069: batchingEvents--;
1070: if (batchingEvents > 0)
1071: return;
1072: events = this .batchedEvents;
1073: this .batchedEvents = new LinkedList<EditBlackboardEvent>();
1074: }
1075:
1076: if (events.isEmpty())
1077: return;
1078:
1079: EditBlackboardListener[] l = listeners
1080: .toArray(new EditBlackboardListener[0]);
1081: startBatchingEvents();
1082: try {
1083: for (EditBlackboardListener listener : l) {
1084: listener.batchChange(events);
1085: }
1086: } finally {
1087: fireBatchedEvents();
1088: }
1089: }
1090:
1091: private LazyCoord doAddCoord(Point p, Coordinate c,
1092: PrimitiveShape hole) {
1093: int index = hole.getNumPoints();
1094: return doInsertCoord(p, c, index, hole);
1095: }
1096:
1097: private LazyCoord doInsertCoord(Point point, Coordinate c,
1098: int pointIndex, PrimitiveShape hole) {
1099: if (hole == null || c == null || point == null)
1100: throw new IllegalArgumentException(
1101: "hole=" + hole + " coordIndex=" + pointIndex + " c=" + c + " p=" + point); //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$
1102:
1103: // So that all the vertices don't make a big mess look around point in a 3x3 radius
1104: // if another point is there add to that point.
1105: Point overLappingPoint = null;
1106: if (collapseVertices)
1107: overLappingPoint = overVertex(point, PreferenceUtil
1108: .instance().getVertexRadius());
1109:
1110: Point p = overLappingPoint;
1111: if (p == null || !collapseVertices)
1112: p = point;
1113:
1114: Coordinate coord = new Coordinate(c);
1115:
1116: Collection<LazyCoord> added = hole.getMutator().addPoint(
1117: pointIndex, p, Collections.singletonList(coord));
1118: LazyCoord lazyCoord = added.iterator().next();
1119: Collection<EditGeom> geomList = updateMappings(p, lazyCoord);
1120:
1121: if (!geomList.contains(hole.getEditGeom()))
1122: geomList.add(hole.getEditGeom());
1123: return lazyCoord;
1124: }
1125:
1126: /**
1127: * Updates the coordMapping and geomMapping ensuring that there are lists at the Point and adds
1128: * c to the CoordMapping.
1129: */
1130: private Set<EditGeom> updateMappings(Point p, LazyCoord c) {
1131: List<LazyCoord> coordList = coordMapping.get(p);
1132: Set<EditGeom> geomList = geomMapping.get(p);
1133: if (coordList == null) {
1134: coordList = new ArrayList<LazyCoord>();
1135: geomList = new HashSet<EditGeom>();
1136: coordMapping.put(p, coordList);
1137: geomMapping.put(p, geomList);
1138: }
1139: coordList.add(c);
1140: return geomList;
1141: }
1142:
1143: private void doAddGeometry(Geometry geom,
1144: Map<Geometry, EditGeom> jtsEditGeomMapping, String featureID) {
1145:
1146: Envelope bbox = geom.getEnvelopeInternal();
1147:
1148: if (geom instanceof GeometryCollection) {
1149: int num = geom.getNumGeometries();
1150: for (int i = 0; i < num; i++) {
1151: doAddGeometry(geom.getGeometryN(i), jtsEditGeomMapping,
1152: featureID);
1153: }
1154: } else {
1155: EditGeom geomShape = new EditGeom(this , featureID, bbox);
1156: geomShape.initializing = true;
1157: geomShape.setShapeType(ShapeType.valueOf(geom));
1158: geometries.add(geomShape);
1159: jtsEditGeomMapping.put(geom, geomShape);
1160:
1161: if (geom instanceof Polygon) {
1162: Polygon poly = (Polygon) geom;
1163: addShell(poly.getExteriorRing(), geomShape);
1164: for (int i = 0, numHoles = poly.getNumInteriorRing(); i < numHoles; i++) {
1165: addHole(poly.getInteriorRingN(i), geomShape, i);
1166: }
1167: } else {
1168: addShell(geom, geomShape);
1169: }
1170: geomShape.initializing = false;
1171:
1172: if (geomShape.isChanged())
1173: geomShape.setChanged(false);
1174: }
1175: }
1176:
1177: private void addHole(Geometry geom, EditGeom geomShape,
1178: int holeIndex) {
1179: PrimitiveShape hole;
1180: if (holeIndex == geomShape.getHoles().size()) {
1181: hole = geomShape.newHole();
1182: } else {
1183: hole = geomShape.getHoles().get(holeIndex);
1184: }
1185:
1186: Coordinate[] coords = geom.getCoordinates();
1187: for (int i = 0; i < coords.length; i++) {
1188: doAddCoord(toPoint(coords[i]), coords[i], hole);
1189: }
1190: }
1191:
1192: private void addShell(Geometry geom, EditGeom editGeom) {
1193: Coordinate[] coords = geom.getCoordinates();
1194: for (int i = 0; i < coords.length; i++) {
1195: doAddCoord(toPoint(coords[i]), coords[i], editGeom
1196: .getShell());
1197: editGeom.getShell().assertValid();
1198: }
1199: }
1200:
1201: void notify(EditBlackboardEvent event) {
1202: if (event == null)
1203: throw new NullPointerException();
1204: EditBlackboardListener[] l = null;
1205: synchronized (this ) {
1206: if (batchingEvents > 0) {
1207: batchedEvents.add(event);
1208: } else {
1209: l = listeners.toArray(new EditBlackboardListener[0]);
1210: }
1211: }
1212: if (l != null) {
1213: for (EditBlackboardListener listener : l) {
1214: listener.changed(event);
1215: }
1216: }
1217: }
1218:
1219: /**
1220: * Searchs for a vertext in a square i pixels away from the location.
1221: *
1222: * @param location center of search
1223: * @param i distance from center to search (is not an area search)
1224: * @param ignore
1225: * @param element
1226: */
1227: private Point findVertex(Point location, int i) {
1228:
1229: final int maxX = location.getX() + i;
1230: final int maxY = location.getY() + i;
1231: final int minX = location.getX() - i;
1232: final int minY = location.getY() - i;
1233:
1234: for (int x = minX; x <= maxX; x++) {
1235: if (getCoords(x, minY).size() > 0)
1236: return Point.valueOf(x, minY);
1237: }
1238:
1239: for (int y = minY + 1; y <= maxY; y++) {
1240: if (getCoords(maxX, y).size() > 0)
1241: return Point.valueOf(maxX, y);
1242: }
1243:
1244: for (int x = maxX - 1; x >= minX; x--) {
1245: if (getCoords(x, maxY).size() > 0)
1246: return Point.valueOf(x, maxY);
1247: }
1248:
1249: for (int y = maxY - 1; y >= minY; y--) {
1250: if (getCoords(minX, y).size() > 0)
1251: return Point.valueOf(minX, y);
1252: }
1253:
1254: return null;
1255: }
1256:
1257: public boolean selectionAdd(Point point) {
1258: return selection.doAdd(point);
1259: }
1260:
1261: public boolean selectionAddAll(Collection<Point> points) {
1262: return selection.doAddAll(points);
1263: }
1264:
1265: public void selectionClear() {
1266: selection.doClear();
1267: }
1268:
1269: public boolean selectionRemoveAll(Collection<Point> points) {
1270: return selection.doRemoveAll(points, true);
1271: }
1272:
1273: public boolean selectionRemove(Point point) {
1274: return selection.doRemove(point);
1275: }
1276:
1277: public boolean selectionRetainAll(Collection<Point> points) {
1278: return selection.doRetainAll(points);
1279: }
1280:
1281: /**
1282: * Returns true if the blackboard currently holds the noted feature ID.
1283: *
1284: * @param fid Feature ID
1285: * @return boolean
1286: */
1287: public boolean contains(String fid) {
1288: List<EditGeom> geoms = getGeoms();
1289: for (EditGeom geom : geoms) {
1290: if (geom.getFeatureIDRef().toString().equals(fid))
1291: return true;
1292: }
1293: return false;
1294: }
1295:
1296: public void setMapLayerTransform(MathTransform mapToLayer) {
1297: AffineTransform oldToScreen = null;
1298: Map<Point, List<Point>> map = new HashMap<Point, List<Point>>();
1299: synchronized (this ) {
1300: if (mapToLayer.equals(pointCoordCalculator.mapToLayer))
1301: return;
1302:
1303: oldToScreen = new AffineTransform(
1304: pointCoordCalculator.toScreen);
1305: AffineTransform oldToWorld = new AffineTransform(
1306: pointCoordCalculator.toWorld);
1307:
1308: geomMapping.clear();
1309: coordMapping.clear();
1310: PointCoordCalculator calculator = new PointCoordCalculator(
1311: pointCoordCalculator.toScreen, mapToLayer);
1312: for (EditGeom geom : geometries) {
1313: for (PrimitiveShape shape : geom) {
1314: map.putAll(shape.getMutator().transform(
1315: oldToScreen, oldToWorld, calculator));
1316: }
1317: }
1318:
1319: pointCoordCalculator.setMapToLayer(mapToLayer);
1320:
1321: if (EditPlugin.isDebugging(EditPlugin.RUN_ASSERTIONS))
1322: for (EditGeom geom : geometries) {
1323: geom.assertValid();
1324: }
1325: }
1326: notify(new EditBlackboardEvent(this , this ,
1327: EventType.TRANFORMATION, oldToScreen, map));
1328:
1329: }
1330:
1331: /**
1332: * Sets all the coordinates at the point to provided coordinate.
1333: * <em>The coodinate must still map to the point</em>
1334: *
1335: * @param point the point at which all the coordinates will be changed
1336: * @param newValue the new coordinate value of coordinates at the point
1337: */
1338: public void setCoords(Point point, Coordinate newValue) {
1339: synchronized (this ) {
1340: if (!toPoint(newValue).equals(point))
1341: throw new IllegalArgumentException(
1342: "newValue has to map to point. newValue maps to: " + toPoint(newValue) //$NON-NLS-1$
1343: + " but should map to" + point); //$NON-NLS-1$
1344: List<LazyCoord> coords = coordMapping.get(point);
1345: for (LazyCoord coord : coords) {
1346: coord.get(point);
1347: coord.coord = newValue;
1348: coord.x = newValue.x;
1349: coord.y = newValue.y;
1350: coord.z = newValue.z;
1351: }
1352: }
1353: }
1354:
1355: }
|