refactor TileClipper:
- move clipLine() to LineClipper
This commit is contained in:
parent
f62ea65f25
commit
dfe6ca99ce
@ -238,7 +238,7 @@ public class PathLayer extends Layer {
|
||||
|
||||
public Worker(Map map) {
|
||||
super(map, 0, new Task(), new Task());
|
||||
mClipper = new LineClipper(-max, -max, max, max, true);
|
||||
mClipper = new LineClipper(-max, -max, max, max);
|
||||
mPPoints = new float[0];
|
||||
}
|
||||
|
||||
@ -339,6 +339,8 @@ public class PathLayer extends Layer {
|
||||
float prevX = x;
|
||||
float prevY = y;
|
||||
|
||||
float[] segment = null;
|
||||
|
||||
for (int j = 2; j < size * 2; j += 2) {
|
||||
x = (int) ((mPreprojected[j + 0] - mx) * scale);
|
||||
y = (int) ((mPreprojected[j + 1] - my) * scale);
|
||||
@ -368,10 +370,11 @@ public class PathLayer extends Layer {
|
||||
ll.addLine(projected, i, false);
|
||||
|
||||
if (clip < 0) {
|
||||
// add line segment
|
||||
ll.addLine(mClipper.out, 4, false);
|
||||
prevX = mClipper.out[2];
|
||||
prevY = mClipper.out[3];
|
||||
/* add line segment */
|
||||
segment = mClipper.getLine(segment, 0);
|
||||
ll.addLine(segment, 4, false);
|
||||
prevX = mClipper.outX2;
|
||||
prevY = mClipper.outY2;
|
||||
}
|
||||
i = 0;
|
||||
continue;
|
||||
|
@ -16,6 +16,8 @@
|
||||
*/
|
||||
package org.oscim.utils.geom;
|
||||
|
||||
import org.oscim.core.GeometryBuffer;
|
||||
|
||||
/**
|
||||
* from http://en.wikipedia.org/wiki/Cohen%E2%80%93
|
||||
* Sutherland_algorithm
|
||||
@ -29,34 +31,30 @@ public class LineClipper {
|
||||
public static final int BOTTOM = 4; // 0100
|
||||
public static final int TOP = 8; // 1000
|
||||
|
||||
private final int xmin, xmax, ymin, ymax;
|
||||
public final float[] out;
|
||||
private float xmin, xmax, ymin, ymax;
|
||||
|
||||
public LineClipper(int minx, int miny, int maxx, int maxy) {
|
||||
public LineClipper(float minx, float miny, float maxx, float maxy) {
|
||||
this.xmin = minx;
|
||||
this.ymin = miny;
|
||||
this.xmax = maxx;
|
||||
this.ymax = maxy;
|
||||
this.out = null;
|
||||
}
|
||||
|
||||
public LineClipper(int minx, int miny, int maxx, int maxy, boolean keepResult) {
|
||||
public void setRect(float minx, float miny, float maxx, float maxy) {
|
||||
this.xmin = minx;
|
||||
this.ymin = miny;
|
||||
this.xmax = maxx;
|
||||
this.ymax = maxy;
|
||||
if (keepResult)
|
||||
this.out = new float[4];
|
||||
else
|
||||
this.out = null;
|
||||
}
|
||||
|
||||
private int mPrevOutcode;
|
||||
private float mPrevX;
|
||||
private float mPrevY;
|
||||
|
||||
//public int outX;
|
||||
//public int outY;
|
||||
public float outX1;
|
||||
public float outY1;
|
||||
public float outX2;
|
||||
public float outY2;
|
||||
|
||||
public boolean clipStart(float x0, float y0) {
|
||||
mPrevX = x0;
|
||||
@ -76,8 +74,6 @@ public class LineClipper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param x1 ...
|
||||
* @param y1 ...
|
||||
* @return 0 if not intersection, 1 fully within, -1 clipped (and 'out' set
|
||||
* to new points)
|
||||
*/
|
||||
@ -101,8 +97,7 @@ public class LineClipper {
|
||||
// Bitwise AND is not 0. Trivially reject
|
||||
accept = 0;
|
||||
} else {
|
||||
accept = clip(mPrevX, mPrevY, x1, y1, xmin, ymin, xmax, ymax, mPrevOutcode, outcode,
|
||||
this.out) ? -1 : 0;
|
||||
accept = clip(mPrevX, mPrevY, x1, y1, mPrevOutcode, outcode) ? -1 : 0;
|
||||
}
|
||||
mPrevOutcode = outcode;
|
||||
mPrevX = x1;
|
||||
@ -111,45 +106,51 @@ public class LineClipper {
|
||||
return accept;
|
||||
}
|
||||
|
||||
// CohenSutherland clipping algorithm clips a line from
|
||||
// P0 = (x0, y0) to P1 = (x1, y1) against a rectangle with
|
||||
// diagonal from (xmin, ymin) to (xmax, ymax).
|
||||
private static boolean clip(float x0, float y0, float x1, float y1,
|
||||
int xmin, int ymin, int xmax, int ymax, int outcode0, int outcode1, float[] out) {
|
||||
public int clipSegment(float x1, float y1, float x2, float y2) {
|
||||
clipStart(x1, y1);
|
||||
return clipNext(x2, y2);
|
||||
}
|
||||
|
||||
/* CohenSutherland clipping algorithm clips a line from
|
||||
* P0 = (x0, y0) to P1 = (x1, y1) against a rectangle with
|
||||
* diagonal from (xmin, ymin) to (xmax, ymax).
|
||||
* based on en.wikipedia.org/wiki/Cohen-Sutherland */
|
||||
private boolean clip(float x0, float y0, float x1, float y1, int outcode0, int outcode1) {
|
||||
boolean accept = false;
|
||||
|
||||
while (true) {
|
||||
if ((outcode0 | outcode1) == 0) {
|
||||
// Bitwise OR is 0. Trivially accept and get out of loop
|
||||
/* Bitwise OR is 0. Trivially accept and get out of loop */
|
||||
accept = true;
|
||||
break;
|
||||
} else if ((outcode0 & outcode1) != 0) {
|
||||
// Bitwise AND is not 0. Trivially reject and get out of loop
|
||||
/* Bitwise AND is not 0. Trivially reject and get out of loop */
|
||||
break;
|
||||
} else {
|
||||
// failed both tests, so calculate the line segment to clip
|
||||
// from an outside point to an intersection with clip edge
|
||||
/* failed both tests, so calculate the line segment to clip
|
||||
* from an outside point to an intersection with clip edge */
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
|
||||
// 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;
|
||||
// Now find the intersection point;
|
||||
// use formulas y = y0 + slope * (x - x0), x = x0 + (1 / slope) * (y - y0)
|
||||
if ((outcodeOut & TOP) != 0) { // point is above the clip rectangle
|
||||
/* Now find the intersection point;
|
||||
* use formulas y = y0 + slope * (x - x0), x = x0 + (1 / slope)
|
||||
* * (y - y0) */
|
||||
if ((outcodeOut & TOP) != 0) {
|
||||
/* point is above the clip rectangle */
|
||||
x = x0 + (x1 - x0) * (ymax - y0) / (y1 - y0);
|
||||
y = ymax;
|
||||
} else if ((outcodeOut & BOTTOM) != 0) {
|
||||
// point is below the clip rectangle
|
||||
/* point is below the clip rectangle */
|
||||
x = x0 + (x1 - x0) * (ymin - y0) / (y1 - y0);
|
||||
y = ymin;
|
||||
} else if ((outcodeOut & RIGHT) != 0) {
|
||||
// point is to the right of clip rectangle
|
||||
/* point is to the right of clip rectangle */
|
||||
y = y0 + (y1 - y0) * (xmax - x0) / (x1 - x0);
|
||||
x = xmax;
|
||||
} else if ((outcodeOut & LEFT) != 0) {
|
||||
// point is to the left of clip rectangle
|
||||
/* point is to the left of clip rectangle */
|
||||
y = y0 + (y1 - y0) * (xmin - x0) / (x1 - x0);
|
||||
x = xmin;
|
||||
}
|
||||
@ -164,8 +165,8 @@ public class LineClipper {
|
||||
else if (y > ymax)
|
||||
outcode |= TOP;
|
||||
|
||||
// Now we move outside point to intersection point to clip
|
||||
// and get ready for next pass.
|
||||
/* Now we move outside point to intersection point to clip
|
||||
* and get ready for next pass. */
|
||||
if (outcodeOut == outcode0) {
|
||||
x0 = x;
|
||||
y0 = y;
|
||||
@ -177,12 +178,88 @@ public class LineClipper {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (accept && out != null) {
|
||||
out[0] = x0;
|
||||
out[1] = y0;
|
||||
out[2] = x1;
|
||||
out[3] = y1;
|
||||
if (accept) {
|
||||
outX1 = x0;
|
||||
outY1 = y0;
|
||||
outX2 = x1;
|
||||
outY2 = y1;
|
||||
}
|
||||
return accept;
|
||||
}
|
||||
|
||||
public float[] getLine(float out[], int offset) {
|
||||
if (out == null)
|
||||
return new float[] { outX1, outY1, outX2, outY2 };
|
||||
|
||||
out[offset + 0] = outX1;
|
||||
out[offset + 1] = outY1;
|
||||
out[offset + 2] = outX2;
|
||||
out[offset + 3] = outY2;
|
||||
return out;
|
||||
}
|
||||
|
||||
public int clipLine(GeometryBuffer in, GeometryBuffer out) {
|
||||
int pointPos = 0;
|
||||
int numLines = 0;
|
||||
for (int i = 0, n = in.index.length; i < n; i++) {
|
||||
int len = in.index[i];
|
||||
if (len < 0)
|
||||
break;
|
||||
|
||||
if (len < 4) {
|
||||
pointPos += len;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int inPos = pointPos;
|
||||
int end = inPos + len;
|
||||
|
||||
float prevX = in.points[inPos + 0];
|
||||
float prevY = in.points[inPos + 1];
|
||||
|
||||
boolean inside = clipStart(prevX, prevY);
|
||||
|
||||
if (inside) {
|
||||
out.startLine();
|
||||
out.addPoint(prevX, prevY);
|
||||
numLines++;
|
||||
}
|
||||
|
||||
for (inPos += 2; inPos < end; inPos += 2) {
|
||||
/* get the current way point coordinates */
|
||||
float curX = in.points[inPos];
|
||||
float curY = in.points[inPos + 1];
|
||||
|
||||
int clip;
|
||||
if ((clip = clipNext(curX, curY)) != 0) {
|
||||
if (clip < 0) {
|
||||
if (inside) {
|
||||
/* previous was inside */
|
||||
out.addPoint(outX2, outY2);
|
||||
inside = false;
|
||||
|
||||
} else {
|
||||
/* previous was outside */
|
||||
out.startLine();
|
||||
numLines++;
|
||||
out.addPoint(outX1, outY1);
|
||||
out.addPoint(outX2, outY2);
|
||||
|
||||
inside = clipStart(curX, curY);
|
||||
}
|
||||
} else {
|
||||
out.addPoint(curX, curY);
|
||||
}
|
||||
} else {
|
||||
inside = false;
|
||||
}
|
||||
}
|
||||
pointPos += len;
|
||||
}
|
||||
return numLines;
|
||||
}
|
||||
}
|
||||
|
@ -19,12 +19,12 @@ package org.oscim.utils.geom;
|
||||
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
|
||||
* Clip polygons and lines to a rectangle. Output cannot expected to be valid
|
||||
* Simple-Feature geometry, i.e. all polygon 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;
|
||||
@ -36,7 +36,7 @@ public class TileClipper {
|
||||
this.minY = minY;
|
||||
this.maxX = maxX;
|
||||
this.maxY = maxY;
|
||||
mLineClipper = new LineClipper((int) minX, (int) minY, (int) maxX, (int) maxY, true);
|
||||
mLineClipper = new LineClipper(minX, minY, maxX, maxY);
|
||||
}
|
||||
|
||||
public void setRect(float minX, float minY, float maxX, float maxY) {
|
||||
@ -44,10 +44,10 @@ public class TileClipper {
|
||||
this.minY = minY;
|
||||
this.maxX = maxX;
|
||||
this.maxY = maxY;
|
||||
mLineClipper = new LineClipper((int) minX, (int) minY, (int) maxX, (int) maxY, true);
|
||||
mLineClipper.setRect(minX, minY, maxX, maxY);
|
||||
}
|
||||
|
||||
private LineClipper mLineClipper;
|
||||
private final LineClipper mLineClipper;
|
||||
|
||||
private final GeometryBuffer mGeomOut = new GeometryBuffer(10, 1);
|
||||
|
||||
@ -77,7 +77,7 @@ public class TileClipper {
|
||||
GeometryBuffer out = mGeomOut;
|
||||
out.clear();
|
||||
|
||||
int numLines = clipLine(geom, out);
|
||||
int numLines = mLineClipper.clipLine(geom, out);
|
||||
|
||||
short idx[] = geom.ensureIndexSize(numLines + 1, false);
|
||||
System.arraycopy(out.index, 0, idx, 0, numLines);
|
||||
@ -255,76 +255,4 @@ public class TileClipper {
|
||||
py = cy;
|
||||
}
|
||||
}
|
||||
|
||||
private int clipLine(GeometryBuffer in, GeometryBuffer out) {
|
||||
|
||||
int pointPos = 0;
|
||||
int numLines = 0;
|
||||
for (int i = 0, n = in.index.length; i < n; i++) {
|
||||
int len = in.index[i];
|
||||
if (len < 0)
|
||||
break;
|
||||
|
||||
if (len < 4) {
|
||||
pointPos += len;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int inPos = pointPos;
|
||||
int end = inPos + len;
|
||||
|
||||
float prevX = in.points[inPos + 0];
|
||||
float prevY = in.points[inPos + 1];
|
||||
|
||||
boolean inside = mLineClipper.clipStart(prevX, prevY);
|
||||
|
||||
if (inside) {
|
||||
out.startLine();
|
||||
out.addPoint(prevX, prevY);
|
||||
numLines++;
|
||||
}
|
||||
|
||||
for (inPos += 2; inPos < end; inPos += 2) {
|
||||
// get the current way point coordinates
|
||||
float curX = in.points[inPos];
|
||||
float curY = in.points[inPos + 1];
|
||||
|
||||
int clip;
|
||||
if ((clip = mLineClipper.clipNext(curX, curY)) != 0) {
|
||||
//System.out.println(inside + " clip: " + clip + " "
|
||||
// + Arrays.toString(mLineClipper.out));
|
||||
if (clip < 0) {
|
||||
if (inside) {
|
||||
// previous was inside
|
||||
out.addPoint(mLineClipper.out[2], mLineClipper.out[3]);
|
||||
inside = false;
|
||||
|
||||
} else {
|
||||
// previous was outside
|
||||
out.startLine();
|
||||
numLines++;
|
||||
out.addPoint(mLineClipper.out[0], mLineClipper.out[1]);
|
||||
out.addPoint(mLineClipper.out[2], mLineClipper.out[3]);
|
||||
|
||||
inside = mLineClipper.clipStart(curX, curY);
|
||||
}
|
||||
} else {
|
||||
out.addPoint(curX, curY);
|
||||
|
||||
}
|
||||
} else {
|
||||
inside = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pointPos += len;
|
||||
}
|
||||
|
||||
return numLines;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user