diff --git a/vtm/src/org/oscim/utils/geom/GeometryUtils.java b/vtm/src/org/oscim/utils/geom/GeometryUtils.java
index cdd2c85a..89d6a8da 100644
--- a/vtm/src/org/oscim/utils/geom/GeometryUtils.java
+++ b/vtm/src/org/oscim/utils/geom/GeometryUtils.java
@@ -116,20 +116,36 @@ public final class GeometryUtils {
public static double dotProduct(float[] p, int a, int b, int c) {
- double ab = distance(p, a, b);
- double bc = distance(p, b, c);
- double d = ab * bc;
- double dotp = 0;
+ double ux = (p[b] - p[a]);
+ double uy = (p[b + 1] - p[a + 1]);
+ double ab = Math.sqrt(ux * ux + uy * uy);
+ double vx = (p[b] - p[c]);
+ double vy = (p[b + 1] - p[c + 1]);
+ double bc = Math.sqrt(vx * vx + vy * vy);
+
+ double d = ab * bc;
+
+ if (d <= 0)
+ return 0;
+
+ double dotp = (ux * -vx + uy * -vy) / d;
+
+ if (dotp > 1)
+ dotp = 1;
+ else if (dotp < -1)
+ dotp = -1;
- if (d > 0) {
- dotp = ((p[a] - p[b]) * (p[c] - p[b]) +
- (p[a + 1] - p[b + 1]) * (p[c + 1] - p[b + 1]))
- / d;
- if (dotp > 1)
- dotp = 1;
- else if (dotp < 0)
- dotp = 0;
- }
return dotp;
}
+
+ public static void main(String[] args) {
+ float[] p = { -1, 0, 0, 0, 0, 0 };
+
+ for (int i = 0; i < 9; i++) {
+ p[4] = (float) Math.cos(Math.toRadians(i * 45));
+ p[5] = (float) Math.sin(Math.toRadians(i * 45));
+ System.out.println("\n> " + (i * 45) + " " + p[3] + ":" + p[4] + "\n="
+ + dotProduct(p, 0, 2, 4));
+ }
+ }
}
diff --git a/vtm/src/org/oscim/utils/geom/SimplifyDP.java b/vtm/src/org/oscim/utils/geom/SimplifyDP.java
index f8aefee2..7b6c09ea 100644
--- a/vtm/src/org/oscim/utils/geom/SimplifyDP.java
+++ b/vtm/src/org/oscim/utils/geom/SimplifyDP.java
@@ -1,5 +1,3 @@
-package org.oscim.utils.geom;
-
/*
* Copyright 2012, 2013 Hannes Janetzek
*
@@ -17,6 +15,8 @@ package org.oscim.utils.geom;
* this program. If not, see .
*/
+package org.oscim.utils.geom;
+
import static org.oscim.utils.geom.GeometryUtils.squareSegmentDistance;
import org.oscim.core.GeometryBuffer;
diff --git a/vtm/src/org/oscim/utils/geom/SimplifyVW.java b/vtm/src/org/oscim/utils/geom/SimplifyVW.java
index f6f68e0e..7c3f6a9d 100644
--- a/vtm/src/org/oscim/utils/geom/SimplifyVW.java
+++ b/vtm/src/org/oscim/utils/geom/SimplifyVW.java
@@ -1,3 +1,20 @@
+/*
+ * Copyright 2012, 2013 Hannes Janetzek
+ *
+ * This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
+ *
+ * This program is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program. If not, see .
+ */
+
package org.oscim.utils.geom;
import org.oscim.core.GeometryBuffer;
@@ -7,7 +24,7 @@ import org.oscim.utils.pool.Pool;
/**
* Visvalingam-Wyatt simplification
*
- * ported from:
+ * based on:
* https://github.com/mbloch/mapshaper/blob/master/src/mapshaper-visvalingam.js
* */
public class SimplifyVW {
@@ -62,12 +79,18 @@ public class SimplifyVW {
}
Item last = push(geom.pointPos - 2, Float.MAX_VALUE);
+
+ // sorter.doSort(heap, DistanceComparator, 0, size);
+ // for (int i = 0; i < size; i++)
+ // heap[i].index = i;
+
last.prev = prev;
prev.next = last;
last.next = first;
first.prev = last;
+ int cnt = 0;
while ((it = pop()) != null) {
if (it.area > minArea)
break;
@@ -85,8 +108,9 @@ public class SimplifyVW {
update(geom, it.next);
it = pool.release(it);
+ cnt++;
}
-
+ //System.out.println("dropped: " + cnt + "/" + (geom.pointPos >> 1));
first.prev.next = null;
first.prev = null;
it = first;
@@ -104,63 +128,26 @@ public class SimplifyVW {
it = it.next;
}
- //if (merged > 0)
- // System.out.println("merged: " + merged);
-
- // if (geom.points[0] == geom.points[geom.pointPos - 2]
- // && geom.points[1] == geom.points[geom.pointPos - 1]) {
- // System.out.println("same points");
- // geom.pointPos -= 2;
- // geom.index[geom.indexPos] -= 2;
- // }
-
first = pool.release(first);
}
public static float area(float[] a, int p1, int p2, int p3) {
- // float ax = a[p1], ay = a[p1+1];
- // float bx = a[p2], by = a[p2+1];
- // float cx = a[p3], cy = a[p3+1];
- //
- // float area = ((ax - cx) * (by - cy) - (bx - cx) * (ay - cy));
- //
- // area = (area < 0 ? -area : area) * 0.5f;
- // float ab = distance2D(ax, ay, bx, by),
- // bc = distance2D(bx, by, cx, cy),
- // theta, dotp;
- //
- // if (ab == 0 || bc == 0) {
- // theta = 0;
- // } else {
- // dotp = ((ax - bx) * (cx - bx) + (ay - by) * (cy - by)) / ab * bc;
- // if (dotp >= 1) {
- // theta = 0;
- // } else if (dotp <= -1) {
- // theta = Math.PI;
- // } else {
- // theta = Math.acos(dotp); // consider using other formula at small dp
- // }
- // }
- // return theta;
- //
- // float angle = innerAngle(ax, ay, bx, by, cx, cy),
- // weight = angle < 0.5 ? 0.1 : angle < 1 ? 0.3 : 1;
float area = GeometryUtils.area(a, p1, p2, p3);
- //area *= (1 + GeometryUtils.squareSegmentDistance(a, p2, p1, p3) * 10);
+ double dotp = GeometryUtils.dotProduct(a, p1, p2, p3);
+ //return (float) (area * (0.5 + 0.5 * (1 - dotp * dotp)));
- float dotp = (float) GeometryUtils.dotProduct(a, p1, p2, p3);
- if (dotp > 0)
- return area * (1 - dotp);
-
- return area;
+ dotp = Math.abs(dotp);
+ double weight = dotp < 0.5 ? 0.1 : dotp < 1 ? 0.3 : 1;
+ return (float) (area * weight);
}
private void update(GeometryBuffer geom, Item it) {
- remove(it);
- it.area = area(geom.points, it.prev.id, it.id, it.next.id);
- //System.out.println("< " + it.area);
- push(it);
+ float area = area(geom.points, it.prev.id, it.id, it.next.id);
+ update(it, area);
+ //remove(it);
+ //it.area = area(geom.points, it.prev.id, it.id, it.next.id);
+ //push(it);
}
public void push(Item it) {
@@ -194,6 +181,16 @@ public class SimplifyVW {
return removed;
}
+ public void update(Item it, float area) {
+ if (area < it.area) {
+ it.area = area;
+ up(it.index);
+ } else {
+ it.area = area;
+ down(it.index);
+ }
+ }
+
public int remove(Item removed) {
if (size == 0)
throw new IllegalStateException("size == 0");
@@ -202,14 +199,19 @@ public class SimplifyVW {
Item obj = heap[--size];
heap[size] = null;
- if (i != size) {
- heap[obj.index = i] = obj;
+ /* if min obj was popped */
+ if (i == size)
+ return i;
+
+ /* else put min obj in place of the removed item */
+ obj.index = i;
+ heap[i] = obj;
+
+ if (obj.area < removed.area) {
+ up(i);
+ } else
+ down(i);
- if (obj.area < removed.area)
- up(i);
- else
- down(i);
- }
return i;
};
@@ -222,8 +224,11 @@ public class SimplifyVW {
if (it.area >= parent.area)
break;
- heap[parent.index = i] = parent;
- heap[it.index = i = up] = it;
+ parent.index = i;
+ heap[i] = parent;
+
+ it.index = i = up;
+ heap[i] = it;
}
}
@@ -249,4 +254,48 @@ public class SimplifyVW {
heap[it.index = i = down] = it;
}
}
+ // final static Comparator- DistanceComparator = new Comparator
- () {
+ // @Override
+ // public int compare(Item a, Item b) {
+ //
+ // if (a.area > b.area) {
+ // return -1;
+ // }
+ // if (a.area < b.area) {
+ // return 1;
+ // }
+ // return 0;
+ // }
+ // };
+ // TimSort
- sorter = new TimSort
- ();
+ //
+ // Item push(int id, float area) {
+ // Item it = pool.get();
+ // //heap[size] = it;
+ // //it.index = size;
+ // it.area = area;
+ // it.id = id;
+ //
+ // heap[size++] = it;
+ // return it;
+ // }
+ //
+ // Item pop() {
+ // return heap[--size];
+ // }
+ //
+ // void update(Item it, float area) {
+ // boolean up = it.area < area;
+ // it.area = area;
+ // if (up) {
+ // sorter.doSort(heap, DistanceComparator, 0, it.index + 1);
+ // for (int i = 0, end = it.index + 1; i < end; i++)
+ // heap[i].index = i;
+ // } else {
+ // sorter.doSort(heap, DistanceComparator, it.index, size);
+ // for (int i = it.index; i < size; i++)
+ // heap[i].index = i;
+ // }
+ // }
+
}