001 // License: GPL. Copyright 2007 by Immanuel Scholz and others 002 package org.openstreetmap.josm.data.osm.visitor; 003 004 import java.util.Collection; 005 006 import org.openstreetmap.josm.Main; 007 import org.openstreetmap.josm.data.Bounds; 008 import org.openstreetmap.josm.data.ProjectionBounds; 009 import org.openstreetmap.josm.data.coor.CachedLatLon; 010 import org.openstreetmap.josm.data.coor.EastNorth; 011 import org.openstreetmap.josm.data.coor.LatLon; 012 import org.openstreetmap.josm.data.osm.Node; 013 import org.openstreetmap.josm.data.osm.OsmPrimitive; 014 import org.openstreetmap.josm.data.osm.Relation; 015 import org.openstreetmap.josm.data.osm.RelationMember; 016 import org.openstreetmap.josm.data.osm.Way; 017 018 /** 019 * Calculates the total bounding rectangle of a series of {@link OsmPrimitive} objects, using the 020 * EastNorth values as reference. 021 * @author imi 022 */ 023 public class BoundingXYVisitor extends AbstractVisitor { 024 025 private ProjectionBounds bounds = null; 026 027 public void visit(Node n) { 028 visit(n.getEastNorth()); 029 } 030 031 public void visit(Way w) { 032 if (w.isIncomplete()) return; 033 for (Node n : w.getNodes()) { 034 visit(n); 035 } 036 } 037 038 public void visit(Relation e) { 039 // only use direct members 040 for (RelationMember m : e.getMembers()) { 041 if (!m.isRelation()) { 042 m.getMember().visit(this); 043 } 044 } 045 } 046 047 public void visit(Bounds b) { 048 if(b != null) 049 { 050 visit(b.getMin()); 051 visit(b.getMax()); 052 } 053 } 054 055 public void visit(ProjectionBounds b) { 056 if(b != null) 057 { 058 visit(b.getMin()); 059 visit(b.getMax()); 060 } 061 } 062 063 public void visit(LatLon latlon) { 064 if(latlon != null) 065 { 066 if(latlon instanceof CachedLatLon) { 067 visit(((CachedLatLon)latlon).getEastNorth()); 068 } else { 069 visit(Main.getProjection().latlon2eastNorth(latlon)); 070 } 071 } 072 } 073 074 public void visit(EastNorth eastNorth) { 075 if (eastNorth != null) { 076 if (bounds == null) { 077 bounds = new ProjectionBounds(eastNorth); 078 } else { 079 bounds.extend(eastNorth); 080 } 081 } 082 } 083 084 public boolean hasExtend() 085 { 086 return bounds != null && !bounds.getMin().equals(bounds.getMax()); 087 } 088 089 /** 090 * @return The bounding box or <code>null</code> if no coordinates have passed 091 */ 092 public ProjectionBounds getBounds() { 093 return bounds; 094 } 095 096 /** 097 * Enlarges the calculated bounding box by 0.002 degrees. 098 * If the bounding box has not been set (<code>min</code> or <code>max</code> 099 * equal <code>null</code>) this method does not do anything. 100 */ 101 public void enlargeBoundingBox() { 102 enlargeBoundingBox(Main.pref.getDouble("edit.zoom-enlarge-bbox", 0.002)); 103 } 104 105 /** 106 * Enlarges the calculated bounding box by the specified number of degrees. 107 * If the bounding box has not been set (<code>min</code> or <code>max</code> 108 * equal <code>null</code>) this method does not do anything. 109 * 110 * @param enlargeDegree 111 */ 112 public void enlargeBoundingBox(double enlargeDegree) { 113 if (bounds == null) 114 return; 115 LatLon minLatlon = Main.getProjection().eastNorth2latlon(bounds.getMin()); 116 LatLon maxLatlon = Main.getProjection().eastNorth2latlon(bounds.getMax()); 117 bounds = new ProjectionBounds( 118 Main.getProjection().latlon2eastNorth(new LatLon(minLatlon.lat() - enlargeDegree, minLatlon.lon() - enlargeDegree)), 119 Main.getProjection().latlon2eastNorth(new LatLon(maxLatlon.lat() + enlargeDegree, maxLatlon.lon() + enlargeDegree))); 120 } 121 122 @Override public String toString() { 123 return "BoundingXYVisitor["+bounds+"]"; 124 } 125 126 public void computeBoundingBox(Collection<? extends OsmPrimitive> primitives) { 127 if (primitives == null) return; 128 for (OsmPrimitive p: primitives) { 129 if (p == null) { 130 continue; 131 } 132 p.visit(this); 133 } 134 } 135 }