diff --git a/cave/build/static/common/cave/etc/bundles/maps/Locations.xml b/cave/build/static/common/cave/etc/bundles/maps/Locations.xml new file mode 100644 index 0000000000..4bcb92f960 --- /dev/null +++ b/cave/build/static/common/cave/etc/bundles/maps/Locations.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + PLAN_VIEW + + + + + + mapdata.location
+ cwa = '${site}' + Locations +
+
+
+
+
+
\ No newline at end of file diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/config/AbstractDbSourceDataAdaptor.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/config/AbstractDbSourceDataAdaptor.java new file mode 100644 index 0000000000..c1d4d113b9 --- /dev/null +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/config/AbstractDbSourceDataAdaptor.java @@ -0,0 +1,163 @@ +package com.raytheon.viz.warngen.config; + +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang.StringUtils; + +import com.raytheon.uf.common.dataplugin.warning.config.PointSourceConfiguration; +import com.raytheon.uf.common.dataplugin.warning.config.WarngenConfiguration; +import com.raytheon.uf.common.dataquery.requests.RequestConstraint; +import com.raytheon.uf.common.geospatial.ISpatialQuery.SearchMode; +import com.raytheon.uf.common.geospatial.SpatialException; +import com.raytheon.uf.common.geospatial.SpatialQueryFactory; +import com.raytheon.uf.common.geospatial.SpatialQueryResult; +import com.raytheon.uf.viz.core.exception.VizException; +import com.raytheon.uf.viz.core.maps.rsc.DbMapQueryFactory; +import com.raytheon.viz.warngen.gis.ClosestPoint; +import com.vividsolutions.jts.geom.Geometry; + +abstract public class AbstractDbSourceDataAdaptor { + + protected Set sortFields = new HashSet( + Arrays.asList(new String[] { "distance", "area", "parentArea" })); + + protected PointSourceConfiguration pointConfig; + + protected Geometry searchArea; + + protected String localizedSite; + + abstract protected Set createSpatialQueryField(); + + abstract protected ClosestPoint createClosestPoint(Set ptFields, + SpatialQueryResult ptRslt); + + abstract protected Map processFilterSubstitution(); + + public Collection getData(WarngenConfiguration config, + PointSourceConfiguration pointConfig, Geometry searchArea, + String localizedSite) throws VizException { + this.pointConfig = pointConfig; + this.searchArea = searchArea; + this.localizedSite = localizedSite; + + Map filter = processFilterSubstitution(); + Set ptFields = createSpatialQueryField(); + List points = null; + + try { + long t0 = System.currentTimeMillis(); + SpatialQueryResult[] ptFeatures = null; + Double decimationTolerance = pointConfig + .getGeometryDecimationTolerance(); + String field = "the_geom"; + + if (decimationTolerance != null && decimationTolerance > 0) { + // find available tolerances + List results = DbMapQueryFactory + .getMapQuery( + "mapdata." + + pointConfig.getPointSource() + .toLowerCase(), field) + .getLevels(); + Collections.sort(results, Collections.reverseOrder()); + + boolean found = false; + for (Double val : results) { + if (val <= decimationTolerance) { + decimationTolerance = val; + found = true; + break; + } + } + + if (!found) { + decimationTolerance = null; + } + } + + if (decimationTolerance != null) { + DecimalFormat df = new DecimalFormat("0.######"); + String suffix = "_" + + StringUtils.replaceChars( + df.format(decimationTolerance), '.', '_'); + ptFeatures = SpatialQueryFactory.create().query( + pointConfig.getPointSource(), field + suffix, + ptFields.toArray(new String[ptFields.size()]), + searchArea, filter, SearchMode.INTERSECTS); + } else { + ptFeatures = SpatialQueryFactory.create().query( + pointConfig.getPointSource(), + ptFields.toArray(new String[ptFields.size()]), + searchArea, filter, SearchMode.INTERSECTS); + } + + if (ptFeatures != null) { + points = new ArrayList(ptFeatures.length); + } else { + points = new ArrayList(0); + } + + for (SpatialQueryResult ptRslt : ptFeatures) { + if (ptRslt != null && ptRslt.geometry != null) { + Object nameObj = ptRslt.attributes.get(pointConfig + .getPointField()); + if (nameObj != null) { + ClosestPoint cp = createClosestPoint(ptFields, ptRslt); + points.add(cp); + } + } + } + System.out.println("Retrieve location data for '" + + pointConfig.getVariable() + "' = " + + (System.currentTimeMillis() - t0)); + } catch (SpatialException e) { + throw new VizException("Error querying " + + pointConfig.getPointSource() + " table: " + + e.getLocalizedMessage(), e); + } + + return points; + } + + protected int getPopulation(Set ptFields, + Map attributes) { + int population = 0; + + if (ptFields.contains("population")) { + try { + population = Integer.valueOf(String.valueOf(attributes + .get("population"))); + } catch (Exception e) { + // Ignore + } + } + + return population; + } + + protected int getWangenlev(Set ptFields, + Map attributes) { + int warngenlev = 0; + + if (ptFields.contains("warngenlev")) { + try { + warngenlev = Integer.valueOf(String.valueOf(attributes + .get("warngenlev"))); + } catch (Exception e) { + // Ignore + } + } + + return warngenlev; + } + +} diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/config/DataAdaptorFactory.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/config/DataAdaptorFactory.java index 0d495e0a83..30c27729fb 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/config/DataAdaptorFactory.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/config/DataAdaptorFactory.java @@ -19,10 +19,8 @@ **/ package com.raytheon.viz.warngen.config; -import java.util.HashMap; -import java.util.Map; - import com.raytheon.uf.common.dataplugin.warning.config.PointSourceConfiguration; +import com.raytheon.uf.common.dataplugin.warning.config.PointSourceConfiguration.PointType; /** * Creates data adaptors for PointSource and Pathcast data. @@ -43,16 +41,17 @@ import com.raytheon.uf.common.dataplugin.warning.config.PointSourceConfiguration public class DataAdaptorFactory { - private static Map, IPointSourceDataAdaptor> adapterMap = new HashMap, IPointSourceDataAdaptor>(); - static { - // Only data source config so far - adapterMap.put(PointSourceConfiguration.class, - new DbPointSourceDataAdaptor()); - } - - public static IPointSourceDataAdaptor createPointSource( + public static AbstractDbSourceDataAdaptor createPointSource( PointSourceConfiguration pointConfig) { - return adapterMap.get(pointConfig.getClass()); - } + AbstractDbSourceDataAdaptor adaptor = null; + + if (pointConfig.getType() == PointType.AREA) { + adaptor = new DbAreaSourceDataAdaptor(); + } else if (pointConfig.getType() == PointType.POINT) { + adaptor = new DbPointSourceDataAdaptor(); + } + + return adaptor; + } } 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 new file mode 100644 index 0000000000..9a7b476aef --- /dev/null +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/config/DbAreaSourceDataAdaptor.java @@ -0,0 +1,124 @@ +package com.raytheon.viz.warngen.config; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.geotools.referencing.GeodeticCalculator; + +import com.raytheon.uf.common.dataquery.requests.RequestConstraint; +import com.raytheon.uf.common.geospatial.SpatialQueryResult; +import com.raytheon.viz.warngen.PreferenceUtil; +import com.raytheon.viz.warngen.gis.ClosestPoint; +import com.raytheon.viz.warngen.gis.GisUtil; +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.Geometry; + +/** + * + * @author jsanchez + * + */ +public class DbAreaSourceDataAdaptor extends AbstractDbSourceDataAdaptor { + + private static final String useDirectionField = "usedirs"; + + private static final String suppressedDirectionsField = "supdirs"; + + private static final String cwaField = "cwa"; + + private GeodeticCalculator gc = new GeodeticCalculator(); + + /** + * + */ + @Override + protected Set createSpatialQueryField() { + Set ptFields = new HashSet(); + ptFields.add(pointConfig.getPointField()); + ptFields.add(useDirectionField); + ptFields.add(suppressedDirectionsField); + + List fields = new ArrayList(); + if (pointConfig.getSortBy() != null) { + fields = Arrays.asList(pointConfig.getSortBy()); + } + + for (String field : fields) { + if (sortFields.contains(field.toLowerCase()) == false) { + ptFields.add(field.toLowerCase()); + } + } + + return ptFields; + } + + /** + * + */ + @Override + protected ClosestPoint createClosestPoint(Set ptFields, + SpatialQueryResult ptRslt) { + Map attributes = ptRslt.attributes; + + String name = String + .valueOf(attributes.get(pointConfig.getPointField())); + Coordinate point = ptRslt.geometry.getCoordinate(); + int population = getPopulation(ptFields, attributes); + int warngenlev = getWangenlev(ptFields, attributes); + List partOfArea = getPartOfArea(ptFields, attributes, + ptRslt.geometry); + + return new ClosestPoint(name, point, population, warngenlev, partOfArea); + } + + /** + * + * @param ptFields + * @param attributes + * @param geom + * @return + */ + private List getPartOfArea(Set ptFields, + Map attributes, Geometry geom) { + List partOfArea = null; + + boolean userDirections = Boolean.valueOf(String.valueOf(attributes + .get(useDirectionField))); + if (userDirections) { + Geometry intersection = searchArea.intersection(geom); + partOfArea = GisUtil.asStringList(GisUtil.calculatePortion(geom, + intersection, gc, "")); + + String suppressedDirections = String.valueOf(attributes + .get(suppressedDirectionsField)); + partOfArea.remove(suppressedDirections); + } + + return partOfArea; + } + + @Override + protected Map processFilterSubstitution() { + Map filter = pointConfig.getFilter(); + if (filter != null) { + // Process substitutes for filter + for (RequestConstraint rc : filter.values()) { + rc.setConstraintValue(PreferenceUtil.substitute( + rc.getConstraintValue(), localizedSite)); + } + } + + if (filter == null) { + filter = new HashMap(); + } + + filter.put(cwaField, new RequestConstraint(localizedSite)); + + return filter; + } +} diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/config/DbPointSourceDataAdaptor.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/config/DbPointSourceDataAdaptor.java index 5016f1dad5..351224ce2c 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/config/DbPointSourceDataAdaptor.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/config/DbPointSourceDataAdaptor.java @@ -21,23 +21,16 @@ package com.raytheon.viz.warngen.config; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; -import com.raytheon.uf.common.dataplugin.warning.config.PointSourceConfiguration; -import com.raytheon.uf.common.dataplugin.warning.config.WarngenConfiguration; import com.raytheon.uf.common.dataquery.requests.RequestConstraint; -import com.raytheon.uf.common.geospatial.ISpatialQuery.SearchMode; -import com.raytheon.uf.common.geospatial.SpatialException; -import com.raytheon.uf.common.geospatial.SpatialQueryFactory; import com.raytheon.uf.common.geospatial.SpatialQueryResult; -import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.viz.warngen.PreferenceUtil; import com.raytheon.viz.warngen.gis.ClosestPoint; -import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.Coordinate; /** * PointSource data adaptor for data retrieved from a Database. @@ -56,24 +49,43 @@ import com.vividsolutions.jts.geom.Geometry; * @version 1.0 */ -public class DbPointSourceDataAdaptor implements IPointSourceDataAdaptor { +public class DbPointSourceDataAdaptor extends AbstractDbSourceDataAdaptor { - /* - * (non-Javadoc) - * - * @see - * com.raytheon.viz.warngen.config.IPointSourceDataAdaptor#findClosestPoints - * ( - * com.raytheon.uf.common.dataplugin.warning.config.PointSourceConfiguration - * , java.lang.String) - */ @Override - public Collection getData(WarngenConfiguration warngenConfig, - PointSourceConfiguration pointConfig, Geometry searchArea, - String localizedSite) throws VizException { - String pointSource = pointConfig.getPointSource(); - String pointField = pointConfig.getPointField(); + protected Set createSpatialQueryField() { + Set ptFields = new HashSet(); + ptFields.add(pointConfig.getPointField()); + List fields = new ArrayList(); + if (pointConfig.getSortBy() != null) { + fields = Arrays.asList(pointConfig.getSortBy()); + } + + for (String field : fields) { + if (sortFields.contains(field.toLowerCase()) == false) { + ptFields.add(field.toLowerCase()); + } + } + + return ptFields; + } + + @Override + protected ClosestPoint createClosestPoint(Set ptFields, + SpatialQueryResult ptRslt) { + Map attributes = ptRslt.attributes; + + String name = String + .valueOf(attributes.get(pointConfig.getPointField())); + Coordinate point = ptRslt.geometry.getCoordinate(); + int population = getPopulation(ptFields, attributes); + int warngenlev = getWangenlev(ptFields, attributes); + + return new ClosestPoint(name, point, population, warngenlev, null); + } + + @Override + protected Map processFilterSubstitution() { Map filter = pointConfig.getFilter(); if (filter != null) { // Process substitutes for filter @@ -83,64 +95,6 @@ public class DbPointSourceDataAdaptor implements IPointSourceDataAdaptor { } } - List fields = pointConfig.getSortBy() != null ? Arrays - .asList(pointConfig.getSortBy()) : new ArrayList(); - - Set ptFields = new HashSet(); - ptFields.add(pointField); - for (String field : fields) { - if (!field.equalsIgnoreCase("distance") - && !field.equalsIgnoreCase("area") - && !field.equalsIgnoreCase("parentArea")) { - ptFields.add(field.toLowerCase()); - } - } - - List points = new ArrayList(); - - try { - SpatialQueryResult[] ptFeatures = SpatialQueryFactory.create() - .query(pointSource, - ptFields.toArray(new String[ptFields.size()]), - searchArea, filter, SearchMode.INTERSECTS); - for (SpatialQueryResult ptRslt : ptFeatures) { - if (ptRslt != null && ptRslt.geometry != null) { - Object nameObj = ptRslt.attributes.get(pointField); - if (nameObj != null) { - int population = 0; - int warngenlev = 0; - ClosestPoint cp = new ClosestPoint(); - - if (ptFields.contains("population")) { - try { - population = Integer.valueOf(String - .valueOf(ptRslt.attributes - .get("population"))); - } catch (Exception e) { - // Ignore - } - } - if (ptFields.contains("warngenlev")) { - try { - warngenlev = Integer.valueOf(String - .valueOf(ptRslt.attributes - .get("warngenlev"))); - } catch (Exception e) { - // Ignore - } - } - - points.add(new ClosestPoint(nameObj.toString(), - ptRslt.geometry.getCoordinate(), population, - warngenlev)); - } - } - } - } catch (SpatialException e) { - throw new VizException("Error querying " + pointSource + " table: " - + e.getLocalizedMessage(), e); - } - - return points; + return filter; } } diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/config/IPointSourceDataAdaptor.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/config/IPointSourceDataAdaptor.java deleted file mode 100644 index 3b6f798198..0000000000 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/config/IPointSourceDataAdaptor.java +++ /dev/null @@ -1,54 +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.viz.warngen.config; - -import java.util.Collection; - -import com.raytheon.uf.common.dataplugin.warning.config.PointSourceConfiguration; -import com.raytheon.uf.common.dataplugin.warning.config.WarngenConfiguration; -import com.raytheon.uf.viz.core.exception.VizException; -import com.raytheon.viz.warngen.gis.ClosestPoint; -import com.vividsolutions.jts.geom.Geometry; - -/** - * PointSource data. Implementations need to be stateless as they will be used - * as singletons. - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Oct 26, 2011            bgonzale     Initial creation
- * 
- * 
- * - * @author bgonzale - * @version 1.0 - */ - -public interface IPointSourceDataAdaptor { - - public Collection getData(WarngenConfiguration warngenConfig, - PointSourceConfiguration pointConfig, Geometry searchArea, - String localizedSite) throws VizException; - -} 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 951197ee00..d9a6e9f085 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 @@ -27,8 +27,8 @@ import java.util.List; import java.util.Map; import org.apache.commons.lang.Validate; +import org.geotools.referencing.GeodeticCalculator; -import com.raytheon.uf.common.dataplugin.warning.config.AreaConfiguration; import com.raytheon.uf.common.dataplugin.warning.config.AreaSourceConfiguration; import com.raytheon.uf.common.dataplugin.warning.config.AreaSourceConfiguration.AreaType; import com.raytheon.uf.common.dataplugin.warning.config.GeospatialConfiguration; @@ -70,7 +70,7 @@ import com.vividsolutions.jts.geom.Geometry; * MarineZones shapefiles have no FE_AREA. * Apr 13, 2012 #14691 Qinglu lin Added code for two more fe_area: er and nr. * May 4, 2012 #14887 Qinglu lin Changed 0.25 to 0.60 for DEFAULT_PORTION_TOLERANCE; - * added code to pass a Envelope calculatePortion(). + * added code to pass a Envelope calculatePortion(). * * * @@ -105,14 +105,14 @@ public class Area { GeometryUtil.buildGeometryList(geoms, warningArea); GeospatialConfiguration geospatialConfig = config.getGeospatialConfig(); - AreaConfiguration areaConfig = config.getAreaConfig(); + AreaSourceConfiguration areaConfig = config.getHatchedAreaSource(); return findAffectedAreas(areaConfig, geospatialConfig, polygon, localizedSite, geoms); } private static AffectedAreas[] findAffectedAreas( - AreaConfiguration areaConfig, + AreaSourceConfiguration areaConfig, GeospatialConfiguration geospatialConfig, Geometry polygon, String localizedSite, List geoms) throws VizException { String areaSource = areaConfig.getAreaSource(); @@ -172,8 +172,9 @@ public class Area { List uniqueFips = new ArrayList(); List areas = new ArrayList(); + GeodeticCalculator gc = new GeodeticCalculator(); for (GeospatialData regionFeature : countyMap.values()) { - Geometry regionGeom = regionFeature.geometry; + Geometry regionGeom = regionFeature.geometry; AffectedAreas area = new AffectedAreas(); area.name = regionFeature.attributes.get(areaField).toString(); area.fips = regionFeature.attributes.get(fipsField).toString(); @@ -217,7 +218,8 @@ public class Area { * DEFAULT_PORTION_TOLERANCE; if (areaIntersection < tolerCheck) { area.partOfArea = GisUtil.asStringList(GisUtil - .calculatePortion(regionGeom, intersection, area.suppress)); + .calculatePortion(regionGeom, intersection, gc, + area.suppress)); } // Search the parent region @@ -225,66 +227,67 @@ public class Area { if (parentRegion != null) { area.parentRegion = String.valueOf(parentRegion.attributes .get(parentAreaField)); - String feArea = (String)regionFeature.attributes.get("FE_AREA"); - final List partList = new ArrayList(); + String feArea = (String) regionFeature.attributes + .get("FE_AREA"); + final List partList = new ArrayList(); if (feArea == null) { - // Marine warnings - partList.add(""); + // Marine warnings + partList.add(""); } else { - if (feArea.equals("pa")) - partList.add("PA"); - else if(feArea.equals("mi")) - partList.add("MI"); - else if(feArea.equals("pd")) - partList.add("PD"); - else if(feArea.equals("up")) - partList.add("UP"); - else if(feArea.equals("bb")) - partList.add("BB"); - else if(feArea.equals("er")) - partList.add("ER"); - else if(feArea.equals("eu")) - partList.add("EU"); - else if(feArea.equals("sr")) - partList.add("SR"); - else if(feArea.equals("nr")) - partList.add("NR"); - else if(feArea.equals("wu")) - partList.add("WU"); - else if(feArea.equals("ds")) - partList.add("DS"); - else if(feArea.equals("ne")) - partList.add("NE"); - else if(feArea.equals("nw")) - partList.add("NW"); - else if(feArea.equals("se")) - partList.add("SE"); - else if(feArea.equals("sw")) - partList.add("SW"); - else { - for (int i=0; i areasMap = new HashMap(); for (AreaSourceConfiguration asc : config.getAreaSources()) { - if (asc.getAreaType() == AreaType.INTERSECT) { + if (asc.getType() == AreaType.INTERSECT) { String areaSource = asc.getAreaSource(); String key = areaSource + "." + localizedSite; @@ -339,9 +342,9 @@ public class Area { } } - AffectedAreas[] affectedAreas = findAffectedAreas( - asc.getAreaConfig(), config.getGeospatialConfig(), - warnPolygon, localizedSite, geoms); + AffectedAreas[] affectedAreas = findAffectedAreas(asc, + config.getGeospatialConfig(), warnPolygon, + localizedSite, geoms); areasMap.put(asc.getVariable(), affectedAreas); } diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/ClosestPoint.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/ClosestPoint.java index 4a7a7d35ea..5f9bbf0c16 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/ClosestPoint.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/ClosestPoint.java @@ -20,6 +20,7 @@ package com.raytheon.viz.warngen.gis; import java.util.Date; +import java.util.List; import com.vividsolutions.jts.geom.Coordinate; @@ -69,36 +70,40 @@ public class ClosestPoint implements Comparable { protected Date time; + protected List partOfArea; + public ClosestPoint() { } public ClosestPoint(ClosestPoint o) { - this.name = o.name; - this.area = o.area; - this.parentArea = o.parentArea; - this.point = o.point; - this.distance = o.distance; - this.roundedDistance = o.roundedDistance; - this.azimuth = o.azimuth; - this.roundedAzimuth = o.roundedAzimuth; - this.oppositeAzimuth = o.oppositeAzimuth; - this.oppositeRoundedAzimuth = o.oppositeRoundedAzimuth; - this.population = o.population; - this.warngenlev = o.warngenlev; - this.time = o.time; - } + this.name = o.name; + this.area = o.area; + this.parentArea = o.parentArea; + this.point = o.point; + this.distance = o.distance; + this.roundedDistance = o.roundedDistance; + this.azimuth = o.azimuth; + this.roundedAzimuth = o.roundedAzimuth; + this.oppositeAzimuth = o.oppositeAzimuth; + this.oppositeRoundedAzimuth = o.oppositeRoundedAzimuth; + this.population = o.population; + this.warngenlev = o.warngenlev; + this.time = o.time; + this.partOfArea = o.partOfArea; + } - public ClosestPoint(String name, Coordinate point) { - this(name, point, 0, 0); + public ClosestPoint(String name, Coordinate point) { + this(name, point, 0, 0, null); } public ClosestPoint(String name, Coordinate point, int population, - int warngenlev) { + int warngenlev, List partOfArea) { this.name = name; this.point = point; this.population = population; this.warngenlev = warngenlev; + this.partOfArea = partOfArea; } /** @@ -108,6 +113,10 @@ public class ClosestPoint implements Comparable { return name; } + public Coordinate getPoint() { + return point; + } + /** * @return the distance */ @@ -160,6 +169,10 @@ public class ClosestPoint implements Comparable { return parentArea; } + public List getPartOfArea() { + return partOfArea; + } + /** * Adjusts the angle from -360/360 to be between -180/180 * 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 667c25d1ee..538a6294a7 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 @@ -66,27 +66,33 @@ import com.vividsolutions.jts.geom.Polygon; public class GisUtil { private static final float PORTION_OF_CENTER = 0.16875f; - + private static final float DIRECTION_DELTA = 15; private static final float EXTREME_DELTA = 0.0625f; private static final double CONTAINS_PERCENTAGE = 0.1; - - // When both xDirection and yDirection are Direction.CENTRAL, for a rectangle - // polygon, MIN1 is the maximum value of either distanceX or distanceY + + // When both xDirection and yDirection are Direction.CENTRAL, for a + // rectangle + // polygon, MIN1 is the maximum value of either distanceX or distanceY // for EnumSet.of(xDirection,yDirection) to be returned. private static final float MIN1 = 0.01f; - - // When both xDirection and yDirection are Direction.CENTRAL, for a right triangle - // polygon, MIN2 is the maximum value of both distanceX and distanceY + + // When both xDirection and yDirection are Direction.CENTRAL, for a right + // triangle + // polygon, MIN2 is the maximum value of both distanceX and distanceY // for EnumSet.of(xDirection,yDirection) to be returned. private static final float MIN2 = 0.045f; - - // When yDirection is NORTH or SOUTH, in order to add CENTRAL to retval, required - // minimum ratio of width of intersection envelope to that of county envelope; - // when xDirection is EAST or WEST, in order to add CENTRAL to retval, required - // minimum ratio of height of intersection envelope to that of county envelope; + + // When yDirection is NORTH or SOUTH, in order to add CENTRAL to retval, + // required + // minimum ratio of width of intersection envelope to that of county + // envelope; + // when xDirection is EAST or WEST, in order to add CENTRAL to retval, + // required + // minimum ratio of height of intersection envelope to that of county + // envelope; private static final float RATIO = 0.5f; public static enum Direction { @@ -135,12 +141,12 @@ public class GisUtil { } public static EnumSet calculatePortion(Geometry geom, - Geometry geom2) { - return calculatePortion(geom, geom2, SuppressMap.NONE); + Geometry geom2, GeodeticCalculator gc) { + return calculatePortion(geom, geom2, gc, SuppressMap.NONE); } public static EnumSet calculatePortion(Geometry geom, - Geometry intersection, String suppressType) { + Geometry intersection, GeodeticCalculator gc, String suppressType) { Direction xDirection = null; Direction yDirection = null; @@ -161,23 +167,25 @@ public class GisUtil { double extremaThresholdY = approximateHeight * EXTREME_DELTA; if (distanceX < centerThresholdX) { - xDirection = Direction.CENTRAL; - if (distanceY < centerThresholdY) - yDirection = Direction.CENTRAL; + xDirection = Direction.CENTRAL; + if (distanceY < centerThresholdY) + yDirection = Direction.CENTRAL; } if (xDirection != null && yDirection != null) { - // Both xDirection equals Direction.CENTRAL and yDirection equals Direction.CENTRAL - // calculated above is not always correct for returning EnumSet.of(xDirection,yDirection). - // The following 'if statement' filters out some cases. - if (distanceX < MIN1 || distanceY < MIN1 || (distanceX < MIN2 && distanceY < MIN2)) - return EnumSet.of(xDirection,yDirection); + // Both xDirection equals Direction.CENTRAL and yDirection equals + // Direction.CENTRAL + // calculated above is not always correct for returning + // EnumSet.of(xDirection,yDirection). + // The following 'if statement' filters out some cases. + if (distanceX < MIN1 || distanceY < MIN1 + || (distanceX < MIN2 && distanceY < MIN2)) + return EnumSet.of(xDirection, yDirection); } - + xDirection = null; yDirection = null; - - GeodeticCalculator gc = new GeodeticCalculator(); + gc.setStartingGeographicPoint(centroid.x, centroid.y); gc.setDestinationGeographicPoint(point.x, point.y); double azimuth = gc.getAzimuth(); @@ -229,26 +237,32 @@ public class GisUtil { && !suppressType.equals(SuppressMap.ALL)) retVal.add(yDirection); - if (xDirection != null && - (xDirection.equals(Direction.WEST) || xDirection.equals(Direction.EAST))) { - if ( env.getHeight() < RATIO*approximateHeight) { + if (xDirection != null + && (xDirection.equals(Direction.WEST) || xDirection + .equals(Direction.EAST))) { + if (env.getHeight() < RATIO * approximateHeight) { retVal.add(Direction.CENTRAL); } } - if (yDirection != null && - (yDirection.equals(Direction.NORTH) || yDirection.equals(Direction.SOUTH))) { - if ( env.getWidth() < RATIO*approximateWidth) { + if (yDirection != null + && (yDirection.equals(Direction.NORTH) || yDirection + .equals(Direction.SOUTH))) { + if (env.getWidth() < RATIO * approximateWidth) { retVal.add(Direction.CENTRAL); } } - - if ((retVal.contains(Direction.NORTH) && retVal.contains(Direction.WEST)) || - (retVal.contains(Direction.NORTH) && retVal.contains(Direction.EAST)) || - (retVal.contains(Direction.SOUTH) && retVal.contains(Direction.WEST)) || - (retVal.contains(Direction.SOUTH) && retVal.contains(Direction.EAST)) ) { - if (retVal.contains(Direction.CENTRAL)) - retVal.remove(Direction.CENTRAL); + + if ((retVal.contains(Direction.NORTH) && retVal + .contains(Direction.WEST)) + || (retVal.contains(Direction.NORTH) && retVal + .contains(Direction.EAST)) + || (retVal.contains(Direction.SOUTH) && retVal + .contains(Direction.WEST)) + || (retVal.contains(Direction.SOUTH) && retVal + .contains(Direction.EAST))) { + if (retVal.contains(Direction.CENTRAL)) + retVal.remove(Direction.CENTRAL); } if (isExtreme && !suppressType.equals(SuppressMap.ALL)) @@ -286,11 +300,11 @@ public class GisUtil { coord.x = oldCoord.x; } coord.y = oldCoord.y; - + return coord; - + } - + public static Coordinate[] d2dCoordinates(Coordinate[] oldCoords) { int length = oldCoords.length; Coordinate[] coords = new Coordinate[length]; @@ -327,15 +341,15 @@ public class GisUtil { /** * restoreAlaskaLon() * - * Feb 28, 2012 DR13596 Qinglu Lin Created. + * Feb 28, 2012 DR13596 Qinglu Lin Created. * - * If the longitude of a Coordinate is less than -180 and corresponding - * latitude is larger than 45 degree North, convert it to a value - * equivalent to (360 + the longitude). + * If the longitude of a Coordinate is less than -180 and corresponding + * latitude is larger than 45 degree North, convert it to a value equivalent + * to (360 + the longitude). */ public static Coordinate restoreAlaskaLon(Coordinate oldCoords) { Coordinate coord = new Coordinate(); - if (oldCoords.x < -180. && oldCoords.y > 45.) { + if (oldCoords.x < -180. && oldCoords.y > 45.) { coord.x = 360. + oldCoords.x; } else { coord.x = oldCoords.x; 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 d043a14cad..e2aa149cc5 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 @@ -40,7 +40,6 @@ import javax.measure.converter.UnitConverter; import javax.measure.unit.NonSI; import javax.measure.unit.SI; -import org.apache.commons.lang.Validate; import org.eclipse.jface.action.IMenuManager; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; @@ -53,8 +52,6 @@ import org.opengis.referencing.operation.MathTransform; import com.raytheon.uf.common.activetable.ActiveTableRecord; import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord; -import com.raytheon.uf.common.dataplugin.warning.config.AreaSourceConfiguration; -import com.raytheon.uf.common.dataplugin.warning.config.AreaSourceConfiguration.AreaType; import com.raytheon.uf.common.dataplugin.warning.config.BulletActionGroup; import com.raytheon.uf.common.dataplugin.warning.config.DialogConfiguration; import com.raytheon.uf.common.dataplugin.warning.config.GridSpacing; @@ -169,7 +166,7 @@ public class WarngenLayer extends AbstractStormTrackResource { } private static Map siteMap = new HashMap(); - + private static Map timezoneMap = new HashMap(); public static final String GID = "gid"; @@ -678,17 +675,6 @@ public class WarngenLayer extends AbstractStormTrackResource { private void init(WarngenConfiguration config) { long t0 = System.currentTimeMillis(); - boolean validAreaSource = false; - for (AreaSourceConfiguration as : config.getAreaSources()) { - if (as.getAreaType() == AreaType.HATCHING) { - validAreaSource = true; - break; - } - } - - Validate.isTrue(validAreaSource, - "At least one area source should have an areaType 'HATCHING'"); - String site = getLocalizedSite(); Map metadataMap = GeospatialFactory .getMetaDataMap(config); @@ -746,20 +732,22 @@ public class WarngenLayer extends AbstractStormTrackResource { locals).getEnvelopeInternal(); IExtent localExtent = new PixelExtent(env.getMinX(), env.getMaxX(), env.getMinY(), env.getMaxY()); - + int nx = 600; int ny = 600; - // Boolean to change the aspect ratio of the extent to match + // Boolean to change the aspect ratio of the extent to + // match boolean keepAspectRatio = true; - + GridSpacing gridSpacing = dialogConfig.getGridSpacing(); - - if (gridSpacing != null && gridSpacing.getNx() != null && gridSpacing != null) { + + if (gridSpacing != null && gridSpacing.getNx() != null + && gridSpacing != null) { nx = gridSpacing.getNx(); ny = gridSpacing.getNy(); keepAspectRatio = gridSpacing.isKeepAspectRatio(); } - + double xinc, yinc; double width = localExtent.getWidth(); double height = localExtent.getHeight(); @@ -786,20 +774,25 @@ public class WarngenLayer extends AbstractStormTrackResource { System.out.println("Time to lookup geospatial data " + (System.currentTimeMillis() - tq0)); siteMap.put(currKey, gData); - - GeospatialData[] timezones = GeospatialFactory.getTimezones(); + + GeospatialData[] timezones = GeospatialFactory + .getTimezones(); if (timezones != null) { for (GeospatialData timezone : timezones) { - if (timezone.attributes.containsKey(gmd.getTimeZoneField())) { - String oneLetterTimezone = String.valueOf( - timezone.attributes.get(gmd.getTimeZoneField())); - if (timezoneMap.containsKey(oneLetterTimezone) == false) { - timezoneMap.put(oneLetterTimezone, timezone.geometry); + if (timezone.attributes.containsKey(gmd + .getTimeZoneField())) { + String oneLetterTimezone = String + .valueOf(timezone.attributes + .get(gmd.getTimeZoneField())); + if (timezoneMap + .containsKey(oneLetterTimezone) == false) { + timezoneMap.put(oneLetterTimezone, + timezone.geometry); } } } } - + } catch (Exception e) { statusHandler.handle(Priority.WARN, "Error in initializing geometries.", e); @@ -857,7 +850,7 @@ public class WarngenLayer extends AbstractStormTrackResource { return new GeospatialData[0]; } - + public Geometry getTimezoneGeom(String oneLetterTimezone) { return timezoneMap.get(oneLetterTimezone); } @@ -990,9 +983,10 @@ public class WarngenLayer extends AbstractStormTrackResource { if (polygon != null) { for (GeospatialData r : geoData.features) { PreparedGeometry prepGeom = (PreparedGeometry) r.attributes - .get(GeospatialDataList.LOCAL_PREP_GEOM); + .get(GeospatialDataList.LOCAL_PREP_GEOM); try { - Geometry intersection = GeometryUtil.intersection(polygon, prepGeom); + Geometry intersection = GeometryUtil.intersection(polygon, + prepGeom); if (intersection.isEmpty()) { continue; } @@ -1035,7 +1029,7 @@ public class WarngenLayer extends AbstractStormTrackResource { if (configuration.getGeospatialConfig().getAreaSource() .equalsIgnoreCase(MARINE)) { fips = String.valueOf(data.entry.attributes.get(configuration - .getAreaConfig().getFipsField())); + .getHatchedAreaSource().getFipsField())); if (countyMap.containsKey(fips.substring(0, 2))) { ids = countyMap.get(fips.substring(0, 2)); for (String id : ids) { @@ -1047,12 +1041,13 @@ public class WarngenLayer extends AbstractStormTrackResource { } } else { String stateAbbr = String.valueOf(data.entry.attributes - .get(configuration.getAreaConfig() + .get(configuration.getHatchedAreaSource() .getAreaNotationField())); if (countyMap.containsKey(stateAbbr)) { ids = countyMap.get(stateAbbr); fips = String.valueOf(data.entry.attributes - .get(configuration.getAreaConfig().getFipsField())); + .get(configuration.getHatchedAreaSource() + .getFipsField())); for (String id : ids) { if (fips.endsWith(id)) { newList.add(geom); @@ -1180,19 +1175,19 @@ public class WarngenLayer extends AbstractStormTrackResource { boolean includeArea = false; if (!determineInclusion) { includeArea = areaInKmSqOfIntersection > 1; - } else if (getConfiguration().getAreaConfig() + } else if (getConfiguration().getHatchedAreaSource() .getInclusionAndOr().equalsIgnoreCase("AND")) { - if ((ratioInPercent >= getConfiguration().getAreaConfig() - .getInclusionPercent()) + if ((ratioInPercent >= getConfiguration() + .getHatchedAreaSource().getInclusionPercent()) && (areaInKmSqOfIntersection > getConfiguration() - .getAreaConfig().getInclusionArea())) { + .getHatchedAreaSource().getInclusionArea())) { includeArea = true; } } else { - if ((ratioInPercent >= getConfiguration().getAreaConfig() - .getInclusionPercent()) + if ((ratioInPercent >= getConfiguration() + .getHatchedAreaSource().getInclusionPercent()) || (areaInKmSqOfIntersection > getConfiguration() - .getAreaConfig().getInclusionArea())) { + .getHatchedAreaSource().getInclusionArea())) { includeArea = true; } } @@ -1356,7 +1351,7 @@ public class WarngenLayer extends AbstractStormTrackResource { c[2] = new Coordinate(p3.getX(), p3.getY()); c[3] = new Coordinate(p4.getX(), p4.getY()); c[4] = c[0]; - + PolygonUtil.truncate(c, 2); LinearRing lr = gf.createLinearRing(c); @@ -1564,7 +1559,7 @@ public class WarngenLayer extends AbstractStormTrackResource { c[2] = new Coordinate(p3.getX(), p3.getY()); c[3] = new Coordinate(p4.getX(), p4.getY()); c[4] = c[0]; - + PolygonUtil.truncate(c, 2); LinearRing lr = gf.createLinearRing(c); @@ -1946,10 +1941,10 @@ public class WarngenLayer extends AbstractStormTrackResource { for (int j = 0; j < ls.length; j++) { if (i != j && ls[i].intersection(ls[j]) != null - && ls[i].intersection(ls[j]).equals(ls[i] - .getCoordinate(0)) == false - && ls[i].intersection(ls[j]).equals(ls[i] - .getCoordinate(1)) == false) { + && ls[i].intersection(ls[j]).equals( + ls[i].getCoordinate(0)) == false + && ls[i].intersection(ls[j]).equals( + ls[i].getCoordinate(1)) == false) { intersectFlag = true; } } @@ -2150,7 +2145,8 @@ public class WarngenLayer extends AbstractStormTrackResource { for (GeospatialData f : geoData.features) { Geometry geom = f.geometry; if (prefixes.contains(GeometryUtil.getPrefix(geom.getUserData()))) { - Coordinate center = GisUtil.d2dCoordinate(geom.getCentroid().getCoordinate()); + Coordinate center = GisUtil.d2dCoordinate(geom.getCentroid() + .getCoordinate()); state.strings.put(center, "W"); } } diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/template/TemplateRunner.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/template/TemplateRunner.java index 6808209fb6..fc75fba333 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/template/TemplateRunner.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/template/TemplateRunner.java @@ -22,14 +22,17 @@ package com.raytheon.viz.warngen.template; import java.awt.geom.Point2D; import java.io.StringWriter; import java.text.DateFormat; +import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; +import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.HashMap; import java.util.Properties; @@ -41,12 +44,14 @@ import javax.measure.converter.UnitConverter; import javax.measure.unit.NonSI; import javax.measure.unit.SI; +import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.Validate; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.Velocity; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.tools.generic.ListTool; +import org.geotools.referencing.GeodeticCalculator; import com.raytheon.uf.common.activetable.ActiveTableMode; import com.raytheon.uf.common.activetable.ActiveTableRecord; @@ -67,6 +72,7 @@ import com.raytheon.uf.common.time.DataTime; import com.raytheon.uf.common.time.SimulatedTime; import com.raytheon.uf.edex.core.EdexException; import com.raytheon.uf.viz.core.exception.VizException; +import com.raytheon.uf.viz.core.maps.rsc.DbMapQueryFactory; import com.raytheon.uf.viz.core.requests.ThriftClient; import com.raytheon.viz.awipstools.ToolsDataManager; import com.raytheon.viz.awipstools.common.StormTrackData; @@ -96,6 +102,7 @@ import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryCollection; import com.vividsolutions.jts.geom.Polygon; +import com.vividsolutions.jts.geom.prep.PreparedGeometry; import com.vividsolutions.jts.io.WKTReader; /** @@ -218,7 +225,8 @@ public class TemplateRunner { context.put("dateUtil", new DateUtil()); context.put("pointComparator", new ClosestPointComparator()); - String action = followupData != null ? followupData.getAct() : WarningAction.NEW.toString(); + String action = followupData != null ? followupData.getAct() + : WarningAction.NEW.toString(); String phen = followupData != null ? followupData.getPhen() : null; String sig = followupData != null ? followupData.getSig() : null; String etn = followupData != null ? followupData.getEtn() : null; @@ -234,7 +242,7 @@ public class TemplateRunner { threeLetterSiteId); System.out.println("Time to get areas = " + (System.currentTimeMillis() - t0)); - context.put(config.getAreaConfig().getVariable(), areas); + context.put(config.getHatchedAreaSource().getVariable(), areas); t0 = System.currentTimeMillis(); intersectAreas = Area.findInsectingAreas(config, warnPolygon, @@ -249,20 +257,21 @@ public class TemplateRunner { String[] oneLetterTZ; double minSize = 1.0E-3d; if (areas != null && areas.length > 0) { - Set timeZones = new HashSet(); + Set timeZones = new HashSet(); for (AffectedAreas area : areas) { if (area.getTimezone() != null) { // Handles counties that span two time zones String oneLetterTimeZones = area.getTimezone().trim(); oneLetterTZ = new String[oneLetterTimeZones.length()]; if (oneLetterTimeZones.length() == 1) { - timeZones.add(String.valueOf(oneLetterTimeZones.charAt(0))); + timeZones.add(String.valueOf(oneLetterTimeZones + .charAt(0))); } else { // Determine if one letter timezone is going to be put into timeZones. Polygon[] poly1, poly2; int n1, n2; double size, totalSize; - for (int i = 0; i < oneLetterTimeZones.length(); i++) { + for (int i = 0; i < oneLetterTimeZones.length(); i++) { oneLetterTZ[i] = String.valueOf(oneLetterTimeZones.charAt(i)); Geometry timezoneGeom = warngenLayer.getTimezoneGeom(oneLetterTZ[i]); t0 = System.currentTimeMillis(); @@ -298,8 +307,8 @@ public class TemplateRunner { + (System.currentTimeMillis() - t0)); if (totalSize > minSize) { timeZones.add(oneLetterTZ[i]); - } - } + } + } // If timeZones has nothing in it when the hatched area is very small, // use the timezone of larger intersection size. if (timeZones.size() == 0 ) { @@ -321,11 +330,11 @@ public class TemplateRunner { Iterator iterator = timeZones.iterator(); while (iterator.hasNext()) { - if (context.get("localtimezone") == null) { - context.put("localtimezone", iterator.next()); - } else if (context.get("secondtimezone") == null) { - context.put("secondtimezone", iterator.next()); - } + if (context.get("localtimezone") == null) { + context.put("localtimezone", iterator.next()); + } else if (context.get("secondtimezone") == null) { + context.put("secondtimezone", iterator.next()); + } } } @@ -392,8 +401,7 @@ public class TemplateRunner { context.put("movementDirection", motionDirection); // Convert to Point2D representation as Velocity requires // getX() and getY() methods which Coordinate does not have - Coordinate[] newStormLocs = GisUtil - .d2dCoordinates(stormLocs); + Coordinate[] newStormLocs = GisUtil.d2dCoordinates(stormLocs); Point2D.Double[] coords = new Point2D.Double[newStormLocs.length]; for (int i = 0; i < newStormLocs.length; i++) { coords[i] = new Point2D.Double(newStormLocs[i].x, @@ -524,8 +532,10 @@ public class TemplateRunner { if (totalSegments > 1) { al = FollowUpUtil.canceledAreasFromText(originalText); } - context.put("cancel"+ config.getAreaConfig().getVariable(), al); - context.put("ugclinecan", FollowUpUtil.getUgcLineCanFromText(originalText)); + context.put("cancel" + + config.getHatchedAreaSource().getVariable(), al); + context.put("ugclinecan", + FollowUpUtil.getUgcLineCanFromText(originalText)); } else if (selectedAction == WarningAction.EXT) { context.put("action", WarningAction.EXT.toString()); context.put("etn", etn); @@ -573,7 +583,8 @@ public class TemplateRunner { } } context.put("cancel" - + config.getAreaConfig().getVariable(), al); + + config.getHatchedAreaSource().getVariable(), + al); // This may not be efficient enough. Is it possible that // a removed intersected county be in the affected @@ -641,7 +652,7 @@ public class TemplateRunner { + (System.currentTimeMillis() - tz0)); return WarningTextHandler.handle(script.toString().toUpperCase(), - areas, cancelareas, selectedAction, + areas, cancelareas, selectedAction, WarningAction.valueOf((String) context.get("action")), config.getAutoLockText()); } @@ -717,18 +728,16 @@ public class TemplateRunner { private static WatchUtil getWatches(WarngenLayer warngenLayer, WarngenConfiguration config, Geometry polygon, String fourLetterSiteId) throws Exception { - Validate.isTrue( - config.getAreaConfig().getIncludedWatchAreaBuffer() >= 0, + Validate.isTrue(config.getHatchedAreaSource() + .getIncludedWatchAreaBuffer() >= 0, "IncludedWatchAreaBuffer can not be negative"); - Polygon watchArea = (Polygon) polygon.buffer(milesToKilometer - .convert(config.getAreaConfig().getIncludedWatchAreaBuffer()) - / KmToDegrees); + WatchUtil rval = null; GetActiveTableRequest req = new GetActiveTableRequest(); + String[] includedWatches = config.getIncludedWatches(); - if (config.getIncludedWatches() != null - && config.getIncludedWatches().length > 0) { + if (includedWatches != null && includedWatches.length > 0) { String phensigList = null; - for (String includedWatch : config.getIncludedWatches()) { + for (String includedWatch : includedWatches) { if (includedWatch.equalsIgnoreCase("torWatches")) { phensigList = phensigList == null ? "TO.A" : phensigList + ",TO.A"; @@ -737,62 +746,134 @@ public class TemplateRunner { + ",SV.A"; } } + req.setPhensigList(phensigList); - } else { - return null; - } - if (CAVEMode.getMode().equals(CAVEMode.PRACTICE)) { - req.setMode(ActiveTableMode.PRACTICE); - } else { - req.setMode(ActiveTableMode.OPERATIONAL); - } + if (CAVEMode.getMode().equals(CAVEMode.PRACTICE)) { + req.setMode(ActiveTableMode.PRACTICE); + } else { + req.setMode(ActiveTableMode.OPERATIONAL); + } - req.setSiteID(fourLetterSiteId); - req.setRequestValidTimes(true); + req.setSiteID(fourLetterSiteId); + req.setRequestValidTimes(true); - GetActiveTableResponse resp = (GetActiveTableResponse) ThriftClient - .sendRequest(req); - java.util.List activeTable = resp.getActiveTable(); + long t0 = System.currentTimeMillis(); + GetActiveTableResponse resp = (GetActiveTableResponse) ThriftClient + .sendRequest(req); + long t1 = System.currentTimeMillis(); + java.util.List activeTable = resp + .getActiveTable(); - if (activeTable != null && activeTable.isEmpty() == false) { - warngenLayer.createGeometryForWatches(watchArea, activeTable); - } else { - return null; - } + System.out.println("getWatches.getActiveTable time: " + (t1 - t0) + + ", found " + + (activeTable != null ? activeTable.size() : "0") + + " watches"); + boolean val = activeTable != null && !activeTable.isEmpty(); + if (val) { + // Look for ones with valid geometry - SpatialQueryResult[] parentRegionFeatures = null; - try { - parentRegionFeatures = SpatialQueryFactory.create().query("States", - new String[] { "Name" }, watchArea, null, false, - SearchMode.INTERSECTS); - } catch (Exception e) { - return null; - } + 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)); - WatchUtil rval = new WatchUtil(); - WeatherAdvisoryWatch watch = null; + t0 = System.currentTimeMillis(); + warngenLayer.createGeometryForWatches(watchArea, activeTable); + t1 = System.currentTimeMillis(); + System.out.println("getWatches.createWatchGeometry time: " + + (t1 - t0)); + SpatialQueryResult[] parentRegionFeatures = null; - for (ActiveTableRecord atr : activeTable) { - // For each State in our watchArea... - for (int j = 0; j < parentRegionFeatures.length; j++) { - watch = new WeatherAdvisoryWatch(); - watch.setEndTime(atr.getEndTime().getTime()); - watch.setPhensig(atr.getPhensig()); + try { + String field = "the_geom"; + t0 = System.currentTimeMillis(); + List results = DbMapQueryFactory.getMapQuery( + "mapdata.states", field).getLevels(); + Collections.sort(results, Collections.reverseOrder()); + Double decimationTolerance = null; + for (Double result : results) { + if (result <= 0.064) { + decimationTolerance = result; + } + } - // Get the intersection of watchArea with State. - Geometry parentGeom = parentRegionFeatures[j].geometry; + if (decimationTolerance != null) { + DecimalFormat df = new DecimalFormat("0.######"); + String suffix = "_" + + StringUtils.replaceChars(df.format(results + .get(results.size() - 1)), '.', '_'); + parentRegionFeatures = SpatialQueryFactory.create() + .query("states", field + suffix, + new String[] { "Name" }, watchArea, + null, false, SearchMode.INTERSECTS); + } else { + parentRegionFeatures = SpatialQueryFactory.create() + .query("states", new String[] { "Name" }, + watchArea, null, false, + SearchMode.INTERSECTS); + } - // If State intersections intersects with out ATR record, add - // watch - if (GeometryUtil.intersects(parentGeom, atr.getGeometry())) { - watch.setParentRegion(parentRegionFeatures[j].attributes - .get("Name").toString()); - - watch.setPartOfParentRegion(GisUtil.asStringList(GisUtil - .calculatePortion(parentGeom, atr.getGeometry()))); - rval.addWaw(watch); + t1 = System.currentTimeMillis(); + System.out.println("getWatches.stateSpatialQuery time: " + + (t1 - t0) + ", found " + + parentRegionFeatures.length + " states"); + } catch (Exception e) { + statusHandler.handle(Priority.PROBLEM, + "Error querying state geometries", e); + return null; } + + rval = new WatchUtil(); + WeatherAdvisoryWatch watch = null; + long cumulativeIntersect = 0; + long cumulativeCalcPortion = 0; + GeodeticCalculator gc = new GeodeticCalculator(); + + // For each State in our watchArea... + for (int j = 0; j < parentRegionFeatures.length; j++) { + Geometry parentGeom = parentRegionFeatures[j].geometry; + List prepGeoms = new ArrayList(); + GeometryUtil.recursivePreparedGeometry(parentGeom, + prepGeoms); + + for (ActiveTableRecord atr : activeTable) { + // Get the intersection of watchArea with State. + watch = new WeatherAdvisoryWatch(); + watch.setEndTime(atr.getEndTime().getTime()); + watch.setPhensig(atr.getPhensig()); + + // If State intersections intersects with out ATR + // record, add watch + t0 = System.currentTimeMillis(); + boolean intersects = GeometryUtil.intersects(prepGeoms, + atr.getGeometry()); + t1 = System.currentTimeMillis(); + cumulativeIntersect = (t1 - t0); + + if (intersects) { + watch.setParentRegion(parentRegionFeatures[j].attributes + .get("Name").toString()); + + t0 = System.currentTimeMillis(); + watch.setPartOfParentRegion(GisUtil + .asStringList(GisUtil.calculatePortion( + parentGeom, atr.getGeometry(), gc))); + t1 = System.currentTimeMillis(); + cumulativeCalcPortion = (t1 - t0); + rval.addWaw(watch); + } + } + } + + System.out.println("getWatches.cumulativeIntersect: " + + cumulativeIntersect); + System.out.println("getWatches.cumulativeCalcPortion: " + + cumulativeCalcPortion); } } diff --git a/edexOsgi/com.raytheon.edex.plugin.warning/src/com/raytheon/edex/plugin/warning/gis/GeospatialDataGenerator.java b/edexOsgi/com.raytheon.edex.plugin.warning/src/com/raytheon/edex/plugin/warning/gis/GeospatialDataGenerator.java index f216bc066c..4c30b775cd 100644 --- a/edexOsgi/com.raytheon.edex.plugin.warning/src/com/raytheon/edex/plugin/warning/gis/GeospatialDataGenerator.java +++ b/edexOsgi/com.raytheon.edex.plugin.warning/src/com/raytheon/edex/plugin/warning/gis/GeospatialDataGenerator.java @@ -31,7 +31,7 @@ import javax.xml.bind.JAXBException; import com.raytheon.edex.site.SiteUtil; import com.raytheon.uf.common.dataplugin.warning.WarningConstants; -import com.raytheon.uf.common.dataplugin.warning.config.AreaConfiguration; +import com.raytheon.uf.common.dataplugin.warning.config.AreaSourceConfiguration; import com.raytheon.uf.common.dataplugin.warning.config.DialogConfiguration; import com.raytheon.uf.common.dataplugin.warning.config.GeospatialConfiguration; import com.raytheon.uf.common.dataplugin.warning.config.WarngenConfiguration; @@ -225,7 +225,8 @@ public class GeospatialDataGenerator { } if (dataSet == null) { - // If the file does not exist, then geoms need to be deleted. + // If the file does not exist, then geoms need to be + // deleted. deleteGeomFiles(site, lastRunTime); } else { generate = false; @@ -298,7 +299,7 @@ public class GeospatialDataGenerator { public static GeospatialMetadata getMetaData(WarngenConfiguration template) { GeospatialMetadata rval = new GeospatialMetadata(); GeospatialConfiguration geoConfig = template.getGeospatialConfig(); - AreaConfiguration areaConfig = template.getAreaConfig(); + AreaSourceConfiguration areaConfig = template.getHatchedAreaSource(); rval.setAreaSource(geoConfig.getAreaSource()); List areaFields = new ArrayList(); areaFields.add(WarningConstants.GID); @@ -449,7 +450,7 @@ public class GeospatialDataGenerator { */ private static GeospatialData[] queryTimeZones(GeospatialMetadata metaData, Geometry hull, GeospatialData[] geoData) throws SpatialException { - GeospatialData[] rval = null; + GeospatialData[] rval = null; String timezonePathcastTable = metaData.getTimeZoneSource(); String timezonePathcastField = metaData.getTimeZoneField(); @@ -459,7 +460,7 @@ public class GeospatialDataGenerator { .query(timezonePathcastTable, new String[] { timezonePathcastField }, hull, null, false, SearchMode.INTERSECTS); - + rval = new GeospatialData[timeZoneResults.length]; for (int i = 0; i < timeZoneResults.length; i++) { SpatialQueryResult result = timeZoneResults[i]; diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/config/AreaSourceConfiguration.java b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/config/AreaSourceConfiguration.java index 14e6c046b5..3b9b9ba2e5 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/config/AreaSourceConfiguration.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/config/AreaSourceConfiguration.java @@ -21,11 +21,11 @@ import com.raytheon.uf.common.dataquery.requests.RequestableMetadataMarshaller; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Mar 29, 2012 #14691 Qinglu Lin Added feAreaField and its getter and setter, etc. + * Mar 29, 2012 #14691 Qinglu Lin Added feAreaField and its getter and setter, etc. * * * - * @author + * @author * @version 1 */ @@ -37,7 +37,7 @@ public class AreaSourceConfiguration { } @XmlElement - private AreaType areaType = AreaType.INTERSECT; + private AreaType type = AreaType.HATCHING; @XmlAttribute private String variable; @@ -93,7 +93,6 @@ public class AreaSourceConfiguration { } public AreaSourceConfiguration(AreaConfiguration areaConfig) { - setAreaType(AreaType.HATCHING); setVariable("areas"); setAreaField(areaConfig.getAreaField()); setAreaNotationField(areaConfig.getAreaNotationField()); @@ -247,14 +246,6 @@ public class AreaSourceConfiguration { this.includedWatchAreaBuffer = includedWatchAreaBuffer; } - public AreaType getAreaType() { - return areaType; - } - - public void setAreaType(AreaType areaType) { - this.areaType = areaType; - } - public String getVariable() { return variable; } @@ -263,12 +254,20 @@ public class AreaSourceConfiguration { this.variable = variable; } - public String getTimeZoneField() { - return timeZoneField; - } + public String getTimeZoneField() { + return timeZoneField; + } - public void setTimeZoneField(String timeZoneField) { - this.timeZoneField = timeZoneField; - } + public void setTimeZoneField(String timeZoneField) { + this.timeZoneField = timeZoneField; + } + + public AreaType getType() { + return type; + } + + public void setType(AreaType type) { + this.type = type; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/config/PointSourceConfiguration.java b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/config/PointSourceConfiguration.java index 66bd7c5e4b..0ec069c298 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/config/PointSourceConfiguration.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/config/PointSourceConfiguration.java @@ -40,12 +40,20 @@ public class PointSourceConfiguration { TRACK, POINTS; } + @XmlAccessorType(XmlAccessType.NONE) + public static enum PointType { + AREA, POINT; + } + @XmlAttribute private String variable; @XmlElement private String pointSource; + @XmlElement + private Double geometryDecimationTolerance; + @XmlElement private String pointField; @@ -60,6 +68,9 @@ public class PointSourceConfiguration { @XmlElement private SearchMethod searchMethod = SearchMethod.TRACK; + @XmlElement + private PointType type = PointType.POINT; + @XmlElement private boolean withinPolygon = false; @@ -145,4 +156,21 @@ public class PointSourceConfiguration { this.withinPolygon = withinPolygon; } + public Double getGeometryDecimationTolerance() { + return geometryDecimationTolerance; + } + + public void setGeometryDecimationTolerance( + Double geometryDecimationTolerance) { + this.geometryDecimationTolerance = geometryDecimationTolerance; + } + + public PointType getType() { + return type; + } + + public void setType(PointType type) { + this.type = type; + } + } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/config/WarngenConfiguration.java b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/config/WarngenConfiguration.java index 5d5b99ce12..55d0c45a22 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/config/WarngenConfiguration.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/config/WarngenConfiguration.java @@ -24,8 +24,6 @@ import java.io.IOException; import java.text.ParseException; import java.text.ParsePosition; import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -81,6 +79,8 @@ public class WarngenConfiguration implements ISerializableObject { @XmlElement private PathcastConfiguration pathcastConfig; + private AreaSourceConfiguration hatchedAreaSource; + @XmlElement private AreaConfiguration areaConfig; @@ -200,31 +200,28 @@ public class WarngenConfiguration implements ISerializableObject { } } - List ascList = new ArrayList(); - if (config.getAreaConfig() != null) { - AreaSourceConfiguration areaSourceConfig = new AreaSourceConfiguration( - config.getAreaConfig()); - ascList.add(areaSourceConfig); + // TODO This section needs to be removed after new templates have been + // adopted dropping 'areaConfig' + if (config.getAreaSources() == null) { + ArrayList areaSources = new ArrayList(); + if (config.getAreaConfig() != null) { + areaSources.add(new AreaSourceConfiguration(config + .getAreaConfig())); + } + config.setAreaSources(areaSources + .toArray(new AreaSourceConfiguration[areaSources.size()])); } - AreaSourceConfiguration ascs[] = config.getAreaSources(); - if (ascs != null) { - ascList.addAll(Arrays.asList(ascs)); - } - - for (AreaSourceConfiguration asc : ascList) { + for (AreaSourceConfiguration asc : config.getAreaSources()) { if (asc.getAreaSource() == null) { asc.setAreaSource(config.getGeospatialConfig().getAreaSource()); } - if (asc.getAreaType() == AreaType.HATCHING) { - config.setAreaConfig(asc.getAreaConfig()); + if (asc.getType() == AreaType.HATCHING) { + config.setHatchedAreaSource(asc); } } - config.setAreaSources(ascList - .toArray(new AreaSourceConfiguration[ascList.size()])); - if (config.getPathcastConfig() != null && config.getPathcastConfig().getPointSource() == null) { config.getPathcastConfig().setPointSource( @@ -482,4 +479,12 @@ public class WarngenConfiguration implements ISerializableObject { this.enableDuration = enableDuration; } + public AreaSourceConfiguration getHatchedAreaSource() { + return hatchedAreaSource; + } + + public void setHatchedAreaSource(AreaSourceConfiguration hatchedAreaSource) { + this.hatchedAreaSource = hatchedAreaSource; + } + }