Merge "Issue #1500 Sped up warngen text creation by calculating hatched polygon and area in Job when polygon or area changes, initializing velocity for template running when warngen starts, only requesting full warning records when they are requested for use from CurrentWarnings, and only requesting partial ActivateTableRecords for determining active watch info." into development
Former-commit-id: fd8ff178849afdf24c5ff01c9b709a71eb1bee87
This commit is contained in:
commit
e993b72a39
18 changed files with 921 additions and 1042 deletions
|
@ -5,7 +5,7 @@ Bundle-SymbolicName: com.raytheon.viz.warngen;singleton:=true
|
|||
Bundle-Version: 1.12.1174.qualifier
|
||||
Bundle-Activator: com.raytheon.viz.warngen.Activator
|
||||
Bundle-Vendor: Raytheon
|
||||
Eclipse-RegisterBuddy: com.raytheon.edex.common, com.raytheon.uf.common.serialization, com.raytheon.viz.awipstools
|
||||
Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization, com.raytheon.viz.awipstools
|
||||
Require-Bundle: org.eclipse.ui,
|
||||
org.eclipse.core.runtime,
|
||||
com.raytheon.viz.core,
|
||||
|
@ -17,9 +17,9 @@ Require-Bundle: org.eclipse.ui,
|
|||
org.apache.commons.lang,
|
||||
org.geotools,
|
||||
com.raytheon.viz.awipstools,
|
||||
com.raytheon.edex.common,
|
||||
com.raytheon.viz.texteditor;bundle-version="1.10.13",
|
||||
com.raytheon.viz.textworkstation;bundle-version="1.11.4",
|
||||
com.raytheon.uf.common.serialization;bundle-version="1.11.17",
|
||||
com.raytheon.uf.common.serialization.comm;bundle-version="1.11.17",
|
||||
javax.jms;bundle-version="1.0.0",
|
||||
com.raytheon.uf.viz.core.maps;bundle-version="1.0.0",
|
||||
|
|
|
@ -15,7 +15,6 @@ import org.geotools.referencing.GeodeticCalculator;
|
|||
|
||||
import com.raytheon.uf.common.dataplugin.warning.config.PathcastConfiguration;
|
||||
import com.raytheon.uf.common.dataplugin.warning.config.PointSourceConfiguration;
|
||||
import com.raytheon.uf.common.dataplugin.warning.gis.PreparedGeometryCollection;
|
||||
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
|
||||
import com.raytheon.uf.common.geospatial.SpatialQueryResult;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
|
@ -27,6 +26,7 @@ import com.vividsolutions.jts.geom.Coordinate;
|
|||
import com.vividsolutions.jts.geom.Envelope;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
||||
import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -146,7 +146,7 @@ public class DbAreaSourceDataAdaptor extends AbstractDbSourceDataAdaptor {
|
|||
boolean userDirections = Boolean.valueOf(String.valueOf(attributes
|
||||
.get(useDirectionField)));
|
||||
if (userDirections) {
|
||||
PreparedGeometry prepGeom = new PreparedGeometryCollection(geom);
|
||||
PreparedGeometry prepGeom = PreparedGeometryFactory.prepare(geom);
|
||||
if (prepGeom.intersects(searchArea) && !prepGeom.within(searchArea)) {
|
||||
Geometry intersection = searchArea.intersection(geom);
|
||||
partOfArea = GisUtil.asStringList(calculateLocationPortion(
|
||||
|
|
|
@ -286,27 +286,13 @@ public class Area {
|
|||
|
||||
for (AreaSourceConfiguration asc : config.getAreaSources()) {
|
||||
if (asc.getType() == AreaType.INTERSECT) {
|
||||
String areaSource = asc.getAreaSource();
|
||||
String key = areaSource + "." + localizedSite;
|
||||
|
||||
List<Geometry> geoms = new ArrayList<Geometry>();
|
||||
|
||||
for (GeospatialData f : warngenLayer.getGeodataFeatures(key)) {
|
||||
for (int i = 0; i < warnArea.getNumGeometries(); i++) {
|
||||
Geometry geom = warnArea.getGeometryN(i);
|
||||
if (GeometryUtil.intersects(f.geometry, geom)) {
|
||||
Geometry intersect = f.geometry.intersection(geom);
|
||||
if (intersect != null && !intersect.isEmpty()) {
|
||||
for (int j = 0; j < intersect
|
||||
.getNumGeometries(); j++) {
|
||||
intersect.getGeometryN(j).setUserData(
|
||||
f.geometry.getUserData());
|
||||
}
|
||||
GeometryUtil
|
||||
.buildGeometryList(geoms, intersect);
|
||||
}
|
||||
break;
|
||||
}
|
||||
for (GeospatialData f : warngenLayer.getGeodataFeatures(
|
||||
asc.getAreaSource(), localizedSite)) {
|
||||
Geometry intersect = GeometryUtil.intersection(warnArea,
|
||||
f.prepGeom);
|
||||
if (intersect.isEmpty() == false) {
|
||||
geoms.add(intersect);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@ import org.geotools.referencing.operation.DefaultMathTransformFactory;
|
|||
import org.opengis.metadata.spatial.PixelOrientation;
|
||||
import org.opengis.referencing.operation.MathTransform;
|
||||
|
||||
import com.raytheon.uf.common.dataplugin.warning.gis.PreparedGeometryCollection;
|
||||
import com.raytheon.uf.common.dataplugin.warning.util.GeometryUtil;
|
||||
import com.raytheon.uf.viz.core.IExtent;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
|
@ -45,6 +44,7 @@ import com.vividsolutions.jts.geom.GeometryFactory;
|
|||
import com.vividsolutions.jts.geom.LineSegment;
|
||||
import com.vividsolutions.jts.geom.Polygon;
|
||||
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
||||
import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory;
|
||||
|
||||
/**
|
||||
* Utility for polygon operations
|
||||
|
@ -850,7 +850,7 @@ public class PolygonUtil {
|
|||
List<PreparedGeometry> prepped = new ArrayList<PreparedGeometry>(
|
||||
geomList.size());
|
||||
for (Geometry g : geomList) {
|
||||
prepped.add(new PreparedGeometryCollection(g));
|
||||
prepped.add(PreparedGeometryFactory.prepare(g));
|
||||
}
|
||||
|
||||
GeometryFactory gf = warningArea.getFactory();
|
||||
|
|
|
@ -322,7 +322,7 @@ public class Wx {
|
|||
|
||||
if (pathcastConfiguration.isWithinPolygon()) {
|
||||
// Means that all points returned must be within the polygon
|
||||
bufferedPathCastArea = warningPolygon;
|
||||
bufferedPathCastArea = warningPolygon.intersection(geom);
|
||||
} else {
|
||||
bufferedPathCastArea = geom;
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ import com.vividsolutions.jts.geom.Polygon;
|
|||
* Nov 02, 2012 DR 15455 Qinglu Lin Added warngenLayer.setWarningAction() in resetPressed()
|
||||
* and in updateListSelected().
|
||||
* Dec 20, 2012 DR 15537 Qinglu Lin Changed the assigned value to trackEditable from false
|
||||
* to true in boxSelected().
|
||||
* to true in boxSelected().
|
||||
* Jan 24, 2013 DR 15723 Qinglu Lin Invoked WarngenLayer's initRemovedGids().
|
||||
*
|
||||
* </pre>
|
||||
|
@ -147,6 +147,17 @@ public class WarngenDialog extends CaveSWTDialog implements
|
|||
|
||||
private static final int FONT_HEIGHT = 9;
|
||||
|
||||
static {
|
||||
// Ensure TemplateRunner gets initialized for use
|
||||
new Job("Template Runner Initialization") {
|
||||
@Override
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
TemplateRunner.initialize();
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
}.schedule();
|
||||
}
|
||||
|
||||
private String result;
|
||||
|
||||
private static String UPDATELISTTEXT = "UPDATE LIST ";
|
||||
|
@ -1452,7 +1463,7 @@ public class WarngenDialog extends CaveSWTDialog implements
|
|||
.equalsIgnoreCase(lastAreaSource);
|
||||
|
||||
try {
|
||||
warngenLayer.updateWarnedAreas(snapHatchedAreaToPolygon, true);
|
||||
warngenLayer.updateWarnedAreas(snapHatchedAreaToPolygon);
|
||||
} catch (VizException e1) {
|
||||
statusHandler.handle(Priority.PROBLEM, "WarnGen Error", e1);
|
||||
}
|
||||
|
|
|
@ -65,7 +65,6 @@ import com.raytheon.uf.common.dataplugin.warning.config.WarngenConfiguration;
|
|||
import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialData;
|
||||
import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialFactory;
|
||||
import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialMetadata;
|
||||
import com.raytheon.uf.common.dataplugin.warning.gis.PreparedGeometryCollection;
|
||||
import com.raytheon.uf.common.dataplugin.warning.util.CountyUserData;
|
||||
import com.raytheon.uf.common.dataplugin.warning.util.GeometryUtil;
|
||||
import com.raytheon.uf.common.geospatial.DestinationGeodeticCalculator;
|
||||
|
@ -124,6 +123,7 @@ import com.vividsolutions.jts.geom.Point;
|
|||
import com.vividsolutions.jts.geom.Polygon;
|
||||
import com.vividsolutions.jts.geom.TopologyException;
|
||||
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
||||
import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory;
|
||||
import com.vividsolutions.jts.io.ParseException;
|
||||
import com.vividsolutions.jts.io.WKTReader;
|
||||
|
||||
|
@ -159,8 +159,7 @@ import com.vividsolutions.jts.io.WKTReader;
|
|||
* Coordinate[] from futurePoints.
|
||||
* 12/18/2012 DR 15571 Qinglu Lin Resolved coordinate issue in TML line caused by clicking Restart button.
|
||||
* 01/24/2013 DR 15723 Qinglu Lin Added initRemovedGids() and updated updateWarnedAreas() to prevent the removed
|
||||
* counties from being re-hatched.
|
||||
*
|
||||
* counties from being re-hatched.
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
|
@ -242,6 +241,91 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
}
|
||||
}
|
||||
|
||||
private class AreaHatcher extends Job {
|
||||
|
||||
private PolygonUtil polygonUtil;
|
||||
|
||||
private Polygon hatchedArea;
|
||||
|
||||
private Geometry hatchedWarningArea;
|
||||
|
||||
private Geometry warningArea;
|
||||
|
||||
private Polygon warningPolygon;
|
||||
|
||||
public AreaHatcher(PolygonUtil polygonUtil) {
|
||||
super("Hatching Warning Area");
|
||||
setSystem(true);
|
||||
this.polygonUtil = polygonUtil;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.
|
||||
* IProgressMonitor)
|
||||
*/
|
||||
@Override
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
while (this.warningArea != null && this.warningPolygon != null) {
|
||||
Geometry warningArea;
|
||||
Polygon warningPolygon;
|
||||
synchronized (polygonUtil) {
|
||||
warningArea = this.warningArea;
|
||||
warningPolygon = this.warningPolygon;
|
||||
this.warningArea = this.warningPolygon = null;
|
||||
}
|
||||
|
||||
try {
|
||||
Polygon hatched = polygonUtil.hatchWarningArea(
|
||||
warningPolygon, warningArea);
|
||||
if (hatched != null) {
|
||||
// DR 15559
|
||||
Coordinate[] coords = hatched.getCoordinates();
|
||||
PolygonUtil.round(coords, 2);
|
||||
WarngenUIState.adjustPolygon(coords);
|
||||
GeometryFactory gf = new GeometryFactory();
|
||||
LinearRing lr = gf.createLinearRing(coords);
|
||||
hatchedArea = gf.createPolygon(lr, null);
|
||||
hatchedWarningArea = createWarnedArea(latLonToLocal(hatchedArea));
|
||||
} else {
|
||||
this.hatchedArea = null;
|
||||
this.hatchedWarningArea = null;
|
||||
}
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
|
||||
public synchronized void hatchArea(Polygon warningPolygon,
|
||||
Geometry warningArea) {
|
||||
synchronized (polygonUtil) {
|
||||
this.warningPolygon = warningPolygon;
|
||||
this.warningArea = warningArea;
|
||||
}
|
||||
schedule();
|
||||
}
|
||||
|
||||
public synchronized Geometry[] getHatchedAreas() {
|
||||
Polygon hatchedArea = null;
|
||||
Geometry hatchedWarningArea = null;
|
||||
if (getState() == Job.RUNNING) {
|
||||
try {
|
||||
join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
hatchedArea = this.hatchedArea;
|
||||
hatchedWarningArea = this.hatchedWarningArea;
|
||||
return new Geometry[] { hatchedArea, hatchedWarningArea };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static Map<String, GeospatialDataList> siteMap = new HashMap<String, GeospatialDataList>();
|
||||
|
||||
private static Map<String, Geometry> timezoneMap = new HashMap<String, Geometry>();
|
||||
|
@ -283,6 +367,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
|
||||
private CustomMaps customMaps;
|
||||
|
||||
private AreaHatcher areaHatcher;
|
||||
|
||||
protected Mode lastMode = null;
|
||||
|
||||
protected boolean redrawBoxFromTrack = false;
|
||||
|
@ -802,7 +888,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
local);
|
||||
gd.attributes.put(
|
||||
GeospatialDataList.LOCAL_PREP_GEOM,
|
||||
new PreparedGeometryCollection(local));
|
||||
PreparedGeometryFactory.prepare(local));
|
||||
locals.add(local);
|
||||
}
|
||||
|
||||
|
@ -880,6 +966,15 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
|
||||
String areaSource = config.getGeospatialConfig().getAreaSource();
|
||||
geoData = siteMap.get(areaSource + "." + site);
|
||||
|
||||
try {
|
||||
areaHatcher = new AreaHatcher(new PolygonUtil(this, geoData.nx,
|
||||
geoData.ny, 20, geoData.localExtent,
|
||||
geoData.localToLatLon));
|
||||
} catch (Exception e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
|
||||
e);
|
||||
}
|
||||
}// end synchronize
|
||||
customMaps.loadCustomMaps(Arrays.asList(config.getMaps()));
|
||||
|
||||
|
@ -888,15 +983,23 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
+ (System.currentTimeMillis() - t0) + "ms");
|
||||
}
|
||||
|
||||
public GeospatialData[] getGeodataFeatures(String key) {
|
||||
GeospatialDataList geoDataList = siteMap.get(key);
|
||||
public GeospatialData[] getGeodataFeatures(String areaSource,
|
||||
String localizedSite) {
|
||||
GeospatialDataList geoDataList = getGeodataList(areaSource,
|
||||
localizedSite);
|
||||
if (geoDataList != null) {
|
||||
return geoDataList.features;
|
||||
return Arrays.copyOf(geoDataList.features,
|
||||
geoDataList.features.length);
|
||||
}
|
||||
|
||||
return new GeospatialData[0];
|
||||
}
|
||||
|
||||
private GeospatialDataList getGeodataList(String areaSource,
|
||||
String localizedSite) {
|
||||
String key = areaSource + "." + localizedSite;
|
||||
return siteMap.get(key);
|
||||
}
|
||||
|
||||
public Geometry getTimezoneGeom(String oneLetterTimezone) {
|
||||
return timezoneMap.get(oneLetterTimezone);
|
||||
}
|
||||
|
@ -1152,35 +1255,40 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
* @param snapHatchedAreaToPolygon
|
||||
* If True, any hatched area outside the polygon will be
|
||||
* eliminated.
|
||||
* @param determineInclusion
|
||||
* If True, the area percent and/or area coverage will be used to
|
||||
* determine if a county/zone should e included
|
||||
* @throws VizException
|
||||
*/
|
||||
public void updateWarnedAreas(boolean snapHatchedAreaToPolygon,
|
||||
boolean determineInclusion) throws VizException {
|
||||
public void updateWarnedAreas(boolean snapHatchedAreaToPolygon)
|
||||
throws VizException {
|
||||
if (getPolygon() == null) {
|
||||
return;
|
||||
}
|
||||
state.snappedToArea = false;
|
||||
|
||||
Geometry warningArea = latLonToLocal(state.getWarningArea());
|
||||
Geometry warningPolygon = latLonToLocal(state.getWarningPolygon());
|
||||
Geometry oldWarningArea = latLonToLocal(state.getOldWarningArea());
|
||||
Geometry oldWarningPolygon = latLonToLocal(state.getOldWarningPolygon());
|
||||
|
||||
if (warningArea == null || snapHatchedAreaToPolygon) {
|
||||
warningArea = warningPolygon;
|
||||
}
|
||||
|
||||
Geometry hatchedArea = warningArea;
|
||||
long t0 = System.currentTimeMillis();
|
||||
|
||||
Geometry warningArea = state.getWarningArea();
|
||||
Geometry warningPolygon = state.getWarningPolygon();
|
||||
Geometry newWarningArea = createWarnedArea(latLonToLocal((snapHatchedAreaToPolygon || warningArea == null) ? warningPolygon
|
||||
: warningArea));
|
||||
updateWarnedAreaState(newWarningArea, snapHatchedAreaToPolygon);
|
||||
|
||||
System.out.println("determining hatchedArea took "
|
||||
+ (System.currentTimeMillis() - t0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a warning area based on the hatched area in local coordinates
|
||||
*
|
||||
* @param hatchedArea
|
||||
* @return
|
||||
*/
|
||||
private Geometry createWarnedArea(Geometry hatchedArea) {
|
||||
Geometry oldWarningPolygon = latLonToLocal(state.getOldWarningPolygon());
|
||||
Geometry newHatchedArea = null;
|
||||
boolean insideCWA = false;
|
||||
|
||||
// Loop through each of our counties returned from the query
|
||||
for (GeospatialData f : geoData.features) {
|
||||
// get the geometry of the county and make sure it intersects with
|
||||
// our hatched area
|
||||
// get the geometry of the county and make sure it intersects
|
||||
// with our hatched area
|
||||
PreparedGeometry prepGeom = (PreparedGeometry) f.attributes
|
||||
.get(GeospatialDataList.LOCAL_PREP_GEOM);
|
||||
Geometry geom = (Geometry) f.attributes
|
||||
|
@ -1192,7 +1300,6 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
if (intersection.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
insideCWA = true;
|
||||
} catch (RuntimeException e) {
|
||||
continue;
|
||||
// This is a workaround for JTS 1.7.1
|
||||
|
@ -1206,9 +1313,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
.convert(areaOfGeom * ratio);
|
||||
|
||||
boolean includeArea = false;
|
||||
if (!determineInclusion) {
|
||||
includeArea = areaInKmSqOfIntersection > 1;
|
||||
} else if (getConfiguration().getHatchedAreaSource()
|
||||
if (getConfiguration().getHatchedAreaSource()
|
||||
.getInclusionAndOr().equalsIgnoreCase("AND")) {
|
||||
if ((ratioInPercent >= getConfiguration()
|
||||
.getHatchedAreaSource().getInclusionPercent())
|
||||
|
@ -1224,6 +1329,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
includeArea = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (includeArea
|
||||
&& (oldWarningPolygon == null || prepGeom
|
||||
.intersects(oldWarningPolygon))) {
|
||||
|
@ -1234,6 +1340,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
intersection);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (TopologyException e) {
|
||||
statusHandler.handle(Priority.VERBOSE,
|
||||
"Geometry error simplifying hatched area.", e);
|
||||
|
@ -1242,113 +1349,125 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
"Inclusion Area not properly configured.", e);
|
||||
}
|
||||
}
|
||||
// All area has been removed from the polygon...
|
||||
if (insideCWA == false) {
|
||||
state.strings.clear();
|
||||
state.setWarningArea(null);
|
||||
state.geometryChanged = true;
|
||||
dialog.getDisplay().asyncExec(new Runnable() {
|
||||
public void run() {
|
||||
dialog.setInstructions();
|
||||
|
||||
return newHatchedArea != null ? newHatchedArea : new GeometryFactory()
|
||||
.createGeometryCollection(new Geometry[0]);
|
||||
}
|
||||
|
||||
private void updateWarnedAreaState(Geometry newHatchedArea,
|
||||
boolean snapToHatchedArea) throws VizException {
|
||||
try {
|
||||
// Ensure all geometries in local coords
|
||||
Geometry warningPolygon = latLonToLocal(state.getWarningPolygon());
|
||||
Geometry oldWarningArea = latLonToLocal(state.getOldWarningArea());
|
||||
Geometry oldWarningPolygon = latLonToLocal(state
|
||||
.getOldWarningPolygon());
|
||||
|
||||
// All area has been removed from the polygon...
|
||||
if (newHatchedArea.isEmpty()) {
|
||||
state.strings.clear();
|
||||
state.setWarningArea(null);
|
||||
state.geometryChanged = true;
|
||||
dialog.getDisplay().asyncExec(new Runnable() {
|
||||
public void run() {
|
||||
dialog.setInstructions();
|
||||
}
|
||||
});
|
||||
if (!state.isMarked() || oldWarningArea == null) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
if (!state.isMarked() || oldWarningArea == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (oldWarningArea != null) {
|
||||
int areaPercent = Double
|
||||
.valueOf(
|
||||
((oldWarningPolygon.intersection(warningPolygon)
|
||||
.getArea() / oldWarningArea.getArea()) * 100))
|
||||
.intValue();
|
||||
if (GeometryUtil.intersects(oldWarningPolygon, warningPolygon) == false
|
||||
&& !state.isMarked()) {
|
||||
// Snap back to polygon
|
||||
state.setWarningPolygon(localToLatLon((Polygon) oldWarningPolygon));
|
||||
newHatchedArea = (Geometry) oldWarningArea.clone();
|
||||
} else if (areaPercent < 10 && state.isMarked()) {
|
||||
// snap back to last valid user selected area
|
||||
state.setWarningPolygon((Polygon) state
|
||||
.getMarkedWarningPolygon().clone());
|
||||
newHatchedArea = latLonToLocal((Geometry) state
|
||||
.getMarkedWarningArea().clone());
|
||||
state.resetMarked();
|
||||
} else if (warningPolygon != null) {
|
||||
// want intersection of warningPolygon and oldWarningArea
|
||||
Geometry intersection = null;
|
||||
for (int n = 0; n < oldWarningArea.getNumGeometries(); ++n) {
|
||||
Geometry oldArea = oldWarningArea.getGeometryN(n);
|
||||
Geometry geom = GeometryUtil.intersection(warningPolygon,
|
||||
oldArea);
|
||||
String[] gids = GeometryUtil.getGID(geom);
|
||||
boolean flag = false;
|
||||
for (String gid: gids) {
|
||||
if (removedGids.contains(gid)) {
|
||||
flag = true;
|
||||
|
||||
if (oldWarningArea != null) {
|
||||
int areaPercent = Double.valueOf(
|
||||
((oldWarningPolygon.intersection(warningPolygon)
|
||||
.getArea() / oldWarningArea.getArea()) * 100))
|
||||
.intValue();
|
||||
if (oldWarningPolygon.intersects(warningPolygon) == false
|
||||
&& !state.isMarked()) {
|
||||
// Snap back to polygon
|
||||
state.setWarningPolygon(localToLatLon((Polygon) oldWarningPolygon));
|
||||
newHatchedArea = (Geometry) oldWarningArea.clone();
|
||||
} else if (areaPercent < 10 && state.isMarked()) {
|
||||
// snap back to last valid user selected area
|
||||
state.setWarningPolygon((Polygon) state
|
||||
.getMarkedWarningPolygon().clone());
|
||||
newHatchedArea = latLonToLocal((Geometry) state
|
||||
.getMarkedWarningArea());
|
||||
state.resetMarked();
|
||||
} else if (warningPolygon != null) {
|
||||
// want intersection of warningPolygon and oldWarningArea
|
||||
newHatchedArea = GeometryUtil.intersection(warningPolygon,
|
||||
oldWarningArea);
|
||||
if (removedGids.size() > 0) {
|
||||
// Remove areas with gid in removedGids
|
||||
List<Geometry> areas = new ArrayList<Geometry>(
|
||||
newHatchedArea.getNumGeometries());
|
||||
for (int n = 0; n < newHatchedArea.getNumGeometries(); ++n) {
|
||||
Geometry newArea = newHatchedArea.getGeometryN(n);
|
||||
String[] gids = GeometryUtil.getGID(newArea);
|
||||
boolean flag = false;
|
||||
for (String gid : gids) {
|
||||
if (removedGids.contains(gid)) {
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!flag) {
|
||||
areas.add(newArea);
|
||||
}
|
||||
}
|
||||
if (areas.size() != newHatchedArea.getNumGeometries()) {
|
||||
// Areas were removed, recreate newHatchedArea
|
||||
newHatchedArea = GeometryUtil.union(areas
|
||||
.toArray(new Geometry[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (newHatchedArea == null || newHatchedArea.isEmpty()) {
|
||||
boolean initialWarning = false;
|
||||
String[] followUps = this.getConfiguration().getFollowUps();
|
||||
if (followUps.length == 0)
|
||||
initialWarning = true;
|
||||
else
|
||||
for (String followup : followUps) {
|
||||
if (followup.equals("NEW")) {
|
||||
initialWarning = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!flag) {
|
||||
if (geom.isEmpty() == false) {
|
||||
if (intersection == null) {
|
||||
intersection = geom;
|
||||
} else {
|
||||
intersection = GeometryUtil.union(intersection,
|
||||
geom);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (initialWarning)
|
||||
state.clear2(); // not to hatch polygon for initial warning
|
||||
else {
|
||||
// Snap back for follow-ups
|
||||
state.setWarningPolygon((Polygon) state
|
||||
.getMarkedWarningPolygon().clone());
|
||||
state.resetMarked();
|
||||
updateWarnedAreas(snapToHatchedArea);
|
||||
}
|
||||
newHatchedArea = intersection;
|
||||
}
|
||||
}
|
||||
System.out.println("determining hatchedArea took "
|
||||
+ (System.currentTimeMillis() - t0));
|
||||
if (newHatchedArea == null) {
|
||||
boolean initialWarning = false;
|
||||
String[] followUps = this.getConfiguration().getFollowUps();
|
||||
if (followUps.length == 0)
|
||||
initialWarning = true;
|
||||
else
|
||||
for (String followup : followUps) {
|
||||
if (followup.equals("NEW")) {
|
||||
initialWarning = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (initialWarning)
|
||||
state.clear2(); // not to hatch polygon for initial warning
|
||||
else {
|
||||
// Snap back for follow-ups
|
||||
state.setWarningPolygon((Polygon) state
|
||||
.getMarkedWarningPolygon().clone());
|
||||
newHatchedArea = latLonToLocal((Geometry) state
|
||||
.getMarkedWarningArea().clone());
|
||||
state.resetMarked();
|
||||
updateWarnedAreas(snapHatchedAreaToPolygon, true);
|
||||
}
|
||||
} else {
|
||||
newHatchedArea = localToLatLon(newHatchedArea);
|
||||
state.setWarningArea(newHatchedArea);
|
||||
state.mark(newHatchedArea);
|
||||
// add "W" strings
|
||||
if (determineInclusion) {
|
||||
} else {
|
||||
state.setWarningArea(localToLatLon(newHatchedArea));
|
||||
state.mark(newHatchedArea);
|
||||
// add "W" strings
|
||||
populateStrings();
|
||||
}
|
||||
}
|
||||
|
||||
// Apply new hatched area
|
||||
state.geometryChanged = true;
|
||||
issueRefresh();
|
||||
// Apply new hatched area
|
||||
state.geometryChanged = true;
|
||||
issueRefresh();
|
||||
|
||||
VizApp.runAsync(new Runnable() {
|
||||
public void run() {
|
||||
if (dialog != null) {
|
||||
dialog.setInstructions();
|
||||
VizApp.runAsync(new Runnable() {
|
||||
public void run() {
|
||||
if (dialog != null) {
|
||||
dialog.setInstructions();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
} finally {
|
||||
warningAreaChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1400,7 +1519,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
LinearRing lr = gf.createLinearRing(c);
|
||||
state.setWarningPolygon(gf.createPolygon(lr, null));
|
||||
|
||||
updateWarnedAreas(true, true);
|
||||
updateWarnedAreas(true);
|
||||
}
|
||||
|
||||
public void redrawBoxFromTrack() throws VizException {
|
||||
|
@ -1559,7 +1678,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
LinearRing lr = gf.createLinearRing(c);
|
||||
state.setWarningPolygon(gf.createPolygon(lr, null));
|
||||
|
||||
updateWarnedAreas(true, true);
|
||||
updateWarnedAreas(true);
|
||||
|
||||
/*
|
||||
* NOT LINE OF STORMS
|
||||
|
@ -1604,7 +1723,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
LinearRing lr = gf.createLinearRing(c);
|
||||
state.setWarningPolygon(gf.createPolygon(lr, null));
|
||||
|
||||
updateWarnedAreas(true, true);
|
||||
updateWarnedAreas(true);
|
||||
}
|
||||
if (dialog.box.getSelection()) {
|
||||
displayState.editable = false;
|
||||
|
@ -1624,20 +1743,17 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
|
||||
try {
|
||||
long t0 = System.currentTimeMillis();
|
||||
state.removeDuplicateCoordinate();
|
||||
Polygon hatched = new PolygonUtil(this, geoData.nx, geoData.ny,
|
||||
20, geoData.localExtent, geoData.localToLatLon)
|
||||
.hatchWarningArea(state.getWarningPolygon(),
|
||||
state.getWarningArea());
|
||||
Polygon hatched = state.getWarningPolygon();
|
||||
Geometry hatchedArea = state.getWarningArea();
|
||||
if (areaHatcher != null) {
|
||||
Geometry[] areas = areaHatcher.getHatchedAreas();
|
||||
hatched = (Polygon) areas[0];
|
||||
hatchedArea = areas[1];
|
||||
}
|
||||
|
||||
if (hatched != null) {
|
||||
// DR 15559
|
||||
Coordinate[] coords = hatched.getCoordinates();
|
||||
PolygonUtil.round(coords, 2);
|
||||
state.adjustPolygon(coords);
|
||||
GeometryFactory gf = new GeometryFactory();
|
||||
LinearRing lr = gf.createLinearRing(coords);
|
||||
state.setWarningPolygon(gf.createPolygon(lr, null));
|
||||
updateWarnedAreas(true, true);
|
||||
state.setWarningPolygon(hatched);
|
||||
updateWarnedAreaState(hatchedArea, true);
|
||||
issueRefresh();
|
||||
// End of DR 15559
|
||||
state.snappedToArea = true;
|
||||
|
@ -1660,7 +1776,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
try {
|
||||
state.setWarningPolygon(gf.createPolygon(lr, null));
|
||||
state.rightClickSelected = false;
|
||||
updateWarnedAreas(true, true);
|
||||
updateWarnedAreas(true);
|
||||
displayState.dragMeGeom = gf.createPoint(pt);
|
||||
displayState.dragMePoint = gf.createPoint(pt);
|
||||
displayState.mode = Mode.TRACK;
|
||||
|
@ -1771,7 +1887,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
state.setWarningPolygon(warnPolygon);
|
||||
state.setWarningArea(getWarningAreaFromPolygon(
|
||||
state.getWarningPolygon(), record));
|
||||
updateWarnedAreas(true, true);
|
||||
updateWarnedAreas(true);
|
||||
}
|
||||
|
||||
private DataTime recordFrameTime(AbstractWarningRecord warnRecord) {
|
||||
|
@ -2142,39 +2258,44 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
String[] gids = GeometryUtil.getGID(geom);
|
||||
if (GeometryUtil.contains(state.getWarningArea(), point)) {
|
||||
// remove county
|
||||
Geometry tmp = GeometryUtil.difference(
|
||||
state.getWarningArea(), geom);
|
||||
Geometry tmp = removeCounty(state.getWarningArea(),
|
||||
getFips(f));
|
||||
if (tmp.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
state.setWarningArea(tmp);
|
||||
for (String gid: gids) {
|
||||
for (String gid : gids) {
|
||||
removedGids.add(gid);
|
||||
}
|
||||
} else {
|
||||
String featureFips = getFips(f);
|
||||
Collection<GeospatialData> dataWithFips = getDataWithFips(featureFips);
|
||||
if (oldWarningArea != null) {
|
||||
// for a CON, prevents extra areas to be added
|
||||
Set<String> limit = new HashSet<String>();
|
||||
limit.addAll(Arrays.asList(GeometryUtil
|
||||
.getGID(oldWarningArea)));
|
||||
String prefix = GeometryUtil.getPrefix(geom
|
||||
.getUserData());
|
||||
|
||||
if (limit.contains(prefix) == false) {
|
||||
Set<String> fipsIds = getAllFipsInArea(oldWarningArea);
|
||||
if (fipsIds.contains(featureFips) == false) {
|
||||
break;
|
||||
} else if (oldWarningPolygon.contains(point) == true) {
|
||||
// only add in intersecting area from old
|
||||
// warning
|
||||
geom = GeometryUtil.intersection(
|
||||
oldWarningArea, geom);
|
||||
boolean first = true;
|
||||
for (GeospatialData g : dataWithFips) {
|
||||
if (first) {
|
||||
geom = GeometryUtil.intersection(
|
||||
g.geometry, oldWarningArea);
|
||||
first = false;
|
||||
} else {
|
||||
geom = GeometryUtil.intersection(
|
||||
g.geometry, geom);
|
||||
}
|
||||
}
|
||||
|
||||
if (warningPolygon.contains(point)) {
|
||||
geom = GeometryUtil.intersection(
|
||||
warningPolygon, geom);
|
||||
geom = GeometryUtil.intersection(geom,
|
||||
warningPolygon);
|
||||
}
|
||||
state.setWarningArea(GeometryUtil.union(
|
||||
state.getWarningArea(), geom));
|
||||
for (String gid: gids) {
|
||||
for (String gid : gids) {
|
||||
removedGids.remove(gid);
|
||||
}
|
||||
}
|
||||
|
@ -2182,14 +2303,21 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
// add county
|
||||
if (warningPolygon.contains(point)) {
|
||||
// add part of county
|
||||
geom = GeometryUtil.intersection(
|
||||
warningPolygon, geom);
|
||||
List<Geometry> parts = new ArrayList<Geometry>(
|
||||
dataWithFips.size() + 1);
|
||||
for (GeospatialData data : dataWithFips) {
|
||||
parts.add(GeometryUtil.intersection(
|
||||
warningPolygon, data.geometry));
|
||||
}
|
||||
geom = geom.getFactory()
|
||||
.createGeometryCollection(
|
||||
parts.toArray(new Geometry[0]));
|
||||
}
|
||||
state.setWarningArea(GeometryUtil.union(
|
||||
state.getWarningArea(), geom));
|
||||
}
|
||||
}
|
||||
state.snappedToArea = false;
|
||||
warningAreaChanged();
|
||||
populateStrings();
|
||||
issueRefresh();
|
||||
break;
|
||||
|
@ -2201,6 +2329,53 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
}
|
||||
}
|
||||
|
||||
private String getFips(GeospatialData data) {
|
||||
return (String) data.attributes.get(configuration.getAreaConfig()
|
||||
.getFipsField());
|
||||
}
|
||||
|
||||
private void warningAreaChanged() {
|
||||
state.snappedToArea = false;
|
||||
if (areaHatcher != null) {
|
||||
areaHatcher.hatchArea(state.getWarningPolygon(),
|
||||
state.getWarningArea());
|
||||
}
|
||||
}
|
||||
|
||||
private Collection<GeospatialData> getDataWithFips(String fips) {
|
||||
List<GeospatialData> data = new ArrayList<GeospatialData>();
|
||||
for (GeospatialData d : geoData.features) {
|
||||
if (fips.equals(getFips(d))) {
|
||||
data.add(d);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
private Set<String> getAllFipsInArea(Geometry warningArea) {
|
||||
Set<String> fipsIds = new HashSet<String>();
|
||||
for (int n = 0; n < warningArea.getNumGeometries(); ++n) {
|
||||
Geometry area = warningArea.getGeometryN(n);
|
||||
fipsIds.add(getFips(((CountyUserData) area.getUserData()).entry));
|
||||
}
|
||||
return fipsIds;
|
||||
}
|
||||
|
||||
private Geometry removeCounty(Geometry warningArea, String fipsToRemove) {
|
||||
List<Geometry> toKeep = new ArrayList<Geometry>(
|
||||
warningArea.getNumGeometries());
|
||||
for (int n = 0; n < warningArea.getNumGeometries(); ++n) {
|
||||
Geometry area = warningArea.getGeometryN(n);
|
||||
CountyUserData userData = (CountyUserData) area.getUserData();
|
||||
String areaFips = getFips(userData.entry);
|
||||
if (fipsToRemove.equals(areaFips) == false) {
|
||||
toKeep.add(area);
|
||||
}
|
||||
}
|
||||
return warningArea.getFactory().createGeometryCollection(
|
||||
toKeep.toArray(new Geometry[0]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the W strings with the included counties
|
||||
*/
|
||||
|
@ -2395,6 +2570,6 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
}
|
||||
|
||||
public void initRemovedGids() {
|
||||
removedGids.clear();
|
||||
removedGids.clear();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -257,7 +257,7 @@ public class WarngenUIManager extends InputAdapter {
|
|||
LinearRing lr = gf.createLinearRing(coordinates);
|
||||
state.setWarningPolygon(gf.createPolygon(lr, null));
|
||||
}
|
||||
warngenLayer.updateWarnedAreas(true, true);
|
||||
warngenLayer.updateWarnedAreas(true);
|
||||
} catch (VizException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -450,7 +450,7 @@ public class WarngenUIManager extends InputAdapter {
|
|||
|
||||
warngenLayer.getWarngenState().setWarningPolygon(newPoly);
|
||||
try {
|
||||
warngenLayer.updateWarnedAreas(true, true);
|
||||
warngenLayer.updateWarnedAreas(true);
|
||||
} catch (VizException e) {
|
||||
Status s = new Status(Status.ERROR, Activator.PLUGIN_ID,
|
||||
"Error updating warned area", e);
|
||||
|
@ -592,7 +592,7 @@ public class WarngenUIManager extends InputAdapter {
|
|||
Polygon newPoly = gf.createPolygon(newLs, null);
|
||||
warngenLayer.getWarngenState().setWarningPolygon(newPoly);
|
||||
try {
|
||||
warngenLayer.updateWarnedAreas(true, true);
|
||||
warngenLayer.updateWarnedAreas(true);
|
||||
} catch (VizException e) {
|
||||
Status s = new Status(Status.ERROR,
|
||||
Activator.PLUGIN_ID,
|
||||
|
|
|
@ -123,173 +123,173 @@ public class WarngenUIState {
|
|||
}
|
||||
|
||||
/**
|
||||
* removeDuplicateCoordinate
|
||||
* remove duplicate intermediate coordinates in warningPolygon.
|
||||
* History
|
||||
* 10-26-2012 Qinglu Lin DR15479 Created.
|
||||
* removeDuplicateCoordinate remove duplicate intermediate coordinates in
|
||||
* warningPolygon. History 10-26-2012 Qinglu Lin DR15479 Created.
|
||||
*/
|
||||
public void removeDuplicateCoordinate() {
|
||||
Coordinate[] verts = warningPolygon.getCoordinates();
|
||||
Set<Coordinate> coords = new LinkedHashSet<Coordinate>();
|
||||
for (Coordinate c: verts)
|
||||
coords.add(c);
|
||||
if ((verts.length-coords.size()) < 2)
|
||||
return;
|
||||
Coordinate[] vertices = new Coordinate[coords.size()+1];
|
||||
Iterator<Coordinate> iter = coords.iterator();
|
||||
int i = 0;
|
||||
while (iter.hasNext()) {
|
||||
vertices[i] = new Coordinate(iter.next());
|
||||
i += 1;
|
||||
}
|
||||
vertices[i] = new Coordinate(vertices[0]);
|
||||
GeometryFactory gf = new GeometryFactory();
|
||||
warningPolygon = gf.createPolygon(gf.createLinearRing(vertices), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* computeSlope
|
||||
* compute the slope of a line.
|
||||
*
|
||||
* History
|
||||
* 12/06/2012 DR 15559 Qinglu Lin Created.
|
||||
*/
|
||||
private double computeSlope(Coordinate[] coords, int i) {
|
||||
double min = 1.0E-08;
|
||||
double dx = coords[i].x-coords[i+1].x;
|
||||
double slope = 0.0;
|
||||
if (Math.abs(dx)>min) {
|
||||
slope = (coords[i].y-coords[i+1].y)/dx;
|
||||
}
|
||||
return slope;
|
||||
}
|
||||
|
||||
/**
|
||||
* computeCoordinate
|
||||
* Compute the x component of a coordinate after its y component
|
||||
* is adjusted.
|
||||
*
|
||||
* History
|
||||
* 12/06/2012 DR 15559 Qinglu Lin Created.
|
||||
*/
|
||||
private void computeCoordinate(Coordinate[] c, int i, int j) {
|
||||
double slope;
|
||||
slope = computeSlope(c,i);
|
||||
int iPlus1 = i+1;
|
||||
if (c[j].x>=c[i].x && c[j].x<=c[iPlus1].x ||
|
||||
c[j].x>=c[iPlus1].x && c[j].x<=c[i].x) {
|
||||
|
||||
double x,y;
|
||||
double min1 = 0.005d;
|
||||
y = slope*(c[j].x-c[i].x) + c[i].y;
|
||||
double d = Math.abs(y-c[j].y);
|
||||
if (d>min1)
|
||||
return;
|
||||
|
||||
double min2 = 1.0E-8d;
|
||||
double delta = 0.005d; // empirical value
|
||||
double dyMin = 0.01d;
|
||||
int jMinus1 = j-1;
|
||||
if (jMinus1<0)
|
||||
jMinus1 = c.length-2;
|
||||
int jPlus1 = j+1;
|
||||
if (Math.abs(y-c[j].y)<min1) {
|
||||
double dy1, dy2;
|
||||
dy1 = Math.abs(c[jMinus1].y-y);
|
||||
dy2 = Math.abs(c[jPlus1].y-y);
|
||||
if (dy1>=dy2 && (Math.abs(dy1)>dyMin || Math.abs(dy2)>dyMin)) {
|
||||
// attempt to use l2 for computation
|
||||
if (c[j].y==c[jMinus1].y && Math.abs(c[j].x-c[jMinus1].x)>min2) {
|
||||
// l2 is a horizontal line, use l3 for computation
|
||||
if (c[jPlus1].y<c[j].y) delta = -delta;
|
||||
slope = computeSlope(c,j);
|
||||
if (Math.abs(slope) > min2) {
|
||||
y = c[j].y+delta;
|
||||
x = (y-c[jPlus1].y)/slope + c[jPlus1].x;
|
||||
} else {
|
||||
// l3 is a vertical line
|
||||
y = c[j].y+delta;
|
||||
x = c[j].x;
|
||||
}
|
||||
} else {
|
||||
// use l2 for computation
|
||||
if (c[jMinus1].y<c[j].y) delta = -delta;
|
||||
slope = computeSlope(c,jMinus1);
|
||||
if (Math.abs(slope) > min2) {
|
||||
y = c[j].y+delta;
|
||||
x = (y-c[jMinus1].y)/slope + c[jMinus1].x;
|
||||
} else {
|
||||
// l2 is a vertical line
|
||||
y = c[j].y+delta;
|
||||
x = c[j].x;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Math.abs(dy1)>dyMin || Math.abs(dy2)>dyMin) {
|
||||
// attempt to use l3 for computation
|
||||
if (c[j].y==c[jPlus1].y && Math.abs(c[j].x-c[jPlus1].x)>min2) {
|
||||
// l3 is a horizontal line, use l2 for computation
|
||||
if (c[jMinus1].y<c[j].y) delta = -delta;
|
||||
slope = computeSlope(c,jMinus1);
|
||||
if (Math.abs(slope) > min2) {
|
||||
y = c[j].y+delta;
|
||||
x = (y-c[jMinus1].y)/slope + c[jMinus1].x;
|
||||
} else {
|
||||
// l2 is a vertical line
|
||||
y = c[j].y+delta;
|
||||
x = c[j].x;
|
||||
}
|
||||
} else {
|
||||
// use l3 for computation
|
||||
if (c[jPlus1].y<c[j].y) delta = -delta;
|
||||
slope = computeSlope(c,j);
|
||||
if (Math.abs(slope) > min2) {
|
||||
y = c[j].y+delta;
|
||||
x = (y-c[jPlus1].y)/slope + c[jPlus1].x;
|
||||
} else {
|
||||
// l3 is a vertical line
|
||||
y = c[j].y+delta;
|
||||
x = c[j].x;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
x = c[j].x;
|
||||
y = c[j].y;
|
||||
}
|
||||
}
|
||||
c[j].x = x;
|
||||
c[j].y = y;
|
||||
if (j==0)
|
||||
c[c.length-1] = c[j];
|
||||
}
|
||||
}
|
||||
private static Polygon removeDuplicateCoordinate(Polygon polygon) {
|
||||
Coordinate[] verts = polygon.getCoordinates();
|
||||
Set<Coordinate> coords = new LinkedHashSet<Coordinate>();
|
||||
for (Coordinate c : verts)
|
||||
coords.add(c);
|
||||
if ((verts.length - coords.size()) < 2)
|
||||
return polygon;
|
||||
Coordinate[] vertices = new Coordinate[coords.size() + 1];
|
||||
Iterator<Coordinate> iter = coords.iterator();
|
||||
int i = 0;
|
||||
while (iter.hasNext()) {
|
||||
vertices[i] = new Coordinate(iter.next());
|
||||
i += 1;
|
||||
}
|
||||
vertices[i] = new Coordinate(vertices[0]);
|
||||
GeometryFactory gf = new GeometryFactory();
|
||||
return gf.createPolygon(gf.createLinearRing(vertices), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* adjustPolygon
|
||||
* When a point is very close to a line in the initial warning polygon, the resulting coordinates
|
||||
* cause the failure of polygon drawing in follow-up. The method move that kind of points away from
|
||||
* the line, and return a Polygon.
|
||||
*
|
||||
* History
|
||||
* 12/06/2012 DR 15559 Qinglu Lin Created.
|
||||
* computeSlope compute the slope of a line.
|
||||
*
|
||||
* History 12/06/2012 DR 15559 Qinglu Lin Created.
|
||||
*/
|
||||
public void adjustPolygon(Coordinate[] coords) {
|
||||
int n = coords.length;
|
||||
for (int i=0; i<n-1; ++i) {
|
||||
int j;
|
||||
for (j=i+2; j<=n-2; j++) {
|
||||
computeCoordinate(coords,i,j);
|
||||
}
|
||||
if (i<=n-3)
|
||||
for (j=0; j<i; j++) {
|
||||
computeCoordinate(coords,i,j);
|
||||
}
|
||||
else
|
||||
for (j=1; j<i; j++) {
|
||||
computeCoordinate(coords,i,j);
|
||||
}
|
||||
}
|
||||
private static double computeSlope(Coordinate[] coords, int i) {
|
||||
double min = 1.0E-08;
|
||||
double dx = coords[i].x - coords[i + 1].x;
|
||||
double slope = 0.0;
|
||||
if (Math.abs(dx) > min) {
|
||||
slope = (coords[i].y - coords[i + 1].y) / dx;
|
||||
}
|
||||
return slope;
|
||||
}
|
||||
|
||||
/**
|
||||
* computeCoordinate Compute the x component of a coordinate after its y
|
||||
* component is adjusted.
|
||||
*
|
||||
* History 12/06/2012 DR 15559 Qinglu Lin Created.
|
||||
*/
|
||||
private static void computeCoordinate(Coordinate[] c, int i, int j) {
|
||||
double slope;
|
||||
slope = computeSlope(c, i);
|
||||
int iPlus1 = i + 1;
|
||||
if (c[j].x >= c[i].x && c[j].x <= c[iPlus1].x || c[j].x >= c[iPlus1].x
|
||||
&& c[j].x <= c[i].x) {
|
||||
|
||||
double x, y;
|
||||
double min1 = 0.005d;
|
||||
y = slope * (c[j].x - c[i].x) + c[i].y;
|
||||
double d = Math.abs(y - c[j].y);
|
||||
if (d > min1)
|
||||
return;
|
||||
|
||||
double min2 = 1.0E-8d;
|
||||
double delta = 0.005d; // empirical value
|
||||
double dyMin = 0.01d;
|
||||
int jMinus1 = j - 1;
|
||||
if (jMinus1 < 0)
|
||||
jMinus1 = c.length - 2;
|
||||
int jPlus1 = j + 1;
|
||||
if (Math.abs(y - c[j].y) < min1) {
|
||||
double dy1, dy2;
|
||||
dy1 = Math.abs(c[jMinus1].y - y);
|
||||
dy2 = Math.abs(c[jPlus1].y - y);
|
||||
if (dy1 >= dy2
|
||||
&& (Math.abs(dy1) > dyMin || Math.abs(dy2) > dyMin)) {
|
||||
// attempt to use l2 for computation
|
||||
if (c[j].y == c[jMinus1].y
|
||||
&& Math.abs(c[j].x - c[jMinus1].x) > min2) {
|
||||
// l2 is a horizontal line, use l3 for computation
|
||||
if (c[jPlus1].y < c[j].y)
|
||||
delta = -delta;
|
||||
slope = computeSlope(c, j);
|
||||
if (Math.abs(slope) > min2) {
|
||||
y = c[j].y + delta;
|
||||
x = (y - c[jPlus1].y) / slope + c[jPlus1].x;
|
||||
} else {
|
||||
// l3 is a vertical line
|
||||
y = c[j].y + delta;
|
||||
x = c[j].x;
|
||||
}
|
||||
} else {
|
||||
// use l2 for computation
|
||||
if (c[jMinus1].y < c[j].y)
|
||||
delta = -delta;
|
||||
slope = computeSlope(c, jMinus1);
|
||||
if (Math.abs(slope) > min2) {
|
||||
y = c[j].y + delta;
|
||||
x = (y - c[jMinus1].y) / slope + c[jMinus1].x;
|
||||
} else {
|
||||
// l2 is a vertical line
|
||||
y = c[j].y + delta;
|
||||
x = c[j].x;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Math.abs(dy1) > dyMin || Math.abs(dy2) > dyMin) {
|
||||
// attempt to use l3 for computation
|
||||
if (c[j].y == c[jPlus1].y
|
||||
&& Math.abs(c[j].x - c[jPlus1].x) > min2) {
|
||||
// l3 is a horizontal line, use l2 for computation
|
||||
if (c[jMinus1].y < c[j].y)
|
||||
delta = -delta;
|
||||
slope = computeSlope(c, jMinus1);
|
||||
if (Math.abs(slope) > min2) {
|
||||
y = c[j].y + delta;
|
||||
x = (y - c[jMinus1].y) / slope + c[jMinus1].x;
|
||||
} else {
|
||||
// l2 is a vertical line
|
||||
y = c[j].y + delta;
|
||||
x = c[j].x;
|
||||
}
|
||||
} else {
|
||||
// use l3 for computation
|
||||
if (c[jPlus1].y < c[j].y)
|
||||
delta = -delta;
|
||||
slope = computeSlope(c, j);
|
||||
if (Math.abs(slope) > min2) {
|
||||
y = c[j].y + delta;
|
||||
x = (y - c[jPlus1].y) / slope + c[jPlus1].x;
|
||||
} else {
|
||||
// l3 is a vertical line
|
||||
y = c[j].y + delta;
|
||||
x = c[j].x;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
x = c[j].x;
|
||||
y = c[j].y;
|
||||
}
|
||||
}
|
||||
c[j].x = x;
|
||||
c[j].y = y;
|
||||
if (j == 0)
|
||||
c[c.length - 1] = c[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* adjustPolygon When a point is very close to a line in the initial warning
|
||||
* polygon, the resulting coordinates cause the failure of polygon drawing
|
||||
* in follow-up. The method move that kind of points away from the line, and
|
||||
* return a Polygon.
|
||||
*
|
||||
* History 12/06/2012 DR 15559 Qinglu Lin Created.
|
||||
*/
|
||||
public static void adjustPolygon(Coordinate[] coords) {
|
||||
int n = coords.length;
|
||||
for (int i = 0; i < n - 1; ++i) {
|
||||
int j;
|
||||
for (j = i + 2; j <= n - 2; j++) {
|
||||
computeCoordinate(coords, i, j);
|
||||
}
|
||||
if (i <= n - 3)
|
||||
for (j = 0; j < i; j++) {
|
||||
computeCoordinate(coords, i, j);
|
||||
}
|
||||
else
|
||||
for (j = 1; j < i; j++) {
|
||||
computeCoordinate(coords, i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -318,7 +318,7 @@ public class WarngenUIState {
|
|||
* the warningPolygon to set
|
||||
*/
|
||||
public void setWarningPolygon(Polygon warningPolygon) {
|
||||
this.warningPolygon = warningPolygon;
|
||||
this.warningPolygon = removeDuplicateCoordinate(warningPolygon);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
|
@ -327,13 +327,11 @@ public class WarngenUIState {
|
|||
}
|
||||
|
||||
/**
|
||||
* clear2
|
||||
* Same as clear(), except for not assigning null to warningPolygon.
|
||||
* History
|
||||
* 03-16-2012 Qinglu Lin DR14690 Created.
|
||||
* clear2 Same as clear(), except for not assigning null to warningPolygon.
|
||||
* History 03-16-2012 Qinglu Lin DR14690 Created.
|
||||
*/
|
||||
public void clear2() {
|
||||
oldWarningArea = null;
|
||||
oldWarningArea = null;
|
||||
oldWarningPolygon = null;
|
||||
oldWarningArea = null;
|
||||
oldWarningPolygon = null;
|
||||
|
|
|
@ -63,6 +63,8 @@ public class LocalizationResourceLoader extends FileResourceLoader implements
|
|||
|
||||
private Map<String, LocalizationFile> fileMap = new HashMap<String, LocalizationFile>();
|
||||
|
||||
private ExtendedProperties configuration;
|
||||
|
||||
@Override
|
||||
public long getLastModified(Resource resource) {
|
||||
return getFile(resource.getName()).getTimeStamp().getTime();
|
||||
|
@ -70,12 +72,9 @@ public class LocalizationResourceLoader extends FileResourceLoader implements
|
|||
|
||||
@Override
|
||||
public void init(ExtendedProperties configuration) {
|
||||
String site = configuration.getString(SITE_KEY);
|
||||
if (site != null && (site.equals(this.site) == false)) {
|
||||
// We changed sites since last time, clear out cache
|
||||
fileMap.clear();
|
||||
if (this.configuration != configuration) {
|
||||
this.configuration = configuration;
|
||||
}
|
||||
this.site = site;
|
||||
super.init(configuration);
|
||||
}
|
||||
|
||||
|
@ -89,18 +88,34 @@ public class LocalizationResourceLoader extends FileResourceLoader implements
|
|||
}
|
||||
}
|
||||
|
||||
private synchronized LocalizationFile getFile(String name) {
|
||||
LocalizationFile file = fileMap.get(name);
|
||||
if (file == null || file.exists() == false) {
|
||||
try {
|
||||
private synchronized LocalizationFile getFile(String name)
|
||||
throws ResourceNotFoundException {
|
||||
if (configuration == null) {
|
||||
throw new RuntimeException("Unable to locate file: " + name
|
||||
+ ", resource loader has not been initialized");
|
||||
}
|
||||
String site = configuration.getString(SITE_KEY);
|
||||
if (site == null || site.equals(this.site) == false) {
|
||||
// We changed sites since last time, clear out cache
|
||||
for (LocalizationFile file : fileMap.values()) {
|
||||
file.removeFileUpdatedObserver(this);
|
||||
}
|
||||
fileMap.clear();
|
||||
this.site = site;
|
||||
}
|
||||
this.site = site;
|
||||
|
||||
try {
|
||||
LocalizationFile file = fileMap.get(name);
|
||||
if (file == null || file.exists() == false) {
|
||||
file = FileUtil.getLocalizationFile(name, site);
|
||||
file.addFileUpdatedObserver(this);
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new RuntimeException("Error retrieving resource file", e);
|
||||
fileMap.put(name, file);
|
||||
}
|
||||
fileMap.put(name, file);
|
||||
return file;
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new ResourceNotFoundException(e);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -110,16 +125,12 @@ public class LocalizationResourceLoader extends FileResourceLoader implements
|
|||
|
||||
@Override
|
||||
public boolean resourceExists(String name) {
|
||||
LocalizationFile file = fileMap.get(name);
|
||||
if (file == null || file.exists() == false) {
|
||||
try {
|
||||
file = FileUtil.getLocalizationFile(name, site);
|
||||
file.addFileUpdatedObserver(this);
|
||||
} catch (FileNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
fileMap.put(name, file);
|
||||
LocalizationFile file;
|
||||
try {
|
||||
file = getFile(name);
|
||||
return file.exists();
|
||||
} catch (ResourceNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,10 +52,9 @@ import org.apache.velocity.app.Velocity;
|
|||
import org.apache.velocity.app.VelocityEngine;
|
||||
import org.apache.velocity.tools.generic.ListTool;
|
||||
|
||||
import com.raytheon.uf.common.activetable.ActiveTableMode;
|
||||
import com.raytheon.uf.common.activetable.ActiveTableRecord;
|
||||
import com.raytheon.uf.common.activetable.GetActiveTableRequest;
|
||||
import com.raytheon.uf.common.activetable.GetActiveTableResponse;
|
||||
import com.raytheon.uf.common.activetable.OperationalActiveTableRecord;
|
||||
import com.raytheon.uf.common.activetable.PracticeActiveTableRecord;
|
||||
import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord;
|
||||
import com.raytheon.uf.common.dataplugin.warning.WarningRecord.WarningAction;
|
||||
import com.raytheon.uf.common.dataplugin.warning.config.AreaSourceConfiguration;
|
||||
|
@ -63,6 +62,10 @@ import com.raytheon.uf.common.dataplugin.warning.config.AreaSourceConfiguration.
|
|||
import com.raytheon.uf.common.dataplugin.warning.config.WarngenConfiguration;
|
||||
import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialData;
|
||||
import com.raytheon.uf.common.dataplugin.warning.util.GeometryUtil;
|
||||
import com.raytheon.uf.common.dataquery.requests.DbQueryRequest;
|
||||
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
|
||||
import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType;
|
||||
import com.raytheon.uf.common.dataquery.responses.DbQueryResponse;
|
||||
import com.raytheon.uf.common.site.SiteMap;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
|
@ -70,7 +73,6 @@ import com.raytheon.uf.common.status.UFStatus.Priority;
|
|||
import com.raytheon.uf.common.time.DataTime;
|
||||
import com.raytheon.uf.common.time.SimulatedTime;
|
||||
import com.raytheon.uf.common.util.FileUtil;
|
||||
import com.raytheon.uf.edex.core.EdexException;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.core.localization.LocalizationManager;
|
||||
import com.raytheon.uf.viz.core.requests.ThriftClient;
|
||||
|
@ -132,8 +134,8 @@ import com.vividsolutions.jts.io.WKTReader;
|
|||
* in oldWarn.
|
||||
* Dec 17, 2012 15571 Qinglu Lin For hydro products, resolved issue caused by calling wkt.read(loc)
|
||||
* while loc is null.
|
||||
* Jan 8, 2013 15664 Qinglu Lin Appended selectedAction to handler.handle()'s argument list.
|
||||
*
|
||||
* Jan 8, 2013 15664 Qinglu Lin Appended selectedAction to handler.handle()'s argument list.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author njensen
|
||||
|
@ -397,9 +399,9 @@ public class TemplateRunner {
|
|||
|
||||
context.put("event", eventTime);
|
||||
if (selectedAction == WarningAction.COR)
|
||||
context.put("TMLtime", eventTime);
|
||||
context.put("TMLtime", eventTime);
|
||||
else
|
||||
context.put("TMLtime", simulatedTime);
|
||||
context.put("TMLtime", simulatedTime);
|
||||
context.put("ugcline",
|
||||
FipsUtil.getUgcLine(areas, wx.getEndTime(), 15));
|
||||
context.put("areaPoly", GisUtil.convertCoords(warngenLayer
|
||||
|
@ -446,15 +448,16 @@ public class TemplateRunner {
|
|||
// Convert to Point2D representation as Velocity requires
|
||||
// getX() and getY() methods which Coordinate does not have
|
||||
if (selectedAction == WarningAction.COR) {
|
||||
AbstractWarningRecord oldWarn = CurrentWarnings.getInstance(
|
||||
threeLetterSiteId).getNewestByTracking(etn, phenSig);
|
||||
AbstractWarningRecord oldWarn = CurrentWarnings
|
||||
.getInstance(threeLetterSiteId)
|
||||
.getNewestByTracking(etn, phenSig);
|
||||
String loc = oldWarn.getLoc();
|
||||
if (loc != null) {
|
||||
Geometry locGeom = wkt.read(loc);
|
||||
stormLocs = locGeom.getCoordinates();
|
||||
Geometry locGeom = wkt.read(loc);
|
||||
stormLocs = locGeom.getCoordinates();
|
||||
}
|
||||
} else {
|
||||
stormLocs = GisUtil.d2dCoordinates(stormLocs);
|
||||
stormLocs = GisUtil.d2dCoordinates(stormLocs);
|
||||
}
|
||||
Point2D.Double[] coords = new Point2D.Double[stormLocs.length];
|
||||
for (int i = 0; i < stormLocs.length; i++) {
|
||||
|
@ -494,16 +497,16 @@ public class TemplateRunner {
|
|||
Point2D.Double[] coords;
|
||||
Coordinate[] locs;
|
||||
if (selectedAction == WarningAction.CAN) {
|
||||
locs = warngenLayer.getStormLocations(stormTrackState);
|
||||
locs = GisUtil.d2dCoordinates(locs);
|
||||
coords = new Point2D.Double[locs.length];
|
||||
locs = warngenLayer.getStormLocations(stormTrackState);
|
||||
locs = GisUtil.d2dCoordinates(locs);
|
||||
coords = new Point2D.Double[locs.length];
|
||||
} else {
|
||||
Geometry locGeom = wkt.read(oldWarn.getLoc());
|
||||
locs = locGeom.getCoordinates();
|
||||
coords = new Point2D.Double[locs.length];
|
||||
coords = new Point2D.Double[locs.length];
|
||||
}
|
||||
for (int i = 0; i < locs.length; i++) {
|
||||
coords[i] = new Point2D.Double(locs[i].x, locs[i].y);
|
||||
coords[i] = new Point2D.Double(locs[i].x, locs[i].y);
|
||||
}
|
||||
context.put("eventLocation", coords);
|
||||
double motionDirection = oldWarn.getMotdir();
|
||||
|
@ -769,13 +772,14 @@ public class TemplateRunner {
|
|||
try {
|
||||
t0 = System.currentTimeMillis();
|
||||
WatchUtil watches = getWatches(warngenLayer, config, warnPolygon,
|
||||
fourLetterSiteId, simulatedTime);
|
||||
areas, fourLetterSiteId, simulatedTime);
|
||||
System.out.println("getWatches time: "
|
||||
+ (System.currentTimeMillis() - t0));
|
||||
if (watches != null) {
|
||||
context.put("watches", watches);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
statusHandler
|
||||
.handle(Priority.VERBOSE,
|
||||
"WarnGen cannot populate Active Watches. Check your local config.xml",
|
||||
|
@ -784,44 +788,60 @@ public class TemplateRunner {
|
|||
|
||||
long tz0 = System.currentTimeMillis();
|
||||
String script = createScript(warngenLayer.getTemplateName() + ".vm",
|
||||
context, warngenLayer.getLocalizedSite(),
|
||||
FileUtil.join(LocalizationManager.getUserDir(), "logs"));
|
||||
context, warngenLayer.getLocalizedSite());
|
||||
System.out.println("velocity time: "
|
||||
+ (System.currentTimeMillis() - tz0));
|
||||
|
||||
String text = script.toString();
|
||||
WarningTextHandler handler = WarningTextHandlerFactory.getHandler(
|
||||
selectedAction, text, config.getAutoLockText());
|
||||
String handledText = handler.handle(text, areas, cancelareas, selectedAction);
|
||||
String handledText = handler.handle(text, areas, cancelareas,
|
||||
selectedAction);
|
||||
|
||||
return handledText;
|
||||
}
|
||||
|
||||
private static VelocityEngine ENGINE = new VelocityEngine();
|
||||
private static VelocityEngine ENGINE;
|
||||
|
||||
private static synchronized String createScript(String vmFile,
|
||||
VelocityContext context, String site, String logDir)
|
||||
throws EdexException {
|
||||
StringWriter sw = new StringWriter();
|
||||
try {
|
||||
Properties p = new Properties();
|
||||
p.setProperty(LocalizationResourceLoader.SITE_KEY, site);
|
||||
p.setProperty("file.resource.loader.class",
|
||||
LocalizationResourceLoader.class.getName());
|
||||
p.setProperty("velocimacro.permissions.allowInline", "true");
|
||||
p.setProperty(
|
||||
"velocimacro.permissions.allow.inline.to.replace.global",
|
||||
"true");
|
||||
p.setProperty("runtime.log", FileUtil.join(logDir, "velocity.log"));
|
||||
ENGINE.init(p);
|
||||
context.put("scriptLibrary", "VM_global_library.vm");
|
||||
Template template = ENGINE.getTemplate(vmFile,
|
||||
Velocity.ENCODING_DEFAULT);
|
||||
template.merge(context, sw);
|
||||
} catch (Exception e) {
|
||||
throw new EdexException("Error generating from template", e);
|
||||
public static void initialize() {
|
||||
synchronized (TemplateRunner.class) {
|
||||
if (ENGINE == null) {
|
||||
ENGINE = new VelocityEngine();
|
||||
Properties p = new Properties();
|
||||
p.setProperty("file.resource.loader.class",
|
||||
LocalizationResourceLoader.class.getName());
|
||||
p.setProperty("runtime.log",
|
||||
FileUtil.join(FileUtil.join(
|
||||
LocalizationManager.getUserDir(), "logs"),
|
||||
"velocity.log"));
|
||||
p.setProperty("velocimacro.permissions.allowInline", "true");
|
||||
p.setProperty(
|
||||
"velocimacro.permissions.allow.inline.to.replace.global",
|
||||
"true");
|
||||
ENGINE.init(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String createScript(String vmFile, VelocityContext context,
|
||||
String site) throws VizException {
|
||||
synchronized (TemplateRunner.class) {
|
||||
if (ENGINE == null) {
|
||||
initialize();
|
||||
}
|
||||
StringWriter sw = new StringWriter();
|
||||
try {
|
||||
// Update site for ENGINE
|
||||
ENGINE.setProperty(LocalizationResourceLoader.SITE_KEY, site);
|
||||
context.put("scriptLibrary", "VM_global_library.vm");
|
||||
Template template = ENGINE.getTemplate(vmFile,
|
||||
Velocity.ENCODING_DEFAULT);
|
||||
template.merge(context, sw);
|
||||
} catch (Exception e) {
|
||||
throw new VizException("Error generating from template", e);
|
||||
}
|
||||
return sw.toString();
|
||||
}
|
||||
return sw.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -870,12 +890,13 @@ public class TemplateRunner {
|
|||
*/
|
||||
private static WatchUtil getWatches(WarngenLayer warngenLayer,
|
||||
WarngenConfiguration config, Geometry polygon,
|
||||
String fourLetterSiteId, Date simulatedTime) throws Exception {
|
||||
AffectedAreas[] affectedAreas, String fourLetterSiteId,
|
||||
Date simulatedTime) throws Exception {
|
||||
Validate.isTrue(config.getHatchedAreaSource()
|
||||
.getIncludedWatchAreaBuffer() >= 0,
|
||||
"IncludedWatchAreaBuffer can not be negative");
|
||||
|
||||
WatchUtil rval = null;
|
||||
GetActiveTableRequest req = new GetActiveTableRequest();
|
||||
String[] includedWatches = config.getIncludedWatches();
|
||||
|
||||
if (includedWatches != null && includedWatches.length > 0) {
|
||||
|
@ -890,67 +911,86 @@ public class TemplateRunner {
|
|||
}
|
||||
}
|
||||
|
||||
req.setPhensigList(phensigList);
|
||||
if (phensigList != null) {
|
||||
// Create start/endtime constraints
|
||||
Date endConstraintTime = simulatedTime;
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTime(simulatedTime);
|
||||
cal.add(Calendar.MINUTE, 3);
|
||||
Date startConstraintTime = cal.getTime();
|
||||
|
||||
if (CAVEMode.getMode().equals(CAVEMode.PRACTICE)) {
|
||||
req.setMode(ActiveTableMode.PRACTICE);
|
||||
} else {
|
||||
req.setMode(ActiveTableMode.OPERATIONAL);
|
||||
}
|
||||
// Get record type
|
||||
Class<? extends ActiveTableRecord> recordType = CAVEMode
|
||||
.getMode() == CAVEMode.OPERATIONAL ? OperationalActiveTableRecord.class
|
||||
: PracticeActiveTableRecord.class;
|
||||
|
||||
req.setSiteID(fourLetterSiteId);
|
||||
req.setRequestValidTimes(true);
|
||||
DbQueryRequest request = new DbQueryRequest();
|
||||
request.setEntityClass(recordType);
|
||||
request.addConstraint("startTime", new RequestConstraint(
|
||||
startConstraintTime.toString(),
|
||||
ConstraintType.LESS_THAN_EQUALS));
|
||||
request.addConstraint("endTime", new RequestConstraint(
|
||||
endConstraintTime.toString(),
|
||||
ConstraintType.GREATER_THAN_EQUALS));
|
||||
request.addConstraint("act", new RequestConstraint("CAN",
|
||||
ConstraintType.NOT_EQUALS));
|
||||
request.addConstraint("act", new RequestConstraint("EXP",
|
||||
ConstraintType.NOT_EQUALS));
|
||||
request.addConstraint("phensig", new RequestConstraint(
|
||||
phensigList, ConstraintType.IN));
|
||||
|
||||
long t0 = System.currentTimeMillis();
|
||||
GetActiveTableResponse resp = (GetActiveTableResponse) ThriftClient
|
||||
.sendRequest(req);
|
||||
long t1 = System.currentTimeMillis();
|
||||
java.util.List<ActiveTableRecord> respList = resp.getActiveTable();
|
||||
ArrayList<ActiveTableRecord> activeTable = new ArrayList<ActiveTableRecord>(
|
||||
respList.size());
|
||||
// Filter out entries representing non-active events.
|
||||
for (ActiveTableRecord ar : respList) {
|
||||
if ("CAN".equals(ar.getAct()) || "EXP".equals(ar.getAct()))
|
||||
continue;
|
||||
if (ar.getEndTime() == null) {
|
||||
statusHandler.handle(Priority.ERROR, String.format(
|
||||
"Watch %s has null end time; not included.",
|
||||
ar.getVtecstr()));
|
||||
continue;
|
||||
// TODO: Talk to Jonathan about this... Do I even need officeid
|
||||
// IN or is ugc zone good enough?
|
||||
Set<String> ugcZones = new HashSet<String>();
|
||||
for (AffectedAreas area : affectedAreas) {
|
||||
ugcZones.add(FipsUtil.getUgc(area));
|
||||
}
|
||||
// From A1 SELSparagraphs.C processWOU
|
||||
if (simulatedTime.before(new Date(ar.getStartTime().getTime()
|
||||
.getTime() - 180 * 1000))
|
||||
|| simulatedTime.after(ar.getEndTime().getTime()))
|
||||
continue;
|
||||
|
||||
activeTable.add(ar);
|
||||
}
|
||||
RequestConstraint ugcConstraint = new RequestConstraint("",
|
||||
ConstraintType.IN);
|
||||
ugcConstraint.setConstraintValueList(ugcZones);
|
||||
request.addConstraint("ugcZone", ugcConstraint);
|
||||
|
||||
System.out.println("getWatches.getActiveTable time: " + (t1 - t0)
|
||||
+ ", found "
|
||||
+ (activeTable != null ? activeTable.size() : "0")
|
||||
+ " watches");
|
||||
boolean val = activeTable != null && !activeTable.isEmpty();
|
||||
if (val) {
|
||||
// Look for ones with valid geometry
|
||||
// These are the only fields we need for processing watches
|
||||
request.addFields(new String[] { "issueTime", "startTime",
|
||||
"endTime", "ugcZone", "phensig", "vtecstr" });
|
||||
|
||||
t0 = System.currentTimeMillis();
|
||||
Polygon watchArea = (Polygon) polygon.buffer(milesToKilometer
|
||||
.convert(config.getHatchedAreaSource()
|
||||
.getIncludedWatchAreaBuffer())
|
||||
/ KmToDegrees);
|
||||
t1 = System.currentTimeMillis();
|
||||
System.out.println("getWatches.polygonBuffer time: "
|
||||
+ (t1 - t0));
|
||||
DbQueryResponse response = (DbQueryResponse) ThriftClient
|
||||
.sendRequest(request);
|
||||
|
||||
t0 = System.currentTimeMillis();
|
||||
warngenLayer.createGeometryForWatches(watchArea, activeTable);
|
||||
t1 = System.currentTimeMillis();
|
||||
System.out.println("getWatches.createWatchGeometry time: "
|
||||
+ (t1 - t0));
|
||||
List<ActiveTableRecord> records = new ArrayList<ActiveTableRecord>(
|
||||
response.getNumResults());
|
||||
for (Map<String, Object> result : response.getResults()) {
|
||||
ActiveTableRecord record = recordType.newInstance();
|
||||
record.setIssueTime((Calendar) result.get("issuetime"));
|
||||
record.setStartTime((Calendar) result.get("starttime"));
|
||||
record.setEndTime((Calendar) result.get("endtime"));
|
||||
record.setUgcZone((String) result.get("ugczone"));
|
||||
record.setPhensig((String) result.get("phensig"));
|
||||
record.setVtecstr((String) result.get("vtecstr"));
|
||||
records.add(record);
|
||||
}
|
||||
|
||||
rval = processATEntries(activeTable, warngenLayer);
|
||||
if (records.size() > 0) {
|
||||
long t0, t1;
|
||||
t0 = System.currentTimeMillis();
|
||||
Polygon watchArea = (Polygon) polygon
|
||||
.buffer(milesToKilometer.convert(config
|
||||
.getHatchedAreaSource()
|
||||
.getIncludedWatchAreaBuffer())
|
||||
/ KmToDegrees);
|
||||
t1 = System.currentTimeMillis();
|
||||
System.out.println("getWatches.polygonBuffer time: "
|
||||
+ (t1 - t0));
|
||||
|
||||
t0 = System.currentTimeMillis();
|
||||
warngenLayer.createGeometryForWatches(watchArea, records);
|
||||
t1 = System.currentTimeMillis();
|
||||
System.out.println("getWatches.createWatchGeometry time: "
|
||||
+ (t1 - t0));
|
||||
|
||||
rval = processATEntries(records, warngenLayer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -959,7 +999,9 @@ public class TemplateRunner {
|
|||
|
||||
private static class WatchWork {
|
||||
public WeatherAdvisoryWatch waw;
|
||||
|
||||
public boolean valid;
|
||||
|
||||
public ArrayList<String> ugcZone = new ArrayList<String>();
|
||||
|
||||
public WatchWork(WeatherAdvisoryWatch waw) {
|
||||
|
@ -995,8 +1037,8 @@ public class TemplateRunner {
|
|||
"Cannot process watches: missing HATCHING area source configuration");
|
||||
return rval;
|
||||
}
|
||||
GeospatialData[] geoData = warngenLayer.getGeodataFeatures(asc
|
||||
.getAreaSource() + "." + warngenLayer.getLocalizedSite());
|
||||
GeospatialData[] geoData = warngenLayer.getGeodataFeatures(
|
||||
asc.getAreaSource(), warngenLayer.getLocalizedSite());
|
||||
if (geoData == null || geoData.length == 0) {
|
||||
statusHandler.handle(Priority.ERROR,
|
||||
"Cannot process watches: cannot get geospatial data");
|
||||
|
@ -1033,11 +1075,12 @@ public class TemplateRunner {
|
|||
if (!ar.getGeometry().isEmpty())
|
||||
work.valid = true;
|
||||
|
||||
/* TODO: Currently adding all zones to the list even if they
|
||||
* are not in the CWA. Validation is currently done in
|
||||
/*
|
||||
* TODO: Currently adding all zones to the list even if they are not
|
||||
* in the CWA. Validation is currently done in
|
||||
* determineAffectedPortions to avoid redundant work.
|
||||
*/
|
||||
work.ugcZone.add(ar.getUgcZone());
|
||||
work.ugcZone.add(ar.getUgcZone());
|
||||
}
|
||||
|
||||
for (WatchWork work : map.values()) {
|
||||
|
@ -1056,7 +1099,7 @@ public class TemplateRunner {
|
|||
|
||||
/**
|
||||
* Given the list of counties in a watch, fill out the "portions" part of
|
||||
* the given WeatherAdvisoryWatch. Also checks if the given counties are
|
||||
* the given WeatherAdvisoryWatch. Also checks if the given counties are
|
||||
* actually in the CWA.
|
||||
*
|
||||
* @param ugcs
|
||||
|
@ -1068,7 +1111,7 @@ public class TemplateRunner {
|
|||
AreaSourceConfiguration asc, GeospatialData[] geoData,
|
||||
WeatherAdvisoryWatch waw) {
|
||||
|
||||
// Maps state abbreviation to unique fe_area values
|
||||
// Maps state abbreviation to unique fe_area values
|
||||
HashMap<String, Set<String>> map = new HashMap<String, Set<String>>();
|
||||
|
||||
for (String ugc : ugcs) {
|
||||
|
@ -1086,15 +1129,15 @@ public class TemplateRunner {
|
|||
String stateAbbrev = e.getKey();
|
||||
String feArea = null;
|
||||
try {
|
||||
feArea = getFeArea(stateAbbrev, e.getValue()[0], asc,
|
||||
geoData);
|
||||
feArea = getFeArea(stateAbbrev, e.getValue()[0], asc, geoData);
|
||||
} catch (RuntimeException exc) {
|
||||
statusHandler.handle(Priority.ERROR, "Error generating included watches.", exc);
|
||||
statusHandler.handle(Priority.ERROR,
|
||||
"Error generating included watches.", exc);
|
||||
return false;
|
||||
}
|
||||
if (feArea == NOT_IN_CWA)
|
||||
continue;
|
||||
|
||||
|
||||
Set<String> feAreas = map.get(stateAbbrev);
|
||||
if (feAreas == null) {
|
||||
feAreas = new HashSet<String>();
|
||||
|
@ -1111,7 +1154,8 @@ public class TemplateRunner {
|
|||
portion.parentRegion = getStateName(e.getKey(), asc, geoData)
|
||||
.toUpperCase();
|
||||
} catch (RuntimeException exc) {
|
||||
statusHandler.handle(Priority.ERROR, "Error generating included watches.", exc);
|
||||
statusHandler.handle(Priority.ERROR,
|
||||
"Error generating included watches.", exc);
|
||||
return false;
|
||||
}
|
||||
portion.partOfParentRegion = Area
|
||||
|
@ -1124,7 +1168,7 @@ public class TemplateRunner {
|
|||
waw.setParentRegion(portions.get(0).parentRegion);
|
||||
waw.setPartOfParentRegion(portions.get(0).partOfParentRegion);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1236,7 +1280,7 @@ public class TemplateRunner {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static String NOT_IN_CWA = new String("NOT_IN_CWA");
|
||||
|
||||
/** Determines if the given UGC is in the CWA and if it is, returns
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
package com.raytheon.viz.warngen.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
@ -48,6 +47,7 @@ import com.raytheon.uf.common.status.UFStatus;
|
|||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||
import com.raytheon.uf.common.time.SimulatedTime;
|
||||
import com.raytheon.uf.common.time.TimeRange;
|
||||
import com.raytheon.uf.viz.core.RecordFactory;
|
||||
import com.raytheon.uf.viz.core.alerts.AlertMessage;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.core.requests.ThriftClient;
|
||||
|
@ -145,17 +145,41 @@ public class CurrentWarnings {
|
|||
|
||||
private String officeId;
|
||||
|
||||
private List<AbstractWarningRecord> records = new LinkedList<AbstractWarningRecord>();
|
||||
private List<AbstractWarningRecord> records = new ArrayList<AbstractWarningRecord>();
|
||||
|
||||
private Map<String, List<AbstractWarningRecord>> warningMap = new HashMap<String, List<AbstractWarningRecord>>();
|
||||
private Map<String, AbstractWarningRecord> recordsMap = new HashMap<String, AbstractWarningRecord>();
|
||||
|
||||
private Map<String, List<AbstractWarningRecord>> warningMap = new HashMap<String, List<AbstractWarningRecord>>() {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public List<AbstractWarningRecord> get(Object key) {
|
||||
List<AbstractWarningRecord> records = super.get(key);
|
||||
if (records != null) {
|
||||
records = prepare(records);
|
||||
}
|
||||
return records;
|
||||
}
|
||||
};
|
||||
|
||||
private CurrentWarnings(String officeId) {
|
||||
this.officeId = officeId;
|
||||
initializeData();
|
||||
}
|
||||
|
||||
public List<AbstractWarningRecord> getWarnings() {
|
||||
return records;
|
||||
/**
|
||||
* request and populate data
|
||||
*/
|
||||
private void initializeData() {
|
||||
Map<String, RequestConstraint> constraints = new HashMap<String, RequestConstraint>();
|
||||
constraints.put("officeid", new RequestConstraint(officeId));
|
||||
|
||||
long t0 = System.currentTimeMillis();
|
||||
List<AbstractWarningRecord> warnings = requestRecords(constraints);
|
||||
System.out.println("Time to request CurrentWarnings records: "
|
||||
+ (System.currentTimeMillis() - t0) + "ms");
|
||||
processRecords(warnings);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -196,27 +220,21 @@ public class CurrentWarnings {
|
|||
current.setTime(SimulatedTime.getSystemTime().getTime());
|
||||
|
||||
synchronized (officeId) {
|
||||
List<AbstractWarningRecord> records = warningMap.get(toKey(
|
||||
warnRec.getPhensig(), warnRec.getEtn()));
|
||||
for (AbstractWarningRecord warning : records) {
|
||||
String phensig = warning.getPhensig();
|
||||
String etn = warning.getEtn();
|
||||
|
||||
if (warnRec.getPhensig().equals(phensig)
|
||||
&& warnRec.getEtn().equals(etn)) {
|
||||
WarningAction action = WarningAction.valueOf(warning
|
||||
.getAct());
|
||||
end.setTime(warning.getStartTime().getTime());
|
||||
end.add(Calendar.MINUTE, 10);
|
||||
TimeRange t = new TimeRange(warning.getStartTime()
|
||||
.getTime(), end.getTime());
|
||||
if ((action == WarningAction.NEW
|
||||
|| action == WarningAction.CON || action == WarningAction.EXT)
|
||||
&& t.contains(current.getTime())) {
|
||||
rval.add(warning);
|
||||
} else if (action == WarningAction.CAN
|
||||
|| action == WarningAction.EXP) {
|
||||
rval.clear();
|
||||
return rval;
|
||||
}
|
||||
WarningAction action = WarningAction.valueOf(warning.getAct());
|
||||
end.setTime(warning.getStartTime().getTime());
|
||||
end.add(Calendar.MINUTE, 10);
|
||||
TimeRange t = new TimeRange(warning.getStartTime().getTime(),
|
||||
end.getTime());
|
||||
if ((action == WarningAction.NEW || action == WarningAction.CON || action == WarningAction.EXT)
|
||||
&& t.contains(current.getTime())) {
|
||||
rval.add(warning);
|
||||
} else if (action == WarningAction.CAN
|
||||
|| action == WarningAction.EXP) {
|
||||
rval.clear();
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -421,28 +439,61 @@ public class CurrentWarnings {
|
|||
}
|
||||
|
||||
/**
|
||||
* request and populate data
|
||||
* Prepares a collection of records to be returned
|
||||
*
|
||||
* @param records
|
||||
* @return
|
||||
*/
|
||||
private void initializeData() {
|
||||
Map<String, RequestConstraint> constraints = new HashMap<String, RequestConstraint>();
|
||||
constraints.put("officeid", new RequestConstraint(officeId));
|
||||
private List<AbstractWarningRecord> prepare(
|
||||
List<AbstractWarningRecord> records) {
|
||||
List<AbstractWarningRecord> prepared = new ArrayList<AbstractWarningRecord>();
|
||||
DbQueryRequest request = new DbQueryRequest();
|
||||
Set<String> dataURIs = new HashSet<String>();
|
||||
for (AbstractWarningRecord record : records) {
|
||||
if (record.getGeometry() == null) {
|
||||
dataURIs.add(record.getDataURI());
|
||||
} else {
|
||||
prepared.add(record);
|
||||
}
|
||||
}
|
||||
|
||||
long t0 = System.currentTimeMillis();
|
||||
List<AbstractWarningRecord> warnings = requestRecords(constraints);
|
||||
System.out.println("Time to request CurrentWarnings records: "
|
||||
+ (System.currentTimeMillis() - t0) + "ms");
|
||||
processRecords(warnings);
|
||||
if (dataURIs.size() > 0) {
|
||||
long t0 = System.currentTimeMillis();
|
||||
RequestConstraint constraint = new RequestConstraint(null,
|
||||
ConstraintType.IN);
|
||||
constraint.setBetweenValueList(dataURIs.toArray(new String[0]));
|
||||
request.addConstraint("dataURI", constraint);
|
||||
request.setEntityClass(getWarningClass());
|
||||
try {
|
||||
List<AbstractWarningRecord> toProcess = new ArrayList<AbstractWarningRecord>();
|
||||
DbQueryResponse response = (DbQueryResponse) ThriftClient
|
||||
.sendRequest(request);
|
||||
for (AbstractWarningRecord record : response
|
||||
.getEntityObjects(AbstractWarningRecord.class)) {
|
||||
toProcess.add(record);
|
||||
}
|
||||
processRecords(toProcess);
|
||||
prepared.addAll(toProcess);
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
|
||||
e);
|
||||
}
|
||||
System.out.println("Time to prepare " + records.size()
|
||||
+ " records = " + (System.currentTimeMillis() - t0) + "ms");
|
||||
}
|
||||
|
||||
return prepared;
|
||||
}
|
||||
|
||||
private void processRecords(List<AbstractWarningRecord> warnings) {
|
||||
synchronized (officeId) {
|
||||
for (AbstractWarningRecord record : warnings) {
|
||||
if (records.contains(record) == false
|
||||
&& record.getGeometry() != null) {
|
||||
records.add(record);
|
||||
}
|
||||
recordsMap.put(record.getDataURI(), record);
|
||||
}
|
||||
|
||||
records.clear();
|
||||
records.addAll(recordsMap.values());
|
||||
|
||||
// Sort by insert time
|
||||
Collections.sort(records, new Comparator<AbstractWarningRecord>() {
|
||||
@Override
|
||||
|
@ -508,7 +559,7 @@ public class CurrentWarnings {
|
|||
for (String key : recordMap.keySet()) {
|
||||
CurrentWarnings cw = instanceMap.get(key);
|
||||
if (cw != null) {
|
||||
cw.processRecords(recordMap.get(key));
|
||||
cw.prepare(recordMap.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -546,16 +597,30 @@ public class CurrentWarnings {
|
|||
*/
|
||||
private static List<AbstractWarningRecord> requestRecords(
|
||||
Map<String, RequestConstraint> constraints) {
|
||||
Map<String, RequestConstraint> constraintsCopy = new HashMap<String, RequestConstraint>(
|
||||
constraints);
|
||||
// Ensures we won't request any records we wont use
|
||||
constraintsCopy.put("geometry", new RequestConstraint(null,
|
||||
ConstraintType.ISNOTNULL));
|
||||
List<AbstractWarningRecord> newRecords = new ArrayList<AbstractWarningRecord>();
|
||||
|
||||
try {
|
||||
String insertTimeField = "insertTime";
|
||||
String dataURIField = "dataURI";
|
||||
DbQueryRequest request = new DbQueryRequest();
|
||||
request.setConstraints(constraints);
|
||||
request.setConstraints(constraintsCopy);
|
||||
request.setEntityClass(getWarningClass());
|
||||
request.addRequestField(dataURIField);
|
||||
request.addRequestField(insertTimeField);
|
||||
DbQueryResponse response = (DbQueryResponse) ThriftClient
|
||||
.sendRequest(request);
|
||||
newRecords.addAll(Arrays.asList(response
|
||||
.getEntityObjects(AbstractWarningRecord.class)));
|
||||
for (Map<String, Object> result : response.getResults()) {
|
||||
String dataURI = (String) result.get(dataURIField);
|
||||
AbstractWarningRecord record = (AbstractWarningRecord) RecordFactory
|
||||
.getInstance().loadRecordFromUri(dataURI);
|
||||
record.setInsertTime((Calendar) result.get(insertTimeField));
|
||||
newRecords.add(record);
|
||||
}
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, "Error retreiving warnings",
|
||||
e);
|
||||
|
|
|
@ -61,7 +61,7 @@ public class FipsUtil {
|
|||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(FipsUtil.class);
|
||||
|
||||
private static HashMap<String, String> fipsToState;
|
||||
private static final Map<String, String> fipsToState;
|
||||
|
||||
private static String[][] abbrlist = new String[][] { { "02", "AK" },
|
||||
{ "01", "AL" }, { "05", "AR" }, { "60", "AS" }, { "04", "AZ" },
|
||||
|
@ -79,6 +79,13 @@ public class FipsUtil {
|
|||
{ "51", "VA" }, { "78", "VI" }, { "50", "VT" }, { "53", "WA" },
|
||||
{ "55", "WI" }, { "54", "WV" }, { "56", "WY" } };
|
||||
|
||||
static {
|
||||
fipsToState = new HashMap<String, String>();
|
||||
for (String[] abbr : abbrlist) {
|
||||
fipsToState.put(abbr[0], abbr[1]);
|
||||
}
|
||||
}
|
||||
|
||||
/** Catch the Date portion of the UGC Header */
|
||||
private static final String DATEPATTERN = "\\-([0-9]{6}\\-)";
|
||||
|
||||
|
@ -103,11 +110,6 @@ public class FipsUtil {
|
|||
ArrayList<String> countiesOrZones = new ArrayList<String>();
|
||||
DateUtil du = new DateUtil();
|
||||
|
||||
fipsToState = new HashMap<String, String>();
|
||||
for (String[] abbr : abbrlist) {
|
||||
fipsToState.put(abbr[0], abbr[1]);
|
||||
}
|
||||
|
||||
ArrayList<AffectedAreas> sortedAreas = new ArrayList<AffectedAreas>();
|
||||
Collections.addAll(sortedAreas, areas);
|
||||
ArrayList<String> fields = new ArrayList<String>();
|
||||
|
@ -122,27 +124,31 @@ public class FipsUtil {
|
|||
Collections.sort(sortedAreas, comparator);
|
||||
|
||||
for (AffectedAreas area : sortedAreas) {
|
||||
String ugc = null;
|
||||
if (Character.isDigit(area.getFips().charAt(0))) {
|
||||
ugc = fipsToState.get(area.getFips().substring(0, 2)) + "C"
|
||||
+ area.getFips().substring(2, 5);
|
||||
} else {
|
||||
ugc = area.getFips().substring(0, 2) + "Z"
|
||||
+ area.getFips().substring(area.getFips().length() - 3);
|
||||
}
|
||||
|
||||
String ugc = getUgc(area);
|
||||
if (ugc != null && countiesOrZones.contains(ugc) == false) {
|
||||
countiesOrZones.add(ugc);
|
||||
}
|
||||
}
|
||||
|
||||
rval.append(simplifyHeader(getUgc(countiesOrZones)));
|
||||
rval.append(simplifyHeader(getUgcLine(countiesOrZones)));
|
||||
rval.append(du
|
||||
.format(endtime, new SimpleDateFormat("ddHHmm"), interval)
|
||||
+ "-");
|
||||
return rval.toString();
|
||||
}
|
||||
|
||||
public static String getUgc(AffectedAreas area) {
|
||||
String ugc = null;
|
||||
if (Character.isDigit(area.getFips().charAt(0))) {
|
||||
ugc = fipsToState.get(area.getFips().substring(0, 2)) + "C"
|
||||
+ area.getFips().substring(2, 5);
|
||||
} else {
|
||||
ugc = area.getFips().substring(0, 2) + "Z"
|
||||
+ area.getFips().substring(area.getFips().length() - 3);
|
||||
}
|
||||
return ugc;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates a correctly formatted UGC Header based on the passed
|
||||
* AffectedAreas. The 6 digit datestamp at the end of the header is
|
||||
|
@ -164,7 +170,7 @@ public class FipsUtil {
|
|||
}
|
||||
}
|
||||
|
||||
rval.append(simplifyHeader(getUgc(countiesOrZones)));
|
||||
rval.append(simplifyHeader(getUgcLine(countiesOrZones)));
|
||||
rval.append(du
|
||||
.format(endtime, new SimpleDateFormat("ddHHmm"), interval)
|
||||
+ "-");
|
||||
|
@ -270,23 +276,23 @@ public class FipsUtil {
|
|||
* @param counties
|
||||
* @return
|
||||
*/
|
||||
private static String getUgc(ArrayList<String> countiesorZones) {
|
||||
private static String getUgcLine(ArrayList<String> ugcs) {
|
||||
ArrayList<String> states = new ArrayList<String>();
|
||||
StringBuffer rval = new StringBuffer();
|
||||
|
||||
int nlCounter = 0;
|
||||
for (String countyOrZone : countiesorZones) {
|
||||
if (!states.contains(countyOrZone.substring(0, 3))) {
|
||||
states.add(countyOrZone.substring(0, 3));
|
||||
for (String ugc : ugcs) {
|
||||
if (!states.contains(ugc.substring(0, 3))) {
|
||||
states.add(ugc.substring(0, 3));
|
||||
}
|
||||
}
|
||||
|
||||
for (String state : states) {
|
||||
rval.append(state);
|
||||
nlCounter += state.length();
|
||||
for (String countyOrZone : countiesorZones) {
|
||||
if (countyOrZone.substring(0, 3).equals(state)) {
|
||||
rval.append(countyOrZone.substring(3) + "-");
|
||||
for (String ugc : ugcs) {
|
||||
if (ugc.substring(0, 3).equals(state)) {
|
||||
rval.append(ugc.substring(3) + "-");
|
||||
nlCounter += 4;
|
||||
if (nlCounter >= 60) {
|
||||
nlCounter = 0;
|
||||
|
@ -327,7 +333,7 @@ public class FipsUtil {
|
|||
* DR15599 - use simplifyHeader to get the correct rval
|
||||
*/
|
||||
if (difference.size() > 0) {
|
||||
rval = simplifyHeader(getUgc(difference));
|
||||
rval = simplifyHeader(getUgcLine(difference));
|
||||
}
|
||||
rval = rval + dateStr;
|
||||
return rval;
|
||||
|
@ -413,10 +419,6 @@ public class FipsUtil {
|
|||
* @return two letter state abbreviation
|
||||
*/
|
||||
public static String getStateNameFromFips(String fips) {
|
||||
fipsToState = new HashMap<String, String>();
|
||||
for (String[] abbr : abbrlist) {
|
||||
fipsToState.put(abbr[0], abbr[1]);
|
||||
}
|
||||
String statefips = fips.substring(0, 2);
|
||||
return fipsToState.get(statefips);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ import com.raytheon.uf.common.dataplugin.warning.WarningConstants;
|
|||
import com.raytheon.uf.common.dataplugin.warning.config.AreaSourceConfiguration;
|
||||
import com.raytheon.uf.common.dataplugin.warning.config.GeospatialConfiguration;
|
||||
import com.raytheon.uf.common.dataplugin.warning.config.WarngenConfiguration;
|
||||
import com.raytheon.uf.common.dataplugin.warning.util.GeometryUtil;
|
||||
import com.raytheon.uf.common.geospatial.SpatialException;
|
||||
import com.raytheon.uf.common.localization.IPathManager;
|
||||
import com.raytheon.uf.common.localization.LocalizationContext;
|
||||
|
@ -43,8 +42,6 @@ import com.raytheon.uf.common.serialization.comm.RequestRouter;
|
|||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.geom.GeometryFactory;
|
||||
import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory;
|
||||
|
||||
/**
|
||||
|
@ -126,43 +123,6 @@ public class GeospatialFactory {
|
|||
}
|
||||
}
|
||||
|
||||
Map<String, List<GeospatialData>> uniqueAreasMap = new HashMap<String, List<GeospatialData>>();
|
||||
for (GeospatialData data : areas) {
|
||||
String key = String.valueOf(data.attributes.get(metaData
|
||||
.getFipsField()));
|
||||
List<GeospatialData> list = uniqueAreasMap.get(key);
|
||||
if (list == null) {
|
||||
list = new ArrayList<GeospatialData>();
|
||||
uniqueAreasMap.put(key, list);
|
||||
}
|
||||
|
||||
list.add(data);
|
||||
}
|
||||
GeospatialData[] uniqueAreas = new GeospatialData[uniqueAreasMap.size()];
|
||||
int index = 0;
|
||||
for (String key : uniqueAreasMap.keySet()) {
|
||||
List<GeospatialData> list = uniqueAreasMap.get(key);
|
||||
GeospatialData data = list.get(0);
|
||||
|
||||
// if multiple areas share a common fips ID, the smaller areas will
|
||||
// have to merge will the largest area
|
||||
if (list.size() > 1) {
|
||||
// collect all individual geometries
|
||||
List<Geometry> geometries = new ArrayList<Geometry>();
|
||||
for (GeospatialData item : list) {
|
||||
GeometryUtil.buildGeometryList(geometries, item.geometry);
|
||||
}
|
||||
// Create multi geometry out of combined areas
|
||||
data.geometry = new GeometryFactory()
|
||||
.createGeometryCollection(geometries
|
||||
.toArray(new Geometry[0]));
|
||||
}
|
||||
uniqueAreas[index] = data;
|
||||
index++;
|
||||
}
|
||||
|
||||
areas = uniqueAreas;
|
||||
|
||||
// process parent regions
|
||||
if (parentAreas != null) {
|
||||
Map<String, GeospatialData> parentMap = new HashMap<String, GeospatialData>(
|
||||
|
@ -184,7 +144,7 @@ public class GeospatialFactory {
|
|||
|
||||
// Prepare the geometries
|
||||
for (GeospatialData data : areas) {
|
||||
data.prepGeom = new PreparedGeometryCollection(data.geometry);
|
||||
data.prepGeom = PreparedGeometryFactory.prepare(data.geometry);
|
||||
}
|
||||
|
||||
return areas;
|
||||
|
|
|
@ -1,246 +0,0 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.uf.common.dataplugin.warning.gis;
|
||||
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.geom.GeometryCollection;
|
||||
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
||||
import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory;
|
||||
|
||||
/**
|
||||
* {@link PreparedGeometry} implementation that can handle
|
||||
* {@link GeometryCollection} objects
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jan 28, 2013 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class PreparedGeometryCollection implements PreparedGeometry {
|
||||
|
||||
private Geometry geometry;
|
||||
|
||||
private PreparedGeometry[] prepared;
|
||||
|
||||
public PreparedGeometryCollection(Geometry geometry) {
|
||||
this.geometry = geometry;
|
||||
int numGeoms = geometry.getNumGeometries();
|
||||
if (geometry.getClass() == GeometryCollection.class) {
|
||||
prepared = new PreparedGeometry[numGeoms];
|
||||
for (int i = 0; i < numGeoms; ++i) {
|
||||
prepared[i] = PreparedGeometryFactory.prepare(geometry
|
||||
.getGeometryN(i));
|
||||
}
|
||||
} else {
|
||||
prepared = new PreparedGeometry[] { PreparedGeometryFactory
|
||||
.prepare(geometry) };
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.vividsolutions.jts.geom.prep.PreparedGeometry#getGeometry()
|
||||
*/
|
||||
@Override
|
||||
public Geometry getGeometry() {
|
||||
return geometry;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.vividsolutions.jts.geom.prep.PreparedGeometry#contains(com.vividsolutions
|
||||
* .jts.geom.Geometry)
|
||||
*/
|
||||
@Override
|
||||
public boolean contains(Geometry geom) {
|
||||
for (PreparedGeometry pg : prepared) {
|
||||
if (pg.contains(geom)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.vividsolutions.jts.geom.prep.PreparedGeometry#containsProperly(com
|
||||
* .vividsolutions.jts.geom.Geometry)
|
||||
*/
|
||||
@Override
|
||||
public boolean containsProperly(Geometry geom) {
|
||||
for (PreparedGeometry pg : prepared) {
|
||||
if (pg.containsProperly(geom)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.vividsolutions.jts.geom.prep.PreparedGeometry#coveredBy(com.
|
||||
* vividsolutions.jts.geom.Geometry)
|
||||
*/
|
||||
@Override
|
||||
public boolean coveredBy(Geometry geom) {
|
||||
boolean coveredBy = true;
|
||||
for (PreparedGeometry pg : prepared) {
|
||||
if (pg.coveredBy(geom) == false) {
|
||||
coveredBy = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return coveredBy;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.vividsolutions.jts.geom.prep.PreparedGeometry#covers(com.vividsolutions
|
||||
* .jts.geom.Geometry)
|
||||
*/
|
||||
@Override
|
||||
public boolean covers(Geometry geom) {
|
||||
throw new UnsupportedOperationException(
|
||||
"PreparedGeometryCollection does not support PreparedGeometry.covers");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.vividsolutions.jts.geom.prep.PreparedGeometry#crosses(com.vividsolutions
|
||||
* .jts.geom.Geometry)
|
||||
*/
|
||||
@Override
|
||||
public boolean crosses(Geometry geom) {
|
||||
for (PreparedGeometry pg : prepared) {
|
||||
if (pg.crosses(geom)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.vividsolutions.jts.geom.prep.PreparedGeometry#disjoint(com.vividsolutions
|
||||
* .jts.geom.Geometry)
|
||||
*/
|
||||
@Override
|
||||
public boolean disjoint(Geometry geom) {
|
||||
boolean disjoint = true;
|
||||
for (PreparedGeometry pg : prepared) {
|
||||
if (pg.disjoint(geom) == false) {
|
||||
disjoint = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return disjoint;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.vividsolutions.jts.geom.prep.PreparedGeometry#intersects(com.
|
||||
* vividsolutions.jts.geom.Geometry)
|
||||
*/
|
||||
@Override
|
||||
public boolean intersects(Geometry geom) {
|
||||
for (PreparedGeometry pg : prepared) {
|
||||
if (pg.intersects(geom)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.vividsolutions.jts.geom.prep.PreparedGeometry#overlaps(com.vividsolutions
|
||||
* .jts.geom.Geometry)
|
||||
*/
|
||||
@Override
|
||||
public boolean overlaps(Geometry geom) {
|
||||
for (PreparedGeometry pg : prepared) {
|
||||
if (pg.overlaps(geom)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.vividsolutions.jts.geom.prep.PreparedGeometry#touches(com.vividsolutions
|
||||
* .jts.geom.Geometry)
|
||||
*/
|
||||
@Override
|
||||
public boolean touches(Geometry geom) {
|
||||
for (PreparedGeometry pg : prepared) {
|
||||
if (pg.touches(geom)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.vividsolutions.jts.geom.prep.PreparedGeometry#within(com.vividsolutions
|
||||
* .jts.geom.Geometry)
|
||||
*/
|
||||
@Override
|
||||
public boolean within(Geometry geom) {
|
||||
boolean within = true;
|
||||
for (PreparedGeometry pg : prepared) {
|
||||
if (pg.within(geom) == false) {
|
||||
within = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return within;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
package com.raytheon.uf.common.dataplugin.warning.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
@ -9,10 +8,9 @@ import java.util.TreeSet;
|
|||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.geom.GeometryCollection;
|
||||
import com.vividsolutions.jts.geom.GeometryFactory;
|
||||
import com.vividsolutions.jts.geom.Point;
|
||||
import com.vividsolutions.jts.geom.Polygon;
|
||||
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
||||
import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory;
|
||||
import com.vividsolutions.jts.operation.overlay.snap.GeometrySnapper;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -63,79 +61,28 @@ public class GeometryUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param parentGeom
|
||||
* @param geometry
|
||||
* @return
|
||||
*/
|
||||
public static boolean intersects(Geometry g1, Geometry g2) {
|
||||
if (g1 instanceof GeometryCollection) {
|
||||
for (int i = 0; i < g1.getNumGeometries(); ++i) {
|
||||
if (intersects(g1.getGeometryN(i), g2)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else if (g2 instanceof GeometryCollection) {
|
||||
for (int i = 0; i < g2.getNumGeometries(); ++i) {
|
||||
if (intersects(g1, g2.getGeometryN(i))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return g1.intersects(g2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if g1 contains g2
|
||||
* Checks to see if g1 contains the point
|
||||
*
|
||||
* @param g1
|
||||
* @param g2
|
||||
* @return
|
||||
*/
|
||||
public static boolean contains(Geometry g1, Geometry g2) {
|
||||
public static boolean contains(Geometry g1, Point p) {
|
||||
if (g1 instanceof GeometryCollection) {
|
||||
for (int i = 0; i < g1.getNumGeometries(); ++i) {
|
||||
if (contains(g1.getGeometryN(i), g2)) {
|
||||
if (contains(g1.getGeometryN(i), p)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return g1.contains(g2);
|
||||
return g1.contains(p);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if g intersects any pGs
|
||||
*
|
||||
* @param pGs
|
||||
* @param g
|
||||
* @return
|
||||
*/
|
||||
public static boolean intersects(List<PreparedGeometry> pGs, Geometry g) {
|
||||
for (PreparedGeometry pg : pGs) {
|
||||
if (pg.intersects(g)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void recursivePreparedGeometry(Geometry g,
|
||||
List<PreparedGeometry> prepGeom) {
|
||||
if (g instanceof GeometryCollection) {
|
||||
for (int i = 0; i < g.getNumGeometries(); ++i) {
|
||||
recursivePreparedGeometry(g.getGeometryN(i), prepGeom);
|
||||
}
|
||||
} else {
|
||||
prepGeom.add(PreparedGeometryFactory.prepare(g));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersection between g1 and g2
|
||||
* Intersection between g1 and g2. Resulting intersection will contain user
|
||||
* data from g2
|
||||
*
|
||||
* @param g1
|
||||
* @param g2
|
||||
|
@ -149,41 +96,10 @@ public class GeometryUtil {
|
|||
intersection(g1, g2, intersection);
|
||||
Geometry rval = gf.createGeometryCollection(intersection
|
||||
.toArray(new Geometry[intersection.size()]));
|
||||
for (int i = 0; i < rval.getNumGeometries(); ++i) {
|
||||
setUserData(rval.getGeometryN(i), (CountyUserData) intersection
|
||||
.get(i).getUserData());
|
||||
// why set it again??
|
||||
rval.getGeometryN(i).setUserData(intersection.get(i).getUserData());
|
||||
}
|
||||
rval.setUserData(g2.getUserData());
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersection between g1 and g2
|
||||
*
|
||||
* @param g1
|
||||
* @param g2
|
||||
*
|
||||
* @return the intersection between g1 and g2
|
||||
*/
|
||||
public static Geometry intersection(Geometry g1, PreparedGeometry pg) {
|
||||
GeometryFactory gf = new GeometryFactory();
|
||||
List<Geometry> intersection = new ArrayList<Geometry>(
|
||||
g1.getNumGeometries() + 1);
|
||||
intersection(g1, pg, intersection);
|
||||
Geometry rval = gf.createGeometryCollection(intersection
|
||||
.toArray(new Geometry[intersection.size()]));
|
||||
for (int i = 0; i < rval.getNumGeometries(); ++i) {
|
||||
setUserData(rval.getGeometryN(i), (CountyUserData) intersection
|
||||
.get(i).getUserData());
|
||||
// why set it again??
|
||||
rval.getGeometryN(i).setUserData(intersection.get(i).getUserData());
|
||||
}
|
||||
rval.setUserData(pg.getGeometry().getUserData());
|
||||
return rval;
|
||||
}
|
||||
|
||||
private static void intersection(Geometry g1, Geometry g2,
|
||||
List<Geometry> intersections) {
|
||||
if (g1 instanceof GeometryCollection) {
|
||||
|
@ -198,27 +114,48 @@ public class GeometryUtil {
|
|||
} else {
|
||||
String g1Name = toString(g1.getUserData());
|
||||
String g2Name = toString(g2.getUserData());
|
||||
String prefix = null;
|
||||
if (g1Name != null && g2Name != null) {
|
||||
prefix = getPrefix(g1Name);
|
||||
}
|
||||
if ((g1Name == null || g2Name == null || g2Name
|
||||
.startsWith(prefix))) {
|
||||
if (g1.isValid() && g2.isValid()) {
|
||||
Geometry section = g1.intersection(g2);
|
||||
if (section.isEmpty() == false) {
|
||||
section = section.buffer(0);
|
||||
setUserData(section,
|
||||
(CountyUserData) g2.getUserData());
|
||||
section.setUserData(g2.getUserData());
|
||||
intersections.add(section);
|
||||
|
||||
if ((g1Name == null || g2Name == null || g2Name.equals(g1Name))) {
|
||||
Geometry section = g1.intersection(g2);
|
||||
if (section.isEmpty() == false) {
|
||||
if (g2.getUserData() != null) {
|
||||
if (section instanceof GeometryCollection) {
|
||||
for (int n = 0; n < section.getNumGeometries(); ++n) {
|
||||
setUserData(section.getGeometryN(n),
|
||||
(CountyUserData) g2.getUserData());
|
||||
}
|
||||
} else {
|
||||
setUserData(section,
|
||||
(CountyUserData) g2.getUserData());
|
||||
}
|
||||
}
|
||||
intersections.add(section);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersection between g1 and prepared geometry pg. Resulting Geometry will
|
||||
* have user data from pg
|
||||
*
|
||||
* @param g1
|
||||
* @param g2
|
||||
*
|
||||
* @return the intersection between g1 and g2
|
||||
*/
|
||||
public static Geometry intersection(Geometry g1, PreparedGeometry pg) {
|
||||
GeometryFactory gf = new GeometryFactory();
|
||||
List<Geometry> intersection = new ArrayList<Geometry>(
|
||||
g1.getNumGeometries() + 1);
|
||||
intersection(g1, pg, intersection);
|
||||
Geometry rval = gf.createGeometryCollection(intersection
|
||||
.toArray(new Geometry[intersection.size()]));
|
||||
rval.setUserData(pg.getGeometry().getUserData());
|
||||
return rval;
|
||||
}
|
||||
|
||||
private static void intersection(Geometry g1, PreparedGeometry pg,
|
||||
List<Geometry> intersections) {
|
||||
if (g1 instanceof GeometryCollection) {
|
||||
|
@ -226,78 +163,17 @@ public class GeometryUtil {
|
|||
intersection(g1.getGeometryN(i), pg, intersections);
|
||||
}
|
||||
} else {
|
||||
if (pg.intersects(g1)) {
|
||||
String g1Name = toString(g1.getUserData());
|
||||
String g2Name = toString(pg.getGeometry().getUserData());
|
||||
|
||||
if ((g2Name != null && g2Name.equals(g1Name))
|
||||
|| ((g1Name == null || g2Name == null) && pg.intersects(g1))) {
|
||||
Geometry g2 = pg.getGeometry();
|
||||
List<Geometry> sections = new ArrayList<Geometry>();
|
||||
for (int n = 0; n < g2.getNumGeometries(); n++) {
|
||||
Geometry section = g1.intersection(g2.getGeometryN(n));
|
||||
if (section.isEmpty() == false) {
|
||||
sections.add(section);
|
||||
}
|
||||
}
|
||||
Geometry section = null;
|
||||
if (sections.size() == 1) {
|
||||
section = sections.get(0);
|
||||
} else if (sections.size() > 0) {
|
||||
section = new GeometryFactory()
|
||||
.createGeometryCollection(sections
|
||||
.toArray(new Geometry[0]));
|
||||
}
|
||||
if (section != null && section.isEmpty() == false) {
|
||||
setUserData(section, (CountyUserData) g2.getUserData());
|
||||
intersections.add(section);
|
||||
}
|
||||
intersection(g1, g2, intersections);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the difference between the 2 geometries
|
||||
*
|
||||
* @param g1
|
||||
* main geometry
|
||||
* @param g2
|
||||
* geometry to remove
|
||||
* @return g1 minus g2
|
||||
*/
|
||||
public static Geometry difference(Geometry g1, Geometry g2) {
|
||||
GeometryFactory gf = new GeometryFactory();
|
||||
List<Geometry> differences = new ArrayList<Geometry>();
|
||||
buildGeometryList(differences, g1);
|
||||
Set<String> prefixes = new HashSet<String>();
|
||||
|
||||
String pre = getPrefix(toString(g2.getUserData()));
|
||||
if (pre != null) {
|
||||
// A one county geometry
|
||||
prefixes.add(pre);
|
||||
} else {
|
||||
// Multi county geometry, add each unique prefix
|
||||
for (int j = 0; j < g2.getNumGeometries(); ++j) {
|
||||
Geometry g2g = g2.getGeometryN(j);
|
||||
prefixes.add(getPrefix(toString(g2g.getUserData())));
|
||||
}
|
||||
}
|
||||
|
||||
for (String prefix : prefixes) {
|
||||
// For each prefix, remove any geometries from g1 that have the same
|
||||
// prefix
|
||||
if (prefix != null) {
|
||||
List<Geometry> toRemove = new ArrayList<Geometry>();
|
||||
for (int i = 0; i < g1.getNumGeometries(); ++i) {
|
||||
Geometry g1g = g1.getGeometryN(i);
|
||||
String g1gPrefix = getPrefix(toString(g1g.getUserData()));
|
||||
if (g1gPrefix.equals(prefix)) {
|
||||
toRemove.add(g1g);
|
||||
}
|
||||
}
|
||||
differences.removeAll(toRemove);
|
||||
}
|
||||
}
|
||||
|
||||
return gf.createGeometryCollection(differences
|
||||
.toArray(new Geometry[differences.size()]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a geometry collection from geoms
|
||||
*
|
||||
|
@ -326,15 +202,6 @@ public class GeometryUtil {
|
|||
}
|
||||
}
|
||||
|
||||
public static Geometry selfSnap(Geometry g, double snapTolerance) {
|
||||
GeometrySnapper snapper = new GeometrySnapper(g);
|
||||
Geometry snapped = snapper.snapTo(g, snapTolerance);
|
||||
// need to "clean" snapped geometry - use buffer(0) as a simple way to
|
||||
// do this
|
||||
Geometry fix = snapped.buffer(0);
|
||||
return fix;
|
||||
}
|
||||
|
||||
public static void printGeoemtry(Geometry g) {
|
||||
printGeoemtry(g, 0);
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ public class RequestConstraint implements ISerializableObject, Cloneable {
|
|||
EQUALS("="), NOT_EQUALS("!="), GREATER_THAN(">"), GREATER_THAN_EQUALS(
|
||||
">="), LESS_THAN("<"), LESS_THAN_EQUALS("<="), BETWEEN(
|
||||
"between"), IN("in"), LIKE("like"), ILIKE("ilike"), ISNULL(
|
||||
"isnull");
|
||||
"isnull"), ISNOTNULL("isnotnull");
|
||||
|
||||
private String operand;
|
||||
|
||||
|
@ -263,6 +263,8 @@ public class RequestConstraint implements ISerializableObject, Cloneable {
|
|||
|
||||
if (constraintType == ConstraintType.ISNULL) {
|
||||
return value == null || "null".equals(value);
|
||||
} else if (constraintType == ConstraintType.ISNOTNULL) {
|
||||
return value != null && "null".equals(value) == false;
|
||||
}
|
||||
|
||||
if (value == null) {
|
||||
|
|
|
@ -122,6 +122,10 @@ public class DbQueryHandler implements IRequestHandler<DbQueryRequest> {
|
|||
op = QueryOperand.ISNULL;
|
||||
break;
|
||||
}
|
||||
case ISNOTNULL: {
|
||||
op = QueryOperand.ISNOTNULL;
|
||||
break;
|
||||
}
|
||||
case LESS_THAN: {
|
||||
op = QueryOperand.LESSTHAN;
|
||||
break;
|
||||
|
|
Loading…
Add table
Reference in a new issue