Merge branch '21.2-Warngen_Urban_Boundaries' into development
Former-commit-id:9068626b55
[formerly8f4941a1b1
] [formerly7d349ce98e
[formerly c7647d728846cf2a22613ea915c40c42ec1d10ee]] Former-commit-id:7d349ce98e
Former-commit-id:877f0b4a98
This commit is contained in:
commit
8cfa4137a8
7 changed files with 736 additions and 292 deletions
|
@ -1,3 +1,22 @@
|
||||||
|
/**
|
||||||
|
* 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;
|
package com.raytheon.viz.warngen.config;
|
||||||
|
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
|
@ -10,8 +29,14 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
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.PointSourceConfiguration;
|
||||||
import com.raytheon.uf.common.dataplugin.warning.config.WarngenConfiguration;
|
import com.raytheon.uf.common.dataplugin.warning.config.WarngenConfiguration;
|
||||||
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
|
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
|
||||||
|
@ -21,52 +46,112 @@ import com.raytheon.uf.common.geospatial.SpatialQueryFactory;
|
||||||
import com.raytheon.uf.common.geospatial.SpatialQueryResult;
|
import com.raytheon.uf.common.geospatial.SpatialQueryResult;
|
||||||
import com.raytheon.uf.viz.core.exception.VizException;
|
import com.raytheon.uf.viz.core.exception.VizException;
|
||||||
import com.raytheon.uf.viz.core.maps.rsc.DbMapQueryFactory;
|
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.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.Geometry;
|
||||||
|
import com.vividsolutions.jts.geom.Point;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract database source adaptor to data.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Sept. 18 jsanchez Added pathcast algorithm.
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author jsanchez
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
abstract public class AbstractDbSourceDataAdaptor {
|
abstract public class AbstractDbSourceDataAdaptor {
|
||||||
|
|
||||||
protected Set<String> sortFields = new HashSet<String>(
|
private static final String transformedKey = "com.raytheon.transformed";
|
||||||
Arrays.asList(new String[] { "distance", "area", "parentArea" }));
|
|
||||||
|
|
||||||
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 Geometry searchArea;
|
||||||
|
|
||||||
protected String localizedSite;
|
protected String localizedSite;
|
||||||
|
|
||||||
abstract protected Set<String> createSpatialQueryField();
|
protected SpatialQueryResult[] ptFeatures;
|
||||||
|
|
||||||
abstract protected ClosestPoint createClosestPoint(Set<String> ptFields,
|
protected Map<String, RequestConstraint> filter;
|
||||||
SpatialQueryResult ptRslt);
|
|
||||||
|
|
||||||
abstract protected Map<String, RequestConstraint> processFilterSubstitution();
|
protected Set<String> ptFields;
|
||||||
|
|
||||||
public Collection<ClosestPoint> getData(WarngenConfiguration config,
|
protected String[] sortBy;
|
||||||
PointSourceConfiguration pointConfig, Geometry searchArea,
|
|
||||||
|
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 {
|
String localizedSite) throws VizException {
|
||||||
this.pointConfig = pointConfig;
|
|
||||||
this.searchArea = searchArea;
|
|
||||||
this.localizedSite = localizedSite;
|
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();
|
public AbstractDbSourceDataAdaptor(
|
||||||
Set<String> ptFields = createSpatialQueryField();
|
PointSourceConfiguration pointSourceConfiguration,
|
||||||
List<ClosestPoint> points = null;
|
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 {
|
||||||
|
|
||||||
|
SpatialQueryResult[] ptFeatures = null;
|
||||||
|
long t0 = System.currentTimeMillis();
|
||||||
try {
|
try {
|
||||||
long t0 = System.currentTimeMillis();
|
|
||||||
SpatialQueryResult[] ptFeatures = null;
|
|
||||||
Double decimationTolerance = pointConfig
|
|
||||||
.getGeometryDecimationTolerance();
|
|
||||||
String field = "the_geom";
|
|
||||||
|
|
||||||
if (decimationTolerance != null && decimationTolerance > 0) {
|
if (decimationTolerance != null && decimationTolerance > 0) {
|
||||||
// find available tolerances
|
// find available tolerances
|
||||||
List<Double> results = DbMapQueryFactory
|
List<Double> results = DbMapQueryFactory.getMapQuery(
|
||||||
.getMapQuery(
|
"mapdata." + pointSource.toLowerCase(), GEOM_FIELD)
|
||||||
"mapdata."
|
|
||||||
+ pointConfig.getPointSource()
|
|
||||||
.toLowerCase(), field)
|
|
||||||
.getLevels();
|
.getLevels();
|
||||||
Collections.sort(results, Collections.reverseOrder());
|
Collections.sort(results, Collections.reverseOrder());
|
||||||
|
|
||||||
|
@ -89,53 +174,212 @@ abstract public class AbstractDbSourceDataAdaptor {
|
||||||
String suffix = "_"
|
String suffix = "_"
|
||||||
+ StringUtils.replaceChars(
|
+ StringUtils.replaceChars(
|
||||||
df.format(decimationTolerance), '.', '_');
|
df.format(decimationTolerance), '.', '_');
|
||||||
ptFeatures = SpatialQueryFactory.create().query(
|
ptFeatures = SpatialQueryFactory.create().query(pointSource,
|
||||||
pointConfig.getPointSource(), field + suffix,
|
GEOM_FIELD + suffix,
|
||||||
ptFields.toArray(new String[ptFields.size()]),
|
ptFields.toArray(new String[ptFields.size()]),
|
||||||
searchArea, filter, SearchMode.INTERSECTS);
|
searchArea, filter, SearchMode.INTERSECTS);
|
||||||
} else {
|
} else {
|
||||||
ptFeatures = SpatialQueryFactory.create().query(
|
ptFeatures = SpatialQueryFactory.create().query(pointSource,
|
||||||
pointConfig.getPointSource(),
|
|
||||||
ptFields.toArray(new String[ptFields.size()]),
|
ptFields.toArray(new String[ptFields.size()]),
|
||||||
searchArea, filter, SearchMode.INTERSECTS);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
if (ptFeatures != null) {
|
return ptFeatures;
|
||||||
points = new ArrayList<ClosestPoint>(ptFeatures.length);
|
}
|
||||||
} else {
|
|
||||||
points = new ArrayList<ClosestPoint>(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (SpatialQueryResult ptRslt : ptFeatures) {
|
/**
|
||||||
if (ptRslt != null && ptRslt.geometry != null) {
|
* Returns the data of the points/areas relative to the searchArea
|
||||||
Object nameObj = ptRslt.attributes.get(pointConfig
|
*
|
||||||
.getPointField());
|
* @param config
|
||||||
if (nameObj != null) {
|
* @param pointConfig
|
||||||
ClosestPoint cp = createClosestPoint(ptFields, ptRslt);
|
* @param localizedSite
|
||||||
points.add(cp);
|
* @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 {
|
||||||
|
points = new ArrayList<ClosestPoint>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (SpatialQueryResult ptRslt : ptFeatures) {
|
||||||
|
if (ptRslt != null && ptRslt.geometry != null) {
|
||||||
|
Object nameObj = ptRslt.attributes.get(pointConfig
|
||||||
|
.getPointField());
|
||||||
|
if (nameObj != null) {
|
||||||
|
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;
|
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,
|
protected int getPopulation(Set<String> ptFields,
|
||||||
Map<String, Object> attributes) {
|
Map<String, Object> attributes) {
|
||||||
int population = 0;
|
int population = 0;
|
||||||
|
|
||||||
if (ptFields.contains("population")) {
|
if (ptFields.contains(String
|
||||||
|
.valueOf(ClosestPointComparator.Sort.POPULATION))) {
|
||||||
try {
|
try {
|
||||||
population = Integer.valueOf(String.valueOf(attributes
|
population = Integer
|
||||||
.get("population")));
|
.valueOf(String.valueOf(attributes.get(String
|
||||||
|
.valueOf(ClosestPointComparator.Sort.POPULATION))));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// Ignore
|
// Ignore
|
||||||
}
|
}
|
||||||
|
@ -144,14 +388,23 @@ abstract public class AbstractDbSourceDataAdaptor {
|
||||||
return population;
|
return population;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the warngenlev from the attributes.
|
||||||
|
*
|
||||||
|
* @param ptFields
|
||||||
|
* @param attributes
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
protected int getWangenlev(Set<String> ptFields,
|
protected int getWangenlev(Set<String> ptFields,
|
||||||
Map<String, Object> attributes) {
|
Map<String, Object> attributes) {
|
||||||
int warngenlev = 0;
|
int warngenlev = 3;
|
||||||
|
|
||||||
if (ptFields.contains("warngenlev")) {
|
if (ptFields.contains(String
|
||||||
|
.valueOf(ClosestPointComparator.Sort.WARNGENLEV))) {
|
||||||
try {
|
try {
|
||||||
warngenlev = Integer.valueOf(String.valueOf(attributes
|
warngenlev = Integer
|
||||||
.get("warngenlev")));
|
.valueOf(String.valueOf(attributes.get(String
|
||||||
|
.valueOf(ClosestPointComparator.Sort.WARNGENLEV))));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// Ignore
|
// Ignore
|
||||||
}
|
}
|
||||||
|
@ -160,4 +413,26 @@ abstract public class AbstractDbSourceDataAdaptor {
|
||||||
return warngenlev;
|
return warngenlev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the gid.
|
||||||
|
*
|
||||||
|
* @param ptFields
|
||||||
|
* @param attributes
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected int getGid(Set<String> ptFields, Map<String, Object> attributes) {
|
||||||
|
int gid = 0;
|
||||||
|
|
||||||
|
if (ptFields.contains(String.valueOf(ClosestPointComparator.Sort.GID))) {
|
||||||
|
try {
|
||||||
|
gid = Integer.valueOf(String.valueOf(attributes.get(String
|
||||||
|
.valueOf(ClosestPointComparator.Sort.GID))));
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return gid;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,16 @@
|
||||||
**/
|
**/
|
||||||
package com.raytheon.viz.warngen.config;
|
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;
|
||||||
import com.raytheon.uf.common.dataplugin.warning.config.PointSourceConfiguration.PointType;
|
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>
|
* <pre>
|
||||||
*
|
*
|
||||||
|
@ -32,6 +37,7 @@ import com.raytheon.uf.common.dataplugin.warning.config.PointSourceConfiguration
|
||||||
* Date Ticket# Engineer Description
|
* Date Ticket# Engineer Description
|
||||||
* ------------ ---------- ----------- --------------------------
|
* ------------ ---------- ----------- --------------------------
|
||||||
* Oct 26, 2011 bgonzale Initial creation
|
* Oct 26, 2011 bgonzale Initial creation
|
||||||
|
* Sep 19, 2012 jsanchez Allowed adaptor to be used for pathcast.
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -41,15 +47,32 @@ import com.raytheon.uf.common.dataplugin.warning.config.PointSourceConfiguration
|
||||||
|
|
||||||
public class DataAdaptorFactory {
|
public class DataAdaptorFactory {
|
||||||
|
|
||||||
public static AbstractDbSourceDataAdaptor createPointSource(
|
public static AbstractDbSourceDataAdaptor createDataAdaptor(
|
||||||
PointSourceConfiguration pointConfig) {
|
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;
|
AbstractDbSourceDataAdaptor adaptor = null;
|
||||||
|
|
||||||
if (pointConfig.getType() == PointType.AREA) {
|
if (pathcastConfiguration.getType() == PointType.AREA) {
|
||||||
adaptor = new DbAreaSourceDataAdaptor();
|
adaptor = new DbAreaSourceDataAdaptor(pathcastConfiguration,
|
||||||
} else if (pointConfig.getType() == PointType.POINT) {
|
distanceToMeters, searchArea, localizedSite);
|
||||||
adaptor = new DbPointSourceDataAdaptor();
|
} else if (pathcastConfiguration.getType() == PointType.POINT) {
|
||||||
|
adaptor = new DbPointSourceDataAdaptor(pathcastConfiguration,
|
||||||
|
distanceToMeters, searchArea, localizedSite);
|
||||||
}
|
}
|
||||||
|
|
||||||
return adaptor;
|
return adaptor;
|
||||||
|
|
|
@ -1,57 +1,108 @@
|
||||||
|
/**
|
||||||
|
* 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;
|
package com.raytheon.viz.warngen.config;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.measure.converter.UnitConverter;
|
||||||
|
|
||||||
import org.geotools.referencing.GeodeticCalculator;
|
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.dataquery.requests.RequestConstraint;
|
||||||
import com.raytheon.uf.common.geospatial.SpatialQueryResult;
|
import com.raytheon.uf.common.geospatial.SpatialQueryResult;
|
||||||
|
import com.raytheon.uf.viz.core.exception.VizException;
|
||||||
import com.raytheon.viz.warngen.PreferenceUtil;
|
import com.raytheon.viz.warngen.PreferenceUtil;
|
||||||
import com.raytheon.viz.warngen.gis.ClosestPoint;
|
import com.raytheon.viz.warngen.gis.ClosestPoint;
|
||||||
import com.raytheon.viz.warngen.gis.GisUtil;
|
import com.raytheon.viz.warngen.gis.GisUtil;
|
||||||
import com.raytheon.viz.warngen.gis.GisUtil.Direction;
|
import com.raytheon.viz.warngen.gis.GisUtil.Direction;
|
||||||
import com.vividsolutions.jts.geom.Coordinate;
|
import com.vividsolutions.jts.geom.Coordinate;
|
||||||
|
import com.vividsolutions.jts.geom.Envelope;
|
||||||
import com.vividsolutions.jts.geom.Geometry;
|
import com.vividsolutions.jts.geom.Geometry;
|
||||||
|
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
||||||
|
import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Area source data adaptor for data retrieved from a Database.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Sept 19, 2012 jsanchez Added pathcast use.
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
*
|
*
|
||||||
* @author jsanchez
|
* @author jsanchez
|
||||||
*
|
* @version 1.0
|
||||||
*/
|
*/
|
||||||
public class DbAreaSourceDataAdaptor extends AbstractDbSourceDataAdaptor {
|
public class DbAreaSourceDataAdaptor extends AbstractDbSourceDataAdaptor {
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
private static final String useDirectionField = "usedirs";
|
private static final String useDirectionField = "usedirs";
|
||||||
|
|
||||||
private static final String suppressedDirectionsField = "supdirs";
|
private static final String suppressedDirectionsField = "supdirs";
|
||||||
|
|
||||||
private static final String cwaField = "cwa";
|
private static final String cwaField = "cwa";
|
||||||
|
|
||||||
private GeodeticCalculator gc = new GeodeticCalculator();
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<String> createSpatialQueryField() {
|
protected Set<String> createSpatialQueryField(String pointField,
|
||||||
|
String[] sortBy) {
|
||||||
Set<String> ptFields = new HashSet<String>();
|
Set<String> ptFields = new HashSet<String>();
|
||||||
ptFields.add(pointConfig.getPointField());
|
ptFields.add(pointField);
|
||||||
ptFields.add(useDirectionField);
|
ptFields.add(useDirectionField);
|
||||||
ptFields.add(suppressedDirectionsField);
|
ptFields.add(suppressedDirectionsField);
|
||||||
|
|
||||||
List<String> fields = new ArrayList<String>();
|
List<String> fields = null;
|
||||||
if (pointConfig.getSortBy() != null) {
|
if (sortBy != null && sortBy.length > 0) {
|
||||||
fields = Arrays.asList(pointConfig.getSortBy());
|
fields = Arrays.asList(sortBy);
|
||||||
|
} else {
|
||||||
|
fields = new ArrayList<String>(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sort fields don't exist in the db.
|
||||||
for (String field : fields) {
|
for (String field : fields) {
|
||||||
if (sortFields.contains(field.toLowerCase()) == false) {
|
if (undatabasedSortableFields.contains(field.toUpperCase()) == false) {
|
||||||
ptFields.add(field.toLowerCase());
|
ptFields.add(field.toUpperCase());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,77 +110,31 @@ public class DbAreaSourceDataAdaptor extends AbstractDbSourceDataAdaptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Creates a closest point object.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected ClosestPoint createClosestPoint(Set<String> ptFields,
|
protected ClosestPoint createClosestPoint(String pointField,
|
||||||
SpatialQueryResult ptRslt) {
|
Set<String> ptFields, SpatialQueryResult ptRslt) {
|
||||||
Map<String, Object> attributes = ptRslt.attributes;
|
Map<String, Object> attributes = ptRslt.attributes;
|
||||||
|
|
||||||
String name = String
|
String name = String.valueOf(attributes.get(pointField));
|
||||||
.valueOf(attributes.get(pointConfig.getPointField()));
|
|
||||||
Coordinate point = ptRslt.geometry.getCoordinate();
|
Coordinate point = ptRslt.geometry.getCoordinate();
|
||||||
int population = getPopulation(ptFields, attributes);
|
int population = getPopulation(ptFields, attributes);
|
||||||
int warngenlev = getWangenlev(ptFields, attributes);
|
int warngenlev = getWangenlev(ptFields, attributes);
|
||||||
List<String> partOfArea = getPartOfArea(ptFields, attributes,
|
List<String> partOfArea = getPartOfArea(ptFields, attributes,
|
||||||
ptRslt.geometry);
|
ptRslt.geometry);
|
||||||
|
ClosestPoint cp = new ClosestPoint(name, point, population, warngenlev,
|
||||||
return new ClosestPoint(name, point, population, warngenlev, partOfArea);
|
partOfArea);
|
||||||
|
cp.setGid(getGid(ptFields, attributes));
|
||||||
|
return cp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Processes the filter to set the localized site.
|
||||||
* @param ptFields
|
|
||||||
* @param attributes
|
|
||||||
* @param geom
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
private List<String> getPartOfArea(Set<String> ptFields,
|
|
||||||
Map<String, Object> attributes, Geometry geom) {
|
|
||||||
List<String> 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, ""));
|
|
||||||
|
|
||||||
if (attributes.get(suppressedDirectionsField) != null) {
|
|
||||||
String suppressedDirections = String.valueOf(
|
|
||||||
attributes.get(suppressedDirectionsField))
|
|
||||||
.toLowerCase();
|
|
||||||
// supdirs can be 'nse', for example
|
|
||||||
// TODO create an enum constructor for Directions
|
|
||||||
for (int i = 0; i < suppressedDirections.length(); i++) {
|
|
||||||
switch (suppressedDirections.charAt(i)) {
|
|
||||||
case 'n':
|
|
||||||
partOfArea.remove(Direction.NORTH.toString());
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
partOfArea.remove(Direction.SOUTH.toString());
|
|
||||||
break;
|
|
||||||
case 'e':
|
|
||||||
partOfArea.remove(Direction.EAST.toString());
|
|
||||||
break;
|
|
||||||
case 'w':
|
|
||||||
partOfArea.remove(Direction.WEST.toString());
|
|
||||||
break;
|
|
||||||
case 'c':
|
|
||||||
partOfArea.remove(Direction.CENTRAL.toString());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return partOfArea;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Map<String, RequestConstraint> processFilterSubstitution() {
|
protected Map<String, RequestConstraint> processFilterSubstitution(
|
||||||
Map<String, RequestConstraint> filter = pointConfig.getFilter();
|
Map<String, RequestConstraint> filter) {
|
||||||
if (filter != null) {
|
if (filter != null) {
|
||||||
// Process substitutes for filter
|
// Process substitutes for filter
|
||||||
for (RequestConstraint rc : filter.values()) {
|
for (RequestConstraint rc : filter.values()) {
|
||||||
|
@ -146,4 +151,139 @@ public class DbAreaSourceDataAdaptor extends AbstractDbSourceDataAdaptor {
|
||||||
|
|
||||||
return filter;
|
return filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the part of area impacted if the userDirectionField is set to
|
||||||
|
* true.
|
||||||
|
*
|
||||||
|
* @param ptFields
|
||||||
|
* @param attributes
|
||||||
|
* @param geom
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private List<String> getPartOfArea(Set<String> ptFields,
|
||||||
|
Map<String, Object> attributes, Geometry geom) {
|
||||||
|
List<String> partOfArea = null;
|
||||||
|
|
||||||
|
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(calculateLocationPortion(
|
||||||
|
geom, intersection, gc));
|
||||||
|
|
||||||
|
if (attributes.get(suppressedDirectionsField) != null) {
|
||||||
|
String suppressedDirections = String.valueOf(
|
||||||
|
attributes.get(suppressedDirectionsField))
|
||||||
|
.toLowerCase();
|
||||||
|
// supdirs can be 'nse', for example
|
||||||
|
// TODO create an enum constructor for Directions
|
||||||
|
for (int i = 0; i < suppressedDirections.length(); i++) {
|
||||||
|
switch (suppressedDirections.charAt(i)) {
|
||||||
|
case 'n':
|
||||||
|
partOfArea.remove(Direction.NORTH.toString());
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
partOfArea.remove(Direction.SOUTH.toString());
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
partOfArea.remove(Direction.EAST.toString());
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
partOfArea.remove(Direction.WEST.toString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (partOfArea != null && !partOfArea.isEmpty()) {
|
||||||
|
return partOfArea;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (CardinalRange range : ranges) {
|
||||||
|
if (degrees > range.lowRange && degrees <= range.highRange) {
|
||||||
|
directions = range.directions;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return directions;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,23 +19,24 @@
|
||||||
**/
|
**/
|
||||||
package com.raytheon.viz.warngen.config;
|
package com.raytheon.viz.warngen.config;
|
||||||
|
|
||||||
import java.text.DecimalFormat;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
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.dataquery.requests.RequestConstraint;
|
||||||
import com.raytheon.uf.common.geospatial.SpatialQueryResult;
|
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.PreferenceUtil;
|
||||||
import com.raytheon.viz.warngen.gis.ClosestPoint;
|
import com.raytheon.viz.warngen.gis.ClosestPoint;
|
||||||
import com.vividsolutions.jts.geom.Coordinate;
|
import com.vividsolutions.jts.geom.Coordinate;
|
||||||
|
import com.vividsolutions.jts.geom.Geometry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PointSource data adaptor for data retrieved from a Database.
|
* PointSource data adaptor for data retrieved from a Database.
|
||||||
|
@ -56,42 +57,38 @@ import com.vividsolutions.jts.geom.Coordinate;
|
||||||
|
|
||||||
public class DbPointSourceDataAdaptor extends AbstractDbSourceDataAdaptor {
|
public class DbPointSourceDataAdaptor extends AbstractDbSourceDataAdaptor {
|
||||||
|
|
||||||
@Override
|
public DbPointSourceDataAdaptor(
|
||||||
protected Set<String> createSpatialQueryField() {
|
PathcastConfiguration pathcastConfiguration,
|
||||||
Set<String> ptFields = new HashSet<String>();
|
UnitConverter distanceToMeters, Geometry searchArea,
|
||||||
ptFields.add(pointConfig.getPointField());
|
String localizedSite) throws VizException {
|
||||||
|
super(pathcastConfiguration, distanceToMeters, searchArea,
|
||||||
|
localizedSite);
|
||||||
|
}
|
||||||
|
|
||||||
List<String> fields = new ArrayList<String>();
|
public DbPointSourceDataAdaptor(
|
||||||
if (pointConfig.getSortBy() != null) {
|
PointSourceConfiguration pointSourceConfiguration,
|
||||||
fields = Arrays.asList(pointConfig.getSortBy());
|
Geometry searchArea, String localizedSite) throws VizException {
|
||||||
}
|
super(pointSourceConfiguration, searchArea, localizedSite);
|
||||||
|
|
||||||
for (String field : fields) {
|
|
||||||
if (sortFields.contains(field.toLowerCase()) == false) {
|
|
||||||
ptFields.add(field.toLowerCase());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ptFields;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ClosestPoint createClosestPoint(Set<String> ptFields,
|
protected ClosestPoint createClosestPoint(String pointField,
|
||||||
SpatialQueryResult ptRslt) {
|
Set<String> ptFields, SpatialQueryResult ptRslt) {
|
||||||
Map<String, Object> attributes = ptRslt.attributes;
|
Map<String, Object> attributes = ptRslt.attributes;
|
||||||
|
|
||||||
String name = String
|
String name = String.valueOf(attributes.get(pointField));
|
||||||
.valueOf(attributes.get(pointConfig.getPointField()));
|
|
||||||
Coordinate point = ptRslt.geometry.getCoordinate();
|
Coordinate point = ptRslt.geometry.getCoordinate();
|
||||||
int population = getPopulation(ptFields, attributes);
|
int population = getPopulation(ptFields, attributes);
|
||||||
int warngenlev = getWangenlev(ptFields, attributes);
|
int warngenlev = getWangenlev(ptFields, attributes);
|
||||||
|
ClosestPoint cp = new ClosestPoint(name, point, population, warngenlev,
|
||||||
return new ClosestPoint(name, point, population, warngenlev, null);
|
null);
|
||||||
|
cp.setGid(getGid(ptFields, attributes));
|
||||||
|
return cp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Map<String, RequestConstraint> processFilterSubstitution() {
|
protected Map<String, RequestConstraint> processFilterSubstitution(
|
||||||
Map<String, RequestConstraint> filter = pointConfig.getFilter();
|
Map<String, RequestConstraint> filter) {
|
||||||
if (filter != null) {
|
if (filter != null) {
|
||||||
// Process substitutes for filter
|
// Process substitutes for filter
|
||||||
for (RequestConstraint rc : filter.values()) {
|
for (RequestConstraint rc : filter.values()) {
|
||||||
|
@ -102,4 +99,25 @@ public class DbPointSourceDataAdaptor extends AbstractDbSourceDataAdaptor {
|
||||||
|
|
||||||
return filter;
|
return filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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 (undatabasedSortableFields.contains(field.toUpperCase()) == false) {
|
||||||
|
ptFields.add(field.toUpperCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptFields;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ import com.vividsolutions.jts.geom.Coordinate;
|
||||||
* Dec 11, 2007 #601 chammack Initial Creation.
|
* Dec 11, 2007 #601 chammack Initial Creation.
|
||||||
* APr 18, 2012 #14733 Qinglu Lin David's fix is used, which adds
|
* APr 18, 2012 #14733 Qinglu Lin David's fix is used, which adds
|
||||||
* a copy constructor.
|
* a copy constructor.
|
||||||
|
* Sep 18, 2012 jsanchez Added setter methods.
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -44,6 +45,8 @@ import com.vividsolutions.jts.geom.Coordinate;
|
||||||
* @version 1
|
* @version 1
|
||||||
*/
|
*/
|
||||||
public class ClosestPoint implements Comparable<ClosestPoint> {
|
public class ClosestPoint implements Comparable<ClosestPoint> {
|
||||||
|
protected int gid;
|
||||||
|
|
||||||
protected String name;
|
protected String name;
|
||||||
|
|
||||||
protected String area;
|
protected String area;
|
||||||
|
@ -173,6 +176,74 @@ public class ClosestPoint implements Comparable<ClosestPoint> {
|
||||||
return partOfArea;
|
return partOfArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getGid() {
|
||||||
|
return gid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getTime() {
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTime(Date time) {
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGid(int gid) {
|
||||||
|
this.gid = gid;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adjusts the angle from -360/360 to be between -180/180
|
* Adjusts the angle from -360/360 to be between -180/180
|
||||||
*
|
*
|
||||||
|
|
|
@ -37,6 +37,7 @@ import org.apache.commons.lang.ArrayUtils;
|
||||||
* Date Ticket# Engineer Description
|
* Date Ticket# Engineer Description
|
||||||
* ------------ ---------- ----------- --------------------------
|
* ------------ ---------- ----------- --------------------------
|
||||||
* Mar 3, 2011 jsanchez Initial creation
|
* Mar 3, 2011 jsanchez Initial creation
|
||||||
|
* Sep 18, 2012 15428 jsanchez Updated the enum sort to be more flexible.
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -46,11 +47,11 @@ import org.apache.commons.lang.ArrayUtils;
|
||||||
|
|
||||||
public class ClosestPointComparator implements Comparator<ClosestPoint> {
|
public class ClosestPointComparator implements Comparator<ClosestPoint> {
|
||||||
|
|
||||||
private enum Sort {
|
public static enum Sort {
|
||||||
NAME, POPULATION, DISTANCE, LEVEL, LAT, LON, AREA, PARENT_AREA
|
NAME, POPULATION, DISTANCE, WARNGENLEV, LAT, LON, AREA, PARENTAREA, GID
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayList<Sort> list;
|
private final ArrayList<Sort> list;
|
||||||
|
|
||||||
private int counter;
|
private int counter;
|
||||||
|
|
||||||
|
@ -63,23 +64,25 @@ public class ClosestPointComparator implements Comparator<ClosestPoint> {
|
||||||
counter = 0;
|
counter = 0;
|
||||||
list = new ArrayList<Sort>();
|
list = new ArrayList<Sort>();
|
||||||
for (String field : fields) {
|
for (String field : fields) {
|
||||||
if (field.equalsIgnoreCase("name")) {
|
if (field.equalsIgnoreCase(Sort.NAME.toString())) {
|
||||||
list.add(Sort.NAME);
|
list.add(Sort.NAME);
|
||||||
} else if (field.equalsIgnoreCase("population")) {
|
} else if (field.equalsIgnoreCase(Sort.POPULATION.toString())) {
|
||||||
list.add(Sort.POPULATION);
|
list.add(Sort.POPULATION);
|
||||||
} else if (field.equalsIgnoreCase("distance")) {
|
} else if (field.equalsIgnoreCase(Sort.DISTANCE.toString())) {
|
||||||
list.add(Sort.DISTANCE);
|
list.add(Sort.DISTANCE);
|
||||||
} else if (field.equalsIgnoreCase("warngenlev")
|
} else if (field.equalsIgnoreCase(Sort.WARNGENLEV.toString())
|
||||||
|| field.equalsIgnoreCase("watch_warn")) {
|
|| field.equalsIgnoreCase("watch_warn")) {
|
||||||
list.add(Sort.LEVEL);
|
list.add(Sort.WARNGENLEV);
|
||||||
} else if (field.equalsIgnoreCase("lat")) {
|
} else if (field.equalsIgnoreCase(Sort.LAT.toString())) {
|
||||||
list.add(Sort.LAT);
|
list.add(Sort.LAT);
|
||||||
} else if (field.equalsIgnoreCase("lon")) {
|
} else if (field.equalsIgnoreCase(Sort.LON.toString())) {
|
||||||
list.add(Sort.LON);
|
list.add(Sort.LON);
|
||||||
} else if (field.equalsIgnoreCase("area")) {
|
} else if (field.equalsIgnoreCase(Sort.AREA.toString())) {
|
||||||
list.add(Sort.AREA);
|
list.add(Sort.AREA);
|
||||||
} else if (field.equalsIgnoreCase("parentArea")) {
|
} else if (field.equalsIgnoreCase(Sort.PARENTAREA.toString())) {
|
||||||
list.add(Sort.PARENT_AREA);
|
list.add(Sort.PARENTAREA);
|
||||||
|
} else if (field.equalsIgnoreCase(Sort.GID.toString())) {
|
||||||
|
list.add(Sort.GID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,13 +105,13 @@ public class ClosestPointComparator implements Comparator<ClosestPoint> {
|
||||||
list.clear();
|
list.clear();
|
||||||
|
|
||||||
ClosestPointComparator comparator = new ClosestPointComparator(
|
ClosestPointComparator comparator = new ClosestPointComparator(
|
||||||
(ArrayList<String>) Arrays.asList(fields));
|
Arrays.asList(fields));
|
||||||
Collections
|
Collections.sort(Arrays.asList(points), comparator);
|
||||||
.sort((List<ClosestPoint>) Arrays.asList(points), comparator);
|
|
||||||
|
|
||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int compare(ClosestPoint cp1, ClosestPoint cp2) {
|
public int compare(ClosestPoint cp1, ClosestPoint cp2) {
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
return cp1.compareTo(cp2);
|
return cp1.compareTo(cp2);
|
||||||
|
@ -118,7 +121,7 @@ public class ClosestPointComparator implements Comparator<ClosestPoint> {
|
||||||
switch (list.get(counter)) {
|
switch (list.get(counter)) {
|
||||||
case NAME:
|
case NAME:
|
||||||
if (cp1.name.matches("((-|\\+)?[0-9]+(\\.[0-9]+)?)+")
|
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(
|
value = Double.valueOf(cp1.name).compareTo(
|
||||||
Double.valueOf(cp2.name));
|
Double.valueOf(cp2.name));
|
||||||
} else {
|
} else {
|
||||||
|
@ -128,7 +131,7 @@ public class ClosestPointComparator implements Comparator<ClosestPoint> {
|
||||||
case POPULATION:
|
case POPULATION:
|
||||||
value = -1 * Double.compare(cp1.population, cp2.population);
|
value = -1 * Double.compare(cp1.population, cp2.population);
|
||||||
break;
|
break;
|
||||||
case LEVEL:
|
case WARNGENLEV:
|
||||||
value = Double.compare(cp1.warngenlev, cp2.warngenlev);
|
value = Double.compare(cp1.warngenlev, cp2.warngenlev);
|
||||||
break;
|
break;
|
||||||
case LAT:
|
case LAT:
|
||||||
|
@ -140,13 +143,16 @@ public class ClosestPointComparator implements Comparator<ClosestPoint> {
|
||||||
case AREA:
|
case AREA:
|
||||||
value = cp1.area.compareTo(cp2.area);
|
value = cp1.area.compareTo(cp2.area);
|
||||||
break;
|
break;
|
||||||
case PARENT_AREA:
|
case PARENTAREA:
|
||||||
value = cp1.parentArea.compareTo(cp2.parentArea);
|
value = cp1.parentArea.compareTo(cp2.parentArea);
|
||||||
break;
|
break;
|
||||||
case DISTANCE:
|
case DISTANCE:
|
||||||
value = new Integer(cp1.roundedDistance)
|
value = new Integer(cp1.roundedDistance)
|
||||||
.compareTo(cp2.roundedDistance);
|
.compareTo(cp2.roundedDistance);
|
||||||
break;
|
break;
|
||||||
|
case GID:
|
||||||
|
value = new Integer(cp1.gid).compareTo(cp2.gid);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value == 0 && counter + 1 < list.size()) {
|
if (value == 0 && counter + 1 < list.size()) {
|
||||||
|
|
|
@ -71,6 +71,7 @@ import com.raytheon.viz.awipstools.common.stormtrack.StormTrackState;
|
||||||
import com.raytheon.viz.core.map.GeoUtil;
|
import com.raytheon.viz.core.map.GeoUtil;
|
||||||
import com.raytheon.viz.warngen.PreferenceUtil;
|
import com.raytheon.viz.warngen.PreferenceUtil;
|
||||||
import com.raytheon.viz.warngen.WarngenException;
|
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.config.DataAdaptorFactory;
|
||||||
import com.raytheon.viz.warngen.util.Abbreviation;
|
import com.raytheon.viz.warngen.util.Abbreviation;
|
||||||
import com.raytheon.viz.warnings.DateUtil;
|
import com.raytheon.viz.warnings.DateUtil;
|
||||||
|
@ -97,6 +98,7 @@ import com.vividsolutions.jts.geom.Point;
|
||||||
* that loops over availablePoints.
|
* that loops over availablePoints.
|
||||||
* May 21, 2012 DR14480 Qinglu Lin Added code to prevent duplicate cities
|
* May 21, 2012 DR14480 Qinglu Lin Added code to prevent duplicate cities
|
||||||
* in pathcast.
|
* in pathcast.
|
||||||
|
* Sep 18, 2012 DR15428 jsanchez Moved the path cast data collecting to a seperate class.
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -107,8 +109,6 @@ public class Wx {
|
||||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||||
.getHandler(Wx.class);
|
.getHandler(Wx.class);
|
||||||
|
|
||||||
private static final String transformedKey = "com.raytheon.transformed";
|
|
||||||
|
|
||||||
private long wwaStopTime;
|
private long wwaStopTime;
|
||||||
|
|
||||||
private long wwaStartTime;
|
private long wwaStartTime;
|
||||||
|
@ -182,7 +182,6 @@ public class Wx {
|
||||||
.getPathcastConfig();
|
.getPathcastConfig();
|
||||||
UnitConverter distanceToMeters = config.getUnitDistance()
|
UnitConverter distanceToMeters = config.getUnitDistance()
|
||||||
.getConverterTo(SI.METER);
|
.getConverterTo(SI.METER);
|
||||||
UnitConverter metersToDistance = distanceToMeters.inverse();
|
|
||||||
|
|
||||||
int maxCount = pathcastConfiguration.getMaxResults();
|
int maxCount = pathcastConfiguration.getMaxResults();
|
||||||
int maxGroup = pathcastConfiguration.getMaxGroup();
|
int maxGroup = pathcastConfiguration.getMaxGroup();
|
||||||
|
@ -194,7 +193,6 @@ public class Wx {
|
||||||
String areaNotationField = pathcastConfiguration.getAreaNotationField();
|
String areaNotationField = pathcastConfiguration.getAreaNotationField();
|
||||||
String areaNotationAbbrevField = pathcastConfiguration
|
String areaNotationAbbrevField = pathcastConfiguration
|
||||||
.getAreaNotationTranslationFile();
|
.getAreaNotationTranslationFile();
|
||||||
String timezoneTable = geospatialConfig.getTimezoneSource();
|
|
||||||
String timezoneField = geospatialConfig.getTimezoneField();
|
String timezoneField = geospatialConfig.getTimezoneField();
|
||||||
String pointSource = pathcastConfiguration.getPointSource();
|
String pointSource = pathcastConfiguration.getPointSource();
|
||||||
String pointField = pathcastConfiguration.getPointField().toLowerCase();
|
String pointField = pathcastConfiguration.getPointField().toLowerCase();
|
||||||
|
@ -342,18 +340,12 @@ public class Wx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SpatialQueryResult[] ptFeatures = null;
|
AbstractDbSourceDataAdaptor pathcastDataAdaptor = null;
|
||||||
if (pointSource != null) {
|
if (pointSource != null) {
|
||||||
ptFeatures = SpatialQueryFactory.create().query(pointSource,
|
pathcastDataAdaptor = DataAdaptorFactory
|
||||||
ptFields.toArray(new String[ptFields.size()]),
|
.createPathcastDataAdaptor(pathcastConfiguration,
|
||||||
bufferedPathCastArea, pointFilter,
|
distanceToMeters, bufferedPathCastArea,
|
||||||
SearchMode.INTERSECTS);
|
localizedSite);
|
||||||
if (latLonToLocal != null) {
|
|
||||||
for (SpatialQueryResult rslt : ptFeatures) {
|
|
||||||
rslt.attributes.put(transformedKey,
|
|
||||||
JTS.transform(rslt.geometry, latLonToLocal));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SpatialQueryResult[] areaFeatures = null;
|
SpatialQueryResult[] areaFeatures = null;
|
||||||
|
@ -430,99 +422,14 @@ public class Wx {
|
||||||
.get(timezoneField));
|
.get(timezoneField));
|
||||||
}
|
}
|
||||||
|
|
||||||
Geometry localPCGeom = null;
|
List<ClosestPoint> points = null;
|
||||||
if (pcGeom != null) {
|
if (pathcastDataAdaptor != null) {
|
||||||
localPCGeom = JTS.transform(pcGeom, latLonToLocal);
|
points = pathcastDataAdaptor.getPathcastData(
|
||||||
}
|
pathcastConfiguration, distanceToMeters,
|
||||||
|
latLonToLocal, pcGeom, centroid, areaFeatures,
|
||||||
// Find closest points
|
pc.area, pc.parentArea);
|
||||||
GeodeticCalculator gc = new GeodeticCalculator();
|
} else {
|
||||||
List<ClosestPoint> points = new ArrayList<ClosestPoint>(
|
points = new ArrayList<ClosestPoint>(0);
|
||||||
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) {
|
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
pcPoints.put(pc, points);
|
pcPoints.put(pc, points);
|
||||||
}
|
}
|
||||||
|
@ -771,9 +678,13 @@ public class Wx {
|
||||||
List<ClosestPoint> availablePoints = new ArrayList<ClosestPoint>();
|
List<ClosestPoint> availablePoints = new ArrayList<ClosestPoint>();
|
||||||
for (PointSourceConfiguration pointConfig : pointConfigs) {
|
for (PointSourceConfiguration pointConfig : pointConfigs) {
|
||||||
long t0 = System.currentTimeMillis();
|
long t0 = System.currentTimeMillis();
|
||||||
availablePoints.addAll(DataAdaptorFactory.createPointSource(
|
AbstractDbSourceDataAdaptor adaptor = DataAdaptorFactory
|
||||||
pointConfig).getData(config, pointConfig,
|
.createDataAdaptor(pointConfig, bufferedSearchArea,
|
||||||
bufferedSearchArea, localizedSite));
|
localizedSite);
|
||||||
|
if (adaptor != null) {
|
||||||
|
availablePoints.addAll(adaptor.getData(config, pointConfig,
|
||||||
|
localizedSite));
|
||||||
|
}
|
||||||
long t1 = System.currentTimeMillis();
|
long t1 = System.currentTimeMillis();
|
||||||
System.out.println("getClosestPoint.dbQuery took " + (t1 - t0)
|
System.out.println("getClosestPoint.dbQuery took " + (t1 - t0)
|
||||||
+ " for point source " + pointConfig.getPointSource());
|
+ " for point source " + pointConfig.getPointSource());
|
||||||
|
|
Loading…
Add table
Reference in a new issue