add dotProduct for float[]

This commit is contained in:
Hannes Janetzek 2014-02-17 06:56:12 +01:00
parent 6d4f344326
commit 6e422ade94
3 changed files with 138 additions and 73 deletions

View File

@ -116,20 +116,36 @@ public final class GeometryUtils {
public static double dotProduct(float[] p, int a, int b, int c) { public static double dotProduct(float[] p, int a, int b, int c) {
double ab = distance(p, a, b); double ux = (p[b] - p[a]);
double bc = distance(p, b, c); double uy = (p[b + 1] - p[a + 1]);
double d = ab * bc; double ab = Math.sqrt(ux * ux + uy * uy);
double dotp = 0; 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 (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) if (dotp > 1)
dotp = 1; dotp = 1;
else if (dotp < 0) else if (dotp < -1)
dotp = 0; dotp = -1;
}
return dotp; 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));
}
}
} }

View File

@ -1,5 +1,3 @@
package org.oscim.utils.geom;
/* /*
* Copyright 2012, 2013 Hannes Janetzek * Copyright 2012, 2013 Hannes Janetzek
* *
@ -17,6 +15,8 @@ package org.oscim.utils.geom;
* this program. If not, see <http://www.gnu.org/licenses/>. * this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.oscim.utils.geom;
import static org.oscim.utils.geom.GeometryUtils.squareSegmentDistance; import static org.oscim.utils.geom.GeometryUtils.squareSegmentDistance;
import org.oscim.core.GeometryBuffer; import org.oscim.core.GeometryBuffer;

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
package org.oscim.utils.geom; package org.oscim.utils.geom;
import org.oscim.core.GeometryBuffer; import org.oscim.core.GeometryBuffer;
@ -7,7 +24,7 @@ import org.oscim.utils.pool.Pool;
/** /**
* Visvalingam-Wyatt simplification * Visvalingam-Wyatt simplification
* *
* ported from: * based on:
* https://github.com/mbloch/mapshaper/blob/master/src/mapshaper-visvalingam.js * https://github.com/mbloch/mapshaper/blob/master/src/mapshaper-visvalingam.js
* */ * */
public class SimplifyVW { public class SimplifyVW {
@ -62,12 +79,18 @@ public class SimplifyVW {
} }
Item last = push(geom.pointPos - 2, Float.MAX_VALUE); 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; last.prev = prev;
prev.next = last; prev.next = last;
last.next = first; last.next = first;
first.prev = last; first.prev = last;
int cnt = 0;
while ((it = pop()) != null) { while ((it = pop()) != null) {
if (it.area > minArea) if (it.area > minArea)
break; break;
@ -85,8 +108,9 @@ public class SimplifyVW {
update(geom, it.next); update(geom, it.next);
it = pool.release(it); it = pool.release(it);
cnt++;
} }
//System.out.println("dropped: " + cnt + "/" + (geom.pointPos >> 1));
first.prev.next = null; first.prev.next = null;
first.prev = null; first.prev = null;
it = first; it = first;
@ -104,63 +128,26 @@ public class SimplifyVW {
it = it.next; 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); first = pool.release(first);
} }
public static float area(float[] a, int p1, int p2, int p3) { 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); 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); dotp = Math.abs(dotp);
if (dotp > 0) double weight = dotp < 0.5 ? 0.1 : dotp < 1 ? 0.3 : 1;
return area * (1 - dotp); return (float) (area * weight);
return area;
} }
private void update(GeometryBuffer geom, Item it) { private void update(GeometryBuffer geom, Item it) {
remove(it); float area = area(geom.points, it.prev.id, it.id, it.next.id);
it.area = area(geom.points, it.prev.id, it.id, it.next.id); update(it, area);
//System.out.println("< " + it.area); //remove(it);
push(it); //it.area = area(geom.points, it.prev.id, it.id, it.next.id);
//push(it);
} }
public void push(Item it) { public void push(Item it) {
@ -194,6 +181,16 @@ public class SimplifyVW {
return removed; 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) { public int remove(Item removed) {
if (size == 0) if (size == 0)
throw new IllegalStateException("size == 0"); throw new IllegalStateException("size == 0");
@ -202,14 +199,19 @@ public class SimplifyVW {
Item obj = heap[--size]; Item obj = heap[--size];
heap[size] = null; heap[size] = null;
if (i != size) { /* if min obj was popped */
heap[obj.index = i] = obj; if (i == size)
return i;
if (obj.area < removed.area) /* else put min obj in place of the removed item */
obj.index = i;
heap[i] = obj;
if (obj.area < removed.area) {
up(i); up(i);
else } else
down(i); down(i);
}
return i; return i;
}; };
@ -222,8 +224,11 @@ public class SimplifyVW {
if (it.area >= parent.area) if (it.area >= parent.area)
break; break;
heap[parent.index = i] = parent; parent.index = i;
heap[it.index = i = up] = it; heap[i] = parent;
it.index = i = up;
heap[i] = it;
} }
} }
@ -249,4 +254,48 @@ public class SimplifyVW {
heap[it.index = i = down] = it; heap[it.index = i = down] = it;
} }
} }
// final static Comparator<Item> DistanceComparator = new Comparator<Item>() {
// @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<Item> sorter = new TimSort<Item>();
//
// 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;
// }
// }
} }