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.
Change-Id: Ia120f2d20b99e4d152554727597b22af762413ac Former-commit-id:f73d55e920
[formerlybb68c95589
] [formerlyf73d55e920
[formerlybb68c95589
] [formerlyfdc5759b53
[formerly 26af6badfffd930b8051af8e33ff6897d6c87073]]] Former-commit-id:fdc5759b53
Former-commit-id:f186c355ac
[formerly014eaa1666
] Former-commit-id:e736a5d5b7
This commit is contained in:
parent
3e5e303037
commit
b085fddff2
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-Version: 1.12.1174.qualifier
|
||||||
Bundle-Activator: com.raytheon.viz.warngen.Activator
|
Bundle-Activator: com.raytheon.viz.warngen.Activator
|
||||||
Bundle-Vendor: Raytheon
|
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,
|
Require-Bundle: org.eclipse.ui,
|
||||||
org.eclipse.core.runtime,
|
org.eclipse.core.runtime,
|
||||||
com.raytheon.viz.core,
|
com.raytheon.viz.core,
|
||||||
|
@ -17,9 +17,9 @@ Require-Bundle: org.eclipse.ui,
|
||||||
org.apache.commons.lang,
|
org.apache.commons.lang,
|
||||||
org.geotools,
|
org.geotools,
|
||||||
com.raytheon.viz.awipstools,
|
com.raytheon.viz.awipstools,
|
||||||
com.raytheon.edex.common,
|
|
||||||
com.raytheon.viz.texteditor;bundle-version="1.10.13",
|
com.raytheon.viz.texteditor;bundle-version="1.10.13",
|
||||||
com.raytheon.viz.textworkstation;bundle-version="1.11.4",
|
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",
|
com.raytheon.uf.common.serialization.comm;bundle-version="1.11.17",
|
||||||
javax.jms;bundle-version="1.0.0",
|
javax.jms;bundle-version="1.0.0",
|
||||||
com.raytheon.uf.viz.core.maps;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.PathcastConfiguration;
|
||||||
import com.raytheon.uf.common.dataplugin.warning.config.PointSourceConfiguration;
|
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.dataquery.requests.RequestConstraint;
|
||||||
import com.raytheon.uf.common.geospatial.SpatialQueryResult;
|
import com.raytheon.uf.common.geospatial.SpatialQueryResult;
|
||||||
import com.raytheon.uf.viz.core.exception.VizException;
|
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.Envelope;
|
||||||
import com.vividsolutions.jts.geom.Geometry;
|
import com.vividsolutions.jts.geom.Geometry;
|
||||||
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
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
|
boolean userDirections = Boolean.valueOf(String.valueOf(attributes
|
||||||
.get(useDirectionField)));
|
.get(useDirectionField)));
|
||||||
if (userDirections) {
|
if (userDirections) {
|
||||||
PreparedGeometry prepGeom = new PreparedGeometryCollection(geom);
|
PreparedGeometry prepGeom = PreparedGeometryFactory.prepare(geom);
|
||||||
if (prepGeom.intersects(searchArea) && !prepGeom.within(searchArea)) {
|
if (prepGeom.intersects(searchArea) && !prepGeom.within(searchArea)) {
|
||||||
Geometry intersection = searchArea.intersection(geom);
|
Geometry intersection = searchArea.intersection(geom);
|
||||||
partOfArea = GisUtil.asStringList(calculateLocationPortion(
|
partOfArea = GisUtil.asStringList(calculateLocationPortion(
|
||||||
|
|
|
@ -286,27 +286,13 @@ public class Area {
|
||||||
|
|
||||||
for (AreaSourceConfiguration asc : config.getAreaSources()) {
|
for (AreaSourceConfiguration asc : config.getAreaSources()) {
|
||||||
if (asc.getType() == AreaType.INTERSECT) {
|
if (asc.getType() == AreaType.INTERSECT) {
|
||||||
String areaSource = asc.getAreaSource();
|
|
||||||
String key = areaSource + "." + localizedSite;
|
|
||||||
|
|
||||||
List<Geometry> geoms = new ArrayList<Geometry>();
|
List<Geometry> geoms = new ArrayList<Geometry>();
|
||||||
|
for (GeospatialData f : warngenLayer.getGeodataFeatures(
|
||||||
for (GeospatialData f : warngenLayer.getGeodataFeatures(key)) {
|
asc.getAreaSource(), localizedSite)) {
|
||||||
for (int i = 0; i < warnArea.getNumGeometries(); i++) {
|
Geometry intersect = GeometryUtil.intersection(warnArea,
|
||||||
Geometry geom = warnArea.getGeometryN(i);
|
f.prepGeom);
|
||||||
if (GeometryUtil.intersects(f.geometry, geom)) {
|
if (intersect.isEmpty() == false) {
|
||||||
Geometry intersect = f.geometry.intersection(geom);
|
geoms.add(intersect);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,6 @@ import org.geotools.referencing.operation.DefaultMathTransformFactory;
|
||||||
import org.opengis.metadata.spatial.PixelOrientation;
|
import org.opengis.metadata.spatial.PixelOrientation;
|
||||||
import org.opengis.referencing.operation.MathTransform;
|
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.common.dataplugin.warning.util.GeometryUtil;
|
||||||
import com.raytheon.uf.viz.core.IExtent;
|
import com.raytheon.uf.viz.core.IExtent;
|
||||||
import com.raytheon.uf.viz.core.exception.VizException;
|
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.LineSegment;
|
||||||
import com.vividsolutions.jts.geom.Polygon;
|
import com.vividsolutions.jts.geom.Polygon;
|
||||||
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
||||||
|
import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility for polygon operations
|
* Utility for polygon operations
|
||||||
|
@ -850,7 +850,7 @@ public class PolygonUtil {
|
||||||
List<PreparedGeometry> prepped = new ArrayList<PreparedGeometry>(
|
List<PreparedGeometry> prepped = new ArrayList<PreparedGeometry>(
|
||||||
geomList.size());
|
geomList.size());
|
||||||
for (Geometry g : geomList) {
|
for (Geometry g : geomList) {
|
||||||
prepped.add(new PreparedGeometryCollection(g));
|
prepped.add(PreparedGeometryFactory.prepare(g));
|
||||||
}
|
}
|
||||||
|
|
||||||
GeometryFactory gf = warningArea.getFactory();
|
GeometryFactory gf = warningArea.getFactory();
|
||||||
|
|
|
@ -322,7 +322,7 @@ public class Wx {
|
||||||
|
|
||||||
if (pathcastConfiguration.isWithinPolygon()) {
|
if (pathcastConfiguration.isWithinPolygon()) {
|
||||||
// Means that all points returned must be within the polygon
|
// Means that all points returned must be within the polygon
|
||||||
bufferedPathCastArea = warningPolygon;
|
bufferedPathCastArea = warningPolygon.intersection(geom);
|
||||||
} else {
|
} else {
|
||||||
bufferedPathCastArea = geom;
|
bufferedPathCastArea = geom;
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,7 +128,7 @@ import com.vividsolutions.jts.geom.Polygon;
|
||||||
* Nov 02, 2012 DR 15455 Qinglu Lin Added warngenLayer.setWarningAction() in resetPressed()
|
* Nov 02, 2012 DR 15455 Qinglu Lin Added warngenLayer.setWarningAction() in resetPressed()
|
||||||
* and in updateListSelected().
|
* and in updateListSelected().
|
||||||
* Dec 20, 2012 DR 15537 Qinglu Lin Changed the assigned value to trackEditable from false
|
* 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().
|
* Jan 24, 2013 DR 15723 Qinglu Lin Invoked WarngenLayer's initRemovedGids().
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
|
@ -147,6 +147,17 @@ public class WarngenDialog extends CaveSWTDialog implements
|
||||||
|
|
||||||
private static final int FONT_HEIGHT = 9;
|
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 String result;
|
||||||
|
|
||||||
private static String UPDATELISTTEXT = "UPDATE LIST ";
|
private static String UPDATELISTTEXT = "UPDATE LIST ";
|
||||||
|
@ -1452,7 +1463,7 @@ public class WarngenDialog extends CaveSWTDialog implements
|
||||||
.equalsIgnoreCase(lastAreaSource);
|
.equalsIgnoreCase(lastAreaSource);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
warngenLayer.updateWarnedAreas(snapHatchedAreaToPolygon, true);
|
warngenLayer.updateWarnedAreas(snapHatchedAreaToPolygon);
|
||||||
} catch (VizException e1) {
|
} catch (VizException e1) {
|
||||||
statusHandler.handle(Priority.PROBLEM, "WarnGen Error", 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.GeospatialData;
|
||||||
import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialFactory;
|
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.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.CountyUserData;
|
||||||
import com.raytheon.uf.common.dataplugin.warning.util.GeometryUtil;
|
import com.raytheon.uf.common.dataplugin.warning.util.GeometryUtil;
|
||||||
import com.raytheon.uf.common.geospatial.DestinationGeodeticCalculator;
|
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.Polygon;
|
||||||
import com.vividsolutions.jts.geom.TopologyException;
|
import com.vividsolutions.jts.geom.TopologyException;
|
||||||
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
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.ParseException;
|
||||||
import com.vividsolutions.jts.io.WKTReader;
|
import com.vividsolutions.jts.io.WKTReader;
|
||||||
|
|
||||||
|
@ -159,8 +159,7 @@ import com.vividsolutions.jts.io.WKTReader;
|
||||||
* Coordinate[] from futurePoints.
|
* Coordinate[] from futurePoints.
|
||||||
* 12/18/2012 DR 15571 Qinglu Lin Resolved coordinate issue in TML line caused by clicking Restart button.
|
* 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
|
* 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>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @author mschenke
|
* @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, GeospatialDataList> siteMap = new HashMap<String, GeospatialDataList>();
|
||||||
|
|
||||||
private static Map<String, Geometry> timezoneMap = new HashMap<String, Geometry>();
|
private static Map<String, Geometry> timezoneMap = new HashMap<String, Geometry>();
|
||||||
|
@ -283,6 +367,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
|
|
||||||
private CustomMaps customMaps;
|
private CustomMaps customMaps;
|
||||||
|
|
||||||
|
private AreaHatcher areaHatcher;
|
||||||
|
|
||||||
protected Mode lastMode = null;
|
protected Mode lastMode = null;
|
||||||
|
|
||||||
protected boolean redrawBoxFromTrack = false;
|
protected boolean redrawBoxFromTrack = false;
|
||||||
|
@ -802,7 +888,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
local);
|
local);
|
||||||
gd.attributes.put(
|
gd.attributes.put(
|
||||||
GeospatialDataList.LOCAL_PREP_GEOM,
|
GeospatialDataList.LOCAL_PREP_GEOM,
|
||||||
new PreparedGeometryCollection(local));
|
PreparedGeometryFactory.prepare(local));
|
||||||
locals.add(local);
|
locals.add(local);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -880,6 +966,15 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
|
|
||||||
String areaSource = config.getGeospatialConfig().getAreaSource();
|
String areaSource = config.getGeospatialConfig().getAreaSource();
|
||||||
geoData = siteMap.get(areaSource + "." + site);
|
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
|
}// end synchronize
|
||||||
customMaps.loadCustomMaps(Arrays.asList(config.getMaps()));
|
customMaps.loadCustomMaps(Arrays.asList(config.getMaps()));
|
||||||
|
|
||||||
|
@ -888,15 +983,23 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
+ (System.currentTimeMillis() - t0) + "ms");
|
+ (System.currentTimeMillis() - t0) + "ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
public GeospatialData[] getGeodataFeatures(String key) {
|
public GeospatialData[] getGeodataFeatures(String areaSource,
|
||||||
GeospatialDataList geoDataList = siteMap.get(key);
|
String localizedSite) {
|
||||||
|
GeospatialDataList geoDataList = getGeodataList(areaSource,
|
||||||
|
localizedSite);
|
||||||
if (geoDataList != null) {
|
if (geoDataList != null) {
|
||||||
return geoDataList.features;
|
return Arrays.copyOf(geoDataList.features,
|
||||||
|
geoDataList.features.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new GeospatialData[0];
|
return new GeospatialData[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private GeospatialDataList getGeodataList(String areaSource,
|
||||||
|
String localizedSite) {
|
||||||
|
String key = areaSource + "." + localizedSite;
|
||||||
|
return siteMap.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
public Geometry getTimezoneGeom(String oneLetterTimezone) {
|
public Geometry getTimezoneGeom(String oneLetterTimezone) {
|
||||||
return timezoneMap.get(oneLetterTimezone);
|
return timezoneMap.get(oneLetterTimezone);
|
||||||
}
|
}
|
||||||
|
@ -1152,35 +1255,40 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
* @param snapHatchedAreaToPolygon
|
* @param snapHatchedAreaToPolygon
|
||||||
* If True, any hatched area outside the polygon will be
|
* If True, any hatched area outside the polygon will be
|
||||||
* eliminated.
|
* 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
|
* @throws VizException
|
||||||
*/
|
*/
|
||||||
public void updateWarnedAreas(boolean snapHatchedAreaToPolygon,
|
public void updateWarnedAreas(boolean snapHatchedAreaToPolygon)
|
||||||
boolean determineInclusion) throws VizException {
|
throws VizException {
|
||||||
if (getPolygon() == null) {
|
if (getPolygon() == null) {
|
||||||
return;
|
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();
|
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;
|
Geometry newHatchedArea = null;
|
||||||
boolean insideCWA = false;
|
|
||||||
// Loop through each of our counties returned from the query
|
// Loop through each of our counties returned from the query
|
||||||
for (GeospatialData f : geoData.features) {
|
for (GeospatialData f : geoData.features) {
|
||||||
// get the geometry of the county and make sure it intersects with
|
// get the geometry of the county and make sure it intersects
|
||||||
// our hatched area
|
// with our hatched area
|
||||||
PreparedGeometry prepGeom = (PreparedGeometry) f.attributes
|
PreparedGeometry prepGeom = (PreparedGeometry) f.attributes
|
||||||
.get(GeospatialDataList.LOCAL_PREP_GEOM);
|
.get(GeospatialDataList.LOCAL_PREP_GEOM);
|
||||||
Geometry geom = (Geometry) f.attributes
|
Geometry geom = (Geometry) f.attributes
|
||||||
|
@ -1192,7 +1300,6 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
if (intersection.isEmpty()) {
|
if (intersection.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
insideCWA = true;
|
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
continue;
|
continue;
|
||||||
// This is a workaround for JTS 1.7.1
|
// This is a workaround for JTS 1.7.1
|
||||||
|
@ -1206,9 +1313,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
.convert(areaOfGeom * ratio);
|
.convert(areaOfGeom * ratio);
|
||||||
|
|
||||||
boolean includeArea = false;
|
boolean includeArea = false;
|
||||||
if (!determineInclusion) {
|
if (getConfiguration().getHatchedAreaSource()
|
||||||
includeArea = areaInKmSqOfIntersection > 1;
|
|
||||||
} else if (getConfiguration().getHatchedAreaSource()
|
|
||||||
.getInclusionAndOr().equalsIgnoreCase("AND")) {
|
.getInclusionAndOr().equalsIgnoreCase("AND")) {
|
||||||
if ((ratioInPercent >= getConfiguration()
|
if ((ratioInPercent >= getConfiguration()
|
||||||
.getHatchedAreaSource().getInclusionPercent())
|
.getHatchedAreaSource().getInclusionPercent())
|
||||||
|
@ -1224,6 +1329,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
includeArea = true;
|
includeArea = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (includeArea
|
if (includeArea
|
||||||
&& (oldWarningPolygon == null || prepGeom
|
&& (oldWarningPolygon == null || prepGeom
|
||||||
.intersects(oldWarningPolygon))) {
|
.intersects(oldWarningPolygon))) {
|
||||||
|
@ -1234,6 +1340,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
intersection);
|
intersection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (TopologyException e) {
|
} catch (TopologyException e) {
|
||||||
statusHandler.handle(Priority.VERBOSE,
|
statusHandler.handle(Priority.VERBOSE,
|
||||||
"Geometry error simplifying hatched area.", e);
|
"Geometry error simplifying hatched area.", e);
|
||||||
|
@ -1242,113 +1349,125 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
"Inclusion Area not properly configured.", e);
|
"Inclusion Area not properly configured.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// All area has been removed from the polygon...
|
|
||||||
if (insideCWA == false) {
|
return newHatchedArea != null ? newHatchedArea : new GeometryFactory()
|
||||||
state.strings.clear();
|
.createGeometryCollection(new Geometry[0]);
|
||||||
state.setWarningArea(null);
|
}
|
||||||
state.geometryChanged = true;
|
|
||||||
dialog.getDisplay().asyncExec(new Runnable() {
|
private void updateWarnedAreaState(Geometry newHatchedArea,
|
||||||
public void run() {
|
boolean snapToHatchedArea) throws VizException {
|
||||||
dialog.setInstructions();
|
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) {
|
if (oldWarningArea != null) {
|
||||||
int areaPercent = Double
|
int areaPercent = Double.valueOf(
|
||||||
.valueOf(
|
((oldWarningPolygon.intersection(warningPolygon)
|
||||||
((oldWarningPolygon.intersection(warningPolygon)
|
.getArea() / oldWarningArea.getArea()) * 100))
|
||||||
.getArea() / oldWarningArea.getArea()) * 100))
|
.intValue();
|
||||||
.intValue();
|
if (oldWarningPolygon.intersects(warningPolygon) == false
|
||||||
if (GeometryUtil.intersects(oldWarningPolygon, warningPolygon) == false
|
&& !state.isMarked()) {
|
||||||
&& !state.isMarked()) {
|
// Snap back to polygon
|
||||||
// Snap back to polygon
|
state.setWarningPolygon(localToLatLon((Polygon) oldWarningPolygon));
|
||||||
state.setWarningPolygon(localToLatLon((Polygon) oldWarningPolygon));
|
newHatchedArea = (Geometry) oldWarningArea.clone();
|
||||||
newHatchedArea = (Geometry) oldWarningArea.clone();
|
} else if (areaPercent < 10 && state.isMarked()) {
|
||||||
} else if (areaPercent < 10 && state.isMarked()) {
|
// snap back to last valid user selected area
|
||||||
// snap back to last valid user selected area
|
state.setWarningPolygon((Polygon) state
|
||||||
state.setWarningPolygon((Polygon) state
|
.getMarkedWarningPolygon().clone());
|
||||||
.getMarkedWarningPolygon().clone());
|
newHatchedArea = latLonToLocal((Geometry) state
|
||||||
newHatchedArea = latLonToLocal((Geometry) state
|
.getMarkedWarningArea());
|
||||||
.getMarkedWarningArea().clone());
|
state.resetMarked();
|
||||||
state.resetMarked();
|
} else if (warningPolygon != null) {
|
||||||
} else if (warningPolygon != null) {
|
// want intersection of warningPolygon and oldWarningArea
|
||||||
// want intersection of warningPolygon and oldWarningArea
|
newHatchedArea = GeometryUtil.intersection(warningPolygon,
|
||||||
Geometry intersection = null;
|
oldWarningArea);
|
||||||
for (int n = 0; n < oldWarningArea.getNumGeometries(); ++n) {
|
if (removedGids.size() > 0) {
|
||||||
Geometry oldArea = oldWarningArea.getGeometryN(n);
|
// Remove areas with gid in removedGids
|
||||||
Geometry geom = GeometryUtil.intersection(warningPolygon,
|
List<Geometry> areas = new ArrayList<Geometry>(
|
||||||
oldArea);
|
newHatchedArea.getNumGeometries());
|
||||||
String[] gids = GeometryUtil.getGID(geom);
|
for (int n = 0; n < newHatchedArea.getNumGeometries(); ++n) {
|
||||||
boolean flag = false;
|
Geometry newArea = newHatchedArea.getGeometryN(n);
|
||||||
for (String gid: gids) {
|
String[] gids = GeometryUtil.getGID(newArea);
|
||||||
if (removedGids.contains(gid)) {
|
boolean flag = false;
|
||||||
flag = true;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!flag) {
|
if (initialWarning)
|
||||||
if (geom.isEmpty() == false) {
|
state.clear2(); // not to hatch polygon for initial warning
|
||||||
if (intersection == null) {
|
else {
|
||||||
intersection = geom;
|
// Snap back for follow-ups
|
||||||
} else {
|
state.setWarningPolygon((Polygon) state
|
||||||
intersection = GeometryUtil.union(intersection,
|
.getMarkedWarningPolygon().clone());
|
||||||
geom);
|
state.resetMarked();
|
||||||
}
|
updateWarnedAreas(snapToHatchedArea);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
newHatchedArea = intersection;
|
} else {
|
||||||
}
|
state.setWarningArea(localToLatLon(newHatchedArea));
|
||||||
}
|
state.mark(newHatchedArea);
|
||||||
System.out.println("determining hatchedArea took "
|
// add "W" strings
|
||||||
+ (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) {
|
|
||||||
populateStrings();
|
populateStrings();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Apply new hatched area
|
// Apply new hatched area
|
||||||
state.geometryChanged = true;
|
state.geometryChanged = true;
|
||||||
issueRefresh();
|
issueRefresh();
|
||||||
|
|
||||||
VizApp.runAsync(new Runnable() {
|
VizApp.runAsync(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
if (dialog != null) {
|
if (dialog != null) {
|
||||||
dialog.setInstructions();
|
dialog.setInstructions();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
} finally {
|
||||||
|
warningAreaChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1400,7 +1519,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
LinearRing lr = gf.createLinearRing(c);
|
LinearRing lr = gf.createLinearRing(c);
|
||||||
state.setWarningPolygon(gf.createPolygon(lr, null));
|
state.setWarningPolygon(gf.createPolygon(lr, null));
|
||||||
|
|
||||||
updateWarnedAreas(true, true);
|
updateWarnedAreas(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void redrawBoxFromTrack() throws VizException {
|
public void redrawBoxFromTrack() throws VizException {
|
||||||
|
@ -1559,7 +1678,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
LinearRing lr = gf.createLinearRing(c);
|
LinearRing lr = gf.createLinearRing(c);
|
||||||
state.setWarningPolygon(gf.createPolygon(lr, null));
|
state.setWarningPolygon(gf.createPolygon(lr, null));
|
||||||
|
|
||||||
updateWarnedAreas(true, true);
|
updateWarnedAreas(true);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOT LINE OF STORMS
|
* NOT LINE OF STORMS
|
||||||
|
@ -1604,7 +1723,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
LinearRing lr = gf.createLinearRing(c);
|
LinearRing lr = gf.createLinearRing(c);
|
||||||
state.setWarningPolygon(gf.createPolygon(lr, null));
|
state.setWarningPolygon(gf.createPolygon(lr, null));
|
||||||
|
|
||||||
updateWarnedAreas(true, true);
|
updateWarnedAreas(true);
|
||||||
}
|
}
|
||||||
if (dialog.box.getSelection()) {
|
if (dialog.box.getSelection()) {
|
||||||
displayState.editable = false;
|
displayState.editable = false;
|
||||||
|
@ -1624,20 +1743,17 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
long t0 = System.currentTimeMillis();
|
long t0 = System.currentTimeMillis();
|
||||||
state.removeDuplicateCoordinate();
|
Polygon hatched = state.getWarningPolygon();
|
||||||
Polygon hatched = new PolygonUtil(this, geoData.nx, geoData.ny,
|
Geometry hatchedArea = state.getWarningArea();
|
||||||
20, geoData.localExtent, geoData.localToLatLon)
|
if (areaHatcher != null) {
|
||||||
.hatchWarningArea(state.getWarningPolygon(),
|
Geometry[] areas = areaHatcher.getHatchedAreas();
|
||||||
state.getWarningArea());
|
hatched = (Polygon) areas[0];
|
||||||
|
hatchedArea = areas[1];
|
||||||
|
}
|
||||||
|
|
||||||
if (hatched != null) {
|
if (hatched != null) {
|
||||||
// DR 15559
|
state.setWarningPolygon(hatched);
|
||||||
Coordinate[] coords = hatched.getCoordinates();
|
updateWarnedAreaState(hatchedArea, true);
|
||||||
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);
|
|
||||||
issueRefresh();
|
issueRefresh();
|
||||||
// End of DR 15559
|
// End of DR 15559
|
||||||
state.snappedToArea = true;
|
state.snappedToArea = true;
|
||||||
|
@ -1660,7 +1776,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
try {
|
try {
|
||||||
state.setWarningPolygon(gf.createPolygon(lr, null));
|
state.setWarningPolygon(gf.createPolygon(lr, null));
|
||||||
state.rightClickSelected = false;
|
state.rightClickSelected = false;
|
||||||
updateWarnedAreas(true, true);
|
updateWarnedAreas(true);
|
||||||
displayState.dragMeGeom = gf.createPoint(pt);
|
displayState.dragMeGeom = gf.createPoint(pt);
|
||||||
displayState.dragMePoint = gf.createPoint(pt);
|
displayState.dragMePoint = gf.createPoint(pt);
|
||||||
displayState.mode = Mode.TRACK;
|
displayState.mode = Mode.TRACK;
|
||||||
|
@ -1771,7 +1887,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
state.setWarningPolygon(warnPolygon);
|
state.setWarningPolygon(warnPolygon);
|
||||||
state.setWarningArea(getWarningAreaFromPolygon(
|
state.setWarningArea(getWarningAreaFromPolygon(
|
||||||
state.getWarningPolygon(), record));
|
state.getWarningPolygon(), record));
|
||||||
updateWarnedAreas(true, true);
|
updateWarnedAreas(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataTime recordFrameTime(AbstractWarningRecord warnRecord) {
|
private DataTime recordFrameTime(AbstractWarningRecord warnRecord) {
|
||||||
|
@ -2142,39 +2258,44 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
String[] gids = GeometryUtil.getGID(geom);
|
String[] gids = GeometryUtil.getGID(geom);
|
||||||
if (GeometryUtil.contains(state.getWarningArea(), point)) {
|
if (GeometryUtil.contains(state.getWarningArea(), point)) {
|
||||||
// remove county
|
// remove county
|
||||||
Geometry tmp = GeometryUtil.difference(
|
Geometry tmp = removeCounty(state.getWarningArea(),
|
||||||
state.getWarningArea(), geom);
|
getFips(f));
|
||||||
if (tmp.isEmpty()) {
|
if (tmp.isEmpty()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.setWarningArea(tmp);
|
state.setWarningArea(tmp);
|
||||||
for (String gid: gids) {
|
for (String gid : gids) {
|
||||||
removedGids.add(gid);
|
removedGids.add(gid);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
String featureFips = getFips(f);
|
||||||
|
Collection<GeospatialData> dataWithFips = getDataWithFips(featureFips);
|
||||||
if (oldWarningArea != null) {
|
if (oldWarningArea != null) {
|
||||||
// for a CON, prevents extra areas to be added
|
// for a CON, prevents extra areas to be added
|
||||||
Set<String> limit = new HashSet<String>();
|
Set<String> fipsIds = getAllFipsInArea(oldWarningArea);
|
||||||
limit.addAll(Arrays.asList(GeometryUtil
|
if (fipsIds.contains(featureFips) == false) {
|
||||||
.getGID(oldWarningArea)));
|
|
||||||
String prefix = GeometryUtil.getPrefix(geom
|
|
||||||
.getUserData());
|
|
||||||
|
|
||||||
if (limit.contains(prefix) == false) {
|
|
||||||
break;
|
break;
|
||||||
} else if (oldWarningPolygon.contains(point) == true) {
|
} else if (oldWarningPolygon.contains(point) == true) {
|
||||||
// only add in intersecting area from old
|
boolean first = true;
|
||||||
// warning
|
for (GeospatialData g : dataWithFips) {
|
||||||
geom = GeometryUtil.intersection(
|
if (first) {
|
||||||
oldWarningArea, geom);
|
geom = GeometryUtil.intersection(
|
||||||
|
g.geometry, oldWarningArea);
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
geom = GeometryUtil.intersection(
|
||||||
|
g.geometry, geom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (warningPolygon.contains(point)) {
|
if (warningPolygon.contains(point)) {
|
||||||
geom = GeometryUtil.intersection(
|
geom = GeometryUtil.intersection(geom,
|
||||||
warningPolygon, geom);
|
warningPolygon);
|
||||||
}
|
}
|
||||||
state.setWarningArea(GeometryUtil.union(
|
state.setWarningArea(GeometryUtil.union(
|
||||||
state.getWarningArea(), geom));
|
state.getWarningArea(), geom));
|
||||||
for (String gid: gids) {
|
for (String gid : gids) {
|
||||||
removedGids.remove(gid);
|
removedGids.remove(gid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2182,14 +2303,21 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
// add county
|
// add county
|
||||||
if (warningPolygon.contains(point)) {
|
if (warningPolygon.contains(point)) {
|
||||||
// add part of county
|
// add part of county
|
||||||
geom = GeometryUtil.intersection(
|
List<Geometry> parts = new ArrayList<Geometry>(
|
||||||
warningPolygon, geom);
|
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.setWarningArea(GeometryUtil.union(
|
||||||
state.getWarningArea(), geom));
|
state.getWarningArea(), geom));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.snappedToArea = false;
|
warningAreaChanged();
|
||||||
populateStrings();
|
populateStrings();
|
||||||
issueRefresh();
|
issueRefresh();
|
||||||
break;
|
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
|
* Populate the W strings with the included counties
|
||||||
*/
|
*/
|
||||||
|
@ -2395,6 +2570,6 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initRemovedGids() {
|
public void initRemovedGids() {
|
||||||
removedGids.clear();
|
removedGids.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -257,7 +257,7 @@ public class WarngenUIManager extends InputAdapter {
|
||||||
LinearRing lr = gf.createLinearRing(coordinates);
|
LinearRing lr = gf.createLinearRing(coordinates);
|
||||||
state.setWarningPolygon(gf.createPolygon(lr, null));
|
state.setWarningPolygon(gf.createPolygon(lr, null));
|
||||||
}
|
}
|
||||||
warngenLayer.updateWarnedAreas(true, true);
|
warngenLayer.updateWarnedAreas(true);
|
||||||
} catch (VizException e) {
|
} catch (VizException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -450,7 +450,7 @@ public class WarngenUIManager extends InputAdapter {
|
||||||
|
|
||||||
warngenLayer.getWarngenState().setWarningPolygon(newPoly);
|
warngenLayer.getWarngenState().setWarningPolygon(newPoly);
|
||||||
try {
|
try {
|
||||||
warngenLayer.updateWarnedAreas(true, true);
|
warngenLayer.updateWarnedAreas(true);
|
||||||
} catch (VizException e) {
|
} catch (VizException e) {
|
||||||
Status s = new Status(Status.ERROR, Activator.PLUGIN_ID,
|
Status s = new Status(Status.ERROR, Activator.PLUGIN_ID,
|
||||||
"Error updating warned area", e);
|
"Error updating warned area", e);
|
||||||
|
@ -592,7 +592,7 @@ public class WarngenUIManager extends InputAdapter {
|
||||||
Polygon newPoly = gf.createPolygon(newLs, null);
|
Polygon newPoly = gf.createPolygon(newLs, null);
|
||||||
warngenLayer.getWarngenState().setWarningPolygon(newPoly);
|
warngenLayer.getWarngenState().setWarningPolygon(newPoly);
|
||||||
try {
|
try {
|
||||||
warngenLayer.updateWarnedAreas(true, true);
|
warngenLayer.updateWarnedAreas(true);
|
||||||
} catch (VizException e) {
|
} catch (VizException e) {
|
||||||
Status s = new Status(Status.ERROR,
|
Status s = new Status(Status.ERROR,
|
||||||
Activator.PLUGIN_ID,
|
Activator.PLUGIN_ID,
|
||||||
|
|
|
@ -123,173 +123,173 @@ public class WarngenUIState {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* removeDuplicateCoordinate
|
* removeDuplicateCoordinate remove duplicate intermediate coordinates in
|
||||||
* remove duplicate intermediate coordinates in warningPolygon.
|
* warningPolygon. History 10-26-2012 Qinglu Lin DR15479 Created.
|
||||||
* History
|
|
||||||
* 10-26-2012 Qinglu Lin DR15479 Created.
|
|
||||||
*/
|
*/
|
||||||
public void removeDuplicateCoordinate() {
|
private static Polygon removeDuplicateCoordinate(Polygon polygon) {
|
||||||
Coordinate[] verts = warningPolygon.getCoordinates();
|
Coordinate[] verts = polygon.getCoordinates();
|
||||||
Set<Coordinate> coords = new LinkedHashSet<Coordinate>();
|
Set<Coordinate> coords = new LinkedHashSet<Coordinate>();
|
||||||
for (Coordinate c: verts)
|
for (Coordinate c : verts)
|
||||||
coords.add(c);
|
coords.add(c);
|
||||||
if ((verts.length-coords.size()) < 2)
|
if ((verts.length - coords.size()) < 2)
|
||||||
return;
|
return polygon;
|
||||||
Coordinate[] vertices = new Coordinate[coords.size()+1];
|
Coordinate[] vertices = new Coordinate[coords.size() + 1];
|
||||||
Iterator<Coordinate> iter = coords.iterator();
|
Iterator<Coordinate> iter = coords.iterator();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
vertices[i] = new Coordinate(iter.next());
|
vertices[i] = new Coordinate(iter.next());
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
vertices[i] = new Coordinate(vertices[0]);
|
vertices[i] = new Coordinate(vertices[0]);
|
||||||
GeometryFactory gf = new GeometryFactory();
|
GeometryFactory gf = new GeometryFactory();
|
||||||
warningPolygon = gf.createPolygon(gf.createLinearRing(vertices), null);
|
return 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];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* adjustPolygon
|
* computeSlope compute the slope of a line.
|
||||||
* 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
|
* History 12/06/2012 DR 15559 Qinglu Lin Created.
|
||||||
* the line, and return a Polygon.
|
|
||||||
*
|
|
||||||
* History
|
|
||||||
* 12/06/2012 DR 15559 Qinglu Lin Created.
|
|
||||||
*/
|
*/
|
||||||
public void adjustPolygon(Coordinate[] coords) {
|
private static double computeSlope(Coordinate[] coords, int i) {
|
||||||
int n = coords.length;
|
double min = 1.0E-08;
|
||||||
for (int i=0; i<n-1; ++i) {
|
double dx = coords[i].x - coords[i + 1].x;
|
||||||
int j;
|
double slope = 0.0;
|
||||||
for (j=i+2; j<=n-2; j++) {
|
if (Math.abs(dx) > min) {
|
||||||
computeCoordinate(coords,i,j);
|
slope = (coords[i].y - coords[i + 1].y) / dx;
|
||||||
}
|
}
|
||||||
if (i<=n-3)
|
return slope;
|
||||||
for (j=0; j<i; j++) {
|
}
|
||||||
computeCoordinate(coords,i,j);
|
|
||||||
}
|
/**
|
||||||
else
|
* computeCoordinate Compute the x component of a coordinate after its y
|
||||||
for (j=1; j<i; j++) {
|
* component is adjusted.
|
||||||
computeCoordinate(coords,i,j);
|
*
|
||||||
}
|
* 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
|
* the warningPolygon to set
|
||||||
*/
|
*/
|
||||||
public void setWarningPolygon(Polygon warningPolygon) {
|
public void setWarningPolygon(Polygon warningPolygon) {
|
||||||
this.warningPolygon = warningPolygon;
|
this.warningPolygon = removeDuplicateCoordinate(warningPolygon);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
|
@ -327,13 +327,11 @@ public class WarngenUIState {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clear2
|
* clear2 Same as clear(), except for not assigning null to warningPolygon.
|
||||||
* Same as clear(), except for not assigning null to warningPolygon.
|
* History 03-16-2012 Qinglu Lin DR14690 Created.
|
||||||
* History
|
|
||||||
* 03-16-2012 Qinglu Lin DR14690 Created.
|
|
||||||
*/
|
*/
|
||||||
public void clear2() {
|
public void clear2() {
|
||||||
oldWarningArea = null;
|
oldWarningArea = null;
|
||||||
oldWarningPolygon = null;
|
oldWarningPolygon = null;
|
||||||
oldWarningArea = null;
|
oldWarningArea = null;
|
||||||
oldWarningPolygon = null;
|
oldWarningPolygon = null;
|
||||||
|
|
|
@ -63,6 +63,8 @@ public class LocalizationResourceLoader extends FileResourceLoader implements
|
||||||
|
|
||||||
private Map<String, LocalizationFile> fileMap = new HashMap<String, LocalizationFile>();
|
private Map<String, LocalizationFile> fileMap = new HashMap<String, LocalizationFile>();
|
||||||
|
|
||||||
|
private ExtendedProperties configuration;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getLastModified(Resource resource) {
|
public long getLastModified(Resource resource) {
|
||||||
return getFile(resource.getName()).getTimeStamp().getTime();
|
return getFile(resource.getName()).getTimeStamp().getTime();
|
||||||
|
@ -70,12 +72,9 @@ public class LocalizationResourceLoader extends FileResourceLoader implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(ExtendedProperties configuration) {
|
public void init(ExtendedProperties configuration) {
|
||||||
String site = configuration.getString(SITE_KEY);
|
if (this.configuration != configuration) {
|
||||||
if (site != null && (site.equals(this.site) == false)) {
|
this.configuration = configuration;
|
||||||
// We changed sites since last time, clear out cache
|
|
||||||
fileMap.clear();
|
|
||||||
}
|
}
|
||||||
this.site = site;
|
|
||||||
super.init(configuration);
|
super.init(configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,18 +88,34 @@ public class LocalizationResourceLoader extends FileResourceLoader implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized LocalizationFile getFile(String name) {
|
private synchronized LocalizationFile getFile(String name)
|
||||||
LocalizationFile file = fileMap.get(name);
|
throws ResourceNotFoundException {
|
||||||
if (file == null || file.exists() == false) {
|
if (configuration == null) {
|
||||||
try {
|
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 = FileUtil.getLocalizationFile(name, site);
|
||||||
file.addFileUpdatedObserver(this);
|
file.addFileUpdatedObserver(this);
|
||||||
} catch (FileNotFoundException e) {
|
fileMap.put(name, file);
|
||||||
throw new RuntimeException("Error retrieving resource file", e);
|
|
||||||
}
|
}
|
||||||
fileMap.put(name, file);
|
return file;
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
throw new ResourceNotFoundException(e);
|
||||||
}
|
}
|
||||||
return file;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -110,16 +125,12 @@ public class LocalizationResourceLoader extends FileResourceLoader implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean resourceExists(String name) {
|
public boolean resourceExists(String name) {
|
||||||
LocalizationFile file = fileMap.get(name);
|
LocalizationFile file;
|
||||||
if (file == null || file.exists() == false) {
|
try {
|
||||||
try {
|
file = getFile(name);
|
||||||
file = FileUtil.getLocalizationFile(name, site);
|
return file.exists();
|
||||||
file.addFileUpdatedObserver(this);
|
} catch (ResourceNotFoundException e) {
|
||||||
} catch (FileNotFoundException e) {
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
fileMap.put(name, file);
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,10 +52,9 @@ import org.apache.velocity.app.Velocity;
|
||||||
import org.apache.velocity.app.VelocityEngine;
|
import org.apache.velocity.app.VelocityEngine;
|
||||||
import org.apache.velocity.tools.generic.ListTool;
|
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.ActiveTableRecord;
|
||||||
import com.raytheon.uf.common.activetable.GetActiveTableRequest;
|
import com.raytheon.uf.common.activetable.OperationalActiveTableRecord;
|
||||||
import com.raytheon.uf.common.activetable.GetActiveTableResponse;
|
import com.raytheon.uf.common.activetable.PracticeActiveTableRecord;
|
||||||
import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord;
|
import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord;
|
||||||
import com.raytheon.uf.common.dataplugin.warning.WarningRecord.WarningAction;
|
import com.raytheon.uf.common.dataplugin.warning.WarningRecord.WarningAction;
|
||||||
import com.raytheon.uf.common.dataplugin.warning.config.AreaSourceConfiguration;
|
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.config.WarngenConfiguration;
|
||||||
import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialData;
|
import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialData;
|
||||||
import com.raytheon.uf.common.dataplugin.warning.util.GeometryUtil;
|
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.site.SiteMap;
|
||||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||||
import com.raytheon.uf.common.status.UFStatus;
|
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.DataTime;
|
||||||
import com.raytheon.uf.common.time.SimulatedTime;
|
import com.raytheon.uf.common.time.SimulatedTime;
|
||||||
import com.raytheon.uf.common.util.FileUtil;
|
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.exception.VizException;
|
||||||
import com.raytheon.uf.viz.core.localization.LocalizationManager;
|
import com.raytheon.uf.viz.core.localization.LocalizationManager;
|
||||||
import com.raytheon.uf.viz.core.requests.ThriftClient;
|
import com.raytheon.uf.viz.core.requests.ThriftClient;
|
||||||
|
@ -132,8 +134,8 @@ import com.vividsolutions.jts.io.WKTReader;
|
||||||
* in oldWarn.
|
* in oldWarn.
|
||||||
* Dec 17, 2012 15571 Qinglu Lin For hydro products, resolved issue caused by calling wkt.read(loc)
|
* Dec 17, 2012 15571 Qinglu Lin For hydro products, resolved issue caused by calling wkt.read(loc)
|
||||||
* while loc is null.
|
* 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>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @author njensen
|
* @author njensen
|
||||||
|
@ -397,9 +399,9 @@ public class TemplateRunner {
|
||||||
|
|
||||||
context.put("event", eventTime);
|
context.put("event", eventTime);
|
||||||
if (selectedAction == WarningAction.COR)
|
if (selectedAction == WarningAction.COR)
|
||||||
context.put("TMLtime", eventTime);
|
context.put("TMLtime", eventTime);
|
||||||
else
|
else
|
||||||
context.put("TMLtime", simulatedTime);
|
context.put("TMLtime", simulatedTime);
|
||||||
context.put("ugcline",
|
context.put("ugcline",
|
||||||
FipsUtil.getUgcLine(areas, wx.getEndTime(), 15));
|
FipsUtil.getUgcLine(areas, wx.getEndTime(), 15));
|
||||||
context.put("areaPoly", GisUtil.convertCoords(warngenLayer
|
context.put("areaPoly", GisUtil.convertCoords(warngenLayer
|
||||||
|
@ -446,15 +448,16 @@ public class TemplateRunner {
|
||||||
// Convert to Point2D representation as Velocity requires
|
// Convert to Point2D representation as Velocity requires
|
||||||
// getX() and getY() methods which Coordinate does not have
|
// getX() and getY() methods which Coordinate does not have
|
||||||
if (selectedAction == WarningAction.COR) {
|
if (selectedAction == WarningAction.COR) {
|
||||||
AbstractWarningRecord oldWarn = CurrentWarnings.getInstance(
|
AbstractWarningRecord oldWarn = CurrentWarnings
|
||||||
threeLetterSiteId).getNewestByTracking(etn, phenSig);
|
.getInstance(threeLetterSiteId)
|
||||||
|
.getNewestByTracking(etn, phenSig);
|
||||||
String loc = oldWarn.getLoc();
|
String loc = oldWarn.getLoc();
|
||||||
if (loc != null) {
|
if (loc != null) {
|
||||||
Geometry locGeom = wkt.read(loc);
|
Geometry locGeom = wkt.read(loc);
|
||||||
stormLocs = locGeom.getCoordinates();
|
stormLocs = locGeom.getCoordinates();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
stormLocs = GisUtil.d2dCoordinates(stormLocs);
|
stormLocs = GisUtil.d2dCoordinates(stormLocs);
|
||||||
}
|
}
|
||||||
Point2D.Double[] coords = new Point2D.Double[stormLocs.length];
|
Point2D.Double[] coords = new Point2D.Double[stormLocs.length];
|
||||||
for (int i = 0; i < stormLocs.length; i++) {
|
for (int i = 0; i < stormLocs.length; i++) {
|
||||||
|
@ -494,16 +497,16 @@ public class TemplateRunner {
|
||||||
Point2D.Double[] coords;
|
Point2D.Double[] coords;
|
||||||
Coordinate[] locs;
|
Coordinate[] locs;
|
||||||
if (selectedAction == WarningAction.CAN) {
|
if (selectedAction == WarningAction.CAN) {
|
||||||
locs = warngenLayer.getStormLocations(stormTrackState);
|
locs = warngenLayer.getStormLocations(stormTrackState);
|
||||||
locs = GisUtil.d2dCoordinates(locs);
|
locs = GisUtil.d2dCoordinates(locs);
|
||||||
coords = new Point2D.Double[locs.length];
|
coords = new Point2D.Double[locs.length];
|
||||||
} else {
|
} else {
|
||||||
Geometry locGeom = wkt.read(oldWarn.getLoc());
|
Geometry locGeom = wkt.read(oldWarn.getLoc());
|
||||||
locs = locGeom.getCoordinates();
|
locs = locGeom.getCoordinates();
|
||||||
coords = new Point2D.Double[locs.length];
|
coords = new Point2D.Double[locs.length];
|
||||||
}
|
}
|
||||||
for (int i = 0; i < locs.length; i++) {
|
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);
|
context.put("eventLocation", coords);
|
||||||
double motionDirection = oldWarn.getMotdir();
|
double motionDirection = oldWarn.getMotdir();
|
||||||
|
@ -769,13 +772,14 @@ public class TemplateRunner {
|
||||||
try {
|
try {
|
||||||
t0 = System.currentTimeMillis();
|
t0 = System.currentTimeMillis();
|
||||||
WatchUtil watches = getWatches(warngenLayer, config, warnPolygon,
|
WatchUtil watches = getWatches(warngenLayer, config, warnPolygon,
|
||||||
fourLetterSiteId, simulatedTime);
|
areas, fourLetterSiteId, simulatedTime);
|
||||||
System.out.println("getWatches time: "
|
System.out.println("getWatches time: "
|
||||||
+ (System.currentTimeMillis() - t0));
|
+ (System.currentTimeMillis() - t0));
|
||||||
if (watches != null) {
|
if (watches != null) {
|
||||||
context.put("watches", watches);
|
context.put("watches", watches);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
statusHandler
|
statusHandler
|
||||||
.handle(Priority.VERBOSE,
|
.handle(Priority.VERBOSE,
|
||||||
"WarnGen cannot populate Active Watches. Check your local config.xml",
|
"WarnGen cannot populate Active Watches. Check your local config.xml",
|
||||||
|
@ -784,44 +788,60 @@ public class TemplateRunner {
|
||||||
|
|
||||||
long tz0 = System.currentTimeMillis();
|
long tz0 = System.currentTimeMillis();
|
||||||
String script = createScript(warngenLayer.getTemplateName() + ".vm",
|
String script = createScript(warngenLayer.getTemplateName() + ".vm",
|
||||||
context, warngenLayer.getLocalizedSite(),
|
context, warngenLayer.getLocalizedSite());
|
||||||
FileUtil.join(LocalizationManager.getUserDir(), "logs"));
|
|
||||||
System.out.println("velocity time: "
|
System.out.println("velocity time: "
|
||||||
+ (System.currentTimeMillis() - tz0));
|
+ (System.currentTimeMillis() - tz0));
|
||||||
|
|
||||||
String text = script.toString();
|
String text = script.toString();
|
||||||
WarningTextHandler handler = WarningTextHandlerFactory.getHandler(
|
WarningTextHandler handler = WarningTextHandlerFactory.getHandler(
|
||||||
selectedAction, text, config.getAutoLockText());
|
selectedAction, text, config.getAutoLockText());
|
||||||
String handledText = handler.handle(text, areas, cancelareas, selectedAction);
|
String handledText = handler.handle(text, areas, cancelareas,
|
||||||
|
selectedAction);
|
||||||
|
|
||||||
return handledText;
|
return handledText;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static VelocityEngine ENGINE = new VelocityEngine();
|
private static VelocityEngine ENGINE;
|
||||||
|
|
||||||
private static synchronized String createScript(String vmFile,
|
public static void initialize() {
|
||||||
VelocityContext context, String site, String logDir)
|
synchronized (TemplateRunner.class) {
|
||||||
throws EdexException {
|
if (ENGINE == null) {
|
||||||
StringWriter sw = new StringWriter();
|
ENGINE = new VelocityEngine();
|
||||||
try {
|
Properties p = new Properties();
|
||||||
Properties p = new Properties();
|
p.setProperty("file.resource.loader.class",
|
||||||
p.setProperty(LocalizationResourceLoader.SITE_KEY, site);
|
LocalizationResourceLoader.class.getName());
|
||||||
p.setProperty("file.resource.loader.class",
|
p.setProperty("runtime.log",
|
||||||
LocalizationResourceLoader.class.getName());
|
FileUtil.join(FileUtil.join(
|
||||||
p.setProperty("velocimacro.permissions.allowInline", "true");
|
LocalizationManager.getUserDir(), "logs"),
|
||||||
p.setProperty(
|
"velocity.log"));
|
||||||
"velocimacro.permissions.allow.inline.to.replace.global",
|
p.setProperty("velocimacro.permissions.allowInline", "true");
|
||||||
"true");
|
p.setProperty(
|
||||||
p.setProperty("runtime.log", FileUtil.join(logDir, "velocity.log"));
|
"velocimacro.permissions.allow.inline.to.replace.global",
|
||||||
ENGINE.init(p);
|
"true");
|
||||||
context.put("scriptLibrary", "VM_global_library.vm");
|
ENGINE.init(p);
|
||||||
Template template = ENGINE.getTemplate(vmFile,
|
}
|
||||||
Velocity.ENCODING_DEFAULT);
|
}
|
||||||
template.merge(context, sw);
|
}
|
||||||
} catch (Exception e) {
|
|
||||||
throw new EdexException("Error generating from template", e);
|
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,
|
private static WatchUtil getWatches(WarngenLayer warngenLayer,
|
||||||
WarngenConfiguration config, Geometry polygon,
|
WarngenConfiguration config, Geometry polygon,
|
||||||
String fourLetterSiteId, Date simulatedTime) throws Exception {
|
AffectedAreas[] affectedAreas, String fourLetterSiteId,
|
||||||
|
Date simulatedTime) throws Exception {
|
||||||
Validate.isTrue(config.getHatchedAreaSource()
|
Validate.isTrue(config.getHatchedAreaSource()
|
||||||
.getIncludedWatchAreaBuffer() >= 0,
|
.getIncludedWatchAreaBuffer() >= 0,
|
||||||
"IncludedWatchAreaBuffer can not be negative");
|
"IncludedWatchAreaBuffer can not be negative");
|
||||||
|
|
||||||
WatchUtil rval = null;
|
WatchUtil rval = null;
|
||||||
GetActiveTableRequest req = new GetActiveTableRequest();
|
|
||||||
String[] includedWatches = config.getIncludedWatches();
|
String[] includedWatches = config.getIncludedWatches();
|
||||||
|
|
||||||
if (includedWatches != null && includedWatches.length > 0) {
|
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)) {
|
// Get record type
|
||||||
req.setMode(ActiveTableMode.PRACTICE);
|
Class<? extends ActiveTableRecord> recordType = CAVEMode
|
||||||
} else {
|
.getMode() == CAVEMode.OPERATIONAL ? OperationalActiveTableRecord.class
|
||||||
req.setMode(ActiveTableMode.OPERATIONAL);
|
: PracticeActiveTableRecord.class;
|
||||||
}
|
|
||||||
|
|
||||||
req.setSiteID(fourLetterSiteId);
|
DbQueryRequest request = new DbQueryRequest();
|
||||||
req.setRequestValidTimes(true);
|
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();
|
// TODO: Talk to Jonathan about this... Do I even need officeid
|
||||||
GetActiveTableResponse resp = (GetActiveTableResponse) ThriftClient
|
// IN or is ugc zone good enough?
|
||||||
.sendRequest(req);
|
Set<String> ugcZones = new HashSet<String>();
|
||||||
long t1 = System.currentTimeMillis();
|
for (AffectedAreas area : affectedAreas) {
|
||||||
java.util.List<ActiveTableRecord> respList = resp.getActiveTable();
|
ugcZones.add(FipsUtil.getUgc(area));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
// 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)
|
// These are the only fields we need for processing watches
|
||||||
+ ", found "
|
request.addFields(new String[] { "issueTime", "startTime",
|
||||||
+ (activeTable != null ? activeTable.size() : "0")
|
"endTime", "ugcZone", "phensig", "vtecstr" });
|
||||||
+ " watches");
|
|
||||||
boolean val = activeTable != null && !activeTable.isEmpty();
|
|
||||||
if (val) {
|
|
||||||
// Look for ones with valid geometry
|
|
||||||
|
|
||||||
t0 = System.currentTimeMillis();
|
DbQueryResponse response = (DbQueryResponse) ThriftClient
|
||||||
Polygon watchArea = (Polygon) polygon.buffer(milesToKilometer
|
.sendRequest(request);
|
||||||
.convert(config.getHatchedAreaSource()
|
|
||||||
.getIncludedWatchAreaBuffer())
|
|
||||||
/ KmToDegrees);
|
|
||||||
t1 = System.currentTimeMillis();
|
|
||||||
System.out.println("getWatches.polygonBuffer time: "
|
|
||||||
+ (t1 - t0));
|
|
||||||
|
|
||||||
t0 = System.currentTimeMillis();
|
List<ActiveTableRecord> records = new ArrayList<ActiveTableRecord>(
|
||||||
warngenLayer.createGeometryForWatches(watchArea, activeTable);
|
response.getNumResults());
|
||||||
t1 = System.currentTimeMillis();
|
for (Map<String, Object> result : response.getResults()) {
|
||||||
System.out.println("getWatches.createWatchGeometry time: "
|
ActiveTableRecord record = recordType.newInstance();
|
||||||
+ (t1 - t0));
|
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 {
|
private static class WatchWork {
|
||||||
public WeatherAdvisoryWatch waw;
|
public WeatherAdvisoryWatch waw;
|
||||||
|
|
||||||
public boolean valid;
|
public boolean valid;
|
||||||
|
|
||||||
public ArrayList<String> ugcZone = new ArrayList<String>();
|
public ArrayList<String> ugcZone = new ArrayList<String>();
|
||||||
|
|
||||||
public WatchWork(WeatherAdvisoryWatch waw) {
|
public WatchWork(WeatherAdvisoryWatch waw) {
|
||||||
|
@ -995,8 +1037,8 @@ public class TemplateRunner {
|
||||||
"Cannot process watches: missing HATCHING area source configuration");
|
"Cannot process watches: missing HATCHING area source configuration");
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
GeospatialData[] geoData = warngenLayer.getGeodataFeatures(asc
|
GeospatialData[] geoData = warngenLayer.getGeodataFeatures(
|
||||||
.getAreaSource() + "." + warngenLayer.getLocalizedSite());
|
asc.getAreaSource(), warngenLayer.getLocalizedSite());
|
||||||
if (geoData == null || geoData.length == 0) {
|
if (geoData == null || geoData.length == 0) {
|
||||||
statusHandler.handle(Priority.ERROR,
|
statusHandler.handle(Priority.ERROR,
|
||||||
"Cannot process watches: cannot get geospatial data");
|
"Cannot process watches: cannot get geospatial data");
|
||||||
|
@ -1033,11 +1075,12 @@ public class TemplateRunner {
|
||||||
if (!ar.getGeometry().isEmpty())
|
if (!ar.getGeometry().isEmpty())
|
||||||
work.valid = true;
|
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.
|
* determineAffectedPortions to avoid redundant work.
|
||||||
*/
|
*/
|
||||||
work.ugcZone.add(ar.getUgcZone());
|
work.ugcZone.add(ar.getUgcZone());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (WatchWork work : map.values()) {
|
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
|
* 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.
|
* actually in the CWA.
|
||||||
*
|
*
|
||||||
* @param ugcs
|
* @param ugcs
|
||||||
|
@ -1068,7 +1111,7 @@ public class TemplateRunner {
|
||||||
AreaSourceConfiguration asc, GeospatialData[] geoData,
|
AreaSourceConfiguration asc, GeospatialData[] geoData,
|
||||||
WeatherAdvisoryWatch waw) {
|
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>>();
|
HashMap<String, Set<String>> map = new HashMap<String, Set<String>>();
|
||||||
|
|
||||||
for (String ugc : ugcs) {
|
for (String ugc : ugcs) {
|
||||||
|
@ -1086,15 +1129,15 @@ public class TemplateRunner {
|
||||||
String stateAbbrev = e.getKey();
|
String stateAbbrev = e.getKey();
|
||||||
String feArea = null;
|
String feArea = null;
|
||||||
try {
|
try {
|
||||||
feArea = getFeArea(stateAbbrev, e.getValue()[0], asc,
|
feArea = getFeArea(stateAbbrev, e.getValue()[0], asc, geoData);
|
||||||
geoData);
|
|
||||||
} catch (RuntimeException exc) {
|
} catch (RuntimeException exc) {
|
||||||
statusHandler.handle(Priority.ERROR, "Error generating included watches.", exc);
|
statusHandler.handle(Priority.ERROR,
|
||||||
|
"Error generating included watches.", exc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (feArea == NOT_IN_CWA)
|
if (feArea == NOT_IN_CWA)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Set<String> feAreas = map.get(stateAbbrev);
|
Set<String> feAreas = map.get(stateAbbrev);
|
||||||
if (feAreas == null) {
|
if (feAreas == null) {
|
||||||
feAreas = new HashSet<String>();
|
feAreas = new HashSet<String>();
|
||||||
|
@ -1111,7 +1154,8 @@ public class TemplateRunner {
|
||||||
portion.parentRegion = getStateName(e.getKey(), asc, geoData)
|
portion.parentRegion = getStateName(e.getKey(), asc, geoData)
|
||||||
.toUpperCase();
|
.toUpperCase();
|
||||||
} catch (RuntimeException exc) {
|
} catch (RuntimeException exc) {
|
||||||
statusHandler.handle(Priority.ERROR, "Error generating included watches.", exc);
|
statusHandler.handle(Priority.ERROR,
|
||||||
|
"Error generating included watches.", exc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
portion.partOfParentRegion = Area
|
portion.partOfParentRegion = Area
|
||||||
|
@ -1124,7 +1168,7 @@ public class TemplateRunner {
|
||||||
waw.setParentRegion(portions.get(0).parentRegion);
|
waw.setParentRegion(portions.get(0).parentRegion);
|
||||||
waw.setPartOfParentRegion(portions.get(0).partOfParentRegion);
|
waw.setPartOfParentRegion(portions.get(0).partOfParentRegion);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1236,7 +1280,7 @@ public class TemplateRunner {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String NOT_IN_CWA = new String("NOT_IN_CWA");
|
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
|
/** Determines if the given UGC is in the CWA and if it is, returns
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
package com.raytheon.viz.warngen.util;
|
package com.raytheon.viz.warngen.util;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
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.status.UFStatus.Priority;
|
||||||
import com.raytheon.uf.common.time.SimulatedTime;
|
import com.raytheon.uf.common.time.SimulatedTime;
|
||||||
import com.raytheon.uf.common.time.TimeRange;
|
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.alerts.AlertMessage;
|
||||||
import com.raytheon.uf.viz.core.exception.VizException;
|
import com.raytheon.uf.viz.core.exception.VizException;
|
||||||
import com.raytheon.uf.viz.core.requests.ThriftClient;
|
import com.raytheon.uf.viz.core.requests.ThriftClient;
|
||||||
|
@ -145,17 +145,41 @@ public class CurrentWarnings {
|
||||||
|
|
||||||
private String officeId;
|
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) {
|
private CurrentWarnings(String officeId) {
|
||||||
this.officeId = officeId;
|
this.officeId = officeId;
|
||||||
initializeData();
|
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());
|
current.setTime(SimulatedTime.getSystemTime().getTime());
|
||||||
|
|
||||||
synchronized (officeId) {
|
synchronized (officeId) {
|
||||||
|
List<AbstractWarningRecord> records = warningMap.get(toKey(
|
||||||
|
warnRec.getPhensig(), warnRec.getEtn()));
|
||||||
for (AbstractWarningRecord warning : records) {
|
for (AbstractWarningRecord warning : records) {
|
||||||
String phensig = warning.getPhensig();
|
WarningAction action = WarningAction.valueOf(warning.getAct());
|
||||||
String etn = warning.getEtn();
|
end.setTime(warning.getStartTime().getTime());
|
||||||
|
end.add(Calendar.MINUTE, 10);
|
||||||
if (warnRec.getPhensig().equals(phensig)
|
TimeRange t = new TimeRange(warning.getStartTime().getTime(),
|
||||||
&& warnRec.getEtn().equals(etn)) {
|
end.getTime());
|
||||||
WarningAction action = WarningAction.valueOf(warning
|
if ((action == WarningAction.NEW || action == WarningAction.CON || action == WarningAction.EXT)
|
||||||
.getAct());
|
&& t.contains(current.getTime())) {
|
||||||
end.setTime(warning.getStartTime().getTime());
|
rval.add(warning);
|
||||||
end.add(Calendar.MINUTE, 10);
|
} else if (action == WarningAction.CAN
|
||||||
TimeRange t = new TimeRange(warning.getStartTime()
|
|| action == WarningAction.EXP) {
|
||||||
.getTime(), end.getTime());
|
rval.clear();
|
||||||
if ((action == WarningAction.NEW
|
return rval;
|
||||||
|| 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() {
|
private List<AbstractWarningRecord> prepare(
|
||||||
Map<String, RequestConstraint> constraints = new HashMap<String, RequestConstraint>();
|
List<AbstractWarningRecord> records) {
|
||||||
constraints.put("officeid", new RequestConstraint(officeId));
|
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();
|
if (dataURIs.size() > 0) {
|
||||||
List<AbstractWarningRecord> warnings = requestRecords(constraints);
|
long t0 = System.currentTimeMillis();
|
||||||
System.out.println("Time to request CurrentWarnings records: "
|
RequestConstraint constraint = new RequestConstraint(null,
|
||||||
+ (System.currentTimeMillis() - t0) + "ms");
|
ConstraintType.IN);
|
||||||
processRecords(warnings);
|
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) {
|
private void processRecords(List<AbstractWarningRecord> warnings) {
|
||||||
synchronized (officeId) {
|
synchronized (officeId) {
|
||||||
for (AbstractWarningRecord record : warnings) {
|
for (AbstractWarningRecord record : warnings) {
|
||||||
if (records.contains(record) == false
|
recordsMap.put(record.getDataURI(), record);
|
||||||
&& record.getGeometry() != null) {
|
|
||||||
records.add(record);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
records.clear();
|
||||||
|
records.addAll(recordsMap.values());
|
||||||
|
|
||||||
// Sort by insert time
|
// Sort by insert time
|
||||||
Collections.sort(records, new Comparator<AbstractWarningRecord>() {
|
Collections.sort(records, new Comparator<AbstractWarningRecord>() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -508,7 +559,7 @@ public class CurrentWarnings {
|
||||||
for (String key : recordMap.keySet()) {
|
for (String key : recordMap.keySet()) {
|
||||||
CurrentWarnings cw = instanceMap.get(key);
|
CurrentWarnings cw = instanceMap.get(key);
|
||||||
if (cw != null) {
|
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(
|
private static List<AbstractWarningRecord> requestRecords(
|
||||||
Map<String, RequestConstraint> constraints) {
|
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>();
|
List<AbstractWarningRecord> newRecords = new ArrayList<AbstractWarningRecord>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
String insertTimeField = "insertTime";
|
||||||
|
String dataURIField = "dataURI";
|
||||||
DbQueryRequest request = new DbQueryRequest();
|
DbQueryRequest request = new DbQueryRequest();
|
||||||
request.setConstraints(constraints);
|
request.setConstraints(constraintsCopy);
|
||||||
request.setEntityClass(getWarningClass());
|
request.setEntityClass(getWarningClass());
|
||||||
|
request.addRequestField(dataURIField);
|
||||||
|
request.addRequestField(insertTimeField);
|
||||||
DbQueryResponse response = (DbQueryResponse) ThriftClient
|
DbQueryResponse response = (DbQueryResponse) ThriftClient
|
||||||
.sendRequest(request);
|
.sendRequest(request);
|
||||||
newRecords.addAll(Arrays.asList(response
|
for (Map<String, Object> result : response.getResults()) {
|
||||||
.getEntityObjects(AbstractWarningRecord.class)));
|
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) {
|
} catch (VizException e) {
|
||||||
statusHandler.handle(Priority.PROBLEM, "Error retreiving warnings",
|
statusHandler.handle(Priority.PROBLEM, "Error retreiving warnings",
|
||||||
e);
|
e);
|
||||||
|
|
|
@ -61,7 +61,7 @@ public class FipsUtil {
|
||||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||||
.getHandler(FipsUtil.class);
|
.getHandler(FipsUtil.class);
|
||||||
|
|
||||||
private static HashMap<String, String> fipsToState;
|
private static final Map<String, String> fipsToState;
|
||||||
|
|
||||||
private static String[][] abbrlist = new String[][] { { "02", "AK" },
|
private static String[][] abbrlist = new String[][] { { "02", "AK" },
|
||||||
{ "01", "AL" }, { "05", "AR" }, { "60", "AS" }, { "04", "AZ" },
|
{ "01", "AL" }, { "05", "AR" }, { "60", "AS" }, { "04", "AZ" },
|
||||||
|
@ -79,6 +79,13 @@ public class FipsUtil {
|
||||||
{ "51", "VA" }, { "78", "VI" }, { "50", "VT" }, { "53", "WA" },
|
{ "51", "VA" }, { "78", "VI" }, { "50", "VT" }, { "53", "WA" },
|
||||||
{ "55", "WI" }, { "54", "WV" }, { "56", "WY" } };
|
{ "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 */
|
/** Catch the Date portion of the UGC Header */
|
||||||
private static final String DATEPATTERN = "\\-([0-9]{6}\\-)";
|
private static final String DATEPATTERN = "\\-([0-9]{6}\\-)";
|
||||||
|
|
||||||
|
@ -103,11 +110,6 @@ public class FipsUtil {
|
||||||
ArrayList<String> countiesOrZones = new ArrayList<String>();
|
ArrayList<String> countiesOrZones = new ArrayList<String>();
|
||||||
DateUtil du = new DateUtil();
|
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>();
|
ArrayList<AffectedAreas> sortedAreas = new ArrayList<AffectedAreas>();
|
||||||
Collections.addAll(sortedAreas, areas);
|
Collections.addAll(sortedAreas, areas);
|
||||||
ArrayList<String> fields = new ArrayList<String>();
|
ArrayList<String> fields = new ArrayList<String>();
|
||||||
|
@ -122,27 +124,31 @@ public class FipsUtil {
|
||||||
Collections.sort(sortedAreas, comparator);
|
Collections.sort(sortedAreas, comparator);
|
||||||
|
|
||||||
for (AffectedAreas area : sortedAreas) {
|
for (AffectedAreas area : sortedAreas) {
|
||||||
String ugc = null;
|
String ugc = getUgc(area);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ugc != null && countiesOrZones.contains(ugc) == false) {
|
if (ugc != null && countiesOrZones.contains(ugc) == false) {
|
||||||
countiesOrZones.add(ugc);
|
countiesOrZones.add(ugc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rval.append(simplifyHeader(getUgc(countiesOrZones)));
|
rval.append(simplifyHeader(getUgcLine(countiesOrZones)));
|
||||||
rval.append(du
|
rval.append(du
|
||||||
.format(endtime, new SimpleDateFormat("ddHHmm"), interval)
|
.format(endtime, new SimpleDateFormat("ddHHmm"), interval)
|
||||||
+ "-");
|
+ "-");
|
||||||
return rval.toString();
|
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
|
* This method creates a correctly formatted UGC Header based on the passed
|
||||||
* AffectedAreas. The 6 digit datestamp at the end of the header is
|
* 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
|
rval.append(du
|
||||||
.format(endtime, new SimpleDateFormat("ddHHmm"), interval)
|
.format(endtime, new SimpleDateFormat("ddHHmm"), interval)
|
||||||
+ "-");
|
+ "-");
|
||||||
|
@ -270,23 +276,23 @@ public class FipsUtil {
|
||||||
* @param counties
|
* @param counties
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private static String getUgc(ArrayList<String> countiesorZones) {
|
private static String getUgcLine(ArrayList<String> ugcs) {
|
||||||
ArrayList<String> states = new ArrayList<String>();
|
ArrayList<String> states = new ArrayList<String>();
|
||||||
StringBuffer rval = new StringBuffer();
|
StringBuffer rval = new StringBuffer();
|
||||||
|
|
||||||
int nlCounter = 0;
|
int nlCounter = 0;
|
||||||
for (String countyOrZone : countiesorZones) {
|
for (String ugc : ugcs) {
|
||||||
if (!states.contains(countyOrZone.substring(0, 3))) {
|
if (!states.contains(ugc.substring(0, 3))) {
|
||||||
states.add(countyOrZone.substring(0, 3));
|
states.add(ugc.substring(0, 3));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (String state : states) {
|
for (String state : states) {
|
||||||
rval.append(state);
|
rval.append(state);
|
||||||
nlCounter += state.length();
|
nlCounter += state.length();
|
||||||
for (String countyOrZone : countiesorZones) {
|
for (String ugc : ugcs) {
|
||||||
if (countyOrZone.substring(0, 3).equals(state)) {
|
if (ugc.substring(0, 3).equals(state)) {
|
||||||
rval.append(countyOrZone.substring(3) + "-");
|
rval.append(ugc.substring(3) + "-");
|
||||||
nlCounter += 4;
|
nlCounter += 4;
|
||||||
if (nlCounter >= 60) {
|
if (nlCounter >= 60) {
|
||||||
nlCounter = 0;
|
nlCounter = 0;
|
||||||
|
@ -327,7 +333,7 @@ public class FipsUtil {
|
||||||
* DR15599 - use simplifyHeader to get the correct rval
|
* DR15599 - use simplifyHeader to get the correct rval
|
||||||
*/
|
*/
|
||||||
if (difference.size() > 0) {
|
if (difference.size() > 0) {
|
||||||
rval = simplifyHeader(getUgc(difference));
|
rval = simplifyHeader(getUgcLine(difference));
|
||||||
}
|
}
|
||||||
rval = rval + dateStr;
|
rval = rval + dateStr;
|
||||||
return rval;
|
return rval;
|
||||||
|
@ -413,10 +419,6 @@ public class FipsUtil {
|
||||||
* @return two letter state abbreviation
|
* @return two letter state abbreviation
|
||||||
*/
|
*/
|
||||||
public static String getStateNameFromFips(String fips) {
|
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);
|
String statefips = fips.substring(0, 2);
|
||||||
return fipsToState.get(statefips);
|
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.AreaSourceConfiguration;
|
||||||
import com.raytheon.uf.common.dataplugin.warning.config.GeospatialConfiguration;
|
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.config.WarngenConfiguration;
|
||||||
import com.raytheon.uf.common.dataplugin.warning.util.GeometryUtil;
|
|
||||||
import com.raytheon.uf.common.geospatial.SpatialException;
|
import com.raytheon.uf.common.geospatial.SpatialException;
|
||||||
import com.raytheon.uf.common.localization.IPathManager;
|
import com.raytheon.uf.common.localization.IPathManager;
|
||||||
import com.raytheon.uf.common.localization.LocalizationContext;
|
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.IUFStatusHandler;
|
||||||
import com.raytheon.uf.common.status.UFStatus;
|
import com.raytheon.uf.common.status.UFStatus;
|
||||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
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;
|
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
|
// process parent regions
|
||||||
if (parentAreas != null) {
|
if (parentAreas != null) {
|
||||||
Map<String, GeospatialData> parentMap = new HashMap<String, GeospatialData>(
|
Map<String, GeospatialData> parentMap = new HashMap<String, GeospatialData>(
|
||||||
|
@ -184,7 +144,7 @@ public class GeospatialFactory {
|
||||||
|
|
||||||
// Prepare the geometries
|
// Prepare the geometries
|
||||||
for (GeospatialData data : areas) {
|
for (GeospatialData data : areas) {
|
||||||
data.prepGeom = new PreparedGeometryCollection(data.geometry);
|
data.prepGeom = PreparedGeometryFactory.prepare(data.geometry);
|
||||||
}
|
}
|
||||||
|
|
||||||
return areas;
|
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;
|
package com.raytheon.uf.common.dataplugin.warning.util;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
@ -9,10 +8,9 @@ import java.util.TreeSet;
|
||||||
import com.vividsolutions.jts.geom.Geometry;
|
import com.vividsolutions.jts.geom.Geometry;
|
||||||
import com.vividsolutions.jts.geom.GeometryCollection;
|
import com.vividsolutions.jts.geom.GeometryCollection;
|
||||||
import com.vividsolutions.jts.geom.GeometryFactory;
|
import com.vividsolutions.jts.geom.GeometryFactory;
|
||||||
|
import com.vividsolutions.jts.geom.Point;
|
||||||
import com.vividsolutions.jts.geom.Polygon;
|
import com.vividsolutions.jts.geom.Polygon;
|
||||||
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
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
|
* Checks to see if g1 contains the point
|
||||||
* @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
|
|
||||||
*
|
*
|
||||||
* @param g1
|
* @param g1
|
||||||
* @param g2
|
* @param g2
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static boolean contains(Geometry g1, Geometry g2) {
|
public static boolean contains(Geometry g1, Point p) {
|
||||||
if (g1 instanceof GeometryCollection) {
|
if (g1 instanceof GeometryCollection) {
|
||||||
for (int i = 0; i < g1.getNumGeometries(); ++i) {
|
for (int i = 0; i < g1.getNumGeometries(); ++i) {
|
||||||
if (contains(g1.getGeometryN(i), g2)) {
|
if (contains(g1.getGeometryN(i), p)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return g1.contains(g2);
|
return g1.contains(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks to see if g intersects any pGs
|
* Intersection between g1 and g2. Resulting intersection will contain user
|
||||||
*
|
* data from g2
|
||||||
* @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
|
|
||||||
*
|
*
|
||||||
* @param g1
|
* @param g1
|
||||||
* @param g2
|
* @param g2
|
||||||
|
@ -149,41 +96,10 @@ public class GeometryUtil {
|
||||||
intersection(g1, g2, intersection);
|
intersection(g1, g2, intersection);
|
||||||
Geometry rval = gf.createGeometryCollection(intersection
|
Geometry rval = gf.createGeometryCollection(intersection
|
||||||
.toArray(new Geometry[intersection.size()]));
|
.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());
|
rval.setUserData(g2.getUserData());
|
||||||
return rval;
|
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,
|
private static void intersection(Geometry g1, Geometry g2,
|
||||||
List<Geometry> intersections) {
|
List<Geometry> intersections) {
|
||||||
if (g1 instanceof GeometryCollection) {
|
if (g1 instanceof GeometryCollection) {
|
||||||
|
@ -198,27 +114,48 @@ public class GeometryUtil {
|
||||||
} else {
|
} else {
|
||||||
String g1Name = toString(g1.getUserData());
|
String g1Name = toString(g1.getUserData());
|
||||||
String g2Name = toString(g2.getUserData());
|
String g2Name = toString(g2.getUserData());
|
||||||
String prefix = null;
|
|
||||||
if (g1Name != null && g2Name != null) {
|
if ((g1Name == null || g2Name == null || g2Name.equals(g1Name))) {
|
||||||
prefix = getPrefix(g1Name);
|
Geometry section = g1.intersection(g2);
|
||||||
}
|
if (section.isEmpty() == false) {
|
||||||
if ((g1Name == null || g2Name == null || g2Name
|
if (g2.getUserData() != null) {
|
||||||
.startsWith(prefix))) {
|
if (section instanceof GeometryCollection) {
|
||||||
if (g1.isValid() && g2.isValid()) {
|
for (int n = 0; n < section.getNumGeometries(); ++n) {
|
||||||
Geometry section = g1.intersection(g2);
|
setUserData(section.getGeometryN(n),
|
||||||
if (section.isEmpty() == false) {
|
(CountyUserData) g2.getUserData());
|
||||||
section = section.buffer(0);
|
}
|
||||||
setUserData(section,
|
} else {
|
||||||
(CountyUserData) g2.getUserData());
|
setUserData(section,
|
||||||
section.setUserData(g2.getUserData());
|
(CountyUserData) g2.getUserData());
|
||||||
intersections.add(section);
|
}
|
||||||
}
|
}
|
||||||
|
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,
|
private static void intersection(Geometry g1, PreparedGeometry pg,
|
||||||
List<Geometry> intersections) {
|
List<Geometry> intersections) {
|
||||||
if (g1 instanceof GeometryCollection) {
|
if (g1 instanceof GeometryCollection) {
|
||||||
|
@ -226,78 +163,17 @@ public class GeometryUtil {
|
||||||
intersection(g1.getGeometryN(i), pg, intersections);
|
intersection(g1.getGeometryN(i), pg, intersections);
|
||||||
}
|
}
|
||||||
} else {
|
} 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();
|
Geometry g2 = pg.getGeometry();
|
||||||
List<Geometry> sections = new ArrayList<Geometry>();
|
intersection(g1, g2, intersections);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
* 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) {
|
public static void printGeoemtry(Geometry g) {
|
||||||
printGeoemtry(g, 0);
|
printGeoemtry(g, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ public class RequestConstraint implements ISerializableObject, Cloneable {
|
||||||
EQUALS("="), NOT_EQUALS("!="), GREATER_THAN(">"), GREATER_THAN_EQUALS(
|
EQUALS("="), NOT_EQUALS("!="), GREATER_THAN(">"), GREATER_THAN_EQUALS(
|
||||||
">="), LESS_THAN("<"), LESS_THAN_EQUALS("<="), BETWEEN(
|
">="), LESS_THAN("<"), LESS_THAN_EQUALS("<="), BETWEEN(
|
||||||
"between"), IN("in"), LIKE("like"), ILIKE("ilike"), ISNULL(
|
"between"), IN("in"), LIKE("like"), ILIKE("ilike"), ISNULL(
|
||||||
"isnull");
|
"isnull"), ISNOTNULL("isnotnull");
|
||||||
|
|
||||||
private String operand;
|
private String operand;
|
||||||
|
|
||||||
|
@ -263,6 +263,8 @@ public class RequestConstraint implements ISerializableObject, Cloneable {
|
||||||
|
|
||||||
if (constraintType == ConstraintType.ISNULL) {
|
if (constraintType == ConstraintType.ISNULL) {
|
||||||
return value == null || "null".equals(value);
|
return value == null || "null".equals(value);
|
||||||
|
} else if (constraintType == ConstraintType.ISNOTNULL) {
|
||||||
|
return value != null && "null".equals(value) == false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
|
|
|
@ -122,6 +122,10 @@ public class DbQueryHandler implements IRequestHandler<DbQueryRequest> {
|
||||||
op = QueryOperand.ISNULL;
|
op = QueryOperand.ISNULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ISNOTNULL: {
|
||||||
|
op = QueryOperand.ISNOTNULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case LESS_THAN: {
|
case LESS_THAN: {
|
||||||
op = QueryOperand.LESSTHAN;
|
op = QueryOperand.LESSTHAN;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Add table
Reference in a new issue