Skip to content
This repository has been archived by the owner on Jan 29, 2024. It is now read-only.

Commit

Permalink
Use JTS to fix the xthreshold clipping. See http://openmap.bbn.com/ma…
Browse files Browse the repository at this point in the history
  • Loading branch information
halset committed Apr 24, 2012
1 parent 0efd6c0 commit be59a8b
Show file tree
Hide file tree
Showing 7 changed files with 285 additions and 47 deletions.
Binary file added ext/jts-1.12.jar
Binary file not shown.
129 changes: 129 additions & 0 deletions src/openmap/com/bbn/openmap/ext/jts/JTS.java
@@ -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;
}

}
@@ -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 src/openmap/com/bbn/openmap/ext/jts/XYCoordinateSequence.java
@@ -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));
}

}
2 changes: 1 addition & 1 deletion src/openmap/com/bbn/openmap/omGraphics/OMAreaList.java
Expand Up @@ -94,7 +94,7 @@ protected void init() {
*/
public synchronized boolean generate(Projection p, boolean forceProjectAll) {
boolean isGenerated = super.generate(p, forceProjectAll);
if (shape != null) {
if ((shape != null) && (shape.getCurrentPoint() != null)) {
shape.closePath();
}
return isGenerated;
Expand Down
58 changes: 13 additions & 45 deletions src/openmap/com/bbn/openmap/proj/GeoProj.java
Expand Up @@ -31,10 +31,14 @@

import com.bbn.openmap.Environment;
import com.bbn.openmap.MoreMath;
import com.bbn.openmap.ext.jts.JTS;
import com.bbn.openmap.proj.coords.GeoCoordTransformation;
import com.bbn.openmap.proj.coords.LatLonGCT;
import com.bbn.openmap.proj.coords.LatLonPoint;
import com.bbn.openmap.util.Debug;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Polygon;

/**
* GeoProj is the base class of all Projections that deal with coordinates on
Expand Down Expand Up @@ -1386,29 +1390,11 @@ public ArrayList<float[]> forwardCircle(LatLonPoint c, boolean radians, double r
*/
public ArrayList<float[]> forwardPoly(float[] rawllpts, int ltype, int nsegs, boolean isFilled) {
ArrayList<float[]> stuff = _forwardPoly(rawllpts, ltype, nsegs, isFilled);
// @HACK: workaround XWindows bug. simple clip to a boundary.
// this is ugly.
// @HACK: workaround XWindows bug. clip to a boundary.
if (Environment.doingXWindowsWorkaround && (scale <= XSCALE_THRESHOLD)) {
int i, j, size = stuff.size();
float[] xpts, ypts;
for (i = 0; i < size; i += 2) {
xpts = (float[]) stuff.get(i);
ypts = (float[]) stuff.get(i + 1);
for (j = 0; j < xpts.length; j++) {
if (xpts[j] <= -XTHRESHOLD) {
xpts[j] = -XTHRESHOLD;
} else if (xpts[j] >= XTHRESHOLD) {
xpts[j] = XTHRESHOLD;
}
if (ypts[j] <= -XTHRESHOLD) {
ypts[j] = -XTHRESHOLD;
} else if (ypts[j] >= XTHRESHOLD) {
ypts[j] = XTHRESHOLD;
}
}
stuff.set(i, xpts);
stuff.set(i + 1, ypts);
}
GeometryFactory gf = new GeometryFactory();
Geometry clip = JTS.createRectangle(gf, -XTHRESHOLD, -XTHRESHOLD, XTHRESHOLD, XTHRESHOLD);
JTS.clip(gf, clip, stuff);
}
return stuff;
}
Expand All @@ -1432,33 +1418,15 @@ public ArrayList<float[]> forwardPoly(float[] rawllpts, int ltype, int nsegs, bo
*/
public ArrayList<float[]> forwardPoly(double[] rawllpts, int ltype, int nsegs, boolean isFilled) {
ArrayList<float[]> stuff = _forwardPoly(rawllpts, ltype, nsegs, isFilled);
// @HACK: workaround XWindows bug. simple clip to a boundary.
// this is ugly.
// @HACK: workaround XWindows bug. clip to a boundary.
if (Environment.doingXWindowsWorkaround && (scale <= XSCALE_THRESHOLD)) {
int i, j, size = stuff.size();
float[] xpts, ypts;
for (i = 0; i < size; i += 2) {
xpts = stuff.get(i);
ypts = stuff.get(i + 1);
for (j = 0; j < xpts.length; j++) {
if (xpts[j] <= -XTHRESHOLD) {
xpts[j] = -XTHRESHOLD;
} else if (xpts[j] >= XTHRESHOLD) {
xpts[j] = XTHRESHOLD;
}
if (ypts[j] <= -XTHRESHOLD) {
ypts[j] = -XTHRESHOLD;
} else if (ypts[j] >= XTHRESHOLD) {
ypts[j] = XTHRESHOLD;
}
}
stuff.set(i, xpts);
stuff.set(i + 1, ypts);
}
GeometryFactory gf = new GeometryFactory();
Geometry clip = JTS.createRectangle(gf, -XTHRESHOLD, -XTHRESHOLD, XTHRESHOLD, XTHRESHOLD);
JTS.clip(gf, clip, stuff);
}
return stuff;
}

/**
* Forward project a lat/lon Poly defined as decimal degree lat/lons.
* <p>
Expand Down
2 changes: 1 addition & 1 deletion src/openmap/com/bbn/openmap/proj/coords/LatLonGCT.java
Expand Up @@ -44,7 +44,7 @@ public LatLonPoint inverse(double x, double y) {
}

public LatLonPoint inverse(double x, double y, LatLonPoint ret) {
ret.setLatLon((float) y, (float) x);
ret.setLatLon(y, x);
return ret;
}

Expand Down

0 comments on commit be59a8b

Please sign in to comment.