add visvalingam-wyatt geometry simplification

This commit is contained in:
Hannes Janetzek 2014-01-23 06:11:21 +01:00
parent e3b279ed6d
commit 2241f3f27f
2 changed files with 297 additions and 0 deletions

View File

@ -0,0 +1,104 @@
package org.oscim.utils;
public class MinHeap {
private int[] data;
private float[] heap;
public static final class Item {
public int pos;
public float prio;
public int index;
}
int size;
private final Item it = new Item();
public MinHeap(float[] heap, int[] data) {
this.heap = heap;
this.data = data;
size = 1;
}
public void push(float prio, int d) {
int idx = size++;
int n = idx >> 1;
while (idx > 1 && heap[n] > prio) {
heap[idx] = heap[n];
data[idx] = data[n];
idx = n;
n >>= 1;
}
heap[idx] = prio;
data[idx] = d;
}
public Item pop() {
if (size == 1)
return null;
it.pos = data[1];
it.prio = heap[1];
int idx = --size;
if (idx > 1) {
heap[1] = heap[idx];
data[1] = data[idx];
heapify();
}
return it;
}
public int peek() {
return data[1];
}
private void heapify() {
float root = heap[1];
int tmp = data[1];
int last = size;
int idx = 1;
while (true) {
// left child
int c = idx << 1;
if (c > last)
break;
// right child
if (c + 1 <= last && heap[c + 1] < heap[c])
c++;
float val = heap[c];
if (val >= root)
break;
heap[idx] = val;
data[idx] = data[c];
idx = c;
}
heap[idx] = root;
data[idx] = tmp;
}
public static void main(String[] args) {
MinHeap h = new MinHeap(new float[10], new int[10]);
h.push(10, 10);
h.push(12, 12);
h.push(21, 21);
h.push(31, 31);
h.push(14, 14);
h.push(2, 2);
Item it;
for (int i = 0; i < 10; i++) {
it = h.pop();
if (it != null)
System.out.println(it.pos + " " + it.prio);
}
}
}

View File

@ -0,0 +1,193 @@
package org.oscim.utils.geom;
import org.oscim.core.GeometryBuffer;
import org.oscim.utils.GeometryUtils;
import org.oscim.utils.pool.Inlist;
import org.oscim.utils.pool.Pool;
public class SimplifyVW {
class Item extends Inlist<Item> {
int index;
int id;
float area;
Item prev;
}
Pool<Item> pool = new Pool<Item>() {
@Override
protected Item createItem() {
return new Item();
}
};
Item[] heap = new Item[100];
int size = 0;
public static void main(String[] args) {
SimplifyVW s = new SimplifyVW();
float[] p2 = { 0, 0, 10, 0, 10, 10, 10, 10, 0, 10, 0, 0 };
GeometryBuffer geom = new GeometryBuffer(p2, new short[2]);
geom.pointPos = 10;
s.simplify(geom, 0.5f);
}
public void simplify(GeometryBuffer geom, float minArea) {
Item prev = null;
Item first = null;
Item it;
size = 0;
if (heap.length < geom.pointPos >> 1)
heap = new Item[geom.pointPos >> 1];
first = prev = push(0, Float.MAX_VALUE);
for (int i = 2; i < geom.pointPos - 2; i += 2) {
it = push(i, GeometryUtils.area(geom.points, i - 2, i, i + 2));
prev.next = it;
it.prev = prev;
prev = it;
}
Item last = push(geom.pointPos - 2, Float.MAX_VALUE);
last.prev = prev;
prev.next = last;
last.next = first;
first.prev = last;
while ((it = pop()) != null) {
if (it.area > minArea)
break;
if (it.prev == it.next)
break;
it.prev.next = it.next;
it.next.prev = it.prev;
if (it.prev != first)
update(geom, it.prev);
if (it.next != first)
update(geom, it.next);
it = pool.release(it);
}
geom.clear();
geom.startPolygon();
first.prev.next = null;
it = first;
while (it != null) {
geom.addPoint(geom.points[it.id], geom.points[it.id + 1]);
//System.out.println(first.id + " " + first.area);
it = it.next;
}
first = pool.release(first);
}
private void update(GeometryBuffer geom, Item it) {
remove(it);
it.area = GeometryUtils.area(geom.points, it.prev.id, it.id, it.next.id);
//System.out.println("< " + it.area);
push(it);
}
public void push(Item it) {
heap[size] = it;
it.index = size;
up(size++);
}
public Item push(int id, float area) {
Item it = pool.get();
heap[size] = it;
it.index = size;
it.area = area;
it.id = id;
up(size++);
return it;
}
public Item pop() {
if (size == 0)
return null;
Item removed = heap[0];
Item obj = heap[--size];
heap[size] = null;
if (size > 0) {
heap[obj.index = 0] = obj;
down(0);
}
return removed;
}
public int remove(Item removed) {
if (size == 0)
throw new IllegalStateException("size == 0");
int i = removed.index;
Item obj = heap[--size];
heap[size] = null;
if (i != size) {
heap[obj.index = i] = obj;
if (obj.area < removed.area)
up(i);
else
down(i);
}
return i;
};
private void up(int i) {
Item obj = heap[i];
while (i > 0) {
int up = ((i + 1) >> 1) - 1;
Item parent = heap[up];
if (obj.area >= parent.area)
break;
heap[parent.index = i] = parent;
heap[obj.index = i = up] = obj;
}
}
private void down(int i) {
Item obj = heap[i];
while (true) {
int right = (i + 1) << 1;
int left = right - 1;
int down = i;
Item child = heap[down];
if (left < size && heap[left].area < child.area)
child = heap[down = left];
if (right < size && heap[right].area < child.area) {
child = heap[down = right];
}
if (down == i)
break;
heap[child.index = i] = child;
heap[obj.index = down] = obj;
i = down;
}
}
}