[mkgmap-splitter] 01/04: Imported Upstream version 0.0.0+svn437

Sebastiaan Couwenberg sebastic at moszumanska.debian.org
Fri Apr 1 23:17:46 UTC 2016


This is an automated email from the git hooks/post-receive script.

sebastic pushed a commit to branch master
in repository mkgmap-splitter.

commit 100c99de7d048f491146d5f921e2031887f8f64b
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Sat Apr 2 01:08:02 2016 +0200

    Imported Upstream version 0.0.0+svn437
---
 resources/splitter-version.properties              |   4 +-
 src/uk/me/parabola/splitter/AbstractOSMWriter.java |  21 +++-
 src/uk/me/parabola/splitter/BinaryMapParser.java   |   7 ++
 src/uk/me/parabola/splitter/BinaryMapWriter.java   |  15 ++-
 .../me/parabola/splitter/DensityMapCollector.java  |  14 ++-
 src/uk/me/parabola/splitter/Element.java           |  10 +-
 .../me/parabola/splitter/EnhancedDensityMap.java   |  41 ++++++--
 src/uk/me/parabola/splitter/Main.java              |  25 ++++-
 src/uk/me/parabola/splitter/O5mMapParser.java      |  12 ++-
 src/uk/me/parabola/splitter/O5mMapWriter.java      |  21 +++-
 src/uk/me/parabola/splitter/OSMParser.java         |  12 ++-
 src/uk/me/parabola/splitter/OSMXMLWriter.java      |  11 +-
 .../parabola/splitter/SplittableDensityArea.java   |  24 +++--
 src/uk/me/parabola/splitter/Tile.java              | 114 +++++++++++++++++++--
 .../me/parabola/splitter/args/SplitterParams.java  |   6 ++
 15 files changed, 294 insertions(+), 43 deletions(-)

diff --git a/resources/splitter-version.properties b/resources/splitter-version.properties
index c670dbc..1d21a42 100644
--- a/resources/splitter-version.properties
+++ b/resources/splitter-version.properties
@@ -1,2 +1,2 @@
-svn.version: 429
-build.timestamp: 2016-03-02T07:39:57+0000
+svn.version: 437
+build.timestamp: 2016-03-26T09:10:19+0000
diff --git a/src/uk/me/parabola/splitter/AbstractOSMWriter.java b/src/uk/me/parabola/splitter/AbstractOSMWriter.java
index e969d03..66023b6 100644
--- a/src/uk/me/parabola/splitter/AbstractOSMWriter.java
+++ b/src/uk/me/parabola/splitter/AbstractOSMWriter.java
@@ -17,12 +17,15 @@ import java.awt.Rectangle;
 import java.io.File;
 
 public abstract class AbstractOSMWriter implements OSMWriter{
-	
+	final static int REMOVE_VERSION = 1;
+	final static int FAKE_VERSION = 2;
+	final static int KEEP_VERSION = 3;
 	protected final Area bounds;
 	protected final Area extendedBounds;
 	protected final File outputDir;
 	protected final int mapId;
-	protected final Rectangle bbox; 
+	protected final Rectangle bbox;
+	protected int versionMethod; 
 	
 
 	public AbstractOSMWriter(Area bounds, File outputDir, int mapId, int extra) {
@@ -36,6 +39,20 @@ public abstract class AbstractOSMWriter implements OSMWriter{
 		this.bbox = Utils.area2Rectangle(bounds, 1);
 	}
 
+	public void setVersionMethod (int versionMethod){
+		this.versionMethod = versionMethod;
+	}
+	
+	protected int getWriteVersion (Element el){
+		if (versionMethod == REMOVE_VERSION)
+			return 0;
+		if (versionMethod == FAKE_VERSION)
+			return 1;
+		// XXX maybe return 1 if no version was read ?
+		return el.getVersion();
+
+	}
+	
 	public Area getBounds() {
 		return bounds;
 	}
diff --git a/src/uk/me/parabola/splitter/BinaryMapParser.java b/src/uk/me/parabola/splitter/BinaryMapParser.java
index 4563de1..0b6c2a8 100644
--- a/src/uk/me/parabola/splitter/BinaryMapParser.java
+++ b/src/uk/me/parabola/splitter/BinaryMapParser.java
@@ -111,6 +111,8 @@ public class BinaryMapParser extends BinaryParser implements MapReader {
 
 			tmp = new Node();
 			tmp.set(id, latf, lonf);
+			if (nodes.hasDenseinfo())
+				tmp.setVersion(nodes.getDenseinfo().getVersion(i));
 
 			if (!skipTags) {
 				if (nodes.getKeysValsCount() > 0) {
@@ -143,6 +145,8 @@ public class BinaryMapParser extends BinaryParser implements MapReader {
 			double latf = parseLat(i.getLat()), lonf = parseLon(i.getLon());
 
 			tmp.set(id, latf, lonf);
+			if (i.hasInfo())
+				tmp.setVersion(i.getInfo().getVersion());
 
 			processor.processNode(tmp);
 			elemCounter.countNode(tmp.getId());
@@ -172,6 +176,8 @@ public class BinaryMapParser extends BinaryParser implements MapReader {
 
 			long id = i.getId();
 			tmp.setId(id);
+			if (i.hasInfo())
+				tmp.setVersion(i.getInfo().getVersion());
 
 			processor.processWay(tmp);
 			elemCounter.countWay(i.getId());
@@ -195,6 +201,7 @@ public class BinaryMapParser extends BinaryParser implements MapReader {
 			}
 			long id = i.getId();
 			tmp.setId(id);
+			tmp.setVersion(i.getInfo().getVersion());
 
 			long last_mid=0;
 			for (int j =0; j < i.getMemidsCount() ; j++) {
diff --git a/src/uk/me/parabola/splitter/BinaryMapWriter.java b/src/uk/me/parabola/splitter/BinaryMapWriter.java
index 649590c..8c44a81 100644
--- a/src/uk/me/parabola/splitter/BinaryMapWriter.java
+++ b/src/uk/me/parabola/splitter/BinaryMapWriter.java
@@ -115,7 +115,10 @@ public class BinaryMapWriter extends AbstractOSMWriter {
         //        }
 
         for(Element e : entities) {
-        	b.addVersion(1);
+        	int version = getWriteVersion(e);
+        	if (versionMethod != KEEP_VERSION || version == 0)
+        		version = 1; // JOSM requires a fake version
+        	b.addVersion(version);
         	b.addTimestamp(0);
         	b.addChangeset(0);
         	b.addUid(0);
@@ -127,7 +130,7 @@ public class BinaryMapWriter extends AbstractOSMWriter {
       {
         //        StringTable stable = serializer.getStringTable();
         Osmformat.Info.Builder b = Osmformat.Info.newBuilder();
-        if(!omit_metadata) {
+//        if(!omit_metadata) {
           //          if(e.getUser() == OsmUser.NONE && warncount < MAXWARN) {
           //            LOG
           //                .warning("Attention: Data being output lacks metadata. Please use omitmetadata=true");
@@ -140,6 +143,14 @@ public class BinaryMapWriter extends AbstractOSMWriter {
           //          b.setTimestamp((int)(e.getTimestamp().getTime() / date_granularity));
           //          b.setVersion(e.getVersion());
           //          b.setChangeset(e.getChangesetId());
+//        }
+        if (versionMethod != REMOVE_VERSION){
+        	int version = getWriteVersion(e);
+        	b.setVersion(version);
+        	b.setTimestamp(0);
+        	b.setChangeset(0);
+        	b.setUid(0);
+        	b.setUserSid(0);
         }
         return b;
       }
diff --git a/src/uk/me/parabola/splitter/DensityMapCollector.java b/src/uk/me/parabola/splitter/DensityMapCollector.java
index cc71e54..367a505 100644
--- a/src/uk/me/parabola/splitter/DensityMapCollector.java
+++ b/src/uk/me/parabola/splitter/DensityMapCollector.java
@@ -19,11 +19,18 @@ package uk.me.parabola.splitter;
 class DensityMapCollector extends AbstractMapProcessor{
 	private final DensityMap densityMap;
 	private final MapDetails details = new MapDetails();
+	private final boolean ignoreBoundsTags; 
 	private Area bounds;
+	
 
-	DensityMapCollector(int resolution) {
+	/**
+	 * @param resolution gives the granularity of the grid
+	 * @param ignoreBoundsTags true means ignore bounds found in the input file(s)
+	 */
+	DensityMapCollector(int resolution, boolean ignoreBoundsTags) {
 		Area densityBounds = new Area(-0x400000, -0x800000, 0x400000, 0x800000);
 		densityMap = new DensityMap(densityBounds, resolution);
+		this.ignoreBoundsTags = ignoreBoundsTags;
 	}
 
 	@Override
@@ -45,8 +52,11 @@ class DensityMapCollector extends AbstractMapProcessor{
 
 	@Override
 	public void boundTag(Area fileBbox) {
-		if (this.bounds == null)
+		if (ignoreBoundsTags)
+			return;
+		if (this.bounds == null){
 			this.bounds = fileBbox;
+		}
 		else
 			this.bounds = this.bounds.add(fileBbox);
 	}
diff --git a/src/uk/me/parabola/splitter/Element.java b/src/uk/me/parabola/splitter/Element.java
index 7fb1358..dd8fccb 100644
--- a/src/uk/me/parabola/splitter/Element.java
+++ b/src/uk/me/parabola/splitter/Element.java
@@ -22,7 +22,7 @@ import java.util.Iterator;
 public abstract class Element {
 	protected ArrayList<Tag> tags; 
 	private long id;
-
+	private int version;
 	
 	public void setId(long id) {
 		this.id = id;
@@ -32,6 +32,14 @@ public abstract class Element {
 		return id;
 	}
 
+	public int getVersion() {
+		return version;
+	}
+
+	public void setVersion(int version) {
+		this.version = version;
+	}
+
 	class Tag {
 		public Tag(String key,String value) {
 			this.key = key;
diff --git a/src/uk/me/parabola/splitter/EnhancedDensityMap.java b/src/uk/me/parabola/splitter/EnhancedDensityMap.java
index 5c42cec..90ef497 100644
--- a/src/uk/me/parabola/splitter/EnhancedDensityMap.java
+++ b/src/uk/me/parabola/splitter/EnhancedDensityMap.java
@@ -13,6 +13,7 @@
 package uk.me.parabola.splitter;
 
 import java.awt.Rectangle;
+import java.util.BitSet;
 
 /**
  * Contains info that is needed by the {@link Tile} class. For a given
@@ -26,13 +27,17 @@ public class EnhancedDensityMap {
 	private final DensityMap densityMap;
 	private int[][] xyMap;
 	private int[][] yxMap;
+	private BitSet xyInPolygon;
 	private double[] aspectRatioFactor;
 	private int minAspectRatioFactorPos;
 	private int maxNodesInDensityMapGridElement = Integer.MIN_VALUE;
+	private int maxNodesInDensityMapGridElementInPoly = Integer.MIN_VALUE;
+	private java.awt.geom.Area polygonArea;
 
 	public EnhancedDensityMap(DensityMap densities, java.awt.geom.Area polygonArea) {
 		this.densityMap = densities;
-		prepare(polygonArea);
+		this.polygonArea = polygonArea;
+		prepare();
 	}
 
 	
@@ -40,12 +45,8 @@ public class EnhancedDensityMap {
 	 * If a polygon is given, filter the density data Compute once complex
 	 * trigonometric results for needed for proper aspect ratio calculations.
 	 * 
-	 * @param polygonArea
-	 *            if not null, this is used to filter the data in the density
-	 *            map so that grid elements outside of the polygon are 
-	 *            reduced
 	 */
-	private void prepare(java.awt.geom.Area polygonArea){
+	private void prepare(){
 		// performance: calculate only once the needed complex math results
 		aspectRatioFactor = new double[densityMap.getHeight()+1]; 
 		int minLat = densityMap.getBounds().getMinLat(); 
@@ -69,6 +70,8 @@ public class EnhancedDensityMap {
 		int width = densityMap.getWidth();
 		int height = densityMap.getHeight();
 		xyMap = new int [width][height];
+		if (polygonArea != null)
+			xyInPolygon = new BitSet(width * height);
 		int shift = densityMap.getShift();
 		for (int x = 0; x < width; x++){
 			int polyXPos = densityMap.getBounds().getMinLong() +  (x << shift);
@@ -77,14 +80,17 @@ public class EnhancedDensityMap {
 				int count = densityMap.getNodeCount(x, y);
 				if (polygonArea != null){
 					int polyYPos = densityMap.getBounds().getMinLat() + (y << shift);
-					if (polygonArea.intersects(polyXPos, polyYPos, 1<<shift, 1<<shift))
-						count = Math.max(1, count);
-					else 
-						count = 0;
+					if (polygonArea.intersects(polyXPos, polyYPos, 1<<shift, 1<<shift)){
+						xyInPolygon.set(x * height + y);
+						if (count > maxNodesInDensityMapGridElementInPoly){
+							maxNodesInDensityMapGridElementInPoly = count;
+						}
+					}
 				}
 				if (count > 0){
 					if (count > maxNodesInDensityMapGridElement)
 						maxNodesInDensityMapGridElement = count;
+
 					xCol[y] = count;
 				}
 			}
@@ -99,6 +105,12 @@ public class EnhancedDensityMap {
 		}
 	}
 
+	public boolean isGridElemInPolygon (int x, int y){
+		if (polygonArea == null)
+			return true;
+		return xyInPolygon.get(x* densityMap.getHeight() + y);
+	}
+	
 	// calculate aspect ratio of a tile which is a view on the densityMap
 	public double getAspectRatio(Rectangle r) {
 		double ratio;
@@ -140,4 +152,13 @@ public class EnhancedDensityMap {
 	public int getMaxNodesInDensityMapGridElement() {
 		return maxNodesInDensityMapGridElement;
 	}
+
+	public int getMaxNodesInDensityMapGridElementInPoly() {
+		return maxNodesInDensityMapGridElementInPoly;
+	}
+
+	public java.awt.geom.Area getPolygonArea() {
+		return polygonArea;
+	}
+	
 }
diff --git a/src/uk/me/parabola/splitter/Main.java b/src/uk/me/parabola/splitter/Main.java
index 0e983dc..3a2c9a6 100644
--- a/src/uk/me/parabola/splitter/Main.java
+++ b/src/uk/me/parabola/splitter/Main.java
@@ -149,6 +149,10 @@ public class Main {
 
 	private int searchLimit;
 	
+	private String handleElementVersion;
+
+	private boolean ignoreBoundsTags;
+	
 	public static void main(String[] args) {
 		Main m = new Main();
 		try{
@@ -577,6 +581,11 @@ public class Main {
 			searchLimit = 1000;
 			System.err.println("The --search-limit parameter must be 1000 or higher. Resetting to 1000.");
 		}
+		handleElementVersion = params.getHandleElementVersion();
+		if (Arrays.asList("remove", "fake" , "keep").contains(handleElementVersion) == false){
+			throw new IllegalArgumentException("the --handle-element-version parameter must be either remove, fake, or keep.");
+		}
+		ignoreBoundsTags = params.getIgnoreOsmBounds();
 	}
 
 	/**
@@ -585,7 +594,7 @@ public class Main {
 	 */
 	private AreaList calculateAreas() throws XmlPullParserException {
 
-		DensityMapCollector pass1Collector = new DensityMapCollector(resolution); 
+		DensityMapCollector pass1Collector = new DensityMapCollector(resolution, ignoreBoundsTags); 
 		MapProcessor processor = pass1Collector;
 		
 		File densityData = new File("densities.txt");
@@ -613,7 +622,7 @@ public class Main {
 		if (precompSeaDir != null){
 			System.out.println("Counting nodes of precompiled sea data ...");
 			long startSea = System.currentTimeMillis();
-			DensityMapCollector seaCollector = new DensityMapCollector(resolution);
+			DensityMapCollector seaCollector = new DensityMapCollector(resolution, true);
 			PrecompSeaReader precompSeaReader = new PrecompSeaReader(exactArea, new File(precompSeaDir));
 			precompSeaReader.processMap(seaCollector);
 			pass1Collector.mergeSeaData(seaCollector, trim, resolution);
@@ -825,7 +834,7 @@ public class Main {
 		
 		for (int j = 0; j < allWriters.length; j++) {
 			Area area = areas.get(j);
-			OSMWriter w;
+			AbstractOSMWriter w;
 			if ("pbf".equals(outputType)) 
 				w = new BinaryMapWriter(area, fileOutputDir, area.getMapId(), overlapAmount );
 			else if ("o5m".equals(outputType))
@@ -834,6 +843,16 @@ public class Main {
 				w = new PseudoOSMWriter(area, area.getMapId(), false, overlapAmount);
 			else 
 				w = new OSMXMLWriter(area, fileOutputDir, area.getMapId(), overlapAmount );
+			switch (handleElementVersion) {
+			case "keep": 
+				w.setVersionMethod(AbstractOSMWriter.KEEP_VERSION);
+				break;
+			case "remove": 
+				w.setVersionMethod(AbstractOSMWriter.REMOVE_VERSION);
+				break;
+			default:
+				w.setVersionMethod(AbstractOSMWriter.FAKE_VERSION);
+			}
 			allWriters[j] = w;
 		}
 
diff --git a/src/uk/me/parabola/splitter/O5mMapParser.java b/src/uk/me/parabola/splitter/O5mMapParser.java
index 14a1793..6dedf04 100644
--- a/src/uk/me/parabola/splitter/O5mMapParser.java
+++ b/src/uk/me/parabola/splitter/O5mMapParser.java
@@ -248,7 +248,8 @@ public class O5mMapParser implements MapReader{
 		lastNodeId += readSignedNum64();
 		if (bytesToRead == 0)
 			return; // only nodeId: this is a delete action, we ignore it 
-		readVersionTsAuthor();
+		int version = readVersionTsAuthor();
+		node.setVersion(version);
 		if (bytesToRead == 0)
 			return; // only nodeId+version: this is a delete action, we ignore it 
 		int lon = readSignedNum32() + lastLon; lastLon = lon;
@@ -274,11 +275,12 @@ public class O5mMapParser implements MapReader{
 		if (bytesToRead == 0)
 			return; // only wayId: this is a delete action, we ignore it 
 
-		readVersionTsAuthor();
+		int version = readVersionTsAuthor();
 		if (bytesToRead == 0)
 			return; // only wayId + version: this is a delete action, we ignore it 
 		Way way = new Way();
 		way.setId(lastWayId);
+		way.setVersion(version);
 		long refSize = readUnsignedNum32();
 		long stop = bytesToRead - refSize;
 		
@@ -301,12 +303,13 @@ public class O5mMapParser implements MapReader{
 		lastRelId += readSignedNum64(); 
 		if (bytesToRead == 0)
 			return; // only relId: this is a delete action, we ignore it 
-		readVersionTsAuthor();
+		int version = readVersionTsAuthor();
 		if (bytesToRead == 0)
 			return; // only relId + version: this is a delete action, we ignore it 
 		
 		Relation rel = new Relation();
 		rel.setId(lastRelId);
+		rel.setVersion(version);
 		long refSize = readUnsignedNum32();
 		long stop = bytesToRead - refSize;
 		while(bytesToRead > stop){
@@ -365,7 +368,7 @@ public class O5mMapParser implements MapReader{
 	 * @throws IOException
 	 */
 	
-	private void readVersionTsAuthor() throws IOException {
+	private int readVersionTsAuthor() throws IOException {
 		int version = readUnsignedNum32(); 
 		if (version != 0){
 			// version info
@@ -375,6 +378,7 @@ public class O5mMapParser implements MapReader{
 				readAuthor();
 			}
 		}
+		return version;
 	}
 	/**
 	 * Read author . 
diff --git a/src/uk/me/parabola/splitter/O5mMapWriter.java b/src/uk/me/parabola/splitter/O5mMapWriter.java
index 478b43c..e684fde 100644
--- a/src/uk/me/parabola/splitter/O5mMapWriter.java
+++ b/src/uk/me/parabola/splitter/O5mMapWriter.java
@@ -189,7 +189,8 @@ public class O5mMapWriter extends AbstractOSMWriter{
 		ByteArrayOutputStream stream = new ByteArrayOutputStream();
 		long delta = node.getId() - lastNodeId; lastNodeId = node.getId(); 
 		writeSignedNum(delta, stream);
-		stream.write(0x00); // no version info
+		writeVersion(node, stream);
+		//TODO : write version
 		int o5Lon = (int)(node.getLon() * FACTOR);
 		int o5Lat = (int)(node.getLat() * FACTOR);
 		int deltaLon = o5Lon - lastLon; lastLon = o5Lon;
@@ -207,7 +208,7 @@ public class O5mMapWriter extends AbstractOSMWriter{
 		ByteArrayOutputStream stream = new ByteArrayOutputStream();
 		long delta = way.getId() - lastWayId; lastWayId = way.getId();
 		writeSignedNum(delta, stream);
-		stream.write(0x00); // no version info
+		writeVersion(way, stream);
 		ByteArrayOutputStream refStream = new ByteArrayOutputStream();
 		LongArrayList refs = way.getRefs();
 		int numRefs = refs.size();
@@ -229,7 +230,7 @@ public class O5mMapWriter extends AbstractOSMWriter{
 		ByteArrayOutputStream stream = new ByteArrayOutputStream(256);
 		long delta = rel.getId() - lastRelId; lastRelId = rel.getId();
 		writeSignedNum(delta, stream);
-		stream.write(0x00); // no version info
+		writeVersion(rel, stream);
 		ByteArrayOutputStream memStream = new ByteArrayOutputStream(256);
 		for (Member mem: rel.getMembers()){
 			writeRelRef(mem, memStream);
@@ -257,6 +258,20 @@ public class O5mMapWriter extends AbstractOSMWriter{
 		stw_write(REL_REF_TYPES[refType] + mem.getRole(), null, memStream); 
 	}
 
+	private void writeVersion (Element element, OutputStream stream) throws IOException {
+		if (versionMethod == REMOVE_VERSION){
+			stream.write(0x00); // no version 
+			return;
+		}
+		int version = 1;
+		if (versionMethod == KEEP_VERSION)
+			version = element.getVersion();
+		if (version != 0){
+			writeUnsignedNum(version, stream);
+		}
+		stream.write(0x00); // no author or time-stamp info  
+	}
+	
 	private void writeTags(Element element, OutputStream stream) throws IOException {
 		if (!element.hasTags())
 			return;
diff --git a/src/uk/me/parabola/splitter/OSMParser.java b/src/uk/me/parabola/splitter/OSMParser.java
index a2dec98..230b038 100644
--- a/src/uk/me/parabola/splitter/OSMParser.java
+++ b/src/uk/me/parabola/splitter/OSMParser.java
@@ -104,28 +104,38 @@ class OSMParser extends AbstractXppParser implements MapReader {
 			System.err.println("Node encountered with missing data. Bad/corrupt osm file? id=" + idStr + ", lat=" + latStr + ", lon=" + lonStr + ". Ignoring this node");
 			return;
 		}
-
 		long id = Long.parseLong(idStr);
 		double lat = Convert.parseDouble(latStr);
 		double lon = Convert.parseDouble(lonStr);
 
 		currentNode = new Node();
 		currentNode.set(id, lat, lon);
+		currentNode.setVersion(parseVersion());
+
 		state = State.Node;
 	}
 
 	private void startWay() {
 		currentWay = new Way();
 		currentWay.setId(getLongAttr("id"));
+		currentWay.setVersion(parseVersion());
 		state = State.Way;
 	}
 
 	private void startRelation() {
 		currentRelation = new Relation();
 		currentRelation.setId(getLongAttr("id"));
+		currentRelation.setVersion(parseVersion());
 		state = State.Relation;
 	}
 
+	private int parseVersion () {
+		String versionStr = getAttr("version");
+		if (versionStr == null)
+			return 0;
+		return Integer.parseInt(versionStr);
+		
+	}
 	private void processNode(CharSequence name) {
 		if (name.equals("tag")) {
 			if (!skipTags)
diff --git a/src/uk/me/parabola/splitter/OSMXMLWriter.java b/src/uk/me/parabola/splitter/OSMXMLWriter.java
index 854cf7e..3d7d45c 100644
--- a/src/uk/me/parabola/splitter/OSMXMLWriter.java
+++ b/src/uk/me/parabola/splitter/OSMXMLWriter.java
@@ -57,7 +57,9 @@ public class OSMXMLWriter extends AbstractOSMWriter{
 
 	private void writeHeader() throws IOException {
 		writeString("<?xml version='1.0' encoding='UTF-8'?>\n");
-		writeString("<osm version='0.5' generator='splitter' upload='false'>\n");
+		String apiVersion = (versionMethod == REMOVE_VERSION) ? "version='0.5'" : "version='0.6'";
+			
+		writeString("<osm " + apiVersion + " generator='splitter' upload='false'>\n");
 
 		writeString("<bounds minlat='");
 		writeLongDouble(Utils.toDegrees(bounds.getMinLat()));
@@ -88,6 +90,8 @@ public class OSMXMLWriter extends AbstractOSMWriter{
 		writeDouble(node.getLat());
 		writeString("' lon='");
 		writeDouble(node.getLon());
+		if (versionMethod != REMOVE_VERSION)
+			writeString("' version='" + getWriteVersion(node));
 		if (node.hasTags()) {
 			writeString("'>\n");
 			writeTags(node);
@@ -95,11 +99,14 @@ public class OSMXMLWriter extends AbstractOSMWriter{
 		} else {
 			writeString("'/>\n");
 		}
+		
 	}
 
 	public void write(Way way) throws IOException {
 		writeString("<way id='");
 		writeLong(way.getId());
+		if (versionMethod != REMOVE_VERSION)
+			writeString("' version='" + getWriteVersion(way));
 		writeString("'>\n");
 		LongArrayList refs = way.getRefs();
 		for (int i = 0; i < refs.size(); i++) {
@@ -115,6 +122,8 @@ public class OSMXMLWriter extends AbstractOSMWriter{
 	public void write(Relation rel) throws IOException {
 		writeString("<relation id='");
 		writeLong(rel.getId());
+		if (versionMethod != REMOVE_VERSION)
+			writeString("' version='" + getWriteVersion(rel));
 		writeString("'>\n");
 		List<Relation.Member> memlist = rel.getMembers();
 		for (Relation.Member m : memlist) {
diff --git a/src/uk/me/parabola/splitter/SplittableDensityArea.java b/src/uk/me/parabola/splitter/SplittableDensityArea.java
index 1428322..6c0fca1 100644
--- a/src/uk/me/parabola/splitter/SplittableDensityArea.java
+++ b/src/uk/me/parabola/splitter/SplittableDensityArea.java
@@ -46,6 +46,7 @@ public class SplittableDensityArea {
 	private long minNodes;
 	private final int startSearchLimit;
 	private int searchLimit;
+	private double maxOutsidePolygonRatio = 0.5; // TODO: maybe reduce it when a good solution was found
 
 	private final DensityMap allDensities;
 	private EnhancedDensityMap extraDensityInfo;
@@ -330,9 +331,13 @@ public class SplittableDensityArea {
 	 */
 	private void prepare(java.awt.geom.Area polygonArea){
 		extraDensityInfo = new EnhancedDensityMap(allDensities, polygonArea);
-		if (!beQuiet)
+		if (!beQuiet){
 			System.out.println("Highest node count in a single grid element is "
-							+ Utils.format(extraDensityInfo.getMaxNodesInDensityMapGridElement()));
+					+ Utils.format(extraDensityInfo.getMaxNodesInDensityMapGridElement()));
+			if (polygonArea != null)
+			System.out.println("Highest node count in a single grid element within the bounding polygon is "
+					+ Utils.format(extraDensityInfo.getMaxNodesInDensityMapGridElementInPoly()));
+		}
 		if (polygonArea != null)
 			trimTiles = true;
 
@@ -611,7 +616,14 @@ public class SplittableDensityArea {
 		} else if (tile.width < 2 && tile.height < 2) {
 			return null;
 		} 
+		if (tile.outsidePolygon()){
+			return new Solution(maxNodes);
+		}
 		if (addAndReturn){
+			double outsidePolygonRatio = tile.calcOutsidePolygonRatio();
+			if (outsidePolygonRatio > maxOutsidePolygonRatio ){
+				return null;
+			}
 			Solution solution = new Solution(maxNodes);
 			solution.add(tile);  // can't split further
 			return solution;
@@ -678,16 +690,16 @@ public class SplittableDensityArea {
 				continue;
 
 			Tile[] parts = smi.getParts();
+			if (trimTiles){
+				parts[0] = parts[0].trim();
+				parts[1] = parts[1].trim();
+			}
 			if (parts[0].count > parts[1].count){
 				// first try the less populated part
 				Tile help = parts[0];
 				parts[0] = parts[1];
 				parts[1] = help;
 			}
-			if (trimTiles){
-				parts[0] = parts[0].trim();
-				parts[1] = parts[1].trim();
-			}
 			Solution [] sols = new Solution[2];
 			int countOK = 0;
 			for (int i = 0; i < 2; i++){
diff --git a/src/uk/me/parabola/splitter/Tile.java b/src/uk/me/parabola/splitter/Tile.java
index c6048c8..71efebc 100644
--- a/src/uk/me/parabola/splitter/Tile.java
+++ b/src/uk/me/parabola/splitter/Tile.java
@@ -468,40 +468,142 @@ import java.awt.Rectangle;
 		 * @return the trimmed version of the tile.
 		 */
 		public Tile trim() {
+			long sumRemovedColCounts = 0;
+			long sumRemovedRowCounts = 0;
 			int minX = -1;
 			for (int i = 0; i < width; i++) {
-				if (getColSum(i) > 0){
+				long colSum = getColSum(i) ; 
+				boolean needed = (densityInfo.getPolygonArea() == null) ? colSum > 0 : (colOutsidePolygon(i) == false);
+				if (needed){
 					minX = x + i;
 					break;
 				}
+				sumRemovedColCounts += colSum;
 			}
 			int maxX = -1;
 			for (int i = width - 1; i >= 0; i--) {
-				if (getColSum(i) > 0){
+				long colSum = getColSum(i) ; 
+				boolean needed = (densityInfo.getPolygonArea() == null) ? colSum > 0 : (colOutsidePolygon(i) == false);
+				if (needed){
 					maxX = x + i;
 					break;
 				}
+				sumRemovedColCounts += colSum;
 			}
 			int minY = -1;
 			for (int i = 0; i < height; i++) {
-				if (getRowSum(i) > 0){
+				long rowSum = getRowSum(i);
+				boolean needed = (densityInfo.getPolygonArea() == null) ? rowSum > 0 : (rowOutsidePolygon(i) == false);
+				if (needed){
 					minY = y + i;
 					break;
 				}
+				sumRemovedRowCounts += rowSum;
 			}
 			int maxY = -1;
 			for (int i = height - 1; i >= 0; i--) {
-				if (getRowSum(i) > 0){
+				long rowSum = getRowSum(i);
+				boolean needed = (densityInfo.getPolygonArea() == null) ? rowSum > 0 : (rowOutsidePolygon(i) == false);
+				if (needed){
 					maxY = y + i;
 					break;
 				}
+				sumRemovedRowCounts += rowSum;
 			}
-
 			assert minX <= maxX;
 			assert minY <= maxY;
-			return new Tile(densityInfo, minX, minY, maxX - minX + 1, maxY - minY + 1, count);
+			assert maxX >= 0;
+			assert maxY >= 0;
+			long newCount = count;
+			int modWidth = maxX - minX + 1;
+			int modHeight = maxY - minY + 1;
+			if (densityInfo.getPolygonArea() != null){
+				if (modWidth != width || modHeight != height){
+					// tile was trimmed, try hard to avoid a new costly calculation of the count value
+					if (width == modWidth){
+						newCount = count - sumRemovedRowCounts; 
+					} else if (height == modHeight){
+						newCount = count - sumRemovedColCounts;
+					} else {
+//						System.out.printf("ouch: %d %d %d %d (%d) -> %d %d %d %d\n",x,y,width,height,count,minX,minY, maxX - minX + 1, maxY - minY + 1 );
+						return new Tile (densityInfo, new Rectangle(minX, minY, modWidth, modHeight));
+					}
+				}
+			}
+			return new Tile(densityInfo, minX, minY, modWidth, modHeight, newCount);
+		}
+
+		private boolean rowOutsidePolygon(int row) {
+			if (densityInfo.getPolygonArea() == null)
+				return false;
+			// performance critical part, check corners first
+			if (densityInfo.isGridElemInPolygon(x, y + row) || densityInfo.isGridElemInPolygon(x + width-1, y + row))
+				return false;
+			// check rest of row
+			for (int i = 1; i < width-1; i++) {
+				if (densityInfo.isGridElemInPolygon(x + i, y + row))
+					return false;
+			}
+			return true;
+		}
+
+		private boolean colOutsidePolygon(int col) {
+			if (densityInfo.getPolygonArea() == null)
+				return false;
+			// performance critical part, check corners first
+			if (densityInfo.isGridElemInPolygon(x + col, y) || densityInfo.isGridElemInPolygon(x + col, y + height - 1))
+				return false;
+			// check rest of column
+			for (int i = 1; i < height - 1; i++) {
+				if (densityInfo.isGridElemInPolygon(x + col, y + i))
+					return false;
+			}
+			return true;
+		}
+
+		public boolean outsidePolygon(){
+			java.awt.geom.Area polygonArea = densityInfo.getPolygonArea();
+			if (polygonArea == null)
+				return false;
+			if (polygonArea.intersects(getRealBBox()))
+				return false;
+			return true;
+		}
+
+		/**
+		 * Count the number of grid elements which are outside of the polygon area,
+		 * divide it by the total number of grid elements covered by this tile to
+		 * get a value between 0 and 1 (including).
+		 * @return
+		 */
+		public double calcOutsidePolygonRatio (){
+			if (densityInfo.getPolygonArea() == null)
+				return 0;
+			Rectangle realBBox = getRealBBox();
+//			if (densityInfo.getPolygonArea().contains(realBBox) )
+//				return 0;
+			// check special case: tile may contain the polygon
+			Rectangle polyBBox = densityInfo.getPolygonArea().getBounds();
+			if (realBBox.contains(polyBBox)){
+				return 0;
+			}
+			int countOutside = 0;
+			for (int i = x; i < x+width; i++){
+				for (int j = y; j < y+height; j++){
+					if (densityInfo.isGridElemInPolygon(i,j) == false)
+						countOutside++;
+				}
+			}
+			double ratio = (double) countOutside  / (width * height) ;
+			return ratio;
 		}
 		
+		public Rectangle getRealBBox(){
+			int shift = densityInfo.getDensityMap().getShift();
+			int polyYPos = densityInfo.getDensityMap().getBounds().getMinLat() + (y << shift);
+			int polyXPos = densityInfo.getDensityMap().getBounds().getMinLong() + (x << shift);
+			return new Rectangle(polyXPos, polyYPos, width<<shift, height<<shift);
+		}
 		
 		@Override
 		public String toString(){
diff --git a/src/uk/me/parabola/splitter/args/SplitterParams.java b/src/uk/me/parabola/splitter/args/SplitterParams.java
index c17bc8d..987ca31 100644
--- a/src/uk/me/parabola/splitter/args/SplitterParams.java
+++ b/src/uk/me/parabola/splitter/args/SplitterParams.java
@@ -115,4 +115,10 @@ public interface SplitterParams {
 	@Option(defaultValue = "200000", description = "Search limit in split algo. Higher values may find better splits, but will take longer.")
 	int getSearchLimit();
 
+	@Option(defaultValue = "remove", description = "Define how splitter treats version info in the osm data. Can be remove, fake, or keep")
+	String getHandleElementVersion();
+
+	@Option(defaultValue = "false", description = "Specify if splitter should ignore bounds tags in input files")
+	boolean getIgnoreOsmBounds();
+
 }

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/mkgmap-splitter.git



More information about the Pkg-grass-devel mailing list