[mkgmap] 01/05: Imported Upstream version 0.0.0+svn3686

Bas Couwenberg sebastic at debian.org
Mon Aug 1 08:46:52 UTC 2016


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

sebastic pushed a commit to branch master
in repository mkgmap.

commit 8bcef4e1565c1a1328f311f033b36d369aba7211
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Mon Aug 1 10:26:23 2016 +0200

    Imported Upstream version 0.0.0+svn3686
---
 resources/mkgmap-version.properties                |   4 +-
 resources/styles/default/inc/landuse_polygons      |   1 +
 src/uk/me/parabola/imgfmt/app/BitWriter.java       |  23 +++
 .../parabola/imgfmt/app/trergn/LinePreparer.java   | 204 ++++++++++++---------
 src/uk/me/parabola/imgfmt/app/trergn/Polyline.java |   4 +-
 .../parabola/mkgmap/combiners/OverviewBuilder.java |  72 +++++++-
 .../mkgmap/filters/PolygonSplitterBase.java        |   2 +-
 .../filters/PolygonSubdivSizeSplitterFilter.java   |   4 +
 .../mkgmap/filters/RemoveObsoletePointsFilter.java |  24 ++-
 .../mkgmap/reader/osm/MultiPolygonRelation.java    |  12 +-
 test/uk/me/parabola/imgfmt/app/BitReaderTest.java  |  21 +++
 11 files changed, 260 insertions(+), 111 deletions(-)

diff --git a/resources/mkgmap-version.properties b/resources/mkgmap-version.properties
index 491d833..9f219a3 100644
--- a/resources/mkgmap-version.properties
+++ b/resources/mkgmap-version.properties
@@ -1,2 +1,2 @@
-svn.version: 3677
-build.timestamp: 2016-07-06T10:48:34+0100
+svn.version: 3686
+build.timestamp: 2016-07-29T09:57:12+0100
diff --git a/resources/styles/default/inc/landuse_polygons b/resources/styles/default/inc/landuse_polygons
index 7c6a7f4..c46085a 100644
--- a/resources/styles/default/inc/landuse_polygons
+++ b/resources/styles/default/inc/landuse_polygons
@@ -16,6 +16,7 @@ landuse=residential [0x10 resolution 23-19]
 landuse=retail [0x08 resolution 23-20]
 landuse=village_green [0x17 resolution 20]
 landuse=vineyard [0x4e resolution 20]
+landuse=orchard [0x4e resolution 20]
 
 military=airfield [0x04 resolution 20]
 military=barracks [0x04 resolution 23]
diff --git a/src/uk/me/parabola/imgfmt/app/BitWriter.java b/src/uk/me/parabola/imgfmt/app/BitWriter.java
index 2c813f5..db090e9 100644
--- a/src/uk/me/parabola/imgfmt/app/BitWriter.java
+++ b/src/uk/me/parabola/imgfmt/app/BitWriter.java
@@ -110,11 +110,34 @@ public class BitWriter {
 
 		buflen = (bitoff+7)/8;
 	}
+	
+	/**
+	 * Write a signed value. If the value doesn't fit into nb bits, write one or more 1 << (nb-1)  
+	 * as a flag for extended range.
+	 */
 
+	public void sputn(int bval, int nb) {
+		int top = 1 << (nb - 1);
+		int mask = top - 1;
+		int val = Math.abs(bval);
+		while (val > mask) {
+			putn(top, nb);
+			val -= mask;
+		}
+		if (bval < 0) {
+			putn((top - val) | top, nb);
+		} else {
+			putn(val, nb);
+		}
+	}
+	
 	public byte[] getBytes() {
 		return buf;
 	}
 
+	public int getBitPosition() {
+		return bitoff;
+	}
 	/**
 	 * Get the number of bytes actually used to hold the bit stream. This therefore can be and usually
 	 * is less than the length of the buffer returned by {@link #getBytes()}.
diff --git a/src/uk/me/parabola/imgfmt/app/trergn/LinePreparer.java b/src/uk/me/parabola/imgfmt/app/trergn/LinePreparer.java
index bbdd51a..2efc4b4 100644
--- a/src/uk/me/parabola/imgfmt/app/trergn/LinePreparer.java
+++ b/src/uk/me/parabola/imgfmt/app/trergn/LinePreparer.java
@@ -69,25 +69,91 @@ public class LinePreparer {
 
 	/**
 	 * Write the bit stream to a BitWriter and return it.
+	 * Try different values for xBase and yBase to find the one
+	 * that results in the shortest bit stream.
+	 * 
+	 * @return A class containing the written byte stream.
+	 */
+	public BitWriter makeShortestBitStream(int minPointsRequired) {
+		BitWriter bsSimple = makeBitStream(minPointsRequired, xBase, yBase);
+		if (bsSimple == null)
+			return bsSimple;
+		BitWriter bsBest = bsSimple; 
+		int xBestBase = xBase;
+		int yBestBase = yBase;
+		if (xBase > 0 ||  yBase > 0){
+			if (log.isDebugEnabled())
+				log.debug("start opt:", xBase, yBase, xSameSign, xSignNegative, ySameSign, ySignNegative);
+		}
+		if (xBase > 0){
+			int notBetter = 0;
+			boolean xSameSignBak = xSameSign;
+			xSameSign = false;
+			for (int xTestBase = xBase-1; xTestBase >= 0; xTestBase--){
+				BitWriter bstest = makeBitStream(minPointsRequired, xTestBase, yBase);
+//				System.out.println(xBase + " "  + xTestBase + " -> " + bsBest.getBitPosition() + " " + bstest.getBitPosition());
+				if (bstest.getBitPosition() >= bsBest.getBitPosition() ){
+					if (++notBetter >= 2)
+						break; // give up
+				} else {
+					xBestBase = xTestBase;
+					bsBest = bstest;
+					xSameSignBak = false;
+				}
+			}
+			xSameSign = xSameSignBak;
+		}
+		if (yBase > 0){
+			int notBetter = 0;
+			boolean ySameSignBak = ySameSign;
+			ySameSign = false;
+			for (int yTestBase = yBase-1; yTestBase >= 0; yTestBase--){
+				BitWriter bstest = makeBitStream(minPointsRequired, xBestBase, yTestBase);
+//				System.out.println(yBase + " "  + yTestBase + " -> " + bsBest.getBitPosition() + " " + bstest.getBitPosition());
+				if (bstest.getBitPosition() >= bsBest.getBitPosition()){
+					if (++notBetter >= 2)
+						break; // give up
+				} else {
+					yBestBase = yTestBase;
+					bsBest = bstest;
+					ySameSignBak = false;
+				}
+			}
+			ySameSign = ySameSignBak;
+		}
+		if (xBase != xBestBase || yBestBase != yBase){
+			if (log.isInfoEnabled()){
+				if (bsSimple.getLength() > bsBest.getLength())
+					log.info("optimizer reduced bit stream byte length from",bsSimple.getLength(),"->",bsBest.getLength(),"(" + (bsSimple.getLength()-bsBest.getLength()), " byte(s)) for",polyline.getClass().getSimpleName(),"with",polyline.getPoints().size(),"points");
+				else 
+					log.info("optimizer only reduced bit stream bit length from",bsSimple.getBitPosition(),"->",bsBest.getBitPosition(),"bits for",polyline.getClass().getSimpleName(),"with",polyline.getPoints().size(),"points, using original bit stream");
+			}
+		}
+		if (bsSimple.getLength() == bsBest.getLength()){
+			// if the (byte) length was not improved, 
+			// prefer the bit stream that doesn't need the special "trick"
+			// to encode large values, it is assumed that this can safe a  
+			// few CPU cycles when reading the map
+			return bsSimple;
+		}
+		return bsBest;
+	}
+	/**
+	 * Write the bit stream to a BitWriter and return it.
 	 *
 	 * @return A class containing the written byte stream.
 	 */
-	public BitWriter makeBitStream(int minPointsRequired) {
-
-		assert xBase >= 0 && yBase >= 0;
-
-		int xbits = 2;
-		if (xBase < 10)
-			xbits += xBase;
-		else
-			xbits += (2 * xBase) - 9;
-
-		int ybits = 2;
-		if (yBase < 10)
-			ybits += yBase;
-		else
-			ybits += (2 * yBase) - 9;
+	public BitWriter makeBitStream(int minPointsRequired, int xb, int yb) {
+		assert xb >= 0 && yb >= 0;
+		
+		int xbits = base2Bits(xb);
+		if (!xSameSign)
+			xbits++;
+		int ybits = base2Bits(yb);
+		if (!ySameSign)
+			ybits++;
 
+			
 		// Note no sign included.
 		if (log.isDebugEnabled())
 			log.debug("xbits", xbits, ", y=", ybits);
@@ -96,8 +162,8 @@ public class LinePreparer {
 		BitWriter bw = new BitWriter();
 
 		// Pre bit stream info
-		bw.putn(xBase, 4);
-		bw.putn(yBase, 4);
+		bw.putn(xb, 4);
+		bw.putn(yb, 4);
 
 		bw.put1(xSameSign);
 		if (xSameSign)
@@ -133,28 +199,18 @@ public class LinePreparer {
 
 			if (log.isDebugEnabled())
 				log.debug("x delta", dx, "~", xbits);
-			assert dx >> xbits == 0 || dx >> xbits == -1;
 			if (xSameSign) {
 				bw.putn(Math.abs(dx), xbits);
 			} else {
-				// catch inadvertent output of "magic" value that has
-				// sign bit set but other bits all 0
-				assert dx >= 0 || (dx & ((1 << xbits) - 1)) != 0;
-				bw.putn(dx, xbits);
-				bw.put1(dx < 0);
+				bw.sputn(dx, xbits);
 			}
 
 			if (log.isDebugEnabled())
 				log.debug("y delta", dy, ybits);
-			assert dy >> ybits == 0 || dy >> ybits == -1;
 			if (ySameSign) {
 				bw.putn(Math.abs(dy), ybits);
 			} else {
-				// catch inadvertent output of "magic" value that has
-				// sign bit set but other bits all 0
-				assert dy >= 0 || (dy & ((1 << ybits) - 1)) != 0;
-				bw.putn(dy, ybits);
-				bw.put1(dy < 0);
+				bw.sputn(dy, ybits);
 			}
 			if (extraBit)
 				bw.put1(nodes[i/2+1]);
@@ -191,7 +247,6 @@ public class LinePreparer {
 		Subdivision subdiv = polyline.getSubdiv();
 		if(log.isDebugEnabled())
 			log.debug("label offset", polyline.getLabel().getOffset());
-		int shift = subdiv.getShift();
 		List<Coord> points = polyline.getPoints();
 
 		// Space to hold the deltas
@@ -209,10 +264,6 @@ public class LinePreparer {
 		// OK go through the points
 		int lastLat = 0;
 		int lastLong = 0;
-		boolean xDiffSign = false; // The long values have different sign
-		boolean yDiffSign = false; // The lat values have different sign
-		int xSign = 0;  // If all the same sign, then this 1 or -1 depending on +ve or -ve
-		int ySign = 0;  // As above for lat.
 		int minDx = Integer.MAX_VALUE, maxDx = 0;
 		int minDy = Integer.MAX_VALUE, maxDy = 0;
 		// index of first point in a series of identical coords (after shift)
@@ -231,14 +282,8 @@ public class LinePreparer {
 				continue;
 			}
 
-			// compute normalized differences
-			//   -2^(shift-1) <= dx, dy < 2^(shift-1)
-			// XXX: relies on the fact that java integers are 32 bit signed
-			final int offset = 8+shift;
-			int dx = (lon - lastLong) << offset >> offset;
-			int dy = (lat - lastLat) << offset >> offset;
-			assert (dx == 0 && lon != lastLong) == false: ("delta lon too large: " +  (lon - lastLong));
-			assert (dy == 0 && lat != lastLat) == false: ("delta lat too large: " +  (lat - lastLat));
+			int dx = lon - lastLong;
+			int dy = lat - lastLat;
 			lastLong = lon;
 			lastLat = lat;
 			boolean isSpecialNode = false;
@@ -280,26 +325,6 @@ public class LinePreparer {
 				nodes[firstsame] = nodes[firstsame] || extra;
 			}
 
-			// See if they can all be the same sign.
-			if (!xDiffSign) {
-				int thisSign = (dx >= 0)? 1: -1;
-				if (xSign == 0) {
-					xSign = thisSign;
-				} else if (thisSign != xSign) {
-					// The signs are different
-					xDiffSign = true;
-				}
-			}
-			if (!yDiffSign) {
-				int thisSign = (dy >= 0)? 1: -1;
-				if (ySign == 0) {
-					ySign = thisSign;
-				} else if (thisSign != ySign) {
-					// The signs are different
-					yDiffSign = true;
-				}
-			}
-
 			// find largest delta values
 			if (dx < minDx)
 				minDx = dx;
@@ -323,43 +348,25 @@ public class LinePreparer {
 		// adjustments to get the final value.  We need to try and work
 		// backwards from this.
 		//
-		// I don't care about getting the smallest possible file size so
-		// err on the side of caution.
-		//
 		// Note that the sign bit is already not included so there is
 		// no adjustment needed for it.
 
 		if (log.isDebugEnabled())
 			log.debug("initial xBits, yBits", xBits, yBits);
 
-		if (xBits < 2)
-			xBits = 2;
-		int tmp = xBits - 2;
-		if (tmp > 10) {
-			if ((tmp & 0x1) == 0)
-				tmp++;
-			tmp = 9 + (tmp - 9) / 2;
-		}
-		this.xBase = tmp;
-
-		if (yBits < 2)
-			yBits = 2;
-		tmp = yBits - 2;
-		if (tmp > 10) {
-			if ((tmp & 0x1) == 0)
-				tmp++;
-			tmp = 9 + (tmp - 9) / 2;
-		}
-		this.yBase = tmp;
+		this.xBase = bits2Base(xBits);
+		this.yBase = bits2Base(yBits);
 
 		if (log.isDebugEnabled())
 			log.debug("initial xBase, yBase", xBase, yBase);
 
 		// Set flags for same sign etc.
-		this.xSameSign = !xDiffSign;
-		this.ySameSign = !yDiffSign;
-		this.xSignNegative = xSign < 0;
-		this.ySignNegative = ySign < 0;
+		this.xSameSign = !(minDx < 0 && maxDx > 0);
+		this.ySameSign = !(minDy < 0 && maxDy > 0);
+		if (this.xSameSign)
+			this.xSignNegative = minDx < 0;
+		if (this.ySameSign)
+			this.ySignNegative = minDy < 0;
 	}
 
 	/**
@@ -371,16 +378,35 @@ public class LinePreparer {
 	public static int bitsNeeded(int val) {
 		int n = Math.abs(val);
 
-		int count = val < 0? 1: 0;
+		int count = 0;
 		while (n != 0) {
 			n >>>= 1;
 			count++;
 		}
 		return count;
+//		count should be equal to Integer.SIZE - Integer.numberOfLeadingZeros(Math.abs(val));
+
 	}
 
 	public boolean isExtraBit() {
 		return extraBit;
 	}
 
+	private static int base2Bits(int base){
+		int bits = 2;
+		if (base < 10)
+			return bits + base;
+		else
+			return bits + (2 * base) - 9;
+	}
+	
+	private static int bits2Base(int bits){
+		int base = Math.max(0, bits - 2);
+		if (base > 10) {
+			if ((base & 0x1) == 0)
+				base++;
+			base = 9 + (base - 9) / 2;
+		}
+		return base;
+	}
 }
diff --git a/src/uk/me/parabola/imgfmt/app/trergn/Polyline.java b/src/uk/me/parabola/imgfmt/app/trergn/Polyline.java
index e8f9ce4..6e4550d 100644
--- a/src/uk/me/parabola/imgfmt/app/trergn/Polyline.java
+++ b/src/uk/me/parabola/imgfmt/app/trergn/Polyline.java
@@ -91,7 +91,7 @@ public class Polyline extends MapObject {
 		}
 
 		int minPointsRequired = (this instanceof Polygon)? 3 : 2;
-		BitWriter bw = w.makeBitStream(minPointsRequired);
+		BitWriter bw = w.makeShortestBitStream(minPointsRequired);
 		if(bw == null) {
 			log.error("Level " + getSubdiv().getZoom().getLevel() + " " + ((this instanceof Polygon)? "polygon" : "polyline") + " has less than " + minPointsRequired + " points, discarding");
 			return;
@@ -171,7 +171,7 @@ public class Polyline extends MapObject {
 			return;
 		}
 		int minPointsRequired = (this instanceof Polygon)? 3 : 2;
-		BitWriter bw = w.makeBitStream(minPointsRequired);
+		BitWriter bw = w.makeShortestBitStream(minPointsRequired);
 		if(bw == null) {
 			log.error("Level " + getSubdiv().getZoom().getLevel() + " " + ((this instanceof Polygon)? "polygon" : "polyline") + " has less than " + minPointsRequired + " points, discarding");
 			return;
diff --git a/src/uk/me/parabola/mkgmap/combiners/OverviewBuilder.java b/src/uk/me/parabola/mkgmap/combiners/OverviewBuilder.java
index 9f6fa08..5fa08ab 100644
--- a/src/uk/me/parabola/mkgmap/combiners/OverviewBuilder.java
+++ b/src/uk/me/parabola/mkgmap/combiners/OverviewBuilder.java
@@ -55,12 +55,12 @@ public class OverviewBuilder implements Combiner {
 	private String areaName;
 	private String overviewMapname;
 	private String overviewMapnumber;
-	private Zoom[] levels;
 	private String outputDir;		
 	private Integer codepage;
 	private Integer encodingType;
 	private List<String[]> copyrightMsgs = new ArrayList<String[]>();
 	private List<String[]> licenseInfos = new ArrayList<String[]>();
+	private LevelInfo[] wantedLevels;
 
 
 	public OverviewBuilder(OverviewMap overviewSource) {
@@ -87,9 +87,57 @@ public class OverviewBuilder implements Combiner {
 
 	public void onFinish() {
 		addBackground();
+		calcLevels();
 		writeOverviewMap();
 	}
 	
+	private void calcLevels() {
+		List<MapShape> shapes = overviewSource.getShapes();
+		int maxRes = 16; // we can write a 0x4a polygon for planet in res 16
+		if (wantedLevels != null)
+			maxRes = wantedLevels[wantedLevels.length-1].getBits();
+		int maxSize = 0xffff << (24 - maxRes); 
+		for (MapShape s : shapes){
+			if (s.getType() != 0x4a)
+				continue;
+			int maxDimPoly = s.getBounds().getMaxDimension();
+			if (maxDimPoly > maxSize){
+				int oldMaxRes = maxRes; 
+				while (maxDimPoly > maxSize){
+					maxRes--;
+					maxSize = 0xffff << (24 - maxRes);
+				}
+				String[] name = s.getName().split("\u001d");
+				String msg = "Tile selection (0x4a) polygon for "; 
+				if (name != null && name.length == 2)
+					msg += "tile " + name[1].trim();
+				else 
+					msg += s.getBounds(); 
+				log.error(msg,"cannot be written in level 0 resolution",oldMaxRes + ", using",maxRes,"instead");
+				
+			}
+		}
+		if (wantedLevels == null)
+			setRes(maxRes);
+		else {
+			// make sure that the wanted levels for the overview map
+			// can store the largest 0x4a polygon at level 0
+			int n = wantedLevels.length-1;
+			while (n > 0 && wantedLevels[n].getBits() > maxRes)
+				n--;
+			if (n > 0){
+				int l = 0;
+				while (n >= 0){
+					wantedLevels[n] = new LevelInfo(l++, wantedLevels[n].getBits());
+					n--;
+				}
+				wantedLevels = Arrays.copyOfRange(wantedLevels, 0, l);
+				overviewSource.setMapLevels(wantedLevels);
+			} else
+				setRes(maxRes);	
+		}
+	}
+
 	/**
 	 * Add background polygon that covers the whole area of the overview map. 
 	 */
@@ -187,8 +235,8 @@ public class OverviewBuilder implements Combiner {
 				licenseInfos.add(msgs);
 			
 			
-			levels = mapReader.getLevels();
-			if (overviewSource.mapLevels() == null){
+			Zoom[] levels = mapReader.getLevels();
+			if (wantedLevels == null){
 				LevelInfo[] mapLevels;
 				if (isOverviewImg(filename)){
 					mapLevels = new LevelInfo[levels.length-1]; 
@@ -199,7 +247,7 @@ public class OverviewBuilder implements Combiner {
 					mapLevels = new LevelInfo[1];
 					mapLevels[0] = new LevelInfo(levels[1].getLevel(), levels[1].getResolution());
 				}
-				overviewSource.setMapLevels(mapLevels);
+				wantedLevels = mapLevels;
 			}
 			if (isOverviewImg(filename)){
 				readPoints(mapReader);
@@ -221,6 +269,7 @@ public class OverviewBuilder implements Combiner {
 	 */
 	private void readPoints(MapReader mapReader) {
 		Area bounds = overviewSource.getBounds();
+		Zoom[] levels = mapReader.getLevels();
 		for (int l = 1; l < levels.length; l++){
 			int min = levels[l].getLevel();
 			int res = levels[l].getResolution();
@@ -251,6 +300,7 @@ public class OverviewBuilder implements Combiner {
 	 * @param mapReader Map reader on the detailed .img file.
 	 */
 	private void readLines(MapReader mapReader) {
+		Zoom[] levels = mapReader.getLevels();
 		for (int l = 1; l < levels.length; l++){
 			int min = levels[l].getLevel();
 			int res = levels[l].getResolution();
@@ -286,6 +336,7 @@ public class OverviewBuilder implements Combiner {
 	 * @param mapReader Map reader on the detailed .img file.
 	 */
 	private void readShapes(MapReader mapReader) {
+		Zoom[] levels = mapReader.getLevels();
 		for (int l = 1; l < levels.length; l++){
 			int min = levels[l].getLevel();
 			int res = levels[l].getResolution();
@@ -332,7 +383,7 @@ public class OverviewBuilder implements Combiner {
 		for (Coord co: points){
 			overviewSource.addToBounds(co);
 		}
-		// Create the background rectangle
+		// Create the tile coverage rectangle
 		MapShape bg = new MapShape();
 		bg.setType(0x4a);
 		bg.setPoints(points);
@@ -385,4 +436,15 @@ public class OverviewBuilder implements Combiner {
 		}
 		return list;
 	}
+
+	/**
+	 * Set the highest resolution
+	 * @param resolution
+	 */
+	private void setRes(int resolution) {
+		LevelInfo[] mapLevels = new LevelInfo[1];
+		mapLevels[0] = new LevelInfo(0, resolution);
+		overviewSource.setMapLevels(mapLevels); 
+	}
+
 }
diff --git a/src/uk/me/parabola/mkgmap/filters/PolygonSplitterBase.java b/src/uk/me/parabola/mkgmap/filters/PolygonSplitterBase.java
index 4a19c52..b908c85 100644
--- a/src/uk/me/parabola/mkgmap/filters/PolygonSplitterBase.java
+++ b/src/uk/me/parabola/mkgmap/filters/PolygonSplitterBase.java
@@ -28,7 +28,7 @@ import uk.me.parabola.util.Java2DConverter;
  * @author Steve Ratcliffe
  */
 public class PolygonSplitterBase extends BaseFilter {
-	protected static final int MAX_SIZE = 0x7fff;
+	protected static final int MAX_SIZE = 0xffff; // larger value causes problem in delta encoding of lines
 	private int shift;
 	
 	public void init(FilterConfig config) {
diff --git a/src/uk/me/parabola/mkgmap/filters/PolygonSubdivSizeSplitterFilter.java b/src/uk/me/parabola/mkgmap/filters/PolygonSubdivSizeSplitterFilter.java
index 961278d..760adb5 100644
--- a/src/uk/me/parabola/mkgmap/filters/PolygonSubdivSizeSplitterFilter.java
+++ b/src/uk/me/parabola/mkgmap/filters/PolygonSubdivSizeSplitterFilter.java
@@ -89,6 +89,10 @@ public class PolygonSubdivSizeSplitterFilter extends PolygonSplitterBase impleme
 	}
 
 	private boolean isSizeOk(MapShape shape) {
+		// do not cut the background shape
+		if (shape.getType() == 0x4a)
+			return true;
+		
 		// Estimate the size taken by lines and shapes as a constant plus
 		// a factor based on the number of points.
 		int numPoints = shape.getPoints().size();
diff --git a/src/uk/me/parabola/mkgmap/filters/RemoveObsoletePointsFilter.java b/src/uk/me/parabola/mkgmap/filters/RemoveObsoletePointsFilter.java
index ba2d583..3c2224d 100644
--- a/src/uk/me/parabola/mkgmap/filters/RemoveObsoletePointsFilter.java
+++ b/src/uk/me/parabola/mkgmap/filters/RemoveObsoletePointsFilter.java
@@ -105,13 +105,25 @@ public class RemoveObsoletePointsFilter implements MapFilter {
 			points = newPoints;
 			newPoints = new ArrayList<Coord>(points.size());
 		}
-		if (line instanceof MapShape && newPoints.size() > 3){
-			// check special case: shape starts with spike
-			if (Utils.isStraight(newPoints.get(0), newPoints.get(1), newPoints.get(newPoints.size()-2)) == Utils.STRICTLY_STRAIGHT){
-				newPoints.remove(0);
-				newPoints.set(newPoints.size()-1, newPoints.get(0));
-				if (newPoints.get(newPoints.size()-2).equals(newPoints.get(newPoints.size()-1)))
+		if (line instanceof MapShape){
+			// Check special cases caused by the fact that the first and last point 
+			// in a shape are identical. 
+			while (newPoints.size() > 3){
+				int nPoints = newPoints.size();
+				switch(Utils.isStraight(newPoints.get(newPoints.size()-2), newPoints.get(0), newPoints.get(1))){
+				case Utils.STRAIGHT_SPIKE:
+					newPoints.remove(0);
+					newPoints.set(newPoints.size()-1, newPoints.get(0));
+					if (newPoints.get(newPoints.size()-2).equals(newPoints.get(newPoints.size()-1)))
+						newPoints.remove(newPoints.size()-1);
+					break;
+				case Utils.STRICTLY_STRAIGHT:
 					newPoints.remove(newPoints.size()-1);
+					newPoints.set(0, newPoints.get(newPoints.size()-1));
+					break;
+				}
+				if (nPoints == newPoints.size())
+					break;
 			}
 		}
 		
diff --git a/src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java b/src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java
index 62202dd..4d357b9 100644
--- a/src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java
+++ b/src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java
@@ -2071,11 +2071,11 @@ public class MultiPolygonRelation extends Relation {
 	 */
 	private boolean linesCutEachOther(Coord p1_1, Coord p1_2, Coord p2_1,
 			Coord p2_2) {
-		int width1 = p1_2.getLongitude() - p1_1.getLongitude();
-		int width2 = p2_2.getLongitude() - p2_1.getLongitude();
+		int width1 = p1_2.getHighPrecLon() - p1_1.getHighPrecLon();
+		int width2 = p2_2.getHighPrecLon() - p2_1.getHighPrecLon();
 
-		int height1 = p1_2.getLatitude() - p1_1.getLatitude();
-		int height2 = p2_2.getLatitude() - p2_1.getLatitude();
+		int height1 = p1_2.getHighPrecLat() - p1_1.getHighPrecLat();
+		int height2 = p2_2.getHighPrecLat() - p2_1.getHighPrecLat();
 
 		int denominator = ((height2 * width1) - (width2 * height1));
 		if (denominator == 0) {
@@ -2084,8 +2084,8 @@ public class MultiPolygonRelation extends Relation {
 			return false;
 		}
 		
-		int x1Mx3 = p1_1.getLongitude() - p2_1.getLongitude();
-		int y1My3 = p1_1.getLatitude() - p2_1.getLatitude();
+		int x1Mx3 = p1_1.getHighPrecLon() - p2_1.getHighPrecLon();
+		int y1My3 = p1_1.getHighPrecLat() - p2_1.getHighPrecLat();
 
 		double isx = (double)((width2 * y1My3) - (height2 * x1Mx3))
 				/ denominator;
diff --git a/test/uk/me/parabola/imgfmt/app/BitReaderTest.java b/test/uk/me/parabola/imgfmt/app/BitReaderTest.java
index 6ab84c1..f50dc1b 100644
--- a/test/uk/me/parabola/imgfmt/app/BitReaderTest.java
+++ b/test/uk/me/parabola/imgfmt/app/BitReaderTest.java
@@ -46,6 +46,13 @@ public class BitReaderTest {
 		int s = br.sget2(3);
 		assertEquals(-12, s);
 	}
+	@Test
+	public void testSpecialNegative2() {
+		BitReader br = new BitReader(new byte[]{0x2c, 0x0});
+
+		int s = br.sget2(3);
+		assertEquals(-6, s);
+	}
 
 	@Test
 	public void testSpecialPositive() {
@@ -54,4 +61,18 @@ public class BitReaderTest {
 		int s = br.sget2(3);
 		assertEquals(8, s);
 	}
+	
+	@Test
+	public void testWriteRead() {
+		for (int i = -20; i <= 20; i++){
+			BitWriter bw = new BitWriter();
+			bw.sputn(i,3);
+			BitReader br = new BitReader(bw.getBytes());
+
+			int s = br.sget2(3);
+			assertEquals(i, s);
+		}
+	}
+	
+	
 }

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



More information about the Pkg-grass-devel mailing list