source: josm/trunk/src/org/openstreetmap/josm/data/validation/tests/BuildingInBuilding.java@ 4806

Last change on this file since 4806 was 4806, checked in by stoecker, 12 years ago

unify texts for validator tests, move command where it belongs

File size: 4.7 KB
Line 
1package org.openstreetmap.josm.data.validation.tests;
2
3import static org.openstreetmap.josm.tools.I18n.tr;
4
5import java.util.Collection;
6import java.util.LinkedList;
7import java.util.List;
8
9import org.openstreetmap.josm.data.coor.LatLon;
10import org.openstreetmap.josm.data.osm.Node;
11import org.openstreetmap.josm.data.osm.OsmPrimitive;
12import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
13import org.openstreetmap.josm.data.osm.QuadBuckets;
14import org.openstreetmap.josm.data.osm.Relation;
15import org.openstreetmap.josm.data.osm.RelationMember;
16import org.openstreetmap.josm.data.osm.Way;
17import org.openstreetmap.josm.data.validation.Severity;
18import org.openstreetmap.josm.data.validation.Test;
19import org.openstreetmap.josm.data.validation.TestError;
20import org.openstreetmap.josm.tools.FilteredCollection;
21import org.openstreetmap.josm.tools.Geometry;
22import org.openstreetmap.josm.tools.Predicate;
23
24public class BuildingInBuilding extends Test {
25
26 protected static int BUILDING_INSIDE_BUILDING = 2001;
27 protected List<OsmPrimitive> primitivesToCheck = new LinkedList<OsmPrimitive>();
28 protected QuadBuckets<Way> index = new QuadBuckets<Way>();
29
30 public BuildingInBuilding() {
31 super(tr("Building inside building"), tr("Checks for building areas inside of buildings."));
32 }
33
34 @Override
35 public void visit(Node n) {
36 if (n.isUsable() && isBuilding(n)) {
37 primitivesToCheck.add(n);
38 }
39 }
40
41 @Override
42 public void visit(Way w) {
43 if (w.isUsable() && w.isClosed() && isBuilding(w)) {
44 primitivesToCheck.add(w);
45 index.add(w);
46 }
47 }
48
49 private static boolean isInPolygon(Node n, List<Node> polygon) {
50 return Geometry.nodeInsidePolygon(n, polygon);
51 }
52
53 /**
54 * Return true if w is in polygon.
55 */
56 private static boolean isInPolygon(Way w, List<Node> polygon) {
57 // Check that all nodes of w are in polygon
58 for (Node n : w.getNodes()) {
59 if (!isInPolygon(n, polygon)) {
60 return false;
61 }
62 }
63 // All nodes can be inside polygon and still, w outside:
64 // +-------------+
65 // /| |
66 // / | |
67 // / | |
68 // / w | |
69 // +----+----+ |
70 // | polygon |
71 // |_______________________|
72 //
73 for (int i=1; i<w.getNodesCount(); i++) {
74 LatLon center = w.getNode(i).getCoor().getCenter(w.getNode(i-1).getCoor());
75 if (center != null && !isInPolygon(new Node(center), polygon)) {
76 return false;
77 }
78 }
79 return true;
80 }
81
82 @Override
83 public void endTest() {
84 for (final OsmPrimitive p : primitivesToCheck) {
85 Collection<Way> outers = new FilteredCollection<Way>(index.search(p.getBBox()), new Predicate<Way>() {
86 @Override
87 public boolean evaluate(Way object) {
88 if (p.equals(object)) {
89 return false;
90 } else if (p instanceof Node) {
91 return isInPolygon((Node) p, object.getNodes()) || object.getNodes().contains(p);
92 } else if (p instanceof Way) {
93 return isInPolygon((Way) p, object.getNodes()) && !isInInnerWay((Way)p, object);
94 } else {
95 return false;
96 }
97 }
98 });
99 if (!outers.isEmpty()) {
100 errors.add(new TestError(this, Severity.WARNING,
101 tr("Building inside building"), BUILDING_INSIDE_BUILDING, p));
102 }
103 }
104 }
105
106 private boolean isInInnerWay(Way w, Way outer) {
107 for (OsmPrimitive r : outer.getReferrers()) {
108 if (r instanceof Relation && ((Relation)r).isMultipolygon()) {
109 for (RelationMember m : ((Relation)r).getMembers()) {
110 if (m.hasRole() && m.getRole().equals("inner") && m.getType().equals(OsmPrimitiveType.WAY)) {
111 // Only check inner ways actually inside the current outer
112 Way inner = m.getWay();
113 if (isInPolygon(inner, outer.getNodes())) {
114 // If the tested way is inside this inner, outer is a false positive
115 if (isInPolygon(w, inner.getNodes())) {
116 return true;
117 }
118 }
119 }
120 }
121 }
122 }
123 return false;
124 }
125
126 private static boolean isBuilding(OsmPrimitive p) {
127 return "yes".equals(p.get("building"));
128 }
129}
Note: See TracBrowser for help on using the repository browser.