add TileClipper
This commit is contained in:
parent
6a28480510
commit
d44489819a
@ -23,11 +23,11 @@ package org.oscim.utils;
|
|||||||
|
|
||||||
public class LineClipper {
|
public class LineClipper {
|
||||||
|
|
||||||
private static final int INSIDE = 0; // 0000
|
public static final int INSIDE = 0; // 0000
|
||||||
private static final int LEFT = 1; // 0001
|
public static final int LEFT = 1; // 0001
|
||||||
private static final int RIGHT = 2; // 0010
|
public static final int RIGHT = 2; // 0010
|
||||||
private static final int BOTTOM = 4; // 0100
|
public static final int BOTTOM = 4; // 0100
|
||||||
private static final int TOP = 8; // 1000
|
public static final int TOP = 8; // 1000
|
||||||
|
|
||||||
private final int xmin, xmax, ymin, ymax;
|
private final int xmin, xmax, ymin, ymax;
|
||||||
public final int[] out;
|
public final int[] out;
|
||||||
@ -62,17 +62,15 @@ public class LineClipper {
|
|||||||
mPrevX = x0;
|
mPrevX = x0;
|
||||||
mPrevY = y0;
|
mPrevY = y0;
|
||||||
|
|
||||||
int outcode = INSIDE;
|
mPrevOutcode = INSIDE;
|
||||||
if (x0 < xmin)
|
if (x0 < xmin)
|
||||||
outcode |= LEFT;
|
mPrevOutcode |= LEFT;
|
||||||
else if (x0 > xmax)
|
else if (x0 > xmax)
|
||||||
outcode |= RIGHT;
|
mPrevOutcode |= RIGHT;
|
||||||
if (y0 < ymin)
|
if (y0 < ymin)
|
||||||
outcode |= BOTTOM;
|
mPrevOutcode |= BOTTOM;
|
||||||
else if (y0 > ymax)
|
else if (y0 > ymax)
|
||||||
outcode |= TOP;
|
mPrevOutcode |= TOP;
|
||||||
|
|
||||||
mPrevOutcode = outcode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -135,7 +133,6 @@ public class LineClipper {
|
|||||||
|
|
||||||
// At least one endpoint is outside the clip rectangle; pick it.
|
// At least one endpoint is outside the clip rectangle; pick it.
|
||||||
int outcodeOut = (outcode0 == 0) ? outcode1 : outcode0;
|
int outcodeOut = (outcode0 == 0) ? outcode1 : outcode0;
|
||||||
|
|
||||||
// Now find the intersection point;
|
// Now find the intersection point;
|
||||||
// use formulas y = y0 + slope * (x - x0), x = x0 + (1 / slope) * (y - y0)
|
// use formulas y = y0 + slope * (x - x0), x = x0 + (1 / slope) * (y - y0)
|
||||||
if ((outcodeOut & TOP) != 0) { // point is above the clip rectangle
|
if ((outcodeOut & TOP) != 0) { // point is above the clip rectangle
|
||||||
|
|||||||
208
vtm/src/org/oscim/utils/TileClipper.java
Normal file
208
vtm/src/org/oscim/utils/TileClipper.java
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
package org.oscim.utils;
|
||||||
|
|
||||||
|
import org.oscim.core.GeometryBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clip polygon to a rectangle. Output cannot expected to be valid
|
||||||
|
* Simple-Feature geometry, i.e. all rings are clipped independently
|
||||||
|
* so that inner and outer rings might touch, etc.
|
||||||
|
*
|
||||||
|
* based on http://www.cs.rit.edu/~icss571/clipTrans/PolyClipBack.html
|
||||||
|
* */
|
||||||
|
public class TileClipper {
|
||||||
|
private float minX;
|
||||||
|
private float maxX;
|
||||||
|
private float minY;
|
||||||
|
private float maxY;
|
||||||
|
|
||||||
|
public TileClipper(float minX, float minY, float maxX, float maxY) {
|
||||||
|
this.minX = minX;
|
||||||
|
this.minY = minY;
|
||||||
|
this.maxX = maxX;
|
||||||
|
this.maxY = maxY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRect(float minX, float minY, float maxX, float maxY) {
|
||||||
|
this.minX = minX;
|
||||||
|
this.minY = minY;
|
||||||
|
this.maxX = maxX;
|
||||||
|
this.maxY = maxY;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final GeometryBuffer mGeomOut = new GeometryBuffer(10, 1);
|
||||||
|
|
||||||
|
public boolean clip(GeometryBuffer geom) {
|
||||||
|
GeometryBuffer out = mGeomOut;
|
||||||
|
|
||||||
|
out.clear();
|
||||||
|
|
||||||
|
clipEdge(geom, out, LineClipper.LEFT);
|
||||||
|
geom.clear();
|
||||||
|
|
||||||
|
clipEdge(out, geom, LineClipper.TOP);
|
||||||
|
out.clear();
|
||||||
|
|
||||||
|
clipEdge(geom, out, LineClipper.RIGHT);
|
||||||
|
geom.clear();
|
||||||
|
|
||||||
|
clipEdge(out, geom, LineClipper.BOTTOM);
|
||||||
|
|
||||||
|
if ((geom.indexPos == 0) && (geom.index[0] < 6))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean clipEdge(GeometryBuffer in, GeometryBuffer out, int edge) {
|
||||||
|
|
||||||
|
out.startPolygon();
|
||||||
|
boolean outer = true;
|
||||||
|
|
||||||
|
int pointPos = 0;
|
||||||
|
|
||||||
|
for (int i = 0, n = in.index.length; i < n; i++) {
|
||||||
|
int len = in.index[i];
|
||||||
|
if (len < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (len < 6) {
|
||||||
|
pointPos += len;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == 0) {
|
||||||
|
out.startPolygon();
|
||||||
|
outer = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!outer)
|
||||||
|
out.startHole();
|
||||||
|
|
||||||
|
clipRing(i, pointPos, in, out, edge);
|
||||||
|
|
||||||
|
// if (out.index[i] < 6) {
|
||||||
|
// out.index[i] = 0;
|
||||||
|
// //if (out.indexPos > 0)
|
||||||
|
// // out.indexPos--;
|
||||||
|
// // TODO if outer skip holes
|
||||||
|
// }
|
||||||
|
|
||||||
|
pointPos += len;
|
||||||
|
|
||||||
|
outer = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean clipRing(int indexPos, int pointPos, GeometryBuffer in, GeometryBuffer out,
|
||||||
|
int edge) {
|
||||||
|
|
||||||
|
int len = in.index[indexPos];
|
||||||
|
if (len < 6)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
len += pointPos;
|
||||||
|
|
||||||
|
float px = in.points[len - 2];
|
||||||
|
float py = in.points[len - 1];
|
||||||
|
|
||||||
|
for (int i = pointPos; i < len;) {
|
||||||
|
float cx = in.points[i++];
|
||||||
|
float cy = in.points[i++];
|
||||||
|
|
||||||
|
switch (edge) {
|
||||||
|
case LineClipper.LEFT:
|
||||||
|
if (cx > minX) {
|
||||||
|
// current is inside
|
||||||
|
if (px > minX) {
|
||||||
|
// previous was inside
|
||||||
|
out.addPoint(cx, cy);
|
||||||
|
} else {
|
||||||
|
// previous was outside, add edge point
|
||||||
|
out.addPoint(minX, py + (cy - py) * (minX - px) / (cx - px));
|
||||||
|
out.addPoint(cx, cy);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (px > minX) {
|
||||||
|
// previous was inside, add edge point
|
||||||
|
out.addPoint(minX, py + (cy - py) * (minX - px) / (cx - px));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LineClipper.RIGHT:
|
||||||
|
if (cx < maxX) {
|
||||||
|
if (px < maxX) {
|
||||||
|
out.addPoint(cx, cy);
|
||||||
|
} else {
|
||||||
|
out.addPoint(maxX, py + (cy - py) * (maxX - px) / (cx - px));
|
||||||
|
out.addPoint(cx, cy);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (px < maxX) {
|
||||||
|
out.addPoint(maxX, py + (cy - py) * (maxX - px) / (cx - px));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LineClipper.BOTTOM:
|
||||||
|
if (cy > minY) {
|
||||||
|
if (py > minY) {
|
||||||
|
out.addPoint(cx, cy);
|
||||||
|
} else {
|
||||||
|
out.addPoint(px + (cx - px) * (minY - py) / (cy - py), minY);
|
||||||
|
out.addPoint(cx, cy);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (py > minY) {
|
||||||
|
out.addPoint(px + (cx - px) * (minY - py) / (cy - py), minY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LineClipper.TOP:
|
||||||
|
if (cy < maxY) {
|
||||||
|
if (py < maxY) {
|
||||||
|
out.addPoint(cx, cy);
|
||||||
|
} else {
|
||||||
|
out.addPoint(px + (cx - px) * (maxY - py) / (cy - py), maxY);
|
||||||
|
out.addPoint(cx, cy);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (py < maxY) {
|
||||||
|
out.addPoint(px + (cx - px) * (maxY - py) / (cy - py), maxY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
px = cx;
|
||||||
|
py = cy;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public static void main(String[] args) {
|
||||||
|
// TileClipper clipper = new TileClipper(0, 0, 100, 100);
|
||||||
|
// GeometryBuffer geom = new GeometryBuffer(10, 1);
|
||||||
|
//
|
||||||
|
// geom.startPolygon();
|
||||||
|
// geom.addPoint(-10, -10);
|
||||||
|
// geom.addPoint(110, -10);
|
||||||
|
// geom.addPoint(110, 110);
|
||||||
|
// geom.addPoint(-10, 110);
|
||||||
|
//
|
||||||
|
// geom.startHole();
|
||||||
|
// geom.addPoint(10, 10);
|
||||||
|
// geom.addPoint(110, 10);
|
||||||
|
// geom.addPoint(110, 90);
|
||||||
|
// geom.addPoint(10, 90);
|
||||||
|
//
|
||||||
|
// System.out.println("" + Arrays.toString(geom.points));
|
||||||
|
// clipper.clip(geom);
|
||||||
|
// System.out.println("" + Arrays.toString(geom.points) + " " + geom.index[0]);
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user