add visvalingam-wyatt geometry simplification
This commit is contained in:
parent
e3b279ed6d
commit
2241f3f27f
104
vtm/src/org/oscim/utils/MinHeap.java
Normal file
104
vtm/src/org/oscim/utils/MinHeap.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
193
vtm/src/org/oscim/utils/geom/SimplifyVW.java
Normal file
193
vtm/src/org/oscim/utils/geom/SimplifyVW.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user