This repository has been archived by the owner on Jan 29, 2024. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use JTS to fix the xthreshold clipping. See http://openmap.bbn.com/ma…
…ilArchives/openmap-users/2012-03/6867.html for more details.
- Loading branch information
Showing
7 changed files
with
285 additions
and
47 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
/* | ||
* <copyright> | ||
* Copyright 2012 BBN Technologies | ||
* </copyright> | ||
*/ | ||
package com.bbn.openmap.ext.jts; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
import com.bbn.openmap.proj.Projection; | ||
import com.vividsolutions.jts.geom.Coordinate; | ||
import com.vividsolutions.jts.geom.CoordinateSequence; | ||
import com.vividsolutions.jts.geom.Envelope; | ||
import com.vividsolutions.jts.geom.Geometry; | ||
import com.vividsolutions.jts.geom.GeometryFactory; | ||
import com.vividsolutions.jts.geom.LinearRing; | ||
import com.vividsolutions.jts.geom.Polygon; | ||
|
||
/** | ||
* A collection of utility methods for using JTS in OpenMap | ||
*/ | ||
public class JTS { | ||
|
||
private JTS() { | ||
|
||
} | ||
|
||
/** | ||
* Create a JTS {@link Geometry} for the current view of the given OpenMap | ||
* {@link Projection} expanded with the given pixel buffer. The coordinates | ||
* are all in pixel space. | ||
* | ||
* @param gf | ||
* @param proj | ||
* @param buffer | ||
* @return | ||
*/ | ||
public static Polygon createXYViewPolygon(GeometryFactory gf, Projection proj, int buffer) { | ||
Coordinate[] coords = new Coordinate[5]; | ||
coords[0] = new Coordinate(-buffer, proj.getHeight() + buffer); | ||
coords[1] = new Coordinate(proj.getWidth() + buffer, proj.getHeight() + buffer); | ||
coords[2] = new Coordinate(proj.getWidth() + buffer, -buffer); | ||
coords[3] = new Coordinate(-buffer, -buffer); | ||
coords[4] = coords[0]; | ||
LinearRing ring = gf.createLinearRing(coords); | ||
return gf.createPolygon(ring, null); | ||
} | ||
|
||
|
||
public static Geometry createRectangle(GeometryFactory gf, double minx, double miny, double maxx, double maxy) { | ||
Coordinate[] coords = new Coordinate[5]; | ||
coords[0] = new Coordinate(minx, maxy); | ||
coords[1] = new Coordinate(maxx, maxy); | ||
coords[2] = new Coordinate(maxx, miny); | ||
coords[3] = new Coordinate(minx, miny); | ||
coords[4] = coords[0]; | ||
LinearRing ring = gf.createLinearRing(coords); | ||
return gf.createPolygon(ring, null); | ||
} | ||
|
||
/** | ||
* Clip the given List of xypnts to match the given clipGeometry. The result | ||
* is manipulated in to the xypnts List. | ||
* | ||
* @param gf | ||
* @param clipGeometry | ||
* @param xypnts | ||
*/ | ||
public static void clip(GeometryFactory gf, Geometry clipGeometry, List<float[]> xypnts) { | ||
int size = xypnts.size(); | ||
List<float[]> newxypnts = new ArrayList<float[]>(size); | ||
|
||
for (int i = 0; i < size; i += 2) { | ||
float[] xpts = xypnts.get(i); | ||
float[] ypts = xypnts.get(i + 1); | ||
|
||
// check if the geometry needs to be clipped | ||
if (contains(clipGeometry.getEnvelopeInternal(), xpts, ypts)) { | ||
newxypnts.add(xpts); | ||
newxypnts.add(ypts); | ||
continue; | ||
} | ||
|
||
CoordinateSequence coords = new XYCoordinateSequence(xpts, ypts); | ||
Geometry original = null; | ||
|
||
// try to figure out if it is a line or a polygon | ||
if (coords.getCoordinate(0).equals2D(coords.getCoordinate(coords.size() - 1))) { | ||
LinearRing ring = gf.createLinearRing(coords); | ||
original = gf.createPolygon(ring, null); | ||
} else { | ||
original = gf.createLineString(coords); | ||
} | ||
|
||
Geometry intersection = original.intersection(clipGeometry); | ||
|
||
// the intersection might result in multiple geometries | ||
int numGeometries = intersection.getNumGeometries(); | ||
for (int j = 0; j < numGeometries; j++) { | ||
Geometry intersectionPart = intersection.getGeometryN(j); | ||
int numPoints = intersectionPart.getNumPoints(); | ||
|
||
float[] newxpts = new float[numPoints]; | ||
float[] newypts = new float[numPoints]; | ||
|
||
XYCoordianteSequenceExtractorFilter filter = new XYCoordianteSequenceExtractorFilter(newxpts, newypts); | ||
intersectionPart.apply(filter); | ||
|
||
newxypnts.add(newxpts); | ||
newxypnts.add(newypts); | ||
} | ||
|
||
} | ||
|
||
xypnts.clear(); | ||
xypnts.addAll(newxypnts); | ||
} | ||
|
||
private static boolean contains(Envelope envelope, float[] xpts, float[] ypts) { | ||
for (int i = 0; i < xpts.length; i++) { | ||
if (!envelope.contains(xpts[i], ypts[i])) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
} |
39 changes: 39 additions & 0 deletions
39
src/openmap/com/bbn/openmap/ext/jts/XYCoordianteSequenceExtractorFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* | ||
* <copyright> | ||
* Copyright 2012 BBN Technologies | ||
* </copyright> | ||
*/ | ||
package com.bbn.openmap.ext.jts; | ||
|
||
import com.vividsolutions.jts.geom.CoordinateSequence; | ||
import com.vividsolutions.jts.geom.CoordinateSequenceFilter; | ||
|
||
/** | ||
* A {@link CoordinateSequenceFilter} to extract float[] xpts and ypts from a | ||
* {@link CoordinateSequence} | ||
*/ | ||
class XYCoordianteSequenceExtractorFilter | ||
implements CoordinateSequenceFilter { | ||
|
||
private final float[] xpts; | ||
private final float[] ypts; | ||
|
||
public XYCoordianteSequenceExtractorFilter(float[] xpts, float[] ypts) { | ||
this.xpts = xpts; | ||
this.ypts = ypts; | ||
} | ||
|
||
public void filter(CoordinateSequence seq, int i) { | ||
xpts[i] = (float) seq.getX(i); | ||
ypts[i] = (float) seq.getY(i); | ||
} | ||
|
||
public boolean isDone() { | ||
return false; | ||
} | ||
|
||
public boolean isGeometryChanged() { | ||
return false; | ||
} | ||
|
||
} |
102 changes: 102 additions & 0 deletions
102
src/openmap/com/bbn/openmap/ext/jts/XYCoordinateSequence.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/* | ||
* <copyright> | ||
* Copyright 2012 BBN Technologies | ||
* </copyright> | ||
*/ | ||
package com.bbn.openmap.ext.jts; | ||
|
||
import com.bbn.openmap.util.DeepCopyUtil; | ||
import com.vividsolutions.jts.geom.Coordinate; | ||
import com.vividsolutions.jts.geom.CoordinateSequence; | ||
import com.vividsolutions.jts.geom.Envelope; | ||
|
||
class XYCoordinateSequence | ||
implements CoordinateSequence { | ||
|
||
private float[] xpts; | ||
private float[] ypts; | ||
|
||
public XYCoordinateSequence(float[] xpts, float[] ypts) { | ||
this.xpts = xpts; | ||
this.ypts = ypts; | ||
} | ||
|
||
public XYCoordinateSequence(int size) { | ||
this(new float[size], new float[size]); | ||
} | ||
|
||
public int getDimension() { | ||
return 2; | ||
} | ||
|
||
public Coordinate getCoordinate(int i) { | ||
Coordinate c = new Coordinate(); | ||
getCoordinate(i, c); | ||
return c; | ||
} | ||
|
||
public Coordinate getCoordinateCopy(int i) { | ||
return getCoordinate(i); | ||
} | ||
|
||
public void getCoordinate(int index, Coordinate coord) { | ||
coord.x = xpts[index]; | ||
coord.y = ypts[index]; | ||
coord.z = Double.NaN; | ||
} | ||
|
||
public double getX(int index) { | ||
return xpts[index]; | ||
} | ||
|
||
public double getY(int index) { | ||
return ypts[index]; | ||
} | ||
|
||
public double getOrdinate(int index, int ordinateIndex) { | ||
switch (ordinateIndex) { | ||
case 0: | ||
return xpts[index]; | ||
case 1: | ||
return ypts[index]; | ||
default: | ||
return Double.NaN; | ||
} | ||
} | ||
|
||
public int size() { | ||
return xpts.length; | ||
} | ||
|
||
public void setOrdinate(int index, int ordinateIndex, double value) { | ||
switch (ordinateIndex) { | ||
case 0: | ||
xpts[index] = (float) value; | ||
break; | ||
case 1: | ||
ypts[index] = (float) value; | ||
break; | ||
} | ||
} | ||
|
||
public Coordinate[] toCoordinateArray() { | ||
Coordinate[] cs = new Coordinate[size()]; | ||
for (int i = 0; i < cs.length; i++) { | ||
cs[i] = getCoordinate(i); | ||
} | ||
return cs; | ||
} | ||
|
||
public Envelope expandEnvelope(Envelope env) { | ||
for (int i = 0; i < xpts.length; i++) { | ||
env.expandToInclude(xpts[i], ypts[i]); | ||
} | ||
return env; | ||
} | ||
|
||
@Override | ||
public Object clone() { | ||
return new XYCoordinateSequence(DeepCopyUtil.deepCopy(xpts), DeepCopyUtil.deepCopy(ypts)); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters