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

Last change on this file since 5293 was 5293, checked in by Don-vip, 12 years ago

fix #7758 - Do not restrict building validator tests to "building=yes", but take into account "no" and "entrance"

File size: 4.5 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 final 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 // All nodes can be inside polygon and still, w outside:
63 // +-------------+
64 // /| |
65 // / | |
66 // / | |
67 // / w | |
68 // +----+----+ |
69 // | polygon |
70 // |_______________________|
71 //
72 for (int i=1; i<w.getNodesCount(); i++) {
73 LatLon center = w.getNode(i).getCoor().getCenter(w.getNode(i-1).getCoor());
74 if (center != null && !isInPolygon(new Node(center), polygon))
75 return false;
76 }
77 return true;
78 }
79
80 @Override
81 public void endTest() {
82 for (final OsmPrimitive p : primitivesToCheck) {
83 Collection<Way> outers = new FilteredCollection<Way>(index.search(p.getBBox()), new Predicate<Way>() {
84 @Override
85 public boolean evaluate(Way object) {
86 if (p.equals(object))
87 return false;
88 else if (p instanceof Node)
89 return isInPolygon((Node) p, object.getNodes()) || object.getNodes().contains(p);
90 else if (p instanceof Way)
91 return isInPolygon((Way) p, object.getNodes()) && !isInInnerWay((Way)p, object);
92 else
93 return false;
94 }
95 });
96 if (!outers.isEmpty()) {
97 errors.add(new TestError(this, Severity.WARNING,
98 tr("Building inside building"), BUILDING_INSIDE_BUILDING, p));
99 }
100 }
101
102 super.endTest();
103 }
104
105 private boolean isInInnerWay(Way w, Way outer) {
106 for (OsmPrimitive r : outer.getReferrers()) {
107 if (r instanceof Relation && ((Relation)r).isMultipolygon()) {
108 for (RelationMember m : ((Relation)r).getMembers()) {
109 if (m.hasRole() && m.getRole().equals("inner") && m.getType().equals(OsmPrimitiveType.WAY)) {
110 // Only check inner ways actually inside the current outer
111 Way inner = m.getWay();
112 if (isInPolygon(inner, outer.getNodes())) {
113 // If the tested way is inside this inner, outer is a false positive
114 if (isInPolygon(w, inner.getNodes()))
115 return true;
116 }
117 }
118 }
119 }
120 }
121 return false;
122 }
123}
Note: See TracBrowser for help on using the repository browser.