Source Code Cross Referenced for PrimitiveShape.java in  » GIS » udig-1.1 » net » refractions » udig » tools » edit » support » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » GIS » udig 1.1 » net.refractions.udig.tools.edit.support 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* uDig - User Friendly Desktop Internet GIS client
0002:         * http://udig.refractions.net
0003:         * (C) 2004, Refractions Research Inc.
0004:         *
0005:         * This library is free software; you can redistribute it and/or
0006:         * modify it under the terms of the GNU Lesser General Public
0007:         * License as published by the Free Software Foundation;
0008:         * version 2.1 of the License.
0009:         *
0010:         * This library is distributed in the hope that it will be useful,
0011:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013:         * Lesser General Public License for more details.
0014:         */
0015:        package net.refractions.udig.tools.edit.support;
0016:
0017:        import java.awt.Rectangle;
0018:        import java.awt.Shape;
0019:        import java.awt.geom.AffineTransform;
0020:        import java.awt.geom.GeneralPath;
0021:        import java.awt.geom.PathIterator;
0022:        import java.awt.geom.Point2D;
0023:        import java.awt.geom.Rectangle2D;
0024:        import java.util.ArrayList;
0025:        import java.util.Collections;
0026:        import java.util.HashMap;
0027:        import java.util.HashSet;
0028:        import java.util.Iterator;
0029:        import java.util.List;
0030:        import java.util.ListIterator;
0031:        import java.util.Map;
0032:        import java.util.Set;
0033:        import java.util.concurrent.atomic.AtomicReference;
0034:
0035:        import org.eclipse.jface.viewers.IContentProvider;
0036:        import org.eclipse.jface.viewers.TreeViewer;
0037:        import org.eclipse.jface.viewers.Viewer;
0038:
0039:        import net.refractions.udig.project.ui.internal.LayersView;
0040:        import net.refractions.udig.tools.edit.EditPlugin;
0041:        import net.refractions.udig.tools.edit.preferences.PreferenceUtil;
0042:
0043:        import com.vividsolutions.jts.geom.Coordinate;
0044:        import com.vividsolutions.jts.geom.Envelope;
0045:
0046:        /**
0047:         * Represents the simplest shape. GeomShapes are made up of PrimitiveShapes.
0048:         * <p>
0049:         * This is not a composite pattern.
0050:         * </p>
0051:         * 
0052:         * @author jones
0053:         * @since 1.1.0
0054:         */
0055:        public class PrimitiveShape implements  Iterable<Point>, Shape {
0056:            private Map<Point, List<PointCoordMap>> pointsToModel = new HashMap<Point, List<PointCoordMap>>();
0057:            private Map<LazyCoord, PointCoordMap> coordsToModel = new HashMap<LazyCoord, PointCoordMap>();
0058:            private List<PointCoordMap> points = new ArrayList<PointCoordMap>();
0059:            private final List<LazyCoord> coordinates = new ArrayList<LazyCoord>();
0060:            private final AtomicReference<Mutator> mutable = new AtomicReference<Mutator>();
0061:            private final EditGeom owner;
0062:            private Envelope envelope;
0063:
0064:            public PrimitiveShape(EditGeom owner) {
0065:                this .owner = owner;
0066:            }
0067:
0068:            public PrimitiveShape(PrimitiveShape shape) {
0069:                this (shape.owner);
0070:                points.addAll(shape.points);
0071:                for (LazyCoord coord : shape.coordinates) {
0072:                    coordinates.add(new LazyCoord(coord));
0073:                }
0074:            }
0075:
0076:            public int getNumPoints() {
0077:                return points.size();
0078:            }
0079:
0080:            public Point getPoint(int i) {
0081:                return points.get(i).point;
0082:            }
0083:
0084:            public int getNumCoords() {
0085:                return coordinates.size();
0086:            }
0087:
0088:            public Coordinate getCoord(int i) {
0089:                LazyCoord coord = coordinates.get(i);
0090:                Point point = coordsToModel.get(coord).point;
0091:                return coord.get(point);
0092:            }
0093:
0094:            @Override
0095:            public String toString() {
0096:                if (points.size() == 0)
0097:                    return "[]"; //$NON-NLS-1$
0098:                StringBuffer buffer = new StringBuffer("["); //$NON-NLS-1$
0099:                for (PointCoordMap point : points) {
0100:                    buffer.append(point.point.toString());
0101:                    buffer.append(","); //$NON-NLS-1$
0102:                }
0103:                buffer.deleteCharAt(buffer.length() - 1);
0104:                buffer.append("]"); //$NON-NLS-1$
0105:                return buffer.toString();
0106:            }
0107:
0108:            Mutator getMutator() {
0109:                // Since all copies of a mutable do the same thing this race condition doesn't matter.
0110:                if (mutable.get() == null)
0111:                    mutable.set(new Mutator());
0112:                return mutable.get();
0113:            }
0114:
0115:            class Mutator implements  Iterable<Point> {
0116:
0117:                /**
0118:                 * Adds a point and its corresponding coordinate
0119:                 * 
0120:                 * @param p point to add
0121:                 * @param coords corresponding coordinate or null.
0122:                 */
0123:                public void addPoint(Point p, List<Coordinate> coords) {
0124:                    addPoint(points.size(), p, coords);
0125:                }
0126:
0127:                /**
0128:                 * Adds a point and its corresponding coordinate
0129:                 * 
0130:                 * @param i index of point location. Coordinate will be added as the last of the coordinates
0131:                 *        at that location.
0132:                 * @param p point to add
0133:                 * @param coords corresponding coordinate or null.
0134:                 */
0135:                public List<LazyCoord> addPoint(int i, Point p,
0136:                        List<Coordinate> coords) {
0137:                    List<Coordinate> c = coords;
0138:                    PointCoordMap bag = getBag(i, p);
0139:                    if (c == null)
0140:                        c = Collections.singletonList(getEditBlackboard()
0141:                                .toCoord(p));
0142:                    List<LazyCoord> lazyCoords = addAll(bag.coords.size(),
0143:                            bag.coords, p, c);
0144:                    List<PointCoordMap> bags = pointsToModel.get(p);
0145:                    if (bags == null) {
0146:                        bags = new ArrayList<PointCoordMap>();
0147:                        pointsToModel.put(p, bags);
0148:                    }
0149:                    if (!bags.contains(bag))
0150:                        bags.add(bag);
0151:
0152:                    int index;
0153:                    if (coordinates.size() == 0)
0154:                        index = 0;
0155:                    else if (bag.coords.size() > 1) {
0156:                        LazyCoord lazyCoord = bag.coords
0157:                                .get(bag.coords.size() - 2);
0158:                        index = coordinates.indexOf(lazyCoord) + 1;
0159:                    } else if (i == 0) {
0160:                        index = 0;
0161:                    } else {
0162:                        // add after last coordinate in last bag
0163:                        PointCoordMap lastbag = points.get(i - 1);
0164:                        if (lastbag == bag)
0165:                            lastbag = points.get(i - 2);
0166:
0167:                        index = coordinates.indexOf(lastbag.coords
0168:                                .get(lastbag.coords.size() - 1)) + 1;
0169:                    }
0170:
0171:                    for (LazyCoord coord : lazyCoords) {
0172:                        coordinates.add(index++, coord);
0173:                        coordsToModel.put(coord, bag);
0174:                    }
0175:                    if (!owner.initializing)
0176:                        getEditGeom().setChanged(true);
0177:                    return lazyCoords;
0178:                }
0179:
0180:                private List<LazyCoord> addAll(int i,
0181:                        List<LazyCoord> coordinates, Point p, List<Coordinate> c) {
0182:                    int j = i;
0183:                    EditBlackboard bb = getEditBlackboard();
0184:                    ArrayList<LazyCoord> coords = new ArrayList<LazyCoord>(c
0185:                            .size());
0186:                    for (Coordinate coordinate : c) {
0187:                        LazyCoord lazyCoord = new LazyCoord(p, coordinate, bb);
0188:                        coordinates.add(j++, lazyCoord);
0189:                        coords.add(lazyCoord);
0190:                    }
0191:                    return coords;
0192:                }
0193:
0194:                private PointCoordMap getBag(int i, Point p) {
0195:                    // if previous point or next point is same as point to add then return that bag
0196:                    if (i > 0 && i <= points.size()) {
0197:                        if (points.get(i - 1).point.equals(p)) {
0198:                            return points.get(i - 1);
0199:                        }
0200:                        if (points.size() > i + 1
0201:                                && points.get(i + 1).point.equals(p)) {
0202:                            return points.get(i + 1);
0203:                        }
0204:                    }
0205:                    PointCoordMap bag = new PointCoordMap(p);
0206:                    points.add(i, bag);
0207:                    return bag;
0208:                }
0209:
0210:                /**
0211:                 * Adds a coordinate
0212:                 * 
0213:                 * @param i index of coordinate to add.
0214:                 * @param c corresponding coordinate or null.
0215:                 */
0216:                public void addCoordinate(int i, Coordinate c) {
0217:                    Point p = getEditBlackboard().toPoint(c);
0218:                    coordinates
0219:                            .add(i, new LazyCoord(p, c, getEditBlackboard()));
0220:                    // /TODO
0221:                    getEditGeom().setChanged(true);
0222:                }
0223:
0224:                /**
0225:                 * Remove a point and all the coordinates mapping to it.
0226:                 * 
0227:                 * @param i index of point to remove
0228:                 */
0229:                public Point removePoint(int i) {
0230:                    PointCoordMap p = points.remove(i);
0231:                    pointsToModel.remove(p.point);
0232:                    List<LazyCoord> coords = p.coords;
0233:                    for (LazyCoord coord : coords) {
0234:                        for (Iterator<LazyCoord> iter = coordinates.iterator(); iter
0235:                                .hasNext();) {
0236:                            if (iter.next() == coord) {
0237:                                iter.remove();
0238:                            }
0239:                        }
0240:                    }
0241:                    getEditGeom().setChanged(true);
0242:                    return p.point;
0243:                }
0244:
0245:                /**
0246:                 * Remove a coordinate at location i. Mapped points will be deleted too.
0247:                 * 
0248:                 * @param i index of coordinate to remove
0249:                 */
0250:                public Coordinate removeCoordinate(int i) {
0251:                    getEditGeom().setChanged(true);
0252:                    LazyCoord coord = coordinates.remove(i);
0253:                    return coord.get(coordsToModel.get(coord).point);
0254:                }
0255:
0256:                /**
0257:                 * Remove a point and all the coordinates mapping to it.
0258:                 */
0259:                public boolean remove(Point p) {
0260:                    List<PointCoordMap> mods = pointsToModel.get(p);
0261:                    if (mods == null || mods.size() == 0)
0262:                        return false;
0263:
0264:                    int min = Integer.MAX_VALUE;
0265:                    int firstBag = 0;
0266:                    int current = 0;
0267:                    for (Iterator<PointCoordMap> iter = mods.iterator(); iter
0268:                            .hasNext();) {
0269:                        PointCoordMap element = iter.next();
0270:                        int i = points.indexOf(element);
0271:                        if (i < min) {
0272:                            min = i;
0273:                            firstBag = current;
0274:                        }
0275:                        current++;
0276:                    }
0277:
0278:                    PointCoordMap shapePoint = mods.remove(firstBag);
0279:                    points.remove(shapePoint);
0280:                    coordinates.removeAll(shapePoint.coords);
0281:                    getEditGeom().setChanged(true);
0282:                    return true;
0283:                }
0284:
0285:                /**
0286:                 * Remove a coordinate at location i. Mapped points will be deleted too.
0287:                 * 
0288:                 * @param i index of coordinate to remove
0289:                 */
0290:                public boolean remove(Coordinate c) {
0291:                    getEditGeom().setChanged(true);
0292:                    return coordinates.remove(c);
0293:                }
0294:
0295:                public LazyCoord removePoint(int pointIndex, Coordinate coord) {
0296:
0297:                    PointCoordMap p = points.get(pointIndex);
0298:                    LazyCoord lcoord = null;
0299:                    for (Iterator<LazyCoord> iter = p.coords.iterator(); iter
0300:                            .hasNext();) {
0301:                        LazyCoord lc = iter.next();
0302:                        if (lc.coord.equals(coord)) {
0303:                            lcoord = lc;
0304:                            iter.remove();
0305:                            break;
0306:                        }
0307:                    }
0308:
0309:                    if (p.coords.isEmpty()) {
0310:                        points.remove(pointIndex);
0311:                        List<PointCoordMap> bags = pointsToModel.get(p.point);
0312:                        bags.remove(p);
0313:                        if (bags.isEmpty())
0314:                            pointsToModel.remove(p.point);
0315:                    }
0316:
0317:                    if (lcoord == null)
0318:                        return null;
0319:
0320:                    for (Iterator<LazyCoord> iter = coordinates.iterator(); iter
0321:                            .hasNext();) {
0322:                        LazyCoord next = iter.next();
0323:                        if (next == lcoord) {
0324:                            iter.remove();
0325:                            coordsToModel.remove(next);
0326:                        }
0327:                    }
0328:                    getEditGeom().setChanged(true);
0329:                    return lcoord;
0330:                }
0331:
0332:                /**
0333:                 * Resets shape
0334:                 */
0335:                public void clear() {
0336:                    getEditGeom().setChanged(true);
0337:                    coordinates.clear();
0338:                    points.clear();
0339:                }
0340:
0341:                public boolean hasPoint(Point pointOnLine) {
0342:                    return pointsToModel.containsKey(pointOnLine);
0343:                }
0344:
0345:                /**
0346:                 * @return Returns an iterator that iterates over all points in shape.
0347:                 */
0348:                public ListIterator<Point> iterator() {
0349:                    return new ListIterator<Point>() {
0350:                        ListIterator<PointCoordMap> iter = points
0351:                                .listIterator();
0352:                        PointCoordMap current;
0353:
0354:                        public boolean hasNext() {
0355:                            return iter.hasNext();
0356:                        }
0357:
0358:                        public Point next() {
0359:                            current = iter.next();
0360:                            return current.point;
0361:                        }
0362:
0363:                        public boolean hasPrevious() {
0364:                            return iter.hasPrevious();
0365:                        }
0366:
0367:                        public Point previous() {
0368:                            current = iter.previous();
0369:                            return current.point;
0370:                        }
0371:
0372:                        public int nextIndex() {
0373:                            return iter.nextIndex();
0374:                        }
0375:
0376:                        public int previousIndex() {
0377:                            return iter.previousIndex();
0378:                        }
0379:
0380:                        public void remove() {
0381:                            iter.remove();
0382:                        }
0383:
0384:                        public void set(Point o) {
0385:                            List<PointCoordMap> maps = pointsToModel
0386:                                    .get(current.point);
0387:                            maps.remove(current);
0388:                            if (maps.isEmpty())
0389:                                pointsToModel.remove(current.point);
0390:                            maps = pointsToModel.get(o);
0391:                            if (maps == null) {
0392:                                maps = new ArrayList<PointCoordMap>();
0393:                                pointsToModel.put(o, maps);
0394:                            }
0395:                            maps.add(current);
0396:                            current.point = o;
0397:                            getEditGeom().setChanged(true);
0398:                        }
0399:
0400:                        public void add(Point o) {
0401:
0402:                            ArrayList<LazyCoord> list = new ArrayList<LazyCoord>();
0403:                            list.add(new LazyCoord(o, getEditBlackboard()
0404:                                    .toCoord(o), getEditBlackboard()));
0405:                            iter.add(new PointCoordMap(o, list));
0406:                            getEditGeom().setChanged(true);
0407:                        }
0408:
0409:                    };
0410:                }
0411:
0412:                /**
0413:                 * @return Returns an iterator that iterates over all coordinates in shape. May be modified
0414:                 */
0415:                public ListIterator<Coordinate> coordIterator() {
0416:
0417:                    return new ListIterator<Coordinate>() {
0418:
0419:                        ListIterator<LazyCoord> iter = coordinates
0420:                                .listIterator();
0421:                        private LazyCoord current;
0422:
0423:                        public boolean hasNext() {
0424:                            return iter.hasNext();
0425:                        }
0426:
0427:                        public Coordinate next() {
0428:                            current = iter.next();
0429:                            return current
0430:                                    .get(coordsToModel.get(current).point);
0431:                        }
0432:
0433:                        public boolean hasPrevious() {
0434:                            return iter.hasPrevious();
0435:                        }
0436:
0437:                        public Coordinate previous() {
0438:                            current = iter.previous();
0439:                            return current
0440:                                    .get(coordsToModel.get(current).point);
0441:                        }
0442:
0443:                        public int nextIndex() {
0444:                            return iter.nextIndex();
0445:                        }
0446:
0447:                        public int previousIndex() {
0448:                            return iter.previousIndex();
0449:                        }
0450:
0451:                        public void remove() {
0452:                            iter.remove();
0453:                            PointCoordMap bag = coordsToModel.remove(current);
0454:                            points.remove(bag.point);
0455:                        }
0456:
0457:                        public void set(Coordinate o) {
0458:                            current.set(o, getEditBlackboard().toPoint(o));
0459:                        }
0460:
0461:                        public void add(Coordinate o) {
0462:                            addPoint(iter.nextIndex() - 1, getEditBlackboard()
0463:                                    .toPoint(o), Collections.singletonList(o));
0464:                        }
0465:
0466:                    };
0467:                }
0468:
0469:                /**
0470:                 *
0471:                 */
0472:                public void reverse() {
0473:                    Collections.reverse(points);
0474:                    Collections.reverse(coordinates);
0475:                }
0476:
0477:                public List<LazyCoord> getLazyCoordsAt(int i) {
0478:                    return points.get(i).coords;
0479:                }
0480:
0481:                /**
0482:                 * Applies the transform to all the points in the shape. This is the start of a migration.
0483:                 * This method will update the EditBlackboard rather than the edit blackboard updating
0484:                 * itself and the Primitive Shape. The pointCoordCalculator must have been updated already
0485:                 * with the new toScreen and toWorld transforms.
0486:                 * 
0487:                 * @param oldToNew
0488:                 */
0489:                Map<? extends Point, ? extends List<Point>> transform(
0490:                        AffineTransform oldToScreen,
0491:                        AffineTransform oldToWorld,
0492:                        PointCoordCalculator pointCoordCalculator) {
0493:                    if (Math.abs(pointCoordCalculator.toScreen.getDeterminant()
0494:                            - oldToScreen.getDeterminant()) > 0.000001) {
0495:                        return transformInternal(pointCoordCalculator);
0496:                    } else {
0497:
0498:                        return translate(AffineTransform.getTranslateInstance(
0499:                                pointCoordCalculator.toScreen.getTranslateX()
0500:                                        - oldToScreen.getTranslateX(),
0501:                                pointCoordCalculator.toScreen.getTranslateY()
0502:                                        - oldToScreen.getTranslateY()));
0503:                    }
0504:                }
0505:
0506:                private HashMap<Point, List<Point>> transformInternal(
0507:                        PointCoordCalculator pointCoordCalculator) {
0508:                    List<PointCoordMap> oldPoints = points;
0509:
0510:                    HashMap<Point, List<Point>> oldPointToNew = new HashMap<Point, List<Point>>();
0511:
0512:                    points = new ArrayList<PointCoordMap>();
0513:                    pointsToModel.clear();
0514:                    coordsToModel.clear();
0515:                    EditBlackboard editBlackboard = owner.getEditBlackboard();
0516:
0517:                    for (PointCoordMap map : oldPoints) {
0518:                        Point oldPoint = map.point;
0519:                        for (Iterator<LazyCoord> iter = map.coords.iterator(); iter
0520:                                .hasNext();) {
0521:                            LazyCoord c = iter.next();
0522:                            PointCoordMap tmp = map;
0523:                            Coordinate coord = c.get(oldPoint);
0524:
0525:                            Point newPoint = pointCoordCalculator
0526:                                    .toPoint(coord);
0527:                            // So that all the vertices don't make a big mess look around point in a 3x3
0528:                            // radius
0529:                            // if another point is there add to that point.
0530:                            Point overLappingPoint;
0531:                            overLappingPoint = getEditBlackboard()
0532:                                    .overVertex(
0533:                                            newPoint,
0534:                                            PreferenceUtil.instance()
0535:                                                    .getVertexRadius());
0536:
0537:                            if (overLappingPoint != null
0538:                                    && getEditBlackboard().isCollapseVertices())
0539:                                newPoint = overLappingPoint;
0540:
0541:                            if (!newPoint.equals(oldPoint)) {
0542:                                tmp = new PointCoordMap(newPoint);
0543:                                tmp.coords.add(c);
0544:                                iter.remove();
0545:                            }
0546:
0547:                            c.pointCoordCalculator = new PointCoordCalculator(
0548:                                    pointCoordCalculator);
0549:                            c.start = newPoint;
0550:
0551:                            List<Point> pointMapping = oldPointToNew
0552:                                    .get(oldPoint);
0553:                            if (pointMapping == null) {
0554:                                pointMapping = new ArrayList<Point>();
0555:                                pointMapping.add(newPoint);
0556:                                oldPointToNew.put(oldPoint, pointMapping);
0557:                            } else {
0558:                                pointMapping.add(newPoint);
0559:                            }
0560:                            tmp.point = newPoint;
0561:
0562:                            coordsToModel.put(c, tmp);
0563:
0564:                            // update shape
0565:                            points.add(tmp);
0566:                            List<PointCoordMap> list = pointsToModel
0567:                                    .get(newPoint);
0568:                            if (list == null) {
0569:                                List<PointCoordMap> l = new ArrayList<PointCoordMap>();
0570:                                l.add(tmp);
0571:                                pointsToModel.put(newPoint, l);
0572:                            } else {
0573:                                list.add(tmp);
0574:                            }
0575:
0576:                            // update Blackboard.
0577:                            List<LazyCoord> coords = editBlackboard.coordMapping
0578:                                    .get(newPoint);
0579:                            if (coords == null) {
0580:                                List<LazyCoord> l = new ArrayList<LazyCoord>(
0581:                                        tmp.coords);
0582:                                editBlackboard.coordMapping.put(newPoint, l);
0583:                            } else {
0584:                                coords.addAll(tmp.coords);
0585:                            }
0586:
0587:                            Set<EditGeom> mappedGeoms = editBlackboard.geomMapping
0588:                                    .get(newPoint);
0589:                            if (mappedGeoms == null) {
0590:                                Set<EditGeom> l = new HashSet<EditGeom>();
0591:                                l.add(getEditGeom());
0592:                                editBlackboard.geomMapping.put(newPoint, l);
0593:                            } else {
0594:                                if (!mappedGeoms.contains(getEditGeom()))
0595:                                    mappedGeoms.add(getEditGeom());
0596:                            }
0597:
0598:                        }
0599:                    }
0600:                    return oldPointToNew;
0601:                }
0602:
0603:                private Map<? extends Point, ? extends List<Point>> translate(
0604:                        AffineTransform oldToNew) {
0605:                    List<PointCoordMap> oldPoints = points;
0606:
0607:                    HashMap<Point, List<Point>> oldPointToNew = new HashMap<Point, List<Point>>();
0608:
0609:                    points = new ArrayList<PointCoordMap>();
0610:                    pointsToModel.clear();
0611:                    EditBlackboard editBlackboard = owner.getEditBlackboard();
0612:
0613:                    int diffX = (int) oldToNew.getTranslateX();
0614:                    int diffY = (int) oldToNew.getTranslateY();
0615:                    for (PointCoordMap map : oldPoints) {
0616:
0617:                        Point newPoint = Point.valueOf(
0618:                                map.point.getX() + diffX, map.point.getY()
0619:                                        + diffY);
0620:                        List<Point> pointMapping = oldPointToNew.get(map.point);
0621:                        if (pointMapping == null) {
0622:                            pointMapping = new ArrayList<Point>();
0623:                            pointMapping.add(newPoint);
0624:                            oldPointToNew.put(map.point, pointMapping);
0625:                        } else {
0626:                            pointMapping.add(newPoint);
0627:                        }
0628:                        map.point = newPoint;
0629:
0630:                        // update shape
0631:                        points.add(map);
0632:                        List<PointCoordMap> list = pointsToModel.get(newPoint);
0633:                        if (list == null) {
0634:                            List<PointCoordMap> l = new ArrayList<PointCoordMap>();
0635:                            l.add(map);
0636:                            pointsToModel.put(newPoint, l);
0637:                        } else {
0638:                            list.add(map);
0639:                        }
0640:
0641:                        // update Blackboard.
0642:                        List<LazyCoord> coords = editBlackboard.coordMapping
0643:                                .get(newPoint);
0644:                        if (coords == null) {
0645:                            List<LazyCoord> l = new ArrayList<LazyCoord>(
0646:                                    map.coords);
0647:                            editBlackboard.coordMapping.put(newPoint, l);
0648:                        } else {
0649:                            coords.addAll(map.coords);
0650:                        }
0651:
0652:                        Set<EditGeom> mappedGeoms = editBlackboard.geomMapping
0653:                                .get(newPoint);
0654:                        if (mappedGeoms == null) {
0655:                            Set<EditGeom> l = new HashSet<EditGeom>();
0656:                            l.add(getEditGeom());
0657:                            editBlackboard.geomMapping.put(newPoint, l);
0658:                        } else {
0659:                            if (!mappedGeoms.contains(getEditGeom()))
0660:                                mappedGeoms.add(getEditGeom());
0661:                        }
0662:
0663:                    }
0664:                    return oldPointToNew;
0665:                }
0666:
0667:                /**
0668:                 * Moves a single LazyCoord from the start point to the end point. Keeps the order of the
0669:                 * coordinates in the same order.
0670:                 * 
0671:                 * @param start
0672:                 * @param end
0673:                 * @param coord
0674:                 */
0675:                public void move(Point start, Point end, LazyCoord coord) {
0676:
0677:                    PointCoordMap toRemove = null;
0678:
0679:                    for (PointCoordMap map : pointsToModel.get(start)) {
0680:                        if (map.coords.contains(coord)) {
0681:                            List<PointCoordMap> startBags = pointsToModel
0682:                                    .get(start);
0683:                            PointCoordMap endBag = null;
0684:                            int startIndex = points.indexOf(map);
0685:                            PointCoordMap before = new PointCoordMap(start);
0686:                            endBag = new PointCoordMap(end);
0687:                            PointCoordMap after = new PointCoordMap(start);
0688:
0689:                            points.remove(startIndex);
0690:                            int i = 0;
0691:                            for (LazyCoord coord2 : map.coords) {
0692:                                if (i < map.coords.indexOf(coord)) {
0693:                                    before.coords.add(coord2);
0694:                                    coordsToModel.put(coord2, before);
0695:                                } else if (i > map.coords.indexOf(coord)) {
0696:                                    after.coords.add(coord2);
0697:                                    coordsToModel.put(coord2, after);
0698:                                }
0699:                                i++;
0700:                            }
0701:                            boolean addedBefore = false;
0702:                            boolean addedAfter = false;
0703:                            if (before.coords.size() > 0) {
0704:                                points.add(startIndex, before);
0705:                                startBags.add(before);
0706:                                addedBefore = true;
0707:                            }
0708:                            points.add(addedBefore ? startIndex + 1
0709:                                    : startIndex, endBag);
0710:                            if (after.coords.size() > 0) {
0711:                                points.add(addedBefore ? startIndex + 2
0712:                                        : startIndex + 1, after);
0713:                                startBags.add(after);
0714:                                addedAfter = true;
0715:                            }
0716:
0717:                            toRemove = map;
0718:                            List<PointCoordMap> endBags = pointsToModel
0719:                                    .get(end);
0720:
0721:                            if (endBags == null) {
0722:                                endBags = new ArrayList<PointCoordMap>();
0723:                                pointsToModel.put(end, endBags);
0724:                            }
0725:                            if (!endBags.contains(endBag))
0726:                                endBags.add(endBag);
0727:
0728:                            endBag.coords.add(coord);
0729:                            coordsToModel.put(coord, endBag);
0730:
0731:                            if (addedBefore && !addedAfter || !addedBefore
0732:                                    && addedAfter) {
0733:                                attemptBeforeAndAfterVertexCollapse(startIndex);
0734:                                attemptBeforeAndAfterVertexCollapse(startIndex + 1);
0735:                            } else if (addedBefore && addedAfter) {
0736:                                attemptBeforeAndAfterVertexCollapse(startIndex);
0737:                                attemptBeforeAndAfterVertexCollapse(startIndex + 2);
0738:                            } else if (!addedBefore && !addedAfter) {
0739:                                attemptBeforeAndAfterVertexCollapse(startIndex);
0740:                            }
0741:
0742:                        }
0743:
0744:                        break;
0745:                    }
0746:
0747:                    if (toRemove != null) {
0748:                        pointsToModel.get(start).remove(toRemove);
0749:                    }
0750:                }
0751:
0752:                private void attemptBeforeAndAfterVertexCollapse(int index) {
0753:                    if (points.size() == 1 || index > points.size() - 1)
0754:                        return;
0755:
0756:                    int before = index - 1;
0757:                    int after = index + 1;
0758:
0759:                    if (before > -1) {
0760:                        boolean changed = doCollapseVertices(index, before);
0761:                        if (changed) {
0762:                            index = before;
0763:                            after--;
0764:                        }
0765:                    }
0766:
0767:                    if (after < points.size()) {
0768:                        doCollapseVertices(after, index);
0769:                    }
0770:                }
0771:
0772:                private boolean doCollapseVertices(int index, int before) {
0773:                    boolean changed = false;
0774:                    PointCoordMap currentMap = points.get(index);
0775:                    PointCoordMap beforeMap = points.get(before);
0776:                    if (currentMap.point.equals(beforeMap.point)) {
0777:                        changed = true;
0778:                        points.remove(index);
0779:                        pointsToModel.get(currentMap.point).remove(currentMap);
0780:
0781:                        for (LazyCoord coord : currentMap.coords) {
0782:                            coordsToModel.put(coord, beforeMap);
0783:                            beforeMap.coords.add(coord);
0784:                        }
0785:                    }
0786:                    return changed;
0787:                }
0788:
0789:                public Iterator<Point> getCopyIterator() {
0790:                    return new Iterator<Point>() {
0791:                        List<PointCoordMap> newPoints = new ArrayList<PointCoordMap>(
0792:                                points);
0793:                        Iterator<PointCoordMap> iter;
0794:
0795:                        public boolean hasNext() {
0796:                            if (iter == null)
0797:                                iter = newPoints.iterator();
0798:                            return iter.hasNext();
0799:                        }
0800:
0801:                        public Point next() {
0802:                            if (iter == null)
0803:                                iter = newPoints.iterator();
0804:                            return iter.next().point;
0805:                        }
0806:
0807:                        public void remove() {
0808:                            throw new IllegalArgumentException(
0809:                                    "not supported; to inefficient"); //$NON-NLS-1$
0810:                        }
0811:
0812:                    };
0813:                }
0814:
0815:                /**
0816:                 * Returns lazycoords at point.
0817:                 * 
0818:                 * @param point
0819:                 * @return
0820:                 */
0821:                public List<LazyCoord> getLazyCoordsAt(Point point) {
0822:                    List<PointCoordMap> bags = pointsToModel.get(point);
0823:                    List<LazyCoord> coords = new ArrayList<LazyCoord>();
0824:                    if (bags == null) {
0825:                        return Collections.<LazyCoord> emptyList();
0826:                    }
0827:                    for (PointCoordMap map : bags) {
0828:                        coords.addAll(map.coords);
0829:                    }
0830:
0831:                    return coords;
0832:                }
0833:
0834:                public void move(int deltaX, int deltaY) {
0835:                    Map<Point, List<PointCoordMap>> newPointsToModel = new HashMap<Point, List<PointCoordMap>>();
0836:
0837:                    for (Point point : this ) {
0838:                        Point dest = Point.valueOf(point.getX() + deltaX, point
0839:                                .getY()
0840:                                + deltaY);
0841:                        List<PointCoordMap> oldBags = pointsToModel
0842:                                .remove(point);
0843:
0844:                        if (oldBags == null)
0845:                            continue;
0846:
0847:                        newPointsToModel.put(dest, oldBags);
0848:
0849:                        for (PointCoordMap map : oldBags) {
0850:                            map.point = dest;
0851:                        }
0852:                    }
0853:
0854:                    for (Map.Entry<Point, List<PointCoordMap>> entry : newPointsToModel
0855:                            .entrySet()) {
0856:                        List<PointCoordMap> newBags = pointsToModel.get(entry
0857:                                .getKey());
0858:                        if (newBags == null) {
0859:                            pointsToModel.put(entry.getKey(), entry.getValue());
0860:                        } else {
0861:                            newBags.addAll(entry.getValue());
0862:                        }
0863:                    }
0864:
0865:                    pointsToModel = newPointsToModel;
0866:
0867:                }
0868:
0869:            }
0870:
0871:            /**
0872:             * @return Returns the owner.
0873:             */
0874:            public EditGeom getEditGeom() {
0875:                return owner;
0876:            }
0877:
0878:            public EditBlackboard getEditBlackboard() {
0879:                return owner.getEditBlackboard();
0880:            }
0881:
0882:            /**
0883:             * @return Returns an iterator that iterates over all visible points in shape. Not modifyable
0884:             */
0885:            public Iterator<Point> iterator() {
0886:                final PointCoordMap[] array = points
0887:                        .toArray(new PointCoordMap[points.size()]);
0888:                return new Iterator<Point>() {
0889:                    int i = -1;
0890:
0891:                    public boolean hasNext() {
0892:                        return i < array.length - 1;
0893:                    }
0894:
0895:                    public Point next() {
0896:                        i++;
0897:                        return array[i].point;
0898:                    }
0899:
0900:                    public void remove() {
0901:                        throw new UnsupportedOperationException(
0902:                                "This is iterator does not allow modification"); //$NON-NLS-1$
0903:                    }
0904:                };
0905:            }
0906:
0907:            /**
0908:             * @return Returns an iterator that iterates over all visible coordinates in shape. Not
0909:             *         modifyible
0910:             */
0911:            public Iterator<Coordinate> coordIterator() {
0912:                return getMutator().coordIterator();
0913:            }
0914:
0915:            private static class PointCoordMap {
0916:                Point point;
0917:                final List<LazyCoord> coords;
0918:
0919:                public PointCoordMap(Point p, List<LazyCoord> coords) {
0920:                    point = p;
0921:                    this .coords = coords;
0922:                }
0923:
0924:                public PointCoordMap(Point p) {
0925:                    point = p;
0926:                    this .coords = new ArrayList<LazyCoord>();
0927:                }
0928:
0929:                @Override
0930:                public String toString() {
0931:                    return "{" + point + "=" + coords + "}"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
0932:                }
0933:            }
0934:
0935:            /**
0936:             * Returns an array with all the coordinates in shape.
0937:             * 
0938:             * @return an array with all the coordinates in shape.
0939:             */
0940:            public Coordinate[] coordArray() {
0941:                Coordinate[] array = new Coordinate[coordinates.size()];
0942:                Iterator<Coordinate> iter = coordIterator();
0943:                for (int i = 0; i < array.length; i++) {
0944:                    array[i] = iter.next();
0945:                }
0946:                return array;
0947:            }
0948:
0949:            /**
0950:             * returns true if the point is contained in this shape.
0951:             * 
0952:             * @param p an arbitrary point
0953:             * @return Returns true if the point is contained in this shape.
0954:             */
0955:            public boolean hasVertex(Point p) {
0956:                return pointsToModel.containsKey(p);
0957:            }
0958:
0959:            boolean hasVertex(Point p, LazyCoord coord) {
0960:                List<PointCoordMap> list = pointsToModel.get(p);
0961:                if (list == null)
0962:                    return false;
0963:
0964:                for (PointCoordMap map : list) {
0965:                    if (map.coords == null)
0966:                        return false;
0967:                    for (LazyCoord coord2 : map.coords) {
0968:                        if (coord2 == coord)
0969:                            return true;
0970:                    }
0971:                }
0972:                return false;
0973:            }
0974:
0975:            /**
0976:             * Returns a {@link ClosestEdge} object that has information about the point that closest to the
0977:             * click paramter and is on an edge of the part.
0978:             * 
0979:             * @param click the point to use as the reference point
0980:             * @return
0981:             */
0982:            public ClosestEdge getClosestEdge(Point click,
0983:                    boolean treatUnknownAsPolygon) {
0984:                if (getNumPoints() == 0)
0985:                    return null;
0986:                final int endIndex;
0987:                int startIndex, lastIndex;
0988:                Point coord1;
0989:
0990:                if ((getEditGeom().getShapeType() == ShapeType.UNKNOWN && treatUnknownAsPolygon)
0991:                        || getEditGeom().getShapeType() == ShapeType.POLYGON) {
0992:                    lastIndex = getNumPoints() - 1;
0993:                    coord1 = getPoint(lastIndex);
0994:                    startIndex = 0;
0995:                    endIndex = getNumPoints() - 1;
0996:                } else if ((getEditGeom().getShapeType() == ShapeType.UNKNOWN && !treatUnknownAsPolygon)
0997:                        || getEditGeom().getShapeType() == ShapeType.LINE) {
0998:                    lastIndex = 0;
0999:                    coord1 = getPoint(lastIndex);
1000:                    startIndex = 1;
1001:                    endIndex = getNumPoints() - 1;
1002:
1003:                } else {
1004:                    // points don't have edges
1005:                    return null;
1006:                }
1007:
1008:                double mindist = Double.MAX_VALUE;
1009:
1010:                int prev = -1;
1011:                Point closestPoint = null;
1012:                for (int i = startIndex; i <= endIndex; i++) {
1013:                    Point coord2 = getPoint(i);
1014:                    try {
1015:                        Point point = EditUtils.instance.closestPointOnEdge(
1016:                                coord1, coord2, click);
1017:                        if (point == null) {
1018:                            continue;
1019:                        }
1020:                        int x = click.getX() - point.getX();
1021:                        int y = click.getY() - point.getY();
1022:                        double dist = Math.sqrt(x * x + y * y);
1023:                        if (dist < mindist) {
1024:                            mindist = dist;
1025:                            prev = lastIndex;
1026:                            closestPoint = point;
1027:                        }
1028:                    } finally {
1029:                        coord1 = coord2;
1030:                        lastIndex = i;
1031:                    }
1032:                }
1033:
1034:                if (closestPoint == null)
1035:                    return null;
1036:                return new ClosestEdge(mindist, prev, closestPoint, this );
1037:            }
1038:
1039:            /**
1040:             * Returns the bounding box of the Shape in pixel space.
1041:             * 
1042:             * @return the bounding box of the Shape in pixel space.
1043:             */
1044:            public Rectangle getBounds() {
1045:                int minx = Integer.MAX_VALUE;
1046:                int maxx = Integer.MIN_VALUE;
1047:                int miny = Integer.MAX_VALUE;
1048:                int maxy = Integer.MIN_VALUE;
1049:                for (Point point : getMutator()) {
1050:                    if (point.getX() < minx)
1051:                        minx = point.getX();
1052:                    if (point.getX() > maxx)
1053:                        maxx = point.getX();
1054:                    if (point.getY() < miny)
1055:                        miny = point.getY();
1056:                    if (point.getY() > maxy)
1057:                        maxy = point.getY();
1058:                }
1059:
1060:                return new Rectangle(minx, miny, maxx - minx, maxy - miny);
1061:            }
1062:
1063:            /**
1064:             * Returns true if the point is contained in the shape or on the edge. It is considered on the
1065:             * edge if it is within {@link PreferenceUtil#getVertexRadius()} of the edge.
1066:             * 
1067:             * @param point An astrbitrary point
1068:             * @param treatUnknownGeomsAsPolygon if {@link EditGeom#getShapeType()} return UNKOWN this
1069:             *        parameter is used to determine if this shape should be considered a polygon.
1070:             * @return true if the point is contained in the shape.
1071:             */
1072:            public boolean contains(Point point,
1073:                    boolean treatUnknownGeomsAsPolygon) {
1074:                return contains(point, treatUnknownGeomsAsPolygon, false);
1075:            }
1076:
1077:            /**
1078:             * Returns true if the point is contained in the shape or on the edge.
1079:             * 
1080:             * @param point An astrbitrary point
1081:             * @param treatUnknownGeomsAsPolygon if {@link EditGeom#getShapeType()} return UNKOWN this
1082:             *        parameter is used to determine if this shape should be considered a polygon.
1083:             * @param ignoreVertexRadius if true then the point is only considered to be on the edge if it
1084:             *        is directly on the edge. (within 1 pixel of the line).
1085:             * @return true if the point is contained in the shape.
1086:             */
1087:            public boolean contains(Point point,
1088:                    boolean treatUnknownGeomsAsPolygon,
1089:                    boolean ignoreVertexRadius) {
1090:
1091:                if (points.size() == 0)
1092:                    return false;
1093:
1094:                int vertexRadius;
1095:                if (ignoreVertexRadius)
1096:                    vertexRadius = 1;
1097:                else {
1098:                    vertexRadius = PreferenceUtil.instance().getVertexRadius();
1099:                }
1100:
1101:                if (points.size() == 1) {
1102:                    Point click = points.get(0).point;
1103:                    int x = click.getX() - point.getX();
1104:                    int y = click.getY() - point.getY();
1105:                    double dist = Math.sqrt(x * x + y * y);
1106:
1107:                    return dist < vertexRadius;
1108:                }
1109:
1110:                Point overVertex = getEditBlackboard().overVertex(point,
1111:                        vertexRadius);
1112:                if (overVertex != null && pointsToModel.containsKey(overVertex))
1113:                    return true;
1114:
1115:                ClosestEdge edge = getClosestEdge(point,
1116:                        treatUnknownGeomsAsPolygon);
1117:                if (edge != null && edge.getDistanceToEdge() < vertexRadius)
1118:                    return true;
1119:
1120:                PrimitiveShapeIterator iter = PrimitiveShapeIterator
1121:                        .getPathIterator(this );
1122:                iter.setPolygon(isPolygon(treatUnknownGeomsAsPolygon));
1123:                GeneralPath path = new GeneralPath();
1124:                path.append(iter, false);
1125:                return path.contains(point.getX(), point.getY());
1126:            }
1127:
1128:            public Rectangle2D getBounds2D() {
1129:                return null;
1130:            }
1131:
1132:            public boolean contains(double x, double y) {
1133:                return contains(Point.valueOf((int) x, (int) y), true);
1134:            }
1135:
1136:            public boolean contains(Point2D p) {
1137:                return contains(Point.valueOf((int) p.getX(), (int) p.getY()),
1138:                        true);
1139:            }
1140:
1141:            public boolean intersects(double x, double y, double w, double h) {
1142:                return false;
1143:            }
1144:
1145:            public boolean intersects(Rectangle2D r) {
1146:                return false;
1147:            }
1148:
1149:            public boolean contains(double x, double y, double w, double h) {
1150:                return false;
1151:            }
1152:
1153:            public boolean contains(Rectangle2D r) {
1154:                return false;
1155:            }
1156:
1157:            public PathIterator getPathIterator(AffineTransform at) {
1158:                return PrimitiveShapeIterator.getPathIterator(this );
1159:            }
1160:
1161:            public PathIterator getPathIterator(AffineTransform at,
1162:                    double flatness) {
1163:                return PrimitiveShapeIterator.getPathIterator(this );
1164:            }
1165:
1166:            /**
1167:             * Returns all the coordinates that map to the point at location i.
1168:             * 
1169:             * @param i index of a point in the shape
1170:             * @return Returns all the coordinates that map to the point at location i.
1171:             */
1172:            public List<Coordinate> getCoordsAt(int i) {
1173:                PointCoordMap bag = points.get(i);
1174:                return new CoordResolvingList(bag.coords, bag.point);
1175:            }
1176:
1177:            public List<Coordinate> getCoordsAt(Point point) {
1178:                return new CoordResolvingList(getMutator().getLazyCoordsAt(
1179:                        point), point);
1180:            }
1181:
1182:            public int getAssociatedPointIndex(int coordIndex) {
1183:                return points.indexOf(coordsToModel.get((coordinates
1184:                        .get(coordIndex))));
1185:            }
1186:
1187:            public boolean hasVertex(Coordinate start) {
1188:                // Point point = getEditBlackboard().toPoint(start);
1189:                // List<LazyCoord> coords = getMutator().getLazyCoordsAt(point);
1190:                // for( LazyCoord coord : coords ) {
1191:                // if( coord.get(coordsToModel.get(coord).point).equals(start) )
1192:                // return true;
1193:                // }
1194:                for (LazyCoord coord : coordinates) {
1195:                    if (coord.get(coordsToModel.get(coord).point).equals(start))
1196:                        return true;
1197:                }
1198:                return false;
1199:            }
1200:
1201:            public void assertValid() {
1202:                if (!EditPlugin.isDebugging(EditPlugin.RUN_ASSERTIONS))
1203:                    return;
1204:                if (getNumCoords() == 0 && getNumPoints() != 0
1205:                        || getNumCoords() != 0 && getNumPoints() == 0)
1206:                    throw new AssertionError(
1207:                            "Num Coords=" + getNumCoords() + " NumPoints=" + getNumPoints()); //$NON-NLS-1$ //$NON-NLS-2$
1208:
1209:                if (getNumCoords() < 1) {
1210:                    return;
1211:                }
1212:
1213:                for (LazyCoord lz : coordinates) {
1214:                    if (!coordsToModel.containsKey(lz))
1215:                        throw new AssertionError(lz
1216:                                + " should be in coordsToModel but isn't"); //$NON-NLS-1$
1217:                    PointCoordMap bag = coordsToModel.get(lz);
1218:                    Point findVertex = bag.point;
1219:                    if (findVertex == null)
1220:                        throw new AssertionError(
1221:                                bag.point
1222:                                        + " should equal findVertex(getEditBlackboard().toPoint(lz.get(bag.point)), snappingRadius, false)"); //$NON-NLS-1$
1223:
1224:                    boolean found = false;
1225:                    for (LazyCoord lz2 : bag.coords) {
1226:                        if (lz2 == lz) {
1227:                            found = true;
1228:                            break;
1229:                        }
1230:                    }
1231:                    if (!found) {
1232:                        throw new AssertionError(lz
1233:                                + " is not in the mapped bag " + bag); //$NON-NLS-1$                
1234:                    }
1235:                    if (getEditBlackboard().coordMapping.containsKey(bag.point)) {
1236:                        found = false;
1237:                        List<LazyCoord> list = getEditBlackboard().coordMapping
1238:                                .get(bag.point);
1239:                        for (LazyCoord lz2 : list) {
1240:                            if (lz2 == lz) {
1241:                                found = true;
1242:                                break;
1243:                            }
1244:                        }
1245:
1246:                        if (!found) {
1247:                            throw new AssertionError(
1248:                                    lz
1249:                                            + " is not in editblackboard's coordMapping"); //$NON-NLS-1$                    
1250:                        }
1251:                    } else {
1252:                        throw new AssertionError(bag.point
1253:                                + " should be in the blackboard but isn't"); //$NON-NLS-1$
1254:                    }
1255:
1256:                }
1257:
1258:                for (PointCoordMap b : points) {
1259:                    for (LazyCoord coordinate : b.coords) {
1260:                        if (!coordinates.contains(coordinate)) {
1261:                            throw new AssertionError(
1262:                                    coordinate
1263:                                            + " is not in the list of coordinate but it should be"); //$NON-NLS-1$                
1264:                        }
1265:                        if (!coordsToModel.containsKey(coordinate)) {
1266:                            throw new AssertionError(coordinate
1267:                                    + " is not in coordsToModel map"); //$NON-NLS-1$                
1268:                        }
1269:                        if (!pointsToModel.containsKey(b.point))
1270:                            throw new AssertionError(b.point
1271:                                    + " is not in pointsToModel map"); //$NON-NLS-1$                
1272:                    }
1273:                    if (!getEditBlackboard().coordMapping.get(b.point)
1274:                            .containsAll(b.coords)) {
1275:                        throw new AssertionError(
1276:                                "Not all coordinates in bags are in editblackboard"); //$NON-NLS-1$
1277:                    }
1278:                    if (!getEditBlackboard().geomMapping.get(b.point).contains(
1279:                            getEditGeom())) {
1280:                        throw new AssertionError(
1281:                                "EditGeom is not mapped to " + b.point + " in edit blackboard's geomMapping"); //$NON-NLS-1$ //$NON-NLS-2$                
1282:                    }
1283:                }
1284:
1285:                EditPlugin.trace(EditPlugin.RUN_ASSERTIONS,
1286:                        "shape is valid", null); //$NON-NLS-1$
1287:            }
1288:
1289:            public boolean contains(Coordinate startCoord,
1290:                    boolean treatUnknownGeomsAsPolygon) {
1291:
1292:                for (int i = 0; i < getNumCoords() - 1; i++) {
1293:                    Coordinate intersection = EditUtils.instance
1294:                            .closestCoordinateOnEdge(getCoord(i),
1295:                                    getCoord(i + 1), startCoord);
1296:                    if (intersection != null && intersection.equals(startCoord))
1297:                        return true;
1298:                }
1299:
1300:                PrimitiveShapeIterator iter = PrimitiveShapeIterator
1301:                        .getPathIterator(this );
1302:                iter.setPolygon(treatUnknownGeomsAsPolygon);
1303:                Shape s = iter.toShape();
1304:                return s.contains(startCoord.x, startCoord.y);
1305:            }
1306:
1307:            /**
1308:             * Returns the point closest to location. The search is a square of height and width radius + 1.
1309:             * 
1310:             * @param location the locations to start searching from.
1311:             * @param radius the distance away from location to search.
1312:             * @return the point closest to location or null if no point exists.
1313:             */
1314:            public Point overVertex(Point location, int radius) {
1315:                return overVertex(location, radius, false);
1316:            }
1317:
1318:            /**
1319:             * Returns the point closest to location. If ignore is true the point at locations will not be
1320:             * returned. The search is a square of height and width radius + 1.
1321:             * 
1322:             * @param location the locations to start searching from.
1323:             * @param radius radius the distance away from location to search.
1324:             * @param ignore true if the vertex at location is ignored
1325:             * @return the point closest to location or null if no point exists.
1326:             */
1327:            public synchronized Point overVertex(Point location, int radius,
1328:                    boolean ignore) {
1329:                List<PointCoordMap> list = this .pointsToModel.get(location);
1330:                if (!ignore && list != null && !list.isEmpty())
1331:                    return location;
1332:                for (int i = 1; i <= radius; i++) {
1333:                    Point result = findVertex(location, i);
1334:                    if (result != null)
1335:                        return result;
1336:                }
1337:                return null;
1338:            }
1339:
1340:            /**
1341:             * Searchs for a vertext in a square i pixels away from the location.
1342:             * 
1343:             * @param location center of search
1344:             * @param i distance from center to search (is not an area search)
1345:             * @param ignore
1346:             * @param element
1347:             */
1348:            private Point findVertex(Point location, int i) {
1349:
1350:                final int maxX = location.getX() + i;
1351:                final int maxY = location.getY() + i;
1352:                final int minX = location.getX() - i;
1353:                final int minY = location.getY() - i;
1354:
1355:                for (int x = minX; x <= maxX; x++) {
1356:                    Point temp = Point.valueOf(x, minY);
1357:                    List<PointCoordMap> list = pointsToModel.get(temp);
1358:                    if (list != null && list.size() > 0)
1359:                        return temp;
1360:                }
1361:
1362:                for (int y = minY + 1; y <= maxY; y++) {
1363:                    Point temp = Point.valueOf(maxX, y);
1364:                    List<PointCoordMap> list = pointsToModel.get(temp);
1365:                    if (list != null && list.size() > 0)
1366:                        return temp;
1367:                }
1368:
1369:                for (int x = maxX - 1; x >= minX; x--) {
1370:                    Point temp = Point.valueOf(x, maxY);
1371:                    List<PointCoordMap> list = pointsToModel.get(temp);
1372:                    if (list != null && list.size() > 0)
1373:                        return temp;
1374:                }
1375:
1376:                for (int y = maxY - 1; y >= minY; y--) {
1377:                    Point temp = Point.valueOf(minX, y);
1378:                    List<PointCoordMap> list = pointsToModel.get(temp);
1379:                    if (list != null && list.size() > 0)
1380:                        return temp;
1381:                }
1382:
1383:                return null;
1384:            }
1385:
1386:            public Envelope getEnvelope() {
1387:                if (envelope == null) {
1388:                    envelope = new Envelope();
1389:                    for (int i = 0; i < getNumCoords(); i++) {
1390:                        envelope.expandToInclude(getCoord(i));
1391:                    }
1392:                }
1393:                return envelope;
1394:            }
1395:
1396:            /**
1397:             * Currently a simple stupid implementation for detecting if 2 polygons overlap. Currently it
1398:             * only check the points not the real coordinates so this method must be used with care. Just
1399:             * iterates through all the edges in one shape and checks if it overlap with an edge in the
1400:             * other shape.
1401:             * 
1402:             * <pre>
1403:             *  ------------------
1404:             *  |   ---------    |
1405:             *  |   |       |    |
1406:             *  ----|-------|-----
1407:             *      |       |
1408:             *      ---------
1409:             * </pre>
1410:             * 
1411:             * Above is considered overlapping but below is <em>only</em> if acceptTouches is true:
1412:             * 
1413:             * <pre>
1414:             *  ------------------
1415:             *  |                |
1416:             *  |                |
1417:             *  ------------------
1418:             *      |       |
1419:             *      ---------
1420:             * </pre>
1421:             * 
1422:             * <p> 
1423:             * <b>Note:</b> If one of the shapes is a point and the other is a line or a point then acceptTouches must be true
1424:             * other or this method will always return false.
1425:             * </p>
1426:             * 
1427:             * @param shape2 other shape to test against
1428:             * @param acceptTouches if true then this method will return true if the two shapes simply touch
1429:             *        (but don't fully overlap). See above for more details
1430:             * @return true if the two shapes overlap
1431:             */
1432:            public boolean overlap(PrimitiveShape shape2,
1433:                    boolean treatUnknownAsPolygon, boolean acceptTouches) {
1434:
1435:                if (getNumPoints() == 0)
1436:                    return false;
1437:
1438:                if (shape2.getNumPoints() == 0)
1439:                    return false;
1440:
1441:                if (getNumPoints() == 1)
1442:                    return shape2.contains(getPoint(0), treatUnknownAsPolygon,
1443:                            true)
1444:                            && isAcceptableIntersection(shape2, getPoint(0),
1445:                                    acceptTouches);
1446:
1447:                if (shape2.getNumPoints() == 1)
1448:                    return contains(shape2.getPoint(0), treatUnknownAsPolygon,
1449:                            true)
1450:                            && isAcceptableIntersection(this , shape2
1451:                                    .getPoint(0), acceptTouches);
1452:
1453:                Point last, current;
1454:
1455:                PrimitiveShapeIterator piter = PrimitiveShapeIterator
1456:                        .getPathIterator(this );
1457:                piter.setPolygon(isPolygon(treatUnknownAsPolygon));
1458:                Shape s = piter.toShape();
1459:
1460:                PrimitiveShapeIterator piter2 = PrimitiveShapeIterator
1461:                        .getPathIterator(shape2);
1462:                piter2.setPolygon(isPolygon(treatUnknownAsPolygon));
1463:                Shape s2 = piter2.toShape();
1464:
1465:                for (Point point : shape2) {
1466:                    if (s.contains(point.getX(), point.getY())
1467:                            && isAcceptableIntersection(this , point,
1468:                                    acceptTouches))
1469:                        return true;
1470:                }
1471:
1472:                Iterator<Point> iter = iterator();
1473:                last = iter.next();
1474:
1475:                while (iter.hasNext()) {
1476:                    current = iter.next();
1477:
1478:                    // now check if this shape's vertices are contained in the other shape
1479:                    if (s2.contains(last.getX(), last.getY())
1480:                            && isAcceptableIntersection(shape2, last,
1481:                                    acceptTouches))
1482:                        return true;
1483:
1484:                    if (edgeIntersect(last, current, shape2, acceptTouches))
1485:                        return true;
1486:
1487:                    last = current;
1488:                }
1489:                if (isPolygon(treatUnknownAsPolygon)) {
1490:                    // do edge from last point to first point
1491:                    if (edgeIntersect(getPoint(getNumPoints() - 1),
1492:                            getPoint(0), shape2, acceptTouches))
1493:                        return true;
1494:                }
1495:
1496:                return false;
1497:            }
1498:
1499:            /**
1500:             * detects if the edge intersects with any of the edges in the shape
1501:             */
1502:            private boolean edgeIntersect(Point last, Point current,
1503:                    PrimitiveShape shape2, boolean acceptTouches) {
1504:                Iterator<Point> iter2 = shape2.iterator();
1505:                Point last2 = iter2.next();
1506:
1507:                while (iter2.hasNext()) {
1508:                    Point current2 = iter2.next();
1509:
1510:                    Point intersection = EditUtils.instance.intersectingLines(
1511:                            last, current, last2, current2);
1512:                    if (intersection != null
1513:                            && isAcceptableIntersection(intersection, last2,
1514:                                    current2, acceptTouches)
1515:                            && isAcceptableIntersection(intersection, last,
1516:                                    current, acceptTouches)) {
1517:                        // TODO compare coordinates to ensure it is a real intersection.
1518:                        return true;
1519:                    }
1520:                    last2 = current2;
1521:                }
1522:
1523:                return false;
1524:            }
1525:
1526:            /**
1527:             * Detects if the intersection is just a touch. If it is <em>not</em> then it returns true.  If it
1528:             * is then it returns true only if a touch is considered to be an intersection.
1529:             * @see #isAcceptableIntersection(Point, Point, Point, boolean)
1530:             */
1531:            private boolean isAcceptableIntersection(PrimitiveShape shape,
1532:                    Point point, boolean acceptTouches) {
1533:                if (shape.getNumPoints() == 1) {
1534:                    if (point.equals(shape.getPoint(0)))
1535:                        return acceptTouches;
1536:                }
1537:                Envelope envelope2 = new Envelope(point.getX() - 0.1, point
1538:                        .getX() + 0.1, point.getY() - 0.1, point.getY() + 0.1);
1539:                if (EditUtils.instance.overEdgePixelPrecision(shape, envelope2)) {
1540:                    return acceptTouches;
1541:                }
1542:                return true;
1543:            }
1544:
1545:            /**
1546:             * Detects if the intersection is just a touch. If it is <em>not</em> then it returns true.  If it
1547:             * is then it returns true only if a touch is considered to be an intersection.
1548:             * @see #isAcceptableIntersection(PrimitiveShape, Point, boolean)
1549:             */
1550:            private boolean isAcceptableIntersection(Point intersection,
1551:                    Point endPoint1, Point endPoint2, boolean acceptTouches) {
1552:                if (intersection.equals(endPoint1)
1553:                        || intersection.equals(endPoint2))
1554:                    return acceptTouches;
1555:                return true;
1556:            }
1557:
1558:            private boolean isPolygon(boolean treatUnknownAsPolygon) {
1559:                return owner.getShapeType() == ShapeType.POLYGON
1560:                        || (owner.getShapeType() == ShapeType.UNKNOWN && treatUnknownAsPolygon);
1561:            }
1562:
1563:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.