Issue #117
Change-Id: I52293e2148fdc1fbfd22ad01e03d6d628cd1c09a Former-commit-id:50732574aa
[formerlydb66cbb605
] [formerly5dc466443b
[formerly 6f197a78afa6a8760f852e94861950a230eaedcc]] Former-commit-id:5dc466443b
Former-commit-id:5026332931
This commit is contained in:
parent
a23db3e2d8
commit
66f60fc4a7
3 changed files with 160 additions and 12 deletions
|
@ -76,6 +76,7 @@ import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory;
|
|||
* 10/01/2013 DR 16632 Qinglu Lin Fixed the bug in for loop range.
|
||||
* 10/17/2013 DR 16632 Qinglu Lin Updated removeOverlaidLinesegments().
|
||||
* 10/18/2013 DR 16632 Qinglu Lin Catch exception thrown when coords length is less than 4 and doing createLinearRing(coords).
|
||||
* 12/17/2013 DR 16567 Qinglu Lin Added createPolygonByPoints(). Gerrit testing
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
|
@ -1523,4 +1524,24 @@ public class PolygonUtil {
|
|||
}
|
||||
return slope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a polygon whose two diagonal coordinates are a and b.
|
||||
**/
|
||||
static public Geometry createPolygonByPoints(Coordinate a, Coordinate b) {
|
||||
double maxX, minX, maxY, minY;
|
||||
maxX = Math.max(a.x, b.x);
|
||||
minX = Math.min(a.x, b.x);
|
||||
maxY = Math.max(a.y, b.y);
|
||||
minY = Math.min(a.y, b.y);
|
||||
Coordinate[] coord = new Coordinate[5];
|
||||
coord[0] = new Coordinate(minX, minY);
|
||||
coord[1] = new Coordinate(maxX, minY);
|
||||
coord[2] = new Coordinate(maxX, maxY);
|
||||
coord[3] = new Coordinate(minX, maxY);
|
||||
coord[4] = new Coordinate(coord[0]);
|
||||
GeometryFactory gf = new GeometryFactory();
|
||||
LinearRing lr = gf.createLinearRing(coord);
|
||||
return gf.createPolygon(lr, null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -194,6 +194,8 @@ import com.vividsolutions.jts.io.WKTReader;
|
|||
* 10/21/2013 DR 16632 D. Friedman Modify areaPercent exception handling. Fix an NPE.
|
||||
* Use A1 hatching behavior when no county passes the inclusion filter.
|
||||
* 10/29/2013 DR 16734 D. Friedman If redraw-from-hatched-area fails, don't allow the pollygon the be used.
|
||||
* 12/17/2013 DR 16567 Qinglu Lin Added findLargestGeometry() and findLargestQuadrant(), and updated
|
||||
* populateStrings() and paintText(). TEST gerrit!!!
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
|
@ -959,11 +961,11 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
|
||||
double ratio = paintProps.getView().getExtent().getWidth()
|
||||
/ paintProps.getCanvasBounds().width;
|
||||
double minX = paintProps.getView().getExtent().getMinX();
|
||||
double maxX = paintProps.getView().getExtent().getMaxX();
|
||||
double minY = paintProps.getView().getExtent().getMinY();
|
||||
double maxY = paintProps.getView().getExtent().getMaxY();
|
||||
double boundary = 40 * ratio;
|
||||
double minX = paintProps.getView().getExtent().getMinX() + boundary;
|
||||
double maxX = paintProps.getView().getExtent().getMaxX() - boundary;
|
||||
double minY = paintProps.getView().getExtent().getMinY() + boundary;
|
||||
double maxY = paintProps.getView().getExtent().getMaxY() - boundary;
|
||||
List<DrawableString> strings = new ArrayList<DrawableString>();
|
||||
if (state.strings != null && state.strings.size() > 0) {
|
||||
Iterator<Coordinate> coords = state.strings.keySet().iterator();
|
||||
|
@ -976,14 +978,14 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
in[2] = c.z;
|
||||
double[] out = this.descriptor.worldToPixel(in);
|
||||
if (out[0] > maxX) {
|
||||
out[0] = maxX;
|
||||
out[0] = maxX - boundary;
|
||||
} else if (out[0] < minX) {
|
||||
out[0] = minX;
|
||||
out[0] = minX + boundary;
|
||||
}
|
||||
if (out[1] > maxY) {
|
||||
out[1] = maxY;
|
||||
out[1] = maxY - boundary;
|
||||
} else if (out[1] < minY) {
|
||||
out[1] = minY;
|
||||
out[1] = minY + boundary;
|
||||
}
|
||||
DrawableString string = new DrawableString(text, textColor);
|
||||
string.magnification = magnification;
|
||||
|
@ -3018,10 +3020,52 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
|
||||
for (GeospatialData f : geoData.features) {
|
||||
Geometry geom = f.geometry;
|
||||
if (prefixes.contains(GeometryUtil.getPrefix(geom.getUserData()))) {
|
||||
Coordinate center = GisUtil.d2dCoordinate(geom.getCentroid()
|
||||
.getCoordinate());
|
||||
state.strings.put(center, "W");
|
||||
Geometry geom2 = null;
|
||||
Geometry warningAreaN = null;
|
||||
Coordinate populatePt = null;
|
||||
Geometry populatePtGeom;
|
||||
boolean contained = false, closeTo = false;
|
||||
double shift = 1.E-8, distance, minDistance = 10.0;
|
||||
int loop, maxLoop = 10;
|
||||
Geometry warningArea = state.getWarningArea();
|
||||
String prefix = GeometryUtil.getPrefix(geom.getUserData());
|
||||
if (prefixes.contains(prefix)) {
|
||||
loop = 0;
|
||||
warningAreaN = findLargestGeometry(GeometryUtil.intersection(geom, warningArea));
|
||||
do {
|
||||
if (!warningAreaN.isEmpty()) {
|
||||
populatePt = GisUtil.d2dCoordinate(warningAreaN.getCentroid()
|
||||
.getCoordinate());
|
||||
for (GeospatialData f2 : geoData.features) {
|
||||
geom2 = f2.getGeometry();
|
||||
if (!GeometryUtil.getPrefix(geom2.getUserData()).equals(prefix)) {
|
||||
contained = false;
|
||||
closeTo = false;
|
||||
populatePtGeom = PolygonUtil.createPolygonByPoints(populatePt,
|
||||
new Coordinate(populatePt.x + shift, populatePt.y + shift));
|
||||
if (GeometryUtil.contains(geom2, populatePtGeom)) {
|
||||
// populatePt is in another county/zone.
|
||||
warningAreaN = findLargestQuadrant(warningAreaN, geom);
|
||||
contained = true;
|
||||
break;
|
||||
} else {
|
||||
distance = populatePtGeom.distance(geom2);
|
||||
if (distance < minDistance) {
|
||||
// populatePt is very close to the boundary of another county/zone.
|
||||
warningAreaN = findLargestQuadrant(warningAreaN, geom);
|
||||
closeTo = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// use the existing populatePt
|
||||
break;
|
||||
}
|
||||
loop += 1;
|
||||
} while ((contained || closeTo) && loop <= maxLoop);
|
||||
state.strings.put(populatePt, "W");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3252,4 +3296,65 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If g is a GeometryCollection, find the largest Geomery in it; otherwise (i.e., g is Geometry), return g.
|
||||
*
|
||||
* @param g
|
||||
* A Geometry or a GeometryCollection.
|
||||
* @return Geometry
|
||||
*/
|
||||
private Geometry findLargestGeometry(Geometry g) {
|
||||
int size = g.getNumGeometries();
|
||||
if (size == 1)
|
||||
return g;
|
||||
double area, maxArea = -1.0;
|
||||
int index = 0;
|
||||
for (int i = 0; i < size; i++) {
|
||||
area = g.getGeometryN(i).getArea();
|
||||
if (area > maxArea) {
|
||||
maxArea = area;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
return g.getGeometryN(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Split the hatched area into four quadrants, and return the largest one.
|
||||
*
|
||||
* @param hatchedArea
|
||||
* The initial hatched area or its a sub area.
|
||||
* @param geom
|
||||
* The geometry of a county/zone.
|
||||
* @return Geometry
|
||||
* The geometey of largest quadrant among the four, which are the result of
|
||||
* splitting of hatchedArea.
|
||||
*/
|
||||
private Geometry findLargestQuadrant(Geometry hatchedArea, Geometry geom) {
|
||||
Geometry envelope = hatchedArea.getEnvelope();
|
||||
Coordinate centroidCoord = GisUtil.d2dCoordinate(envelope.getCentroid()
|
||||
.getCoordinate());
|
||||
Coordinate[] envCoords = envelope.getCoordinates();
|
||||
int size = 4;
|
||||
Geometry quadrants[] = new Geometry[size];
|
||||
Geometry intersections[] = new Geometry[size];
|
||||
double largestArea = -1.0, area = -1.0;
|
||||
int index = -1;
|
||||
for (int i = 0; i < size; i++) {
|
||||
quadrants[i] = PolygonUtil.createPolygonByPoints(envCoords[i], centroidCoord);
|
||||
intersections[i] = GeometryUtil.intersection(quadrants[i], hatchedArea);
|
||||
area = intersections[i].getArea();
|
||||
if (area > largestArea) {
|
||||
largestArea = area;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
if (intersections[index].isValid())
|
||||
return intersections[index];
|
||||
else {
|
||||
// "intersections[" + index + "] is invalid"
|
||||
return hatchedArea;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
|||
* Nov 15, 2010 mschenke Initial creation
|
||||
* Apr 28, 2013 1955 jsanchez Added an ignoreUserData flag to intersection method.
|
||||
* Oct 21, 2013 DR 16632 D. Friedman Handle zero-length input in union.
|
||||
* Dec 13, 2013 DR 16567 Qinglu Lin Added contains(). TEST gerrit!
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -299,4 +300,25 @@ public class GeometryUtil {
|
|||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if one geometry contains any portion of the other.
|
||||
* @param g1
|
||||
* @param g2
|
||||
*/
|
||||
public static boolean contains(Geometry g1, Geometry g2) {
|
||||
int m = g1.getNumGeometries();
|
||||
int n = g2.getNumGeometries();
|
||||
Geometry geom1 = null;
|
||||
Geometry geom2 = null;
|
||||
for (int i = 0; i < m; i++) {
|
||||
geom1 = g1.getGeometryN(i);
|
||||
for (int j = 0; j < n; j++) {
|
||||
geom2 = g2.getGeometryN(j);
|
||||
if (geom1.contains(geom2))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue