source: josm/trunk/src/org/openstreetmap/josm/data/osm/visitor/BoundingXYVisitor.java@ 8510

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

checkstyle: enable relevant whitespace checks and fix them

  • Property svn:eol-style set to native
File size: 6.8 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.osm.visitor;
3
4import java.util.Collection;
5
6import org.openstreetmap.josm.Main;
7import org.openstreetmap.josm.data.Bounds;
8import org.openstreetmap.josm.data.ProjectionBounds;
9import org.openstreetmap.josm.data.coor.CachedLatLon;
10import org.openstreetmap.josm.data.coor.EastNorth;
11import org.openstreetmap.josm.data.coor.LatLon;
12import org.openstreetmap.josm.data.osm.Node;
13import org.openstreetmap.josm.data.osm.OsmPrimitive;
14import org.openstreetmap.josm.data.osm.Relation;
15import org.openstreetmap.josm.data.osm.RelationMember;
16import org.openstreetmap.josm.data.osm.Way;
17
18/**
19 * Calculates the total bounding rectangle of a series of {@link OsmPrimitive} objects, using the
20 * EastNorth values as reference.
21 * @author imi
22 */
23public class BoundingXYVisitor extends AbstractVisitor {
24
25 private ProjectionBounds bounds = null;
26
27 @Override
28 public void visit(Node n) {
29 visit(n.getEastNorth());
30 }
31
32 @Override
33 public void visit(Way w) {
34 if (w.isIncomplete()) return;
35 for (Node n : w.getNodes()) {
36 visit(n);
37 }
38 }
39
40 @Override
41 public void visit(Relation e) {
42 // only use direct members
43 for (RelationMember m : e.getMembers()) {
44 if (!m.isRelation()) {
45 m.getMember().accept(this);
46 }
47 }
48 }
49
50 public void visit(Bounds b) {
51 if (b != null) {
52 visit(b.getMin());
53 visit(b.getMax());
54 }
55 }
56
57 public void visit(ProjectionBounds b) {
58 if (b != null) {
59 visit(b.getMin());
60 visit(b.getMax());
61 }
62 }
63
64 public void visit(LatLon latlon) {
65 if (latlon != null) {
66 if (latlon instanceof CachedLatLon) {
67 visit(((CachedLatLon) latlon).getEastNorth());
68 } else {
69 visit(Main.getProjection().latlon2eastNorth(latlon));
70 }
71 }
72 }
73
74 public void visit(EastNorth eastNorth) {
75 if (eastNorth != null) {
76 if (bounds == null) {
77 bounds = new ProjectionBounds(eastNorth);
78 } else {
79 bounds.extend(eastNorth);
80 }
81 }
82 }
83
84 public boolean hasExtend() {
85 return bounds != null && bounds.hasExtend();
86 }
87
88 /**
89 * @return The bounding box or <code>null</code> if no coordinates have passed
90 */
91 public ProjectionBounds getBounds() {
92 return bounds;
93 }
94
95 /**
96 * Enlarges the calculated bounding box by 0.002 degrees.
97 * If the bounding box has not been set (<code>min</code> or <code>max</code>
98 * equal <code>null</code>) this method does not do anything.
99 */
100 public void enlargeBoundingBox() {
101 enlargeBoundingBox(Main.pref.getDouble("edit.zoom-enlarge-bbox", 0.002));
102 }
103
104 /**
105 * Enlarges the calculated bounding box by the specified number of degrees.
106 * If the bounding box has not been set (<code>min</code> or <code>max</code>
107 * equal <code>null</code>) this method does not do anything.
108 *
109 * @param enlargeDegree number of degrees to enlarge on each side
110 */
111 public void enlargeBoundingBox(double enlargeDegree) {
112 if (bounds == null)
113 return;
114 LatLon minLatlon = Main.getProjection().eastNorth2latlon(bounds.getMin());
115 LatLon maxLatlon = Main.getProjection().eastNorth2latlon(bounds.getMax());
116 bounds = new ProjectionBounds(
117 Main.getProjection().latlon2eastNorth(new LatLon(minLatlon.lat() - enlargeDegree, minLatlon.lon() - enlargeDegree)),
118 Main.getProjection().latlon2eastNorth(new LatLon(maxLatlon.lat() + enlargeDegree, maxLatlon.lon() + enlargeDegree)));
119 }
120
121 /**
122 * Enlarges the bounding box up to <code>maxEnlargePercent</code>, depending on
123 * its size. If the bounding box is small, it will be enlarged more in relation
124 * to its beginning size. The larger the bounding box, the smaller the change,
125 * down to the minimum of 1% enlargement.
126 *
127 * Warning: if the bounding box only contains a single node, no expansion takes
128 * place because a node has no width/height. Use <code>enlargeToMinDegrees</code>
129 * instead.
130 *
131 * Example: You specify enlargement to be up to 100%.
132 *
133 * Bounding box is a small house: enlargement will be 95–100%, i.e.
134 * making enough space so that the house fits twice on the screen in
135 * each direction.
136 *
137 * Bounding box is a large landuse, like a forest: Enlargement will
138 * be 1–10%, i.e. just add a little border around the landuse.
139 *
140 * If the bounding box has not been set (<code>min</code> or <code>max</code>
141 * equal <code>null</code>) this method does not do anything.
142 *
143 * @param maxEnlargePercent maximum enlargement in percentage (100.0 for 100%)
144 */
145 public void enlargeBoundingBoxLogarithmically(double maxEnlargePercent) {
146 if (bounds == null)
147 return;
148
149 double diffEast = bounds.getMax().east() - bounds.getMin().east();
150 double diffNorth = bounds.getMax().north() - bounds.getMin().north();
151
152 double enlargeEast = Math.min(maxEnlargePercent - 10*Math.log(diffEast), 1)/100;
153 double enlargeNorth = Math.min(maxEnlargePercent - 10*Math.log(diffNorth), 1)/100;
154
155 visit(bounds.getMin().add(-enlargeEast/2, -enlargeNorth/2));
156 visit(bounds.getMax().add(+enlargeEast/2, +enlargeNorth/2));
157 }
158
159 /**
160 * Specify a degree larger than 0 in order to make the bounding box at least
161 * the specified size in width and height. The value is ignored if the
162 * bounding box is already larger than the specified amount.
163 *
164 * If the bounding box has not been set (<code>min</code> or <code>max</code>
165 * equal <code>null</code>) this method does not do anything.
166 *
167 * If the bounding box contains objects and is to be enlarged, the objects
168 * will be centered within the new bounding box.
169 *
170 * @param size minimum width and height in meter
171 */
172 public void enlargeToMinSize(double size) {
173 if (bounds == null)
174 return;
175 // convert size from meters to east/north units
176 double en_size = size * Main.map.mapView.getScale() / Main.map.mapView.getDist100Pixel() * 100;
177 visit(bounds.getMin().add(-en_size/2, -en_size/2));
178 visit(bounds.getMax().add(+en_size/2, +en_size/2));
179 }
180
181 @Override
182 public String toString() {
183 return "BoundingXYVisitor["+bounds+"]";
184 }
185
186 public void computeBoundingBox(Collection<? extends OsmPrimitive> primitives) {
187 if (primitives == null) return;
188 for (OsmPrimitive p: primitives) {
189 if (p == null) {
190 continue;
191 }
192 p.accept(this);
193 }
194 }
195}
Note: See TracBrowser for help on using the repository browser.