Issue #1275 Merged code from 1225 on top of SS changes.

Former-commit-id: ace2ccf5653fcd791bc049ca17986b233a6a54cc
This commit is contained in:
Jonathan Sanchez 2012-10-17 13:30:44 -05:00
parent 6833c7e04c
commit 9017f4b046
7 changed files with 650 additions and 290 deletions

View file

@ -10,8 +10,14 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import javax.measure.converter.UnitConverter;
import org.apache.commons.lang.StringUtils;
import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.GeodeticCalculator;
import org.opengis.referencing.operation.MathTransform;
import com.raytheon.uf.common.dataplugin.warning.config.PathcastConfiguration;
import com.raytheon.uf.common.dataplugin.warning.config.PointSourceConfiguration;
import com.raytheon.uf.common.dataplugin.warning.config.WarngenConfiguration;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
@ -21,10 +27,18 @@ 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.core.map.GeoUtil;
import com.raytheon.viz.warngen.gis.ClosestPoint;
import com.raytheon.viz.warngen.gis.ClosestPointComparator;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.Point;
/**
*
* TODO Add Description
*
* <pre>
*
* SOFTWARE HISTORY
*
@ -32,51 +46,96 @@ import com.vividsolutions.jts.geom.Geometry;
* ------------ ---------- ----------- --------------------------
* pre-history
* Sep 25, 2012 #15425 Qinglu Lin Added getGid().
* Oct 17, 2012 jsanchez Added pathcast algorithm.
*
* </pre>
*
* @author jsanchez
* @version 1.0
*/
abstract public class AbstractDbSourceDataAdaptor {
protected Set<String> sortFields = new HashSet<String>(
Arrays.asList(new String[] { "distance", "area", "parentArea" }));
private static final String transformedKey = "com.raytheon.transformed";
protected PointSourceConfiguration pointConfig;
private static final String GEOM_FIELD = "the_geom";
protected Set<String> undatabasedSortableFields = new HashSet<String>(
Arrays.asList(new String[] {
ClosestPointComparator.Sort.DISTANCE.toString(),
ClosestPointComparator.Sort.AREA.toString(),
ClosestPointComparator.Sort.PARENTAREA.toString() }));
protected GeodeticCalculator gc = new GeodeticCalculator();
protected Geometry searchArea;
protected String localizedSite;
abstract protected Set<String> createSpatialQueryField();
protected SpatialQueryResult[] ptFeatures;
abstract protected ClosestPoint createClosestPoint(Set<String> ptFields,
SpatialQueryResult ptRslt);
protected Map<String, RequestConstraint> filter;
abstract protected Map<String, RequestConstraint> processFilterSubstitution();
protected Set<String> ptFields;
public Collection<ClosestPoint> getData(WarngenConfiguration config,
PointSourceConfiguration pointConfig, Geometry searchArea,
protected String[] sortBy;
abstract protected Set<String> createSpatialQueryField(String pointField,
String[] sortBy);
abstract protected ClosestPoint createClosestPoint(String pointField,
Set<String> ptFields, SpatialQueryResult ptRslt);
abstract protected Map<String, RequestConstraint> processFilterSubstitution(
Map<String, RequestConstraint> filter);
public AbstractDbSourceDataAdaptor(
PathcastConfiguration pathcastConfiguration,
UnitConverter distanceToMeters, Geometry searchArea,
String localizedSite) throws VizException {
this.pointConfig = pointConfig;
this.searchArea = searchArea;
this.localizedSite = localizedSite;
this.sortBy = pathcastConfiguration.getSortBy();
this.searchArea = searchArea;
this.ptFields = createSpatialQueryField(
pathcastConfiguration.getPointField(), sortBy);
this.filter = processFilterSubstitution(pathcastConfiguration
.getFilter());
this.ptFeatures = spatialQuery(pathcastConfiguration.getPointSource(),
null);
}
Map<String, RequestConstraint> filter = processFilterSubstitution();
Set<String> ptFields = createSpatialQueryField();
List<ClosestPoint> points = null;
public AbstractDbSourceDataAdaptor(
PointSourceConfiguration pointSourceConfiguration,
Geometry searchArea, String localizedSite) throws VizException {
this.localizedSite = localizedSite;
this.sortBy = pointSourceConfiguration.getSortBy();
this.searchArea = searchArea;
this.ptFields = createSpatialQueryField(
pointSourceConfiguration.getPointField(), sortBy);
this.filter = processFilterSubstitution(pointSourceConfiguration
.getFilter());
this.ptFeatures = spatialQuery(
pointSourceConfiguration.getPointSource(), null);
}
/**
* Queries the maps database depending on the point source set in the
* config.
*
* @param pointSource
* @param decimationTolerance
* @return
* @throws VizException
*/
private SpatialQueryResult[] spatialQuery(String pointSource,
Double decimationTolerance) throws VizException {
try {
long t0 = System.currentTimeMillis();
SpatialQueryResult[] ptFeatures = null;
Double decimationTolerance = pointConfig
.getGeometryDecimationTolerance();
String field = "the_geom";
long t0 = System.currentTimeMillis();
try {
if (decimationTolerance != null && decimationTolerance > 0) {
// find available tolerances
List<Double> results = DbMapQueryFactory
.getMapQuery(
"mapdata."
+ pointConfig.getPointSource()
.toLowerCase(), field)
List<Double> results = DbMapQueryFactory.getMapQuery(
"mapdata." + pointSource.toLowerCase(), GEOM_FIELD)
.getLevels();
Collections.sort(results, Collections.reverseOrder());
@ -99,17 +158,40 @@ abstract public class AbstractDbSourceDataAdaptor {
String suffix = "_"
+ StringUtils.replaceChars(
df.format(decimationTolerance), '.', '_');
ptFeatures = SpatialQueryFactory.create().query(
pointConfig.getPointSource(), field + suffix,
ptFeatures = SpatialQueryFactory.create().query(pointSource,
GEOM_FIELD + suffix,
ptFields.toArray(new String[ptFields.size()]),
searchArea, filter, SearchMode.INTERSECTS);
} else {
ptFeatures = SpatialQueryFactory.create().query(
pointConfig.getPointSource(),
ptFeatures = SpatialQueryFactory.create().query(pointSource,
ptFields.toArray(new String[ptFields.size()]),
searchArea, filter, SearchMode.INTERSECTS);
}
System.out.println("Retrieve location data for '" + pointSource
+ "' = " + (System.currentTimeMillis() - t0));
} catch (SpatialException e) {
throw new VizException("Error querying " + pointSource + " table: "
+ e.getLocalizedMessage(), e);
}
return ptFeatures;
}
/**
* Returns the data of the points/areas relative to the searchArea
*
* @param config
* @param pointConfig
* @param localizedSite
* @return
* @throws VizException
*/
public Collection<ClosestPoint> getData(WarngenConfiguration config,
PointSourceConfiguration pointConfig, String localizedSite)
throws VizException {
List<ClosestPoint> points = null;
String pointField = pointConfig.getPointField();
if (ptFeatures != null) {
points = new ArrayList<ClosestPoint>(ptFeatures.length);
} else {
@ -121,31 +203,167 @@ abstract public class AbstractDbSourceDataAdaptor {
Object nameObj = ptRslt.attributes.get(pointConfig
.getPointField());
if (nameObj != null) {
ClosestPoint cp = createClosestPoint(ptFields, ptRslt);
ClosestPoint cp = createClosestPoint(pointField, ptFields,
ptRslt);
cp.setGid(getGid(ptFields, ptRslt.attributes));
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;
}
/**
* Returns a list of implacted points/areas that are relative to the
* centroid.
*
* @param pcGeom
* @param centroid
* @param areaFeatures
* @param pcArea
* @param pcParentArea
* @return
* @throws Exception
*/
public List<ClosestPoint> getPathcastData(
PathcastConfiguration pathcastConfiguration,
UnitConverter distanceToMeters, MathTransform latLonToLocal,
Geometry pcGeom, Point centroid, SpatialQueryResult[] areaFeatures,
String pcArea, String pcParentArea) throws Exception {
String pointField = pathcastConfiguration.getPointField();
String areaField = pathcastConfiguration.getAreaField();
String parentAreaField = pathcastConfiguration.getParentAreaField();
double thresholdInMeters = distanceToMeters
.convert(pathcastConfiguration.getDistanceThreshold());
if (latLonToLocal != null) {
for (SpatialQueryResult rslt : ptFeatures) {
rslt.attributes.put(transformedKey,
JTS.transform(rslt.geometry, latLonToLocal));
}
}
Geometry localPCGeom = null;
if (pcGeom != null) {
localPCGeom = JTS.transform(pcGeom, latLonToLocal);
}
// Find closest points
List<ClosestPoint> points = new ArrayList<ClosestPoint>(
ptFeatures.length);
for (SpatialQueryResult pointRslt : ptFeatures) {
Geometry localPt = (Geometry) pointRslt.attributes
.get(transformedKey);
double minDist = Double.MAX_VALUE;
Coordinate closestCoord = null;
if (localPCGeom != null) {
Coordinate[] localPts = localPCGeom.getCoordinates();
Coordinate[] latLonPts = pcGeom.getCoordinates();
for (int i = 0; i < localPts.length; ++i) {
Coordinate loc = localPts[i];
double distance = loc.distance(localPt.getCoordinate());
if (distance <= thresholdInMeters && distance < minDist) {
minDist = distance;
closestCoord = latLonPts[i];
}
}
} else {
closestCoord = centroid.getCoordinate();
minDist = 0;
}
if (closestCoord != null) {
boolean found = false;
String area = null;
String parentArea = null;
for (SpatialQueryResult areaRslt : areaFeatures) {
if (areaRslt.geometry.contains(pointRslt.geometry)) {
area = String.valueOf(areaRslt.attributes
.get(areaField));
parentArea = String.valueOf(areaRslt.attributes
.get(parentAreaField));
found = true;
break;
}
}
if (!found) {
area = pcArea;
parentArea = pcParentArea;
}
ClosestPoint cp = createClosestPoint(pointField, pointRslt,
minDist, closestCoord, area, parentArea,
distanceToMeters.inverse());
points.add(cp);
}
}
List<String> fields = null;
if (pathcastConfiguration.getSortBy() != null) {
fields = Arrays.asList(pathcastConfiguration.getSortBy());
} else {
fields = new ArrayList<String>(0);
}
if (!fields.isEmpty()) {
// Sort the points based on sortBy fields
Collections.sort(points, new ClosestPointComparator(fields));
}
return points;
}
/**
* Creates a closestPoint setting the distance, azimuth, etc. Used for
* pathcast calculations
*
* @param pointRslt
* @param minDist
* @param closestCoord
* @param area
* @param parentArea
* @return
*/
private ClosestPoint createClosestPoint(String pointField,
SpatialQueryResult pointRslt, double minDist,
Coordinate closestCoord, String area, String parentArea,
UnitConverter metersToDistance) {
ClosestPoint cp = createClosestPoint(pointField, ptFields, pointRslt);
cp.setDistance(minDist);
cp.setRoundedDistance((int) metersToDistance.convert(minDist));
gc.setStartingGeographicPoint(cp.getPoint().x, cp.getPoint().y);
gc.setDestinationGeographicPoint(closestCoord.x, closestCoord.y);
cp.setAzimuth(gc.getAzimuth());
cp.setOppositeAzimuth(ClosestPoint.adjustAngle(cp.getAzimuth() + 180));
cp.setRoundedAzimuth(GeoUtil.roundAzimuth(cp.getAzimuth()));
cp.setOppositeRoundedAzimuth(ClosestPoint.adjustAngle(cp
.getRoundedAzimuth() + 180));
cp.setArea(area);
cp.setParentArea(parentArea);
cp.setGid(getGid(ptFields, pointRslt.attributes));
return cp;
}
/**
* Retrieves the population from the attributes.
*
* @param ptFields
* @param attributes
* @return
*/
protected int getPopulation(Set<String> ptFields,
Map<String, Object> attributes) {
int population = 0;
if (ptFields.contains("population")) {
if (ptFields.contains(String
.valueOf(ClosestPointComparator.Sort.POPULATION))) {
try {
population = Integer.valueOf(String.valueOf(attributes
.get("population")));
population = Integer
.valueOf(String.valueOf(attributes.get(String
.valueOf(ClosestPointComparator.Sort.POPULATION))));
} catch (Exception e) {
// Ignore
}
@ -154,14 +372,23 @@ abstract public class AbstractDbSourceDataAdaptor {
return population;
}
/**
* Retrieves the warngenlev from the attributes.
*
* @param ptFields
* @param attributes
* @return
*/
protected int getWangenlev(Set<String> ptFields,
Map<String, Object> attributes) {
int warngenlev = 0;
int warngenlev = 3;
if (ptFields.contains("warngenlev")) {
if (ptFields.contains(String
.valueOf(ClosestPointComparator.Sort.WARNGENLEV))) {
try {
warngenlev = Integer.valueOf(String.valueOf(attributes
.get("warngenlev")));
warngenlev = Integer
.valueOf(String.valueOf(attributes.get(String
.valueOf(ClosestPointComparator.Sort.WARNGENLEV))));
} catch (Exception e) {
// Ignore
}
@ -170,14 +397,20 @@ abstract public class AbstractDbSourceDataAdaptor {
return warngenlev;
}
protected int getGid(Set<String> ptFields,
Map<String, Object> attributes) {
/**
* Returns the gid.
*
* @param ptFields
* @param attributes
* @return
*/
protected int getGid(Set<String> ptFields, Map<String, Object> attributes) {
int gid = 0;
if (ptFields.contains("gid")) {
if (ptFields.contains(String.valueOf(ClosestPointComparator.Sort.GID))) {
try {
gid = Integer.valueOf(String.valueOf(attributes
.get("gid")));
gid = Integer.valueOf(String.valueOf(attributes.get(String
.valueOf(ClosestPointComparator.Sort.GID))));
} catch (Exception e) {
// Ignore
}

View file

@ -19,11 +19,16 @@
**/
package com.raytheon.viz.warngen.config;
import javax.measure.converter.UnitConverter;
import com.raytheon.uf.common.dataplugin.warning.config.PathcastConfiguration;
import com.raytheon.uf.common.dataplugin.warning.config.PointSourceConfiguration;
import com.raytheon.uf.common.dataplugin.warning.config.PointSourceConfiguration.PointType;
import com.raytheon.uf.viz.core.exception.VizException;
import com.vividsolutions.jts.geom.Geometry;
/**
* Creates data adaptors for PointSource and Pathcast data.
* Creates data adaptors for PointSource data.
*
* <pre>
*
@ -32,6 +37,7 @@ import com.raytheon.uf.common.dataplugin.warning.config.PointSourceConfiguration
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 26, 2011 bgonzale Initial creation
* Oct 17, 2012 jsanchez Allowed adaptor to be used for pathcast.
*
* </pre>
*
@ -41,15 +47,32 @@ import com.raytheon.uf.common.dataplugin.warning.config.PointSourceConfiguration
public class DataAdaptorFactory {
public static AbstractDbSourceDataAdaptor createPointSource(
PointSourceConfiguration pointConfig) {
public static AbstractDbSourceDataAdaptor createDataAdaptor(
PointSourceConfiguration pointConfig, Geometry searchArea,
String localizedSite) throws VizException {
AbstractDbSourceDataAdaptor adaptor = null;
if (pointConfig.getType() == PointType.AREA) {
adaptor = new DbAreaSourceDataAdaptor(pointConfig, searchArea,
localizedSite);
} else if (pointConfig.getType() == PointType.POINT) {
adaptor = new DbPointSourceDataAdaptor(pointConfig, searchArea,
localizedSite);
}
return adaptor;
}
public static AbstractDbSourceDataAdaptor createPathcastDataAdaptor(
PathcastConfiguration pathcastConfiguration,
UnitConverter distanceToMeters, Geometry searchArea,
String localizedSite) throws VizException {
AbstractDbSourceDataAdaptor adaptor = null;
if (pointConfig.getType() == PointType.AREA) {
adaptor = new DbAreaSourceDataAdaptor();
} else if (pointConfig.getType() == PointType.POINT) {
adaptor = new DbPointSourceDataAdaptor();
if (pathcastConfiguration.getType() == PointType.AREA) {
adaptor = new DbAreaSourceDataAdaptor(pathcastConfiguration,
distanceToMeters, searchArea, localizedSite);
} else if (pathcastConfiguration.getType() == PointType.POINT) {
adaptor = new DbPointSourceDataAdaptor(pathcastConfiguration,
distanceToMeters, searchArea, localizedSite);
}
return adaptor;

View file

@ -2,31 +2,40 @@ package com.raytheon.viz.warngen.config;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.measure.converter.UnitConverter;
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.dataquery.requests.RequestConstraint;
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.raytheon.viz.warngen.gis.GisUtil;
import com.raytheon.viz.warngen.gis.GisUtil.Direction;
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;
/**
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* @author jsanchez
* Sep 25, 2012 #15425 Qinglu Lin Updated createClosestPoint().
* Date Ticket# Engineer Description ------------ ---------- -----------
* --------------------------
*
* @author jsanchez Sep 25, 2012 #15425 Qinglu Lin Updated createClosestPoint().
*
*/
public class DbAreaSourceDataAdaptor extends AbstractDbSourceDataAdaptor {
@ -37,26 +46,41 @@ public class DbAreaSourceDataAdaptor extends AbstractDbSourceDataAdaptor {
private static final String cwaField = "cwa";
private GeodeticCalculator gc = new GeodeticCalculator();
public DbAreaSourceDataAdaptor(PathcastConfiguration pathcastConfiguration,
UnitConverter distanceToMeters, Geometry searchArea,
String localizedSite) throws VizException {
super(pathcastConfiguration, distanceToMeters, searchArea,
localizedSite);
}
public DbAreaSourceDataAdaptor(
PointSourceConfiguration pointSourceConfiguration,
Geometry searchArea, String localizedSite) throws VizException {
super(pointSourceConfiguration, searchArea, localizedSite);
}
/**
*
*/
@Override
protected Set<String> createSpatialQueryField() {
protected Set<String> createSpatialQueryField(String pointField,
String[] sortBy) {
Set<String> ptFields = new HashSet<String>();
ptFields.add(pointConfig.getPointField());
ptFields.add(pointField);
ptFields.add(useDirectionField);
ptFields.add(suppressedDirectionsField);
List<String> fields = new ArrayList<String>();
if (pointConfig.getSortBy() != null) {
fields = Arrays.asList(pointConfig.getSortBy());
List<String> fields = null;
if (sortBy != null && sortBy.length > 0) {
fields = Arrays.asList(sortBy);
} else {
fields = new ArrayList<String>(0);
}
// Sort fields don't exist in the db.
for (String field : fields) {
if (sortFields.contains(field.toLowerCase()) == false) {
ptFields.add(field.toLowerCase());
if (undatabasedSortableFields.contains(field.toUpperCase()) == false) {
ptFields.add(field.toUpperCase());
}
}
@ -64,15 +88,14 @@ public class DbAreaSourceDataAdaptor extends AbstractDbSourceDataAdaptor {
}
/**
*
* Creates a closest point object.
*/
@Override
protected ClosestPoint createClosestPoint(Set<String> ptFields,
SpatialQueryResult ptRslt) {
protected ClosestPoint createClosestPoint(String pointField,
Set<String> ptFields, SpatialQueryResult ptRslt) {
Map<String, Object> attributes = ptRslt.attributes;
String name = String
.valueOf(attributes.get(pointConfig.getPointField()));
String name = String.valueOf(attributes.get(pointField));
Coordinate point = ptRslt.geometry.getCoordinate();
int population = getPopulation(ptFields, attributes);
int warngenlev = getWangenlev(ptFields, attributes);
@ -80,10 +103,36 @@ public class DbAreaSourceDataAdaptor extends AbstractDbSourceDataAdaptor {
ptRslt.geometry);
int gid = getGid(ptFields, attributes);
return new ClosestPoint(name, point, population, warngenlev, partOfArea, gid);
return new ClosestPoint(name, point, population, warngenlev,
partOfArea, gid);
}
/**
* Processes the filter to set the localized site.
*/
@Override
protected Map<String, RequestConstraint> processFilterSubstitution(
Map<String, RequestConstraint> filter) {
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<String, RequestConstraint>();
}
filter.put(cwaField, new RequestConstraint(localizedSite));
return filter;
}
/**
* Determines the part of area impacted if the userDirectionField is set to
* true.
*
* @param ptFields
* @param attributes
@ -97,9 +146,11 @@ public class DbAreaSourceDataAdaptor extends AbstractDbSourceDataAdaptor {
boolean userDirections = Boolean.valueOf(String.valueOf(attributes
.get(useDirectionField)));
if (userDirections) {
PreparedGeometry prepGeom = PreparedGeometryFactory.prepare(geom);
if (prepGeom.intersects(searchArea) && !prepGeom.within(searchArea)) {
Geometry intersection = searchArea.intersection(geom);
partOfArea = GisUtil.asStringList(GisUtil.calculatePortion(geom,
intersection, gc, ""));
partOfArea = GisUtil.asStringList(calculateLocationPortion(
geom, intersection, gc));
if (attributes.get(suppressedDirectionsField) != null) {
String suppressedDirections = String.valueOf(
@ -121,35 +172,96 @@ public class DbAreaSourceDataAdaptor extends AbstractDbSourceDataAdaptor {
case 'w':
partOfArea.remove(Direction.WEST.toString());
break;
case 'c':
partOfArea.remove(Direction.CENTRAL.toString());
break;
}
}
}
}
}
}
}
if (partOfArea != null && !partOfArea.isEmpty()) {
return partOfArea;
}
@Override
protected Map<String, RequestConstraint> processFilterSubstitution() {
Map<String, RequestConstraint> filter = pointConfig.getFilter();
if (filter != null) {
// Process substitutes for filter
for (RequestConstraint rc : filter.values()) {
rc.setConstraintValue(PreferenceUtil.substitute(
rc.getConstraintValue(), localizedSite));
return null;
}
/**
* Helper class to store cardinal ranges
*
* @author jsanchez
*
*/
private static class CardinalRange {
public EnumSet<Direction> directions;
public double lowRange;
public double highRange;
public CardinalRange(EnumSet<Direction> directions, double lowRange,
double highRange) {
this.directions = directions;
this.lowRange = lowRange;
this.highRange = highRange;
}
}
if (filter == null) {
filter = new HashMap<String, RequestConstraint>();
private static CardinalRange[] ranges = new CardinalRange[] {
new CardinalRange(EnumSet.of(Direction.NORTH), 0, 22.5),
new CardinalRange(EnumSet.of(Direction.NORTH, Direction.EAST),
22.5, 67.5),
new CardinalRange(EnumSet.of(Direction.EAST), 67.5, 112.5),
new CardinalRange(EnumSet.of(Direction.SOUTH, Direction.EAST),
112.5, 157.5),
new CardinalRange(EnumSet.of(Direction.SOUTH), 157.5, 202.5),
new CardinalRange(EnumSet.of(Direction.SOUTH, Direction.WEST),
202.5, 247.5),
new CardinalRange(EnumSet.of(Direction.WEST), 247.5, 292.5),
new CardinalRange(EnumSet.of(Direction.NORTH, Direction.WEST),
292.5, 337.5),
new CardinalRange(EnumSet.of(Direction.NORTH), 337.5, 360) };
/**
* Calculates the cardinal directions of a location.
*
* @param geom
* @param intersection
* @param gc
* @return
*/
private static EnumSet<Direction> calculateLocationPortion(Geometry geom,
Geometry intersection, GeodeticCalculator gc) {
EnumSet<Direction> directions = EnumSet.noneOf(Direction.class);
Coordinate geomCentroid = geom.convexHull().getCentroid()
.getCoordinate();
Coordinate intersectCentroid = intersection.convexHull().getCentroid()
.getCoordinate();
gc.setStartingGeographicPoint(geomCentroid.x, geomCentroid.y);
gc.setDestinationGeographicPoint(intersectCentroid.x,
intersectCentroid.y);
Envelope envelope = geom.getEnvelopeInternal();
double centerThresholdX = envelope.getWidth() * 0.10;
double centerThresholdY = envelope.getHeight() * 0.10;
double distanceX = Math.abs(intersectCentroid.x - geomCentroid.x);
double distanceY = Math.abs(intersectCentroid.y - geomCentroid.y);
if (distanceX > centerThresholdX || distanceY > centerThresholdY) {
// Convert azimuth from -180/180 to 0/360
double degrees = gc.getAzimuth();
if (degrees < 0) {
degrees += 360;
}
filter.put(cwaField, new RequestConstraint(localizedSite));
for (CardinalRange range : ranges) {
if (degrees > range.lowRange && degrees <= range.highRange) {
directions = range.directions;
break;
}
}
}
return filter;
return directions;
}
}

View file

@ -19,23 +19,24 @@
**/
package com.raytheon.viz.warngen.config;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
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 javax.measure.converter.UnitConverter;
import com.raytheon.uf.common.dataplugin.warning.config.PathcastConfiguration;
import com.raytheon.uf.common.dataplugin.warning.config.PointSourceConfiguration;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.geospatial.SpatialQueryResult;
import com.raytheon.uf.viz.core.maps.rsc.DbMapQueryFactory;
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.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
/**
* PointSource data adaptor for data retrieved from a Database.
@ -57,19 +58,35 @@ import com.vividsolutions.jts.geom.Coordinate;
public class DbPointSourceDataAdaptor extends AbstractDbSourceDataAdaptor {
@Override
protected Set<String> createSpatialQueryField() {
Set<String> ptFields = new HashSet<String>();
ptFields.add(pointConfig.getPointField());
List<String> fields = new ArrayList<String>();
if (pointConfig.getSortBy() != null) {
fields = Arrays.asList(pointConfig.getSortBy());
public DbPointSourceDataAdaptor(
PathcastConfiguration pathcastConfiguration,
UnitConverter distanceToMeters, Geometry searchArea,
String localizedSite) throws VizException {
super(pathcastConfiguration, distanceToMeters, searchArea,
localizedSite);
}
public DbPointSourceDataAdaptor(
PointSourceConfiguration pointSourceConfiguration,
Geometry searchArea, String localizedSite) throws VizException {
super(pointSourceConfiguration, searchArea, localizedSite);
}
@Override
protected Set<String> createSpatialQueryField(String pointField,
String[] sortBy) {
Set<String> ptFields = new HashSet<String>();
ptFields.add(pointField);
List<String> fields = new ArrayList<String>();
if (sortBy != null) {
fields = Arrays.asList(sortBy);
}
// Sort fields don't exist in the db.
for (String field : fields) {
if (sortFields.contains(field.toLowerCase()) == false) {
ptFields.add(field.toLowerCase());
if (undatabasedSortableFields.contains(field.toUpperCase()) == false) {
ptFields.add(field.toUpperCase());
}
}
@ -77,12 +94,11 @@ public class DbPointSourceDataAdaptor extends AbstractDbSourceDataAdaptor {
}
@Override
protected ClosestPoint createClosestPoint(Set<String> ptFields,
SpatialQueryResult ptRslt) {
protected ClosestPoint createClosestPoint(String pointField,
Set<String> ptFields, SpatialQueryResult ptRslt) {
Map<String, Object> attributes = ptRslt.attributes;
String name = String
.valueOf(attributes.get(pointConfig.getPointField()));
String name = String.valueOf(attributes.get(pointField));
Coordinate point = ptRslt.geometry.getCoordinate();
int population = getPopulation(ptFields, attributes);
int warngenlev = getWangenlev(ptFields, attributes);
@ -92,8 +108,8 @@ public class DbPointSourceDataAdaptor extends AbstractDbSourceDataAdaptor {
}
@Override
protected Map<String, RequestConstraint> processFilterSubstitution() {
Map<String, RequestConstraint> filter = pointConfig.getFilter();
protected Map<String, RequestConstraint> processFilterSubstitution(
Map<String, RequestConstraint> filter) {
if (filter != null) {
// Process substitutes for filter
for (RequestConstraint rc : filter.values()) {

View file

@ -38,6 +38,7 @@ import com.vividsolutions.jts.geom.Coordinate;
* APr 18, 2012 #14733 Qinglu Lin David's fix is used, which adds
* a copy constructor.
* Sep 25, 2012 #15425 Qinglu Lin Updated two ClosestPoint() and added getGid().
* Oct 17, 2012 jsanchez Added setter methods.
*
* </pre>
*
@ -182,6 +183,70 @@ public class ClosestPoint implements Comparable<ClosestPoint> {
return gid;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
public void setName(String name) {
this.name = name;
}
public void setArea(String area) {
this.area = area;
}
public void setParentArea(String parentArea) {
this.parentArea = parentArea;
}
public void setPoint(Coordinate point) {
this.point = point;
}
public void setDistance(double distance) {
this.distance = distance;
}
public void setRoundedDistance(int roundedDistance) {
this.roundedDistance = roundedDistance;
}
public void setAzimuth(double azimuth) {
this.azimuth = azimuth;
}
public void setRoundedAzimuth(double roundedAzimuth) {
this.roundedAzimuth = roundedAzimuth;
}
public void setOppositeAzimuth(double oppositeAzimuth) {
this.oppositeAzimuth = oppositeAzimuth;
}
public void setOppositeRoundedAzimuth(double oppositeRoundedAzimuth) {
this.oppositeRoundedAzimuth = oppositeRoundedAzimuth;
}
public void setPopulation(int population) {
this.population = population;
}
public void setWarngenlev(int warngenlev) {
this.warngenlev = warngenlev;
}
public void setPartOfArea(List<String> partOfArea) {
this.partOfArea = partOfArea;
}
public void setGid(int gid) {
this.gid = gid;
}
/**
* Adjusts the angle from -360/360 to be between -180/180
*

View file

@ -38,6 +38,7 @@ import org.apache.commons.lang.ArrayUtils;
* ------------ ---------- ----------- --------------------------
* Mar 3, 2011 jsanchez Initial creation
* Sep 25, 2012 15425 Qinglu Lin Implemented sorting on 'gid' in ascending order.
* Oct 17, 2012 jsanchez Refactored the enum sort to be more flexible.
*
* </pre>
*
@ -47,11 +48,11 @@ import org.apache.commons.lang.ArrayUtils;
public class ClosestPointComparator implements Comparator<ClosestPoint> {
private enum Sort {
NAME, POPULATION, DISTANCE, LEVEL, LAT, LON, AREA, PARENT_AREA, GID
public static enum Sort {
NAME, POPULATION, DISTANCE, WARNGENLEV, LAT, LON, AREA, PARENTAREA, GID
}
private ArrayList<Sort> list;
private final ArrayList<Sort> list;
private int counter;
@ -64,24 +65,24 @@ public class ClosestPointComparator implements Comparator<ClosestPoint> {
counter = 0;
list = new ArrayList<Sort>();
for (String field : fields) {
if (field.equalsIgnoreCase("name")) {
if (field.equalsIgnoreCase(Sort.NAME.toString())) {
list.add(Sort.NAME);
} else if (field.equalsIgnoreCase("population")) {
} else if (field.equalsIgnoreCase(Sort.POPULATION.toString())) {
list.add(Sort.POPULATION);
} else if (field.equalsIgnoreCase("distance")) {
} else if (field.equalsIgnoreCase(Sort.DISTANCE.toString())) {
list.add(Sort.DISTANCE);
} else if (field.equalsIgnoreCase("warngenlev")
} else if (field.equalsIgnoreCase(Sort.WARNGENLEV.toString())
|| field.equalsIgnoreCase("watch_warn")) {
list.add(Sort.LEVEL);
} else if (field.equalsIgnoreCase("lat")) {
list.add(Sort.WARNGENLEV);
} else if (field.equalsIgnoreCase(Sort.LAT.toString())) {
list.add(Sort.LAT);
} else if (field.equalsIgnoreCase("lon")) {
} else if (field.equalsIgnoreCase(Sort.LON.toString())) {
list.add(Sort.LON);
} else if (field.equalsIgnoreCase("area")) {
} else if (field.equalsIgnoreCase(Sort.AREA.toString())) {
list.add(Sort.AREA);
} else if (field.equalsIgnoreCase("parentArea")) {
list.add(Sort.PARENT_AREA);
} else if (field.equalsIgnoreCase("gid")) {
} else if (field.equalsIgnoreCase(Sort.PARENTAREA.toString())) {
list.add(Sort.PARENTAREA);
} else if (field.equalsIgnoreCase(Sort.GID.toString())) {
list.add(Sort.GID);
}
}
@ -105,13 +106,13 @@ public class ClosestPointComparator implements Comparator<ClosestPoint> {
list.clear();
ClosestPointComparator comparator = new ClosestPointComparator(
(ArrayList<String>) Arrays.asList(fields));
Collections
.sort((List<ClosestPoint>) Arrays.asList(points), comparator);
Arrays.asList(fields));
Collections.sort(Arrays.asList(points), comparator);
return points;
}
@Override
public int compare(ClosestPoint cp1, ClosestPoint cp2) {
if (list.isEmpty()) {
return cp1.compareTo(cp2);
@ -121,7 +122,7 @@ public class ClosestPointComparator implements Comparator<ClosestPoint> {
switch (list.get(counter)) {
case NAME:
if (cp1.name.matches("((-|\\+)?[0-9]+(\\.[0-9]+)?)+")
&& cp1.name.matches("((-|\\+)?[0-9]+(\\.[0-9]+)?)+")) {
&& cp2.name.matches("((-|\\+)?[0-9]+(\\.[0-9]+)?)+")) {
value = Double.valueOf(cp1.name).compareTo(
Double.valueOf(cp2.name));
} else {
@ -131,7 +132,7 @@ public class ClosestPointComparator implements Comparator<ClosestPoint> {
case POPULATION:
value = -1 * Double.compare(cp1.population, cp2.population);
break;
case LEVEL:
case WARNGENLEV:
value = Double.compare(cp1.warngenlev, cp2.warngenlev);
break;
case LAT:
@ -143,7 +144,7 @@ public class ClosestPointComparator implements Comparator<ClosestPoint> {
case AREA:
value = cp1.area.compareTo(cp2.area);
break;
case PARENT_AREA:
case PARENTAREA:
value = cp1.parentArea.compareTo(cp2.parentArea);
break;
case DISTANCE:
@ -151,8 +152,7 @@ public class ClosestPointComparator implements Comparator<ClosestPoint> {
.compareTo(cp2.roundedDistance);
break;
case GID:
value = new Integer(cp1.gid)
.compareTo(cp2.gid);
value = new Integer(cp1.gid).compareTo(cp2.gid);
break;
}

View file

@ -71,6 +71,7 @@ import com.raytheon.viz.awipstools.common.stormtrack.StormTrackState;
import com.raytheon.viz.core.map.GeoUtil;
import com.raytheon.viz.warngen.PreferenceUtil;
import com.raytheon.viz.warngen.WarngenException;
import com.raytheon.viz.warngen.config.AbstractDbSourceDataAdaptor;
import com.raytheon.viz.warngen.config.DataAdaptorFactory;
import com.raytheon.viz.warngen.util.Abbreviation;
import com.raytheon.viz.warnings.DateUtil;
@ -99,6 +100,7 @@ import com.vividsolutions.jts.geom.Point;
* in pathcast.
* Oct 05, 2012 DR15429 Qinglu Lin Updated code to keep duplicate names of cities
* which are at different locations in pathcast.
* Oct 17, 2012 jsanchez Moved the path cast data collecting to a seperate class.
*
* </pre>
*
@ -109,8 +111,6 @@ public class Wx {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(Wx.class);
private static final String transformedKey = "com.raytheon.transformed";
private long wwaStopTime;
private long wwaStartTime;
@ -184,7 +184,6 @@ public class Wx {
.getPathcastConfig();
UnitConverter distanceToMeters = config.getUnitDistance()
.getConverterTo(SI.METER);
UnitConverter metersToDistance = distanceToMeters.inverse();
int maxCount = pathcastConfiguration.getMaxResults();
int maxGroup = pathcastConfiguration.getMaxGroup();
@ -196,7 +195,6 @@ public class Wx {
String areaNotationField = pathcastConfiguration.getAreaNotationField();
String areaNotationAbbrevField = pathcastConfiguration
.getAreaNotationTranslationFile();
String timezoneTable = geospatialConfig.getTimezoneSource();
String timezoneField = geospatialConfig.getTimezoneField();
String pointSource = pathcastConfiguration.getPointSource();
String pointField = pathcastConfiguration.getPointField().toLowerCase();
@ -344,18 +342,12 @@ public class Wx {
}
}
SpatialQueryResult[] ptFeatures = null;
AbstractDbSourceDataAdaptor pathcastDataAdaptor = null;
if (pointSource != null) {
ptFeatures = SpatialQueryFactory.create().query(pointSource,
ptFields.toArray(new String[ptFields.size()]),
bufferedPathCastArea, pointFilter,
SearchMode.INTERSECTS);
if (latLonToLocal != null) {
for (SpatialQueryResult rslt : ptFeatures) {
rslt.attributes.put(transformedKey,
JTS.transform(rslt.geometry, latLonToLocal));
}
}
pathcastDataAdaptor = DataAdaptorFactory
.createPathcastDataAdaptor(pathcastConfiguration,
distanceToMeters, bufferedPathCastArea,
localizedSite);
}
SpatialQueryResult[] areaFeatures = null;
@ -432,99 +424,14 @@ public class Wx {
.get(timezoneField));
}
Geometry localPCGeom = null;
if (pcGeom != null) {
localPCGeom = JTS.transform(pcGeom, latLonToLocal);
}
// Find closest points
GeodeticCalculator gc = new GeodeticCalculator();
List<ClosestPoint> points = new ArrayList<ClosestPoint>(
ptFeatures.length);
for (SpatialQueryResult pointRslt : ptFeatures) {
Geometry localPt = (Geometry) pointRslt.attributes
.get(transformedKey);
double minDist = Double.MAX_VALUE;
Coordinate closestCoord = null;
if (localPCGeom != null) {
Coordinate[] localPts = localPCGeom.getCoordinates();
Coordinate[] latLonPts = pcGeom.getCoordinates();
for (int i = 0; i < localPts.length; ++i) {
Coordinate loc = localPts[i];
double distance = loc.distance(localPt
.getCoordinate());
if (distance <= thresholdInMeters
&& distance < minDist) {
minDist = distance;
closestCoord = latLonPts[i];
}
}
List<ClosestPoint> points = null;
if (pathcastDataAdaptor != null) {
points = pathcastDataAdaptor.getPathcastData(
pathcastConfiguration, distanceToMeters,
latLonToLocal, pcGeom, centroid, areaFeatures,
pc.area, pc.parentArea);
} else {
closestCoord = centroid.getCoordinate();
minDist = 0;
}
if (closestCoord != null) {
ClosestPoint cp = new ClosestPoint();
cp.point = pointRslt.geometry.getCoordinate();
cp.name = String.valueOf(pointRslt.attributes
.get(pointField));
cp.distance = minDist;
cp.roundedDistance = (int) metersToDistance
.convert(minDist);
gc.setStartingGeographicPoint(cp.point.x, cp.point.y);
gc.setDestinationGeographicPoint(closestCoord.x,
closestCoord.y);
cp.azimuth = gc.getAzimuth();
cp.oppositeAzimuth = ClosestPoint
.adjustAngle(cp.azimuth + 180);
cp.roundedAzimuth = GeoUtil.roundAzimuth(cp.azimuth);
cp.oppositeRoundedAzimuth = ClosestPoint
.adjustAngle(cp.roundedAzimuth + 180);
boolean found = false;
for (SpatialQueryResult areaRslt : areaFeatures) {
if (areaRslt.geometry.contains(pointRslt.geometry)) {
cp.area = String.valueOf(areaRslt.attributes
.get(areaField));
cp.parentArea = String
.valueOf(areaRslt.attributes
.get(parentAreaField));
found = true;
break;
}
}
if (!found) {
cp.area = pc.area;
cp.parentArea = pc.parentArea;
}
if (ptFields.contains("population")) {
try {
cp.population = Integer.valueOf(String
.valueOf(pointRslt.attributes
.get("population")));
} catch (Exception e) {
cp.population = 0;
}
}
if (ptFields.contains("warngenlev")) {
try {
cp.warngenlev = Integer.valueOf(String
.valueOf(pointRslt.attributes
.get("warngenlev")));
} catch (Exception e) {
cp.warngenlev = 3;
}
}
points.add(cp);
}
}
if (fields.isEmpty() == false) {
// Sort the points based on sortBy fields
Collections
.sort(points, new ClosestPointComparator(fields));
points = new ArrayList<ClosestPoint>(0);
}
pcPoints.put(pc, points);
}
@ -773,9 +680,13 @@ public class Wx {
List<ClosestPoint> availablePoints = new ArrayList<ClosestPoint>();
for (PointSourceConfiguration pointConfig : pointConfigs) {
long t0 = System.currentTimeMillis();
availablePoints.addAll(DataAdaptorFactory.createPointSource(
pointConfig).getData(config, pointConfig,
bufferedSearchArea, localizedSite));
AbstractDbSourceDataAdaptor adaptor = DataAdaptorFactory
.createDataAdaptor(pointConfig, bufferedSearchArea,
localizedSite);
if (adaptor != null) {
availablePoints.addAll(adaptor.getData(config, pointConfig,
localizedSite));
}
long t1 = System.currentTimeMillis();
System.out.println("getClosestPoint.dbQuery took " + (t1 - t0)
+ " for point source " + pointConfig.getPointSource());