diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/config/DbAreaSourceDataAdaptor.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/config/DbAreaSourceDataAdaptor.java index e44dbcf3a5..9ef6bc3676 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/config/DbAreaSourceDataAdaptor.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/config/DbAreaSourceDataAdaptor.java @@ -15,6 +15,7 @@ import org.geotools.referencing.GeodeticCalculator; import com.raytheon.uf.common.dataplugin.warning.config.PathcastConfiguration; import com.raytheon.uf.common.dataplugin.warning.config.PointSourceConfiguration; +import com.raytheon.uf.common.dataplugin.warning.gis.PreparedGeometryCollection; import com.raytheon.uf.common.dataquery.requests.RequestConstraint; import com.raytheon.uf.common.geospatial.SpatialQueryResult; import com.raytheon.uf.viz.core.exception.VizException; @@ -26,7 +27,6 @@ import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.prep.PreparedGeometry; -import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory; /** * @@ -146,7 +146,7 @@ public class DbAreaSourceDataAdaptor extends AbstractDbSourceDataAdaptor { boolean userDirections = Boolean.valueOf(String.valueOf(attributes .get(useDirectionField))); if (userDirections) { - PreparedGeometry prepGeom = PreparedGeometryFactory.prepare(geom); + PreparedGeometry prepGeom = new PreparedGeometryCollection(geom); if (prepGeom.intersects(searchArea) && !prepGeom.within(searchArea)) { Geometry intersection = searchArea.intersection(geom); partOfArea = GisUtil.asStringList(calculateLocationPortion( diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/Area.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/Area.java index ea42c71a28..018126daa8 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/Area.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/Area.java @@ -50,6 +50,7 @@ import com.raytheon.viz.warngen.gui.WarngenLayer; import com.raytheon.viz.warngen.suppress.SuppressMap; import com.raytheon.viz.warngen.util.Abbreviation; import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.prep.PreparedGeometry; /** * Area @@ -176,6 +177,7 @@ public class Area { GeodeticCalculator gc = new GeodeticCalculator(); for (GeospatialData regionFeature : countyMap.values()) { Geometry regionGeom = regionFeature.geometry; + PreparedGeometry preparedRegionGeom = regionFeature.prepGeom; AffectedAreas area = new AffectedAreas(); area.name = regionFeature.attributes.get(areaField).toString(); area.fips = regionFeature.attributes.get(fipsField).toString(); @@ -237,7 +239,7 @@ public class Area { if (ptFeatures != null) { List pointList = new ArrayList(); for (SpatialQueryResult ptRslt : ptFeatures) { - if (regionGeom.contains(ptRslt.geometry)) { + if (preparedRegionGeom.contains(ptRslt.geometry)) { pointList.add(String.valueOf(ptRslt.attributes .get(pointField))); } @@ -331,7 +333,7 @@ public class Area { } return retVal; } - + public static List converFeAreaToPartList(String feArea) { final List partList = new ArrayList(); if (feArea == null) { diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/GisUtil.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/GisUtil.java index 538a6294a7..f677f85ae4 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/GisUtil.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/GisUtil.java @@ -29,6 +29,7 @@ import java.util.List; import org.geotools.referencing.GeodeticCalculator; +import com.raytheon.uf.common.dataplugin.warning.util.GeometryUtil; import com.raytheon.viz.warngen.suppress.SuppressMap; import com.vividsolutions.jts.algorithm.CGAlgorithms; import com.vividsolutions.jts.geom.Coordinate; @@ -37,7 +38,6 @@ import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryCollection; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LineString; -import com.vividsolutions.jts.geom.MultiPolygon; import com.vividsolutions.jts.geom.Polygon; /** @@ -206,27 +206,21 @@ public class GisUtil { yDirection = Direction.SOUTH; } + List geoms = new ArrayList(geom.getNumGeometries()); + GeometryUtil.buildGeometryList(geoms, geom); boolean isExtreme = false; - Coordinate[] coords; - if (geom instanceof Polygon) { - LineString lineString = ((Polygon) geom).getExteriorRing(); - coords = lineString.getCoordinates(); - isExtreme = isExtreme(coords, point, - (extremaThresholdX + extremaThresholdY) / 2.0); - } else if (geom instanceof MultiPolygon) { - int geoms = ((MultiPolygon) geom).getNumGeometries(); - for (int i = 0; i < geoms; i++) { - LineString lineString = ((Polygon) ((MultiPolygon) geom) - .getGeometryN(i)).getExteriorRing(); - coords = lineString.getCoordinates(); - if (isExtreme(coords, point, + for (Geometry g : geoms) { + if (g instanceof Polygon) { + LineString lineString = ((Polygon) g).getExteriorRing(); + if (isExtreme(lineString.getCoordinates(), point, (extremaThresholdX + extremaThresholdY) / 2.0)) { isExtreme = true; break; } } } + EnumSet retVal = EnumSet.noneOf(Direction.class); if (xDirection != null && !suppressType.equals(SuppressMap.EAST_WEST) diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/PolygonUtil.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/PolygonUtil.java index 1d65601dd9..cf583d39d3 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/PolygonUtil.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/PolygonUtil.java @@ -30,6 +30,7 @@ import org.geotools.referencing.operation.DefaultMathTransformFactory; import org.opengis.metadata.spatial.PixelOrientation; import org.opengis.referencing.operation.MathTransform; +import com.raytheon.uf.common.dataplugin.warning.gis.PreparedGeometryCollection; import com.raytheon.uf.common.dataplugin.warning.util.GeometryUtil; import com.raytheon.uf.viz.core.IExtent; import com.raytheon.uf.viz.core.exception.VizException; @@ -44,7 +45,6 @@ import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LineSegment; import com.vividsolutions.jts.geom.Polygon; import com.vividsolutions.jts.geom.prep.PreparedGeometry; -import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory; /** * Utility for polygon operations @@ -57,7 +57,7 @@ import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory; * ------------ ---------- ----------- -------------------------- * Dec 1, 2010 mschenke Initial creation * 12/06/2012 DR 15559 Qinglu Lin Added round() methods. - * + * * * * @author mschenke @@ -850,7 +850,7 @@ public class PolygonUtil { List prepped = new ArrayList( geomList.size()); for (Geometry g : geomList) { - prepped.add(PreparedGeometryFactory.prepare(g)); + prepped.add(new PreparedGeometryCollection(g)); } GeometryFactory gf = warningArea.getFactory(); @@ -931,56 +931,54 @@ public class PolygonUtil { } } } - - public static void truncate(Listcoordinates, int decimalPlaces) { + + public static void truncate(List coordinates, int decimalPlaces) { for (Coordinate coordinate : coordinates) { truncate(coordinate, decimalPlaces); } } - + public static void truncate(Coordinate[] coordinates, int decimalPlaces) { for (Coordinate coordinate : coordinates) { truncate(coordinate, decimalPlaces); } } - + public static void truncate(Coordinate coordinate, int decimalPlaces) { double x = coordinate.x * Math.pow(10, decimalPlaces); double y = coordinate.y * Math.pow(10, decimalPlaces); - + x = x >= 0 ? Math.floor(x) : Math.ceil(x); y = y >= 0 ? Math.floor(y) : Math.ceil(y); - + coordinate.x = x / Math.pow(10, decimalPlaces); coordinate.y = y / Math.pow(10, decimalPlaces); } - public static void round(Listcoordinates, int decimalPlaces) { + public static void round(List coordinates, int decimalPlaces) { for (Coordinate coordinate : coordinates) { round(coordinate, decimalPlaces); } } - + public static void round(Coordinate[] coordinates, int decimalPlaces) { for (Coordinate coordinate : coordinates) { round(coordinate, decimalPlaces); } } - + /** - * round() - * Rounding coordinates, instead of truncating them. - * - * History - * 12/06/2012 DR 15559 Qinglu Lin Created. + * round() Rounding coordinates, instead of truncating them. + * + * History 12/06/2012 DR 15559 Qinglu Lin Created. */ public static void round(Coordinate coordinate, int decimalPlaces) { double x = coordinate.x * Math.pow(10, decimalPlaces); double y = coordinate.y * Math.pow(10, decimalPlaces); - + x = Math.round(x); y = Math.round(y); - + coordinate.x = x / Math.pow(10, decimalPlaces); coordinate.y = y / Math.pow(10, decimalPlaces); } diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java index fbddbdb397..cc1ad4712a 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java @@ -24,13 +24,13 @@ import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; +import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; import java.util.TimeZone; import java.util.regex.Matcher; @@ -40,10 +40,15 @@ import javax.measure.converter.UnitConverter; import javax.measure.unit.NonSI; import javax.measure.unit.SI; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.action.IMenuManager; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; import org.eclipse.ui.PlatformUI; import org.geotools.geometry.jts.JTS; import org.geotools.referencing.GeodeticCalculator; @@ -60,6 +65,7 @@ import com.raytheon.uf.common.dataplugin.warning.config.WarngenConfiguration; import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialData; import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialFactory; import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialMetadata; +import com.raytheon.uf.common.dataplugin.warning.gis.PreparedGeometryCollection; import com.raytheon.uf.common.dataplugin.warning.util.CountyUserData; import com.raytheon.uf.common.dataplugin.warning.util.GeometryUtil; import com.raytheon.uf.common.geospatial.DestinationGeodeticCalculator; @@ -118,7 +124,6 @@ import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.Polygon; import com.vividsolutions.jts.geom.TopologyException; import com.vividsolutions.jts.geom.prep.PreparedGeometry; -import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory; import com.vividsolutions.jts.io.ParseException; import com.vividsolutions.jts.io.WKTReader; @@ -152,8 +157,8 @@ import com.vividsolutions.jts.io.WKTReader; * 12/13/2012 DR 15559 Qinglu Lin Added code to call WarngenUIState's adjustPolygon(). * 12/17/2012 DR 15571 Qinglu Lin For hydro products,futurePoints is null. Resolved an issue caused by trying to get * 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. + * * * * @author mschenke @@ -181,6 +186,60 @@ public class WarngenLayer extends AbstractStormTrackResource { int nx, ny; } + private class CustomMaps extends Job { + + private Set customMaps = new HashSet(); + + private Set mapsToLoad; + + private MapManager manager; + + public CustomMaps() { + super("Loading WarnGen Maps"); + manager = MapManager.getInstance(descriptor); + } + + @Override + protected IStatus run(IProgressMonitor monitor) { + boolean done = false; + while (!done) { + Set toLoad = null; + synchronized (this) { + if (mapsToLoad != null) { + toLoad = mapsToLoad; + mapsToLoad = null; + } + } + + if (toLoad != null) { + for (String loaded : customMaps) { + manager.unloadMap(loaded); + } + + for (String load : toLoad) { + manager.loadMapByName(load); + } + + issueRefresh(); + } + + done = mapsToLoad == null; + } + return Status.OK_STATUS; + } + + public void loadCustomMaps(Collection maps) { + synchronized (this) { + mapsToLoad = new HashSet(maps); + } + schedule(); + } + + public void clearMaps() { + loadCustomMaps(new HashSet()); + } + } + private static Map siteMap = new HashMap(); private static Map timezoneMap = new HashMap(); @@ -220,7 +279,7 @@ public class WarngenLayer extends AbstractStormTrackResource { private boolean boxEditable = true; - private Map> loadedCustomMaps; + private CustomMaps customMaps; protected Mode lastMode = null; @@ -260,7 +319,7 @@ public class WarngenLayer extends AbstractStormTrackResource { super(resourceData, loadProperties, descriptor); displayState.displayType = DisplayType.POINT; getCapability(ColorableCapability.class).setColor(WHITE); - loadedCustomMaps = new HashMap>(); + customMaps = new CustomMaps(); try { dialogConfig = DialogConfiguration @@ -385,13 +444,7 @@ public class WarngenLayer extends AbstractStormTrackResource { @Override protected void disposeInternal() { - for (Entry> entry : loadedCustomMaps - .entrySet()) { - for (String map : entry.getValue()) { - MapManager.getInstance(entry.getKey()).unloadMap(map); - } - } - loadedCustomMaps.clear(); + customMaps.clearMaps(); super.disposeInternal(); @@ -432,7 +485,6 @@ public class WarngenLayer extends AbstractStormTrackResource { } super.initInternal(target); VizApp.runSync(new Runnable() { - @Override public void run() { createDialog(); @@ -493,17 +545,17 @@ public class WarngenLayer extends AbstractStormTrackResource { displayState.geomChanged = false; } if (warningAction == null || warningAction == WarningAction.NEW) { - // Initialize box - if (((configuration.isTrackEnabled() == false || configuration - .getPathcastConfig() == null) && this.displayState.displayType != DisplayType.POLY) - || frameCount == 1) { - createSquare(); - resetInitialFrame(); - } else { - redrawBoxFromTrack(); - } + // Initialize box + if (((configuration.isTrackEnabled() == false || configuration + .getPathcastConfig() == null) && this.displayState.displayType != DisplayType.POLY) + || frameCount == 1) { + createSquare(); + resetInitialFrame(); + } else { + redrawBoxFromTrack(); + } } else { - redrawBoxFromTrack(); + redrawBoxFromTrack(); } } @@ -746,7 +798,7 @@ public class WarngenLayer extends AbstractStormTrackResource { local); gd.attributes.put( GeospatialDataList.LOCAL_PREP_GEOM, - PreparedGeometryFactory.prepare(local)); + new PreparedGeometryCollection(local)); locals.add(local); } @@ -825,43 +877,11 @@ public class WarngenLayer extends AbstractStormTrackResource { String areaSource = config.getGeospatialConfig().getAreaSource(); geoData = siteMap.get(areaSource + "." + site); }// end synchronize - loadCustomMaps(descriptor, config); - this.configuration = config; - System.out.println("Time to init warngen config: " - + (System.currentTimeMillis() - t0)); - } + customMaps.loadCustomMaps(Arrays.asList(config.getMaps())); - protected void loadCustomMaps(MapDescriptor descriptor, - WarngenConfiguration config) { - if (config == null || descriptor == null) { - return; - } - long t1 = System.currentTimeMillis(); - MapManager mapManager = MapManager.getInstance(descriptor); - List maps = Arrays.asList(config.getMaps()); - Set loadedCustomMaps = this.loadedCustomMaps.get(descriptor); - if (loadedCustomMaps == null) { - loadedCustomMaps = new HashSet(); - this.loadedCustomMaps.put(descriptor, loadedCustomMaps); - } - Iterator it = loadedCustomMaps.iterator(); - while (it.hasNext()) { - String map = it.next(); - if (!maps.contains(map)) { - it.remove(); - mapManager.unloadMap(map); - } - } - for (String map : maps) { - if (!loadedCustomMaps.contains(map)) { - if (!mapManager.isMapLoaded(map)) { - mapManager.loadMapByName(map); - loadedCustomMaps.add(map); - } - } - } - System.out.println("Time to load custom maps: " - + (System.currentTimeMillis() - t1)); + this.configuration = config; + System.out.println("Total time to init warngen config = " + + (System.currentTimeMillis() - t0) + "ms"); } public GeospatialData[] getGeodataFeatures(String key) { @@ -1103,30 +1123,17 @@ public class WarngenLayer extends AbstractStormTrackResource { dialog = new WarngenDialog(PlatformUI.getWorkbench() .getActiveWorkbenchWindow().getShell(), this); dialog.open(); - addDialogDisposeListener(descriptor); - } else { - showDialog(true); - } - } - - public void addDialogDisposeListener(final MapDescriptor descriptor) { - if (dialog != null) { - dialog.getShell().addDisposeListener(new DisposeListener() { + dialog.addListener(SWT.Dispose, new Listener() { @Override - public void widgetDisposed(DisposeEvent e) { + public void handleEvent(Event event) { descriptor.getResourceList().removeRsc(WarngenLayer.this); } }); + } else { + showDialog(true); } } - @Override - public void setDescriptor(MapDescriptor descriptor) { - super.setDescriptor(descriptor); - addDialogDisposeListener(descriptor); - loadCustomMaps(descriptor, configuration); - } - /** * Show the WarnGen dialog and move it to the front. */ @@ -1611,15 +1618,15 @@ public class WarngenLayer extends AbstractStormTrackResource { if (hatched != null) { // DR 15559 Coordinate[] coords = hatched.getCoordinates(); - PolygonUtil.round(coords, 2); - state.adjustPolygon(coords); - GeometryFactory gf = new GeometryFactory(); - LinearRing lr = gf.createLinearRing(coords); - state.setWarningPolygon(gf.createPolygon(lr, null)); - updateWarnedAreas(true, true); - issueRefresh(); - // End of DR 15559 - state.snappedToArea = 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(); + // End of DR 15559 + state.snappedToArea = true; } System.out.println("Time to createWarningPolygon: " + (System.currentTimeMillis() - t0) + "ms"); @@ -1838,16 +1845,20 @@ public class WarngenLayer extends AbstractStormTrackResource { Coordinate[] cc = null; switch (stormTrackState.displayType) { case POINT: - cc = new Coordinate[] { stormTrackState.futurePoints == null ? stormTrackState.dragMePoint - .getCoordinate() : stormTrackState.futurePoints[0].coord }; - if (warningAction == null || warningAction == WarningAction.NEW || warningAction == WarningAction.CON - || warningAction == WarningAction.CAN) { - Coordinate coord = new Coordinate(stormTrackState.dragMePoint.getCoordinate()); - DataTime currentDataTime = new DataTime(SimulatedTime.getSystemTime().getTime()); - if (stormTrackState.compuateCurrentStormCenter(coord,currentDataTime)) - cc = new Coordinate[] {coord}; - } - break; + cc = new Coordinate[] { stormTrackState.futurePoints == null ? stormTrackState.dragMePoint + .getCoordinate() : stormTrackState.futurePoints[0].coord }; + if (warningAction == null || warningAction == WarningAction.NEW + || warningAction == WarningAction.CON + || warningAction == WarningAction.CAN) { + Coordinate coord = new Coordinate( + stormTrackState.dragMePoint.getCoordinate()); + DataTime currentDataTime = new DataTime(SimulatedTime + .getSystemTime().getTime()); + if (stormTrackState.compuateCurrentStormCenter(coord, + currentDataTime)) + cc = new Coordinate[] { coord }; + } + break; case POLY: Coordinate[] polyPoints = stormTrackState.dragMeLine .getCoordinates(); @@ -2357,8 +2368,8 @@ public class WarngenLayer extends AbstractStormTrackResource { + e.getLocalizedMessage(), e); } } - + public void setWarningAction(WarningAction warningAction) { - this.warningAction = warningAction; + this.warningAction = warningAction; } } diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/CurrentWarnings.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/CurrentWarnings.java index dab39fd1fd..d82e4d996b 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/CurrentWarnings.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/CurrentWarnings.java @@ -20,6 +20,7 @@ package com.raytheon.viz.warngen.util; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.Collection; import java.util.Collections; @@ -37,8 +38,10 @@ import com.raytheon.uf.common.dataplugin.warning.UGCZone; import com.raytheon.uf.common.dataplugin.warning.WarningRecord; import com.raytheon.uf.common.dataplugin.warning.WarningRecord.WarningAction; import com.raytheon.uf.common.dataplugin.warning.util.AnnotationUtil; +import com.raytheon.uf.common.dataquery.requests.DbQueryRequest; import com.raytheon.uf.common.dataquery.requests.RequestConstraint; import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType; +import com.raytheon.uf.common.dataquery.responses.DbQueryResponse; import com.raytheon.uf.common.site.SiteMap; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; @@ -46,10 +49,8 @@ import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.time.SimulatedTime; import com.raytheon.uf.common.time.TimeRange; import com.raytheon.uf.viz.core.alerts.AlertMessage; -import com.raytheon.uf.viz.core.catalog.LayerProperty; -import com.raytheon.uf.viz.core.catalog.ScriptCreator; -import com.raytheon.uf.viz.core.comm.Connector; -import com.raytheon.uf.viz.core.rsc.ResourceType; +import com.raytheon.uf.viz.core.exception.VizException; +import com.raytheon.uf.viz.core.requests.ThriftClient; import com.raytheon.viz.alerts.IAlertObserver; import com.raytheon.viz.alerts.observers.ProductAlertObserver; import com.raytheon.viz.core.mode.CAVEMode; @@ -187,7 +188,8 @@ public class CurrentWarnings { * @param phenSigs * @return */ - public List getCorrectableWarnings(AbstractWarningRecord warnRec) { + public List getCorrectableWarnings( + AbstractWarningRecord warnRec) { List rval = new ArrayList(); Calendar current = Calendar.getInstance(); Calendar end = Calendar.getInstance(); @@ -197,24 +199,28 @@ public class CurrentWarnings { for (AbstractWarningRecord warning : records) { String phensig = warning.getPhensig(); String etn = warning.getEtn(); - - if (warnRec.getPhensig().equals(phensig) && warnRec.getEtn().equals(etn)) { - WarningAction action = WarningAction.valueOf(warning.getAct()); + + if (warnRec.getPhensig().equals(phensig) + && warnRec.getEtn().equals(etn)) { + WarningAction action = WarningAction.valueOf(warning + .getAct()); end.setTime(warning.getStartTime().getTime()); end.add(Calendar.MINUTE, 10); - TimeRange t = new TimeRange(warning.getStartTime().getTime(), - end.getTime()); - if ((action == WarningAction.NEW || action == WarningAction.CON || action == WarningAction.EXT) + TimeRange t = new TimeRange(warning.getStartTime() + .getTime(), end.getTime()); + if ((action == WarningAction.NEW + || action == WarningAction.CON || action == WarningAction.EXT) && t.contains(current.getTime())) { rval.add(warning); - } else if (action == WarningAction.CAN || action == WarningAction.EXP) { + } else if (action == WarningAction.CAN + || action == WarningAction.EXP) { rval.clear(); return rval; } } } } - + return rval; } @@ -253,7 +259,7 @@ public class CurrentWarnings { for (AbstractWarningRecord warning : warnings) { if (getAction(warning.getAct()) == WarningAction.CON) { if (rval != null) { - //rval.setAct("CON"); + // rval.setAct("CON"); rval.setGeometry(warning.getGeometry()); rval.setCountyheader(warning.getCountyheader()); rval.setUgczones(warning.getUgczones()); @@ -421,7 +427,10 @@ public class CurrentWarnings { Map constraints = new HashMap(); constraints.put("officeid", new RequestConstraint(officeId)); + long t0 = System.currentTimeMillis(); List warnings = requestRecords(constraints); + System.out.println("Time to request CurrentWarnings records: " + + (System.currentTimeMillis() - t0) + "ms"); processRecords(warnings); } @@ -472,6 +481,10 @@ public class CurrentWarnings { } } + if (dataURIs.size() == 0) { + return; + } + Map constraints = new HashMap(); RequestConstraint constraint = new RequestConstraint(null, ConstraintType.IN); @@ -534,25 +547,16 @@ public class CurrentWarnings { private static List requestRecords( Map constraints) { List newRecords = new ArrayList(); - Object[] resp; - LayerProperty lp = new LayerProperty(); + try { - String tableName = AnnotationUtil.getTableName(getWarningClass()); - - constraints.put("pluginName", new RequestConstraint(tableName)); - lp.setDesiredProduct(ResourceType.PLAN_VIEW); - lp.setEntryQueryParameters(constraints, false); - - lp.setNumberOfImages(9999); - - String script = ScriptCreator.createScript(lp); - if (script != null) { - resp = Connector.getInstance().connect(script, null, 60000); - for (int i = 0; i < resp.length; i++) { - newRecords.add((AbstractWarningRecord) resp[i]); - } - } - } catch (Exception e) { + DbQueryRequest request = new DbQueryRequest(); + request.setConstraints(constraints); + request.setEntityClass(getWarningClass()); + DbQueryResponse response = (DbQueryResponse) ThriftClient + .sendRequest(request); + newRecords.addAll(Arrays.asList(response + .getEntityObjects(AbstractWarningRecord.class))); + } catch (VizException e) { statusHandler.handle(Priority.PROBLEM, "Error retreiving warnings", e); } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/gis/GeospatialFactory.java b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/gis/GeospatialFactory.java index faf88b060d..d52333e894 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/gis/GeospatialFactory.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/gis/GeospatialFactory.java @@ -44,6 +44,7 @@ import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory; /** @@ -61,7 +62,7 @@ import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory; * Apr 11, 2012 #14691 Qinglu Lin For marine warnings, getFeAreaField() returns null. * So, do not add the returned value of getFeAreaField() * to areaFields. - * Jan 9, 2013 15600 Qinglu Lin Execute "timezones = myTimeZones;" even if timezones != null. + * Jan 9, 2013 15600 Qinglu Lin Execute "timezones = myTimeZones;" even if timezones != null. * * * @@ -87,13 +88,12 @@ public class GeospatialFactory { boolean generate = true; if (lastRunTime != null) { System.out.println("Loading areas from disk"); - // load from disk try { long t0 = System.currentTimeMillis(); dataSet = loadAreaGeoData(site, lastRunTime); System.out.println("Loading areas from disk took " - + (System.currentTimeMillis() - t0)); + + (System.currentTimeMillis() - t0) + "ms"); } catch (Exception e) { statusHandler.handle(Priority.WARN, "Failed to load area geometry files from disk", e); @@ -119,7 +119,7 @@ public class GeospatialFactory { GeospatialData[] parentAreas = dataSet.getParentAreas(); GeospatialData[] myTimeZones = dataSet.getTimezones(); if (myTimeZones != null && myTimeZones.length > 0) { - timezones = myTimeZones; + timezones = myTimeZones; for (GeospatialData tz : myTimeZones) { tz.prepGeom = PreparedGeometryFactory.prepare(tz.geometry); @@ -138,7 +138,6 @@ public class GeospatialFactory { list.add(data); } - GeospatialData[] uniqueAreas = new GeospatialData[uniqueAreasMap.size()]; int index = 0; for (String key : uniqueAreasMap.keySet()) { @@ -148,34 +147,15 @@ public class GeospatialFactory { // if multiple areas share a common fips ID, the smaller areas will // have to merge will the largest area if (list.size() > 1) { - double maxArea = -1; - for (GeospatialData item : list) { - double area = item.getGeometry().getArea(); - if (area > maxArea) { - data = item; - maxArea = area; - } - } - - // collect all individual geometries that are not a part - // of the maxArea + // collect all individual geometries List geometries = new ArrayList(); for (GeospatialData item : list) { - if (data != item) { - GeometryUtil.buildGeometryList(geometries, - item.geometry); - } - } - - for (int i = 0; i < geometries.size(); i++) { - // convexHull will remove any side location conflicts - // convexHull the geometries individually because they are - // usually not next to each other. - // data.geometry = data.geometry.union(geometries.get(i) - // .convexHull()); - data.geometry = data.geometry.union(geometries.get(i) - .convexHull()); + 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++; @@ -204,7 +184,7 @@ public class GeospatialFactory { // Prepare the geometries for (GeospatialData data : areas) { - data.prepGeom = PreparedGeometryFactory.prepare(data.geometry); + data.prepGeom = new PreparedGeometryCollection(data.geometry); } return areas; diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/gis/PreparedGeometryCollection.java b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/gis/PreparedGeometryCollection.java new file mode 100644 index 0000000000..8b6188438e --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/gis/PreparedGeometryCollection.java @@ -0,0 +1,246 @@ +/** + * 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 + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jan 28, 2013            mschenke     Initial creation
+ * 
+ * 
+ * + * @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; + } + +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/util/GeometryUtil.java b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/util/GeometryUtil.java index 0ce2c7f5f2..a3765c3876 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/util/GeometryUtil.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/util/GeometryUtil.java @@ -1,24 +1,38 @@ package com.raytheon.uf.common.dataplugin.warning.util; import java.util.ArrayList; -import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.TreeSet; -import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryCollection; import com.vividsolutions.jts.geom.GeometryFactory; -import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.Polygon; -import com.vividsolutions.jts.geom.TopologyException; import com.vividsolutions.jts.geom.prep.PreparedGeometry; import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory; import com.vividsolutions.jts.operation.overlay.snap.GeometrySnapper; -import com.vividsolutions.jts.operation.polygonize.Polygonizer; +/** + * + * Performs common geometry operations taking geometry collections into + * account for counties. Makes certain assumptions about these geometries that + * only apply to warngen + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Nov 15, 2010            mschenke     Initial creation
+ * 
+ * 
+ * + * @author mschenke + * @version 1.0 + */ public class GeometryUtil { private static final String SEPARATOR = "_"; @@ -41,7 +55,7 @@ public class GeometryUtil { } for (int i = 0; i < list1.size(); ++i) { - if (list1.get(i).buffer(0).equals(list2.get(i).buffer(0)) == false) { + if (list1.get(i).equals(list2.get(i)) == false) { return false; } } @@ -190,12 +204,15 @@ public class GeometryUtil { } if ((g1Name == null || g2Name == null || g2Name .startsWith(prefix))) { - Geometry section = g1.intersection(g2); - if (section.isEmpty() == false) { - section = section.buffer(0); - setUserData(section, (CountyUserData) g2.getUserData()); - section.setUserData(g2.getUserData()); - intersections.add(section); + if (g1.isValid() && g2.isValid()) { + Geometry section = g1.intersection(g2); + if (section.isEmpty() == false) { + section = section.buffer(0); + setUserData(section, + (CountyUserData) g2.getUserData()); + section.setUserData(g2.getUserData()); + intersections.add(section); + } } } } @@ -209,64 +226,31 @@ public class GeometryUtil { intersection(g1.getGeometryN(i), pg, intersections); } } else { - Geometry g2 = pg.getGeometry(); - String g1Name = toString(g1.getUserData()); - String g2Name = toString(g2.getUserData()); - String prefix = null; - if (g1Name != null && g2Name != null) { - prefix = getPrefix(g1Name); - } - if (g1Name == null || g2Name == null || g2Name.startsWith(prefix)) { - if (pg.intersects(g1)) { - Geometry section = null; - try { - section = g1.intersection(g2); - } catch (TopologyException e) { - // This exception is due to g2 having interior - // intersections - section = clean(g1).intersection(g2.buffer(0)); - } - - if (section != null) { - setUserData(section, (CountyUserData) g2.getUserData()); - section.setUserData(g2.getUserData()); - intersections.add(section); + if (pg.intersects(g1)) { + Geometry g2 = pg.getGeometry(); + List sections = new ArrayList(); + 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); + } } } } - /** - * Returns a geometry from the noded line strings of g. - * - * @param g - * geometry to be cleaned up - * @return - */ - private static Geometry clean(Geometry g) { - Coordinate[] coords = g.getCoordinates(); - - // create a line string - GeometryFactory gf = new GeometryFactory(); - LineString ls = gf.createLineString(coords); - - // node the line string (insert vertices where lines cross) - com.vividsolutions.jts.geom.Point pt = gf.createPoint(ls - .getCoordinate()); - Geometry nodedLines = ls.union(pt); - - // create the polygon(s) from the noded line - Polygonizer polygonizer = new Polygonizer(); - polygonizer.add(nodedLines); - Collection polygons = polygonizer.getPolygons(); - - g = gf.createMultiPolygon( - polygons.toArray(new Polygon[polygons.size()])).buffer(0); - - return g; - } - /** * Get the difference between the 2 geometries * diff --git a/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/responses/DbQueryResponse.java b/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/responses/DbQueryResponse.java index 8d60a25624..62fcae6ef6 100644 --- a/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/responses/DbQueryResponse.java +++ b/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/responses/DbQueryResponse.java @@ -19,6 +19,8 @@ **/ package com.raytheon.uf.common.dataquery.responses; +import java.lang.reflect.Array; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -47,15 +49,31 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; @DynamicSerialize public class DbQueryResponse implements ISerializableObject { + public static final String ENTITY_RESULT_KEY = null; + @DynamicSerializeElement private List> results; public List> getResults() { - return results; + return results == null ? new ArrayList>() : results; } public void setResults(List> results) { this.results = results; } + public int getNumResults() { + return getResults().size(); + } + + @SuppressWarnings("unchecked") + public T[] getEntityObjects(Class entityType) { + List> results = getResults(); + T[] entities = (T[]) Array.newInstance(entityType, results.size()); + int i = 0; + for (Map result : results) { + entities[i++] = entityType.cast(result.get(ENTITY_RESULT_KEY)); + } + return entities; + } }