Merge "Issue #2177 Improve county portion descriptions." into omaha_13.5.2
Former-commit-id:07f087013f
[formerly07f087013f
[formerly 1b7f1d8dce2cc1161ce06ca0c4a8df68803a12e1]] Former-commit-id:321ddebdde
Former-commit-id:0af2308491
This commit is contained in:
commit
2e26b28a40
9 changed files with 1528 additions and 126 deletions
|
@ -32,6 +32,7 @@ import java.util.List;
|
||||||
* Date Ticket# Engineer Description
|
* Date Ticket# Engineer Description
|
||||||
* ------------ ---------- ----------- --------------------------
|
* ------------ ---------- ----------- --------------------------
|
||||||
* Dec 11, 2007 #601 chammack Initial Creation.
|
* Dec 11, 2007 #601 chammack Initial Creation.
|
||||||
|
* Aug 19, 2013 2177 jsanchez Removed suppress attribute.
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -49,11 +50,6 @@ public class AffectedAreas {
|
||||||
*/
|
*/
|
||||||
protected List<String> partOfArea;
|
protected List<String> partOfArea;
|
||||||
|
|
||||||
/**
|
|
||||||
* The partOfArea to suppress (e.g. "ns")
|
|
||||||
*/
|
|
||||||
protected String suppress;
|
|
||||||
|
|
||||||
/** The notation of the area affected (e.g. "COUNTY") */
|
/** The notation of the area affected (e.g. "COUNTY") */
|
||||||
protected String areaNotation;
|
protected String areaNotation;
|
||||||
|
|
||||||
|
@ -89,17 +85,15 @@ public class AffectedAreas {
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param name
|
* @param name
|
||||||
* the name to set
|
* the name to set
|
||||||
*/
|
*/
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the areaNotation
|
* @return the areaNotation
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -46,7 +46,6 @@ import com.raytheon.uf.common.status.UFStatus;
|
||||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||||
import com.raytheon.uf.viz.core.exception.VizException;
|
import com.raytheon.uf.viz.core.exception.VizException;
|
||||||
import com.raytheon.viz.warngen.gui.WarngenLayer;
|
import com.raytheon.viz.warngen.gui.WarngenLayer;
|
||||||
import com.raytheon.viz.warngen.suppress.SuppressMap;
|
|
||||||
import com.raytheon.viz.warngen.util.Abbreviation;
|
import com.raytheon.viz.warngen.util.Abbreviation;
|
||||||
import com.vividsolutions.jts.geom.Geometry;
|
import com.vividsolutions.jts.geom.Geometry;
|
||||||
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
||||||
|
@ -74,6 +73,7 @@ import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
||||||
* Nov 9, 2012 DR 15430 D. Friedman Extracted method converFeAreaToPartList.
|
* Nov 9, 2012 DR 15430 D. Friedman Extracted method converFeAreaToPartList.
|
||||||
* Apr 29, 2013 1955 jsanchez Ignored comparing the geometry's user data when finding intersected areas.
|
* Apr 29, 2013 1955 jsanchez Ignored comparing the geometry's user data when finding intersected areas.
|
||||||
* May 2, 2013 1963 jsanchez Updated method to determine partOfArea.
|
* May 2, 2013 1963 jsanchez Updated method to determine partOfArea.
|
||||||
|
* Aug 19, 2013 2177 jsanchez Used portionsUtil to calculate area portion descriptions.
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @author chammack
|
* @author chammack
|
||||||
|
@ -89,13 +89,15 @@ public class Area {
|
||||||
*/
|
*/
|
||||||
public static final double DEFAULT_PORTION_TOLERANCE = 0.60;
|
public static final double DEFAULT_PORTION_TOLERANCE = 0.60;
|
||||||
|
|
||||||
private Area() {
|
private PortionsUtil portionsUtil;
|
||||||
|
|
||||||
|
public Area(PortionsUtil portionsUtil) {
|
||||||
|
this.portionsUtil = portionsUtil;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AffectedAreas[] findAffectedAreas(
|
public AffectedAreas[] findAffectedAreas(WarngenConfiguration config,
|
||||||
WarngenConfiguration config, Geometry polygon,
|
Geometry polygon, Geometry warningArea, String localizedSite)
|
||||||
Geometry warningArea, String localizedSite) throws VizException {
|
throws VizException {
|
||||||
|
|
||||||
// --- Begin argument checking ---
|
// --- Begin argument checking ---
|
||||||
Validate.notNull(config.getGeospatialConfig().getAreaSource(),
|
Validate.notNull(config.getGeospatialConfig().getAreaSource(),
|
||||||
|
@ -113,7 +115,7 @@ public class Area {
|
||||||
localizedSite, geoms);
|
localizedSite, geoms);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AffectedAreas[] findAffectedAreas(
|
private AffectedAreas[] findAffectedAreas(
|
||||||
AreaSourceConfiguration areaConfig,
|
AreaSourceConfiguration areaConfig,
|
||||||
GeospatialConfiguration geospatialConfig, Geometry polygon,
|
GeospatialConfiguration geospatialConfig, Geometry polygon,
|
||||||
String localizedSite, List<Geometry> geoms) throws VizException {
|
String localizedSite, List<Geometry> geoms) throws VizException {
|
||||||
|
@ -183,7 +185,6 @@ public class Area {
|
||||||
area.stateabbr = regionFeature.attributes.get(areaNotationField)
|
area.stateabbr = regionFeature.attributes.get(areaNotationField)
|
||||||
.toString();
|
.toString();
|
||||||
area.size = regionGeom.getArea();
|
area.size = regionGeom.getArea();
|
||||||
area.suppress = suppressType(areaSource, area.stateabbr, area.fips);
|
|
||||||
|
|
||||||
Object tzData = regionFeature.attributes.get(timezonePathcastField);
|
Object tzData = regionFeature.attributes.get(timezonePathcastField);
|
||||||
|
|
||||||
|
@ -219,9 +220,16 @@ public class Area {
|
||||||
double tolerCheck = regionGeom.getArea()
|
double tolerCheck = regionGeom.getArea()
|
||||||
* DEFAULT_PORTION_TOLERANCE;
|
* DEFAULT_PORTION_TOLERANCE;
|
||||||
if (areaIntersection < tolerCheck) {
|
if (areaIntersection < tolerCheck) {
|
||||||
area.partOfArea = GisUtil
|
try {
|
||||||
.asStringList(GisUtil.calculatePortion(regionGeom,
|
String entityID = area.stateabbr + areaSource.charAt(0)
|
||||||
intersection, true, true));
|
+ area.fips.substring(2);
|
||||||
|
area.partOfArea = GisUtil.asStringList(portionsUtil
|
||||||
|
.getPortions(entityID, regionGeom, intersection,
|
||||||
|
true));
|
||||||
|
} catch (Exception e) {
|
||||||
|
statusHandler.error("Unable to calculate part of area for "
|
||||||
|
+ area.name, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search the parent region
|
// Search the parent region
|
||||||
|
@ -277,10 +285,9 @@ public class Area {
|
||||||
* @return
|
* @return
|
||||||
* @throws VizException
|
* @throws VizException
|
||||||
*/
|
*/
|
||||||
public static Map<String, Object> findInsectingAreas(
|
public Map<String, Object> findInsectingAreas(WarngenConfiguration config,
|
||||||
WarngenConfiguration config, Geometry warnPolygon,
|
Geometry warnPolygon, Geometry warnArea, String localizedSite,
|
||||||
Geometry warnArea, String localizedSite, WarngenLayer warngenLayer)
|
WarngenLayer warngenLayer) throws VizException {
|
||||||
throws VizException {
|
|
||||||
Map<String, Object> areasMap = new HashMap<String, Object>();
|
Map<String, Object> areasMap = new HashMap<String, Object>();
|
||||||
|
|
||||||
String hatchedAreaSource = config.getHatchedAreaSource()
|
String hatchedAreaSource = config.getHatchedAreaSource()
|
||||||
|
@ -311,18 +318,6 @@ public class Area {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String suppressType(String areaSource, String state,
|
|
||||||
String fips) {
|
|
||||||
String retVal = SuppressMap.NONE;
|
|
||||||
String type = areaSource.equalsIgnoreCase("zone") ? "Z" : "C";
|
|
||||||
|
|
||||||
if (state != null && fips != null) {
|
|
||||||
String key = state + type + fips.substring(2);
|
|
||||||
retVal = SuppressMap.getInstance().getType(key);
|
|
||||||
}
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<String> converFeAreaToPartList(String feArea) {
|
public static List<String> converFeAreaToPartList(String feArea) {
|
||||||
final List<String> partList = new ArrayList<String>();
|
final List<String> partList = new ArrayList<String>();
|
||||||
if (feArea == null) {
|
if (feArea == null) {
|
||||||
|
|
|
@ -0,0 +1,178 @@
|
||||||
|
/**
|
||||||
|
* 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.gis;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Port of A1 constants applied to a grid to determine county or zone portions.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Aug 5, 2013 2177 jsanchez Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author jsanchez
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class CoverageConstants {
|
||||||
|
|
||||||
|
public static final int XSOUTH = 0x0001;
|
||||||
|
|
||||||
|
public static final int SOUTH = 0x0002;
|
||||||
|
|
||||||
|
public static final int NORTH = 0x0040;
|
||||||
|
|
||||||
|
public static final int XNORTH = 0x0080;
|
||||||
|
|
||||||
|
public static final int CENTER_NS = 0x0018;
|
||||||
|
|
||||||
|
public static final int CENTRAL_NS = 0x0024;
|
||||||
|
|
||||||
|
public static final int XWEST = 0x0100;
|
||||||
|
|
||||||
|
public static final int WEST = 0x0200;
|
||||||
|
|
||||||
|
public static final int EAST = 0x4000;
|
||||||
|
|
||||||
|
public static final int XEAST = 0x8000;
|
||||||
|
|
||||||
|
public static final int CENTER_EW = 0x1800;
|
||||||
|
|
||||||
|
public static final int CENTRAL_EW = 0x2400;
|
||||||
|
|
||||||
|
public static final int SOUTHERN = 0x0003;
|
||||||
|
|
||||||
|
public static final int NORTHERN = 0x00C0;
|
||||||
|
|
||||||
|
public static final int WESTERN = 0x0300;
|
||||||
|
|
||||||
|
public static final int EASTERN = 0xC000;
|
||||||
|
|
||||||
|
public static final int SOUTHSIDE = 0x000F;
|
||||||
|
|
||||||
|
public static final int NORTHSIDE = 0x00F0;
|
||||||
|
|
||||||
|
public static final int WESTSIDE = 0x0F00;
|
||||||
|
|
||||||
|
public static final int EASTSIDE = 0xF000;
|
||||||
|
|
||||||
|
public static final int EXTREME = 0x8181;
|
||||||
|
|
||||||
|
public static final int NOT_EXTREME = 0x7E7E;
|
||||||
|
|
||||||
|
public static final int EXTREME_NS = 0x0081;
|
||||||
|
|
||||||
|
public static final int EXTREME_EW = 0x8100;
|
||||||
|
|
||||||
|
public static final int CENTRAL = 0x2424;
|
||||||
|
|
||||||
|
public static final int CENTER = 0x1818;
|
||||||
|
|
||||||
|
public static final int NOT_CENTRAL = 0xC3C3;
|
||||||
|
|
||||||
|
public static final int NORTH_SOUTH = 0x00FF;
|
||||||
|
|
||||||
|
public static final int EAST_WEST = 0xFF00;
|
||||||
|
|
||||||
|
public static final int NNE = 0x0001;
|
||||||
|
|
||||||
|
public static final int ENE = 0x0002;
|
||||||
|
|
||||||
|
public static final int ESE = 0x0004;
|
||||||
|
|
||||||
|
public static final int SSE = 0x0008;
|
||||||
|
|
||||||
|
public static final int SSW = 0x0010;
|
||||||
|
|
||||||
|
public static final int WSW = 0x0020;
|
||||||
|
|
||||||
|
public static final int WNW = 0x0040;
|
||||||
|
|
||||||
|
public static final int NNW = 0x0080;
|
||||||
|
|
||||||
|
public static final int EXTREME_YES = 0xFFFF00;
|
||||||
|
|
||||||
|
public static final int EXTREME_NO = 0x00FF;
|
||||||
|
|
||||||
|
public static final int EXTREME_CORNER = 0xFF0000;
|
||||||
|
|
||||||
|
public static int[] NS_MASK = new int[256];
|
||||||
|
|
||||||
|
public static int[] EW_MASK = new int[256];
|
||||||
|
|
||||||
|
static {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
NS_MASK[0] = 0;
|
||||||
|
for (i = 1; i < 256; i++) {
|
||||||
|
if (i < 87) {
|
||||||
|
NS_MASK[i] = XSOUTH | SOUTH;
|
||||||
|
} else if (i > 167) {
|
||||||
|
NS_MASK[i] = XNORTH | NORTH;
|
||||||
|
} else if (i < 106) {
|
||||||
|
NS_MASK[i] = SOUTH;
|
||||||
|
} else if (i > 148) {
|
||||||
|
NS_MASK[i] = NORTH;
|
||||||
|
} else if (i < 118) {
|
||||||
|
NS_MASK[i] = CENTRAL_NS | SOUTH;
|
||||||
|
} else if (i > 138) {
|
||||||
|
NS_MASK[i] = CENTRAL_NS | NORTH;
|
||||||
|
} else if (i < 127) {
|
||||||
|
NS_MASK[i] = CENTER_NS | CENTRAL_NS | SOUTH;
|
||||||
|
} else if (i > 127) {
|
||||||
|
NS_MASK[i] = CENTER_NS | CENTRAL_NS | NORTH;
|
||||||
|
} else {
|
||||||
|
NS_MASK[i] = CENTER_NS | CENTRAL_NS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EW_MASK[0] = 0;
|
||||||
|
for (i = 1; i < 256; i++) {
|
||||||
|
if (i < 87) {
|
||||||
|
EW_MASK[i] = XWEST | WEST;
|
||||||
|
} else if (i > 167) {
|
||||||
|
EW_MASK[i] = XEAST | EAST;
|
||||||
|
} else if (i < 106) {
|
||||||
|
EW_MASK[i] = WEST;
|
||||||
|
} else if (i > 145) {
|
||||||
|
EW_MASK[i] = EAST;
|
||||||
|
} else if (i < 118) {
|
||||||
|
EW_MASK[i] = CENTRAL_EW | WEST;
|
||||||
|
} else if (i > 138) {
|
||||||
|
EW_MASK[i] = CENTRAL_EW | EAST;
|
||||||
|
} else if (i < 127) {
|
||||||
|
EW_MASK[i] = CENTER_EW | CENTRAL_EW | WEST;
|
||||||
|
} else if (i > 127) {
|
||||||
|
EW_MASK[i] = CENTER_EW | CENTRAL_EW | EAST;
|
||||||
|
} else {
|
||||||
|
EW_MASK[i] = CENTER_EW | CENTRAL_EW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CoverageConstants() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
/**
|
||||||
|
* 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.gis;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple port of an A1 struct created by GridUtil and used by PortionsUtil.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Aug 5, 2013 2177 jsanchez Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author jsanchez
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class EntityData {
|
||||||
|
|
||||||
|
private int meanMask = 0;
|
||||||
|
|
||||||
|
private int coverageMask = 0;
|
||||||
|
|
||||||
|
private int octants = 0;
|
||||||
|
|
||||||
|
public EntityData(int meanMask, int coverageMask, int octants) {
|
||||||
|
this.meanMask = meanMask;
|
||||||
|
this.coverageMask = coverageMask;
|
||||||
|
this.octants = octants;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMeanMask() {
|
||||||
|
return meanMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCoverageMask() {
|
||||||
|
return coverageMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getOctants() {
|
||||||
|
return octants;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,616 @@
|
||||||
|
/**
|
||||||
|
* 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.gis;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.geotools.coverage.grid.GeneralGridGeometry;
|
||||||
|
import org.geotools.coverage.grid.GridGeometry2D;
|
||||||
|
import org.geotools.referencing.operation.DefaultMathTransformFactory;
|
||||||
|
import org.opengis.coverage.grid.GridEnvelope;
|
||||||
|
import org.opengis.metadata.spatial.PixelOrientation;
|
||||||
|
import org.opengis.referencing.operation.MathTransform;
|
||||||
|
|
||||||
|
import com.raytheon.uf.common.dataplugin.warning.util.GeometryUtil;
|
||||||
|
import com.raytheon.uf.viz.core.exception.VizException;
|
||||||
|
import com.raytheon.viz.warngen.gui.WarngenLayer;
|
||||||
|
import com.vividsolutions.jts.geom.Coordinate;
|
||||||
|
import com.vividsolutions.jts.geom.CoordinateSequence;
|
||||||
|
import com.vividsolutions.jts.geom.Envelope;
|
||||||
|
import com.vividsolutions.jts.geom.Geometry;
|
||||||
|
import com.vividsolutions.jts.geom.GeometryFactory;
|
||||||
|
import com.vividsolutions.jts.geom.Point;
|
||||||
|
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
||||||
|
import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the county or zone and the intersecting warning area to grids. The
|
||||||
|
* county or zone is also weighted to determine the northern, southern, eastern,
|
||||||
|
* and western parts of the county or zone. Most of the code is ported from A1
|
||||||
|
* to create an EntityData object that will be used by PortionsUtil to determine
|
||||||
|
* the applicable impacted portions of a county or zone.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Aug 5, 2013 jsanchez Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author jsanchez
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class GridUtil {
|
||||||
|
|
||||||
|
private int ny = 0;
|
||||||
|
|
||||||
|
private int nx = 0;
|
||||||
|
|
||||||
|
private int[] ewGrid;
|
||||||
|
|
||||||
|
private int[] nsGrid;
|
||||||
|
|
||||||
|
private byte[] warnedAreaGrid;
|
||||||
|
|
||||||
|
private byte[] countyOrZoneGrid;
|
||||||
|
|
||||||
|
private WarngenLayer layer;
|
||||||
|
|
||||||
|
private MathTransform latLonToContour, contourToLatLon;
|
||||||
|
|
||||||
|
public GridUtil(WarngenLayer layer, GeneralGridGeometry localGridGeometry,
|
||||||
|
MathTransform localToLatLon) throws Exception {
|
||||||
|
this.layer = layer;
|
||||||
|
|
||||||
|
GridEnvelope range = localGridGeometry.getGridRange();
|
||||||
|
this.nx = range.getHigh(0);
|
||||||
|
this.ny = range.getHigh(1);
|
||||||
|
|
||||||
|
org.opengis.geometry.Envelope ge = localGridGeometry.getEnvelope();
|
||||||
|
contourToLatLon = new DefaultMathTransformFactory()
|
||||||
|
.createConcatenatedTransform(new GridGeometry2D(range, ge)
|
||||||
|
.getGridToCRS(PixelOrientation.CENTER), localToLatLon);
|
||||||
|
latLonToContour = contourToLatLon.inverse();
|
||||||
|
|
||||||
|
ewGrid = new int[nx * ny];
|
||||||
|
nsGrid = new int[nx * ny];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the countyOrZone geometry and the warnedArea into grids and sets
|
||||||
|
* the appropriate data in an EntityData object.
|
||||||
|
*
|
||||||
|
* @param countyOrZone
|
||||||
|
* @param warnedArea
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public EntityData calculateGrids(Geometry countyOrZone, Geometry warnedArea)
|
||||||
|
throws Exception {
|
||||||
|
countyOrZoneGrid = toByteArray(countyOrZone);
|
||||||
|
warnedAreaGrid = toByteArray(warnedArea);
|
||||||
|
int[] bounds = awips1FinishAreaEntity();
|
||||||
|
EntityData entityData = finishDefineArea(bounds);
|
||||||
|
return entityData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the geometry into a byte array that is expected by ported A1
|
||||||
|
* code.
|
||||||
|
*
|
||||||
|
* @param geometry
|
||||||
|
* @return
|
||||||
|
* @throws VizException
|
||||||
|
*/
|
||||||
|
private byte[] toByteArray(Geometry geometry) throws VizException {
|
||||||
|
byte[] bytes = new byte[nx * ny];
|
||||||
|
float[][] floatData = toFloatData(geometry);
|
||||||
|
|
||||||
|
// Rotates grid
|
||||||
|
int k = 0;
|
||||||
|
for (int j = ny - 1; j >= 0; j--) {
|
||||||
|
for (int i = 0; i < nx; i++) {
|
||||||
|
if (floatData[i][j] == 1) {
|
||||||
|
bytes[k] = 1;
|
||||||
|
}
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the geometry into a 2-D float array.
|
||||||
|
*
|
||||||
|
* @param geometry
|
||||||
|
* @return
|
||||||
|
* @throws VizException
|
||||||
|
*/
|
||||||
|
private float[][] toFloatData(Geometry geometry) throws VizException {
|
||||||
|
Geometry contoured = layer.convertGeom(geometry, latLonToContour);
|
||||||
|
List<Geometry> geomList = new ArrayList<Geometry>(
|
||||||
|
contoured.getNumGeometries());
|
||||||
|
GeometryUtil.buildGeometryList(geomList, contoured);
|
||||||
|
List<PreparedGeometry> prepped = new ArrayList<PreparedGeometry>(
|
||||||
|
geomList.size());
|
||||||
|
for (Geometry g : geomList) {
|
||||||
|
prepped.add(PreparedGeometryFactory.prepare(g));
|
||||||
|
}
|
||||||
|
|
||||||
|
GeometryFactory gf = geometry.getFactory();
|
||||||
|
Point point = gf.createPoint(new Coordinate(0, 0));
|
||||||
|
CoordinateSequence pointCS = point.getCoordinateSequence();
|
||||||
|
float[][] contourAreaData = new float[nx][ny];
|
||||||
|
for (PreparedGeometry geom : prepped) {
|
||||||
|
Envelope env = geom.getGeometry().getEnvelopeInternal();
|
||||||
|
int startX = (int) env.getMinX();
|
||||||
|
int startY = (int) env.getMinY();
|
||||||
|
int width = (int) env.getMaxX();
|
||||||
|
int height = (int) env.getMaxY();
|
||||||
|
if (startX < 0 || width > nx || startY < 0 || height > ny) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
startX = Math.max(0, startX - 1);
|
||||||
|
startY = Math.max(0, startY - 1);
|
||||||
|
width = Math.min(nx, width + 1);
|
||||||
|
height = Math.min(ny, height + 1);
|
||||||
|
for (int x = startX; x < width; ++x) {
|
||||||
|
for (int y = startY; y < height; ++y) {
|
||||||
|
|
||||||
|
pointCS.setOrdinate(0, 0, x);
|
||||||
|
pointCS.setOrdinate(0, 1, y);
|
||||||
|
point.geometryChanged();
|
||||||
|
if (contourAreaData[x][y] == 0.0f && geom.intersects(point)) {
|
||||||
|
contourAreaData[x][y] = 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return contourAreaData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ported only the logic from A1 code
|
||||||
|
* GeoEntityLookupTable::finishDefineArea() that calculates the meanMask,
|
||||||
|
* coverageMask,and octants for an entity (i.e. county or zone).
|
||||||
|
*
|
||||||
|
* @param countyOrZone
|
||||||
|
* @param warnedArea
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private EntityData finishDefineArea(int[] bounds) {
|
||||||
|
int meanMask = 0;
|
||||||
|
int coverageMask = 0;
|
||||||
|
int octants = 0;
|
||||||
|
|
||||||
|
int ewCount = 0;
|
||||||
|
int nsCount = 0;
|
||||||
|
int ewTotal = 0;
|
||||||
|
int nsTotal = 0;
|
||||||
|
|
||||||
|
int k = 0;
|
||||||
|
int min_i = bounds[0];
|
||||||
|
int max_i = bounds[1];
|
||||||
|
int min_j = bounds[2];
|
||||||
|
int max_j = bounds[3];
|
||||||
|
for (int j = min_j; j < max_j; j++) {
|
||||||
|
k = nx * j + min_i;
|
||||||
|
for (int i = min_i; i < max_i; i++, k++) {
|
||||||
|
if (warnedAreaGrid[k] == 1) {
|
||||||
|
int e = countyOrZoneGrid[k];
|
||||||
|
|
||||||
|
int ii = ewGrid[k];
|
||||||
|
int jj = nsGrid[k];
|
||||||
|
|
||||||
|
if (ii == 0 && jj == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ewTotal += ii;
|
||||||
|
if (ii > 0) {
|
||||||
|
ewCount++;
|
||||||
|
}
|
||||||
|
nsTotal += jj;
|
||||||
|
if (jj > 0) {
|
||||||
|
nsCount++;
|
||||||
|
}
|
||||||
|
int m = CoverageConstants.EW_MASK[ii]
|
||||||
|
| CoverageConstants.NS_MASK[jj];
|
||||||
|
coverageMask |= m;
|
||||||
|
if ((m & CoverageConstants.CENTRAL) == CoverageConstants.CENTRAL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ii == 0) {
|
||||||
|
ii = 127;
|
||||||
|
}
|
||||||
|
if (jj == 0) {
|
||||||
|
jj = 127;
|
||||||
|
}
|
||||||
|
if (ii < 127) {
|
||||||
|
if (jj < 127) {
|
||||||
|
e = (ii > jj ? CoverageConstants.SSW
|
||||||
|
: CoverageConstants.WSW);
|
||||||
|
} else {
|
||||||
|
e = (ii > 254 - jj ? CoverageConstants.NNW
|
||||||
|
: CoverageConstants.WNW);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (jj < 127) {
|
||||||
|
e = (ii < 254 - jj ? CoverageConstants.SSE
|
||||||
|
: CoverageConstants.ESE);
|
||||||
|
} else {
|
||||||
|
e = (ii < jj ? CoverageConstants.NNE
|
||||||
|
: CoverageConstants.ENE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((m & CoverageConstants.EXTREME_NS) > 0) {
|
||||||
|
e <<= 8;
|
||||||
|
}
|
||||||
|
if ((m & CoverageConstants.EXTREME_EW) > 0) {
|
||||||
|
e <<= 8;
|
||||||
|
}
|
||||||
|
octants |= e;
|
||||||
|
} else {
|
||||||
|
warnedAreaGrid[k] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ewCount > 0) {
|
||||||
|
ewTotal = (ewTotal + ewCount / 2) / ewCount;
|
||||||
|
}
|
||||||
|
if (nsCount > 0) {
|
||||||
|
nsTotal = (nsTotal + nsCount / 2) / nsCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
meanMask = CoverageConstants.NS_MASK[nsTotal]
|
||||||
|
| CoverageConstants.EW_MASK[ewTotal];
|
||||||
|
return new EntityData(meanMask, coverageMask, octants);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the _ewGrid and _nsGrid via A1 ~~ mAgIc ~~
|
||||||
|
*/
|
||||||
|
private int[] awips1FinishAreaEntity() {
|
||||||
|
|
||||||
|
final double EXTREME_FRAC = 0.1;
|
||||||
|
final double MIN_EXTREME = 87;
|
||||||
|
final double MAX_EXTREME = 167;
|
||||||
|
|
||||||
|
int k = 0;
|
||||||
|
int ii, jj;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* identify those points on the boundary of the entity so we can shrink
|
||||||
|
* from there
|
||||||
|
*/
|
||||||
|
int i_mean = 0;
|
||||||
|
int j_mean = 0;
|
||||||
|
int new_tot = 0;
|
||||||
|
int ii_mean = 0;
|
||||||
|
int jj_mean = 0;
|
||||||
|
int min_i = Integer.MAX_VALUE;
|
||||||
|
int min_j = Integer.MAX_VALUE;
|
||||||
|
int max_i = Integer.MIN_VALUE;
|
||||||
|
int max_j = Integer.MIN_VALUE;
|
||||||
|
|
||||||
|
for (jj = 0; jj < ny; jj++) {
|
||||||
|
k = nx * jj;
|
||||||
|
for (ii = 0; ii < nx; ii++, k++) {
|
||||||
|
// If the entity is not 1 then it's not part of the county or
|
||||||
|
// zone area.
|
||||||
|
if (countyOrZoneGrid[k] != 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ii > max_i) {
|
||||||
|
max_i = ii;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ii < min_i) {
|
||||||
|
min_i = ii;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jj > max_j) {
|
||||||
|
max_j = jj;
|
||||||
|
}
|
||||||
|
if (jj < min_j) {
|
||||||
|
min_j = jj;
|
||||||
|
}
|
||||||
|
++new_tot;
|
||||||
|
ii_mean += ii;
|
||||||
|
jj_mean += jj;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* restablish some things that might have changed since the first time
|
||||||
|
* they were calculated.
|
||||||
|
*/
|
||||||
|
// if (!outside) {
|
||||||
|
ii_mean /= new_tot;
|
||||||
|
jj_mean /= new_tot;
|
||||||
|
i_mean = ii_mean;
|
||||||
|
j_mean = jj_mean;
|
||||||
|
// }/*endif*/
|
||||||
|
|
||||||
|
/* assign correct base for directional computation */
|
||||||
|
// I changed this from ii_mean to this
|
||||||
|
double i_base = (min_i + max_i) / 2;
|
||||||
|
// I changed this from jj_mean to this
|
||||||
|
double j_base = (min_j + max_j) / 2;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* calculate needed rotation factors for computation of amount each
|
||||||
|
* point is north and east of centroid
|
||||||
|
*/
|
||||||
|
double x_intcpg = 0.5;
|
||||||
|
double y_intcpg = 0.5;
|
||||||
|
|
||||||
|
double dx = 1, dy = 1;
|
||||||
|
double x = (i_base - x_intcpg);
|
||||||
|
double y = (j_base - y_intcpg);
|
||||||
|
|
||||||
|
// Below is some code from the original A1 code. I assumed that x_intcpg
|
||||||
|
// to be 0.5 to avoid porting all the methods in gelt_maker.c.
|
||||||
|
// xy_to_ll(&x,&y,&lat,&lon,&my_proj);
|
||||||
|
// lat01=lat+0.1;
|
||||||
|
// ll_to_xy(&lat01,&lon,&dx,&dy,&my_proj);
|
||||||
|
// dx -= x;
|
||||||
|
|
||||||
|
dy -= y;
|
||||||
|
|
||||||
|
double mag = Math.sqrt(dx * dx + dy * dy);
|
||||||
|
dx /= mag;
|
||||||
|
dy /= mag;
|
||||||
|
double erot_i = -dy;
|
||||||
|
double erot_j = -dx;
|
||||||
|
|
||||||
|
double nrot_i = dx;
|
||||||
|
double nrot_j = dy;
|
||||||
|
|
||||||
|
int[] ew_hist = new int[nx * ny];
|
||||||
|
int[] ns_hist = new int[nx * ny];
|
||||||
|
|
||||||
|
/* Calculate north/south & east/west offsets, create histogram of these. */
|
||||||
|
// TODO I did not fully implement the histograms as used in a1. Using
|
||||||
|
// the histograms created index out of bounds errors. If the field is
|
||||||
|
// unhappy with the portions, then porting the histograms needs to be
|
||||||
|
// re-investigated.
|
||||||
|
int ns1 = 0, ns2 = 0, ew1 = 0, ew2 = 0;
|
||||||
|
int np_n = 0, np_s = 0, np_e = 0, np_w = 0;
|
||||||
|
ns_hist[0] = 0;
|
||||||
|
ew_hist[0] = 0;
|
||||||
|
for (jj = min_j; jj < max_j; jj++) {
|
||||||
|
k = nx * jj + min_i;
|
||||||
|
for (ii = min_i; ii < max_i; ii++, k++) {
|
||||||
|
// If the entity is not 1 then it's not part of the county or
|
||||||
|
// zone area.
|
||||||
|
if (countyOrZoneGrid[k] != 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
double di = ii - i_base;
|
||||||
|
double dj = jj - j_base;
|
||||||
|
|
||||||
|
double dns = (int) (nrot_i * di + nrot_j * dj);
|
||||||
|
while (ns1 > dns) {
|
||||||
|
// ns_hist[--ns1] = 0;
|
||||||
|
--ns1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (ns2 < dns) {
|
||||||
|
// ns_hist[++ns2] = 0;
|
||||||
|
++ns2;
|
||||||
|
}
|
||||||
|
// ns_hist[(int) dns]++;
|
||||||
|
|
||||||
|
double dew = (int) (erot_i * di + erot_j * dj);
|
||||||
|
while (ew1 > dew) {
|
||||||
|
// ew_hist[--ew1] = 0;
|
||||||
|
--ew1;
|
||||||
|
}
|
||||||
|
while (ew2 < dew) {
|
||||||
|
// ew_hist[++ew2] = 0;
|
||||||
|
++ew2;
|
||||||
|
}
|
||||||
|
// ew_hist[(int) dew]++;
|
||||||
|
|
||||||
|
if (dew < 0) {
|
||||||
|
np_w++;
|
||||||
|
}
|
||||||
|
if (dew > 0) {
|
||||||
|
np_e++;
|
||||||
|
}
|
||||||
|
if (dns < 0) {
|
||||||
|
np_s++;
|
||||||
|
}
|
||||||
|
if (dns > 0) {
|
||||||
|
np_n++;
|
||||||
|
}
|
||||||
|
}/* end for */
|
||||||
|
}/* end for */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Transform n-s & e-w offsets into normalized distances north and
|
||||||
|
* south. This is done based on a preferred fraction of each area that
|
||||||
|
* is "extreme".
|
||||||
|
*/
|
||||||
|
|
||||||
|
// a lot of assumptions were made here. therefore, not everything in
|
||||||
|
// this part was fully ported.
|
||||||
|
double target = np_w * EXTREME_FRAC;
|
||||||
|
// for (ii = 0, k = ew1; k < -1 && ii < target; k++) {
|
||||||
|
// ii += ew_hist[k];
|
||||||
|
// }
|
||||||
|
// if (ii / target > 1.5) {
|
||||||
|
// k--;
|
||||||
|
// }
|
||||||
|
// if (k < ew1) {
|
||||||
|
// k = ew1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
k = ew1;
|
||||||
|
double mu_w = (MIN_EXTREME - 127) / (k + 0.5);
|
||||||
|
|
||||||
|
target = np_e * EXTREME_FRAC;
|
||||||
|
// for (ii = 0, k = ew2; k > 1 && ii < target; k--) {
|
||||||
|
// ii += ew_hist[k];
|
||||||
|
// }
|
||||||
|
// if (ii / target > 1.5) {
|
||||||
|
// k++;
|
||||||
|
// }
|
||||||
|
// if (k > ew2) {
|
||||||
|
// k = ew2;
|
||||||
|
// }
|
||||||
|
|
||||||
|
k = ew2;
|
||||||
|
double mu_e = (MAX_EXTREME - 127) / (k - 0.5);
|
||||||
|
|
||||||
|
target = np_s * EXTREME_FRAC;
|
||||||
|
// for (ii = 0, k = ns1; k < -1 && ii < target; k++) {
|
||||||
|
// ii += ns_hist[k];
|
||||||
|
// }
|
||||||
|
// if (ii / target > 1.5) {
|
||||||
|
// k--;
|
||||||
|
// }
|
||||||
|
// if (k < ns1) {
|
||||||
|
// k = ns1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
k = ns1;// TODO - REPLACE WITH ABOVE
|
||||||
|
double mu_s = (MIN_EXTREME - 127) / (k + 0.5);
|
||||||
|
|
||||||
|
target = np_n * EXTREME_FRAC;
|
||||||
|
// for (ii = 0, k = ns2; k > 1 && ii < target; k--) {
|
||||||
|
// ii += ns_hist[k];
|
||||||
|
// }
|
||||||
|
// if (ii / target > 1.5) {
|
||||||
|
// k++;
|
||||||
|
// }
|
||||||
|
// if (k > ns2) {
|
||||||
|
// k = ns2;
|
||||||
|
// }
|
||||||
|
|
||||||
|
k = ns2;
|
||||||
|
double mu_n = (MAX_EXTREME - 127) / (k - 0.5);
|
||||||
|
|
||||||
|
for (jj = min_j; jj < max_j; jj++) {
|
||||||
|
k = nx * jj + min_i;
|
||||||
|
for (ii = min_i; ii < max_i; ii++, k++) {
|
||||||
|
// If the entity is not 1 then it's not part of the county or
|
||||||
|
// zone area.
|
||||||
|
if (countyOrZoneGrid[k] != 1) {
|
||||||
|
ewGrid[k] = 0;
|
||||||
|
nsGrid[k] = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
double di = ii - i_base;
|
||||||
|
double dj = jj - j_base;
|
||||||
|
double dns = (int) (nrot_i * di + nrot_j * dj);
|
||||||
|
double dew = (int) (erot_i * di + erot_j * dj);
|
||||||
|
int c_ns2 = (int) (dns);
|
||||||
|
int c_ew2 = (int) (dew);
|
||||||
|
|
||||||
|
if (c_ew2 < 0) {
|
||||||
|
dx = c_ew2 * mu_w;
|
||||||
|
} else {
|
||||||
|
dx = c_ew2 * mu_e;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dx > 127) {
|
||||||
|
dx = 127;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dx < -127) {
|
||||||
|
dx = -127;
|
||||||
|
}
|
||||||
|
|
||||||
|
ewGrid[k] = (int) (127 + (int) (dx));
|
||||||
|
|
||||||
|
if (c_ns2 < 0) {
|
||||||
|
dy = c_ns2 * mu_s;
|
||||||
|
} else {
|
||||||
|
dy = c_ns2 * mu_n;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dy > 127) {
|
||||||
|
dy = 127;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dy < -127) {
|
||||||
|
dy = -127;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsGrid[k] = (int) (127 + (int) (dy));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// System.out.println("-----------------------------------");
|
||||||
|
// printGrids(countyOrZoneGrid, min_i, max_i, min_j, max_j);
|
||||||
|
// System.out.println("-----------------------------------");
|
||||||
|
// printGrids(_currentArea, min_i, max_i, min_j, max_j);
|
||||||
|
// System.out.println("-------------- EAST WEST ---------------------");
|
||||||
|
// printGrids(ewGrid, min_i, max_i, min_j, max_j);
|
||||||
|
// System.out.println("-------------- NORTH SOUTH ---------------------");
|
||||||
|
// printGrids(nsGrid, min_i, max_i, min_j, max_j);
|
||||||
|
// System.out.println("north/south - east/west done");
|
||||||
|
return new int[] { min_i, max_i, min_j, max_j };
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// For debugging and view the grid in ascii format.
|
||||||
|
private void printGrids(int[] grid, int min_i, int max_i, int min_j,
|
||||||
|
int max_j) {
|
||||||
|
int k = 0;
|
||||||
|
for (int jj = min_j; jj < max_j; jj++) {
|
||||||
|
k = nx * jj + min_i;
|
||||||
|
for (int ii = min_i; ii < max_i; ii++) {
|
||||||
|
System.out.print((int) grid[k]);
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
System.out.println("-");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For debugging and view the grid in ascii format.
|
||||||
|
private void printGrids(byte[] grid, int min_i, int max_i, int min_j,
|
||||||
|
int max_j) {
|
||||||
|
int k = 0;
|
||||||
|
for (int jj = min_j; jj < max_j; jj++) {
|
||||||
|
k = nx * jj + min_i;
|
||||||
|
for (int ii = min_i; ii < max_i; ii++) {
|
||||||
|
System.out.print((int) grid[k]);
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
System.out.println("-");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,471 @@
|
||||||
|
/**
|
||||||
|
* 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.gis;
|
||||||
|
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.raytheon.viz.warngen.gis.GisUtil.Direction;
|
||||||
|
import com.raytheon.viz.warngen.gui.WarngenLayer;
|
||||||
|
import com.vividsolutions.jts.geom.Geometry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Port of A1 code that determines the portions of the county or zone
|
||||||
|
* descriptions, such as NORTHWEST.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Aug 5, 2013 2177 jsanchez Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author jsanchez
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class PortionsUtil {
|
||||||
|
|
||||||
|
private GridUtil gridUtil;
|
||||||
|
|
||||||
|
public PortionsUtil(WarngenLayer layer) throws Exception {
|
||||||
|
gridUtil = new GridUtil(layer, layer.getLocalGridGeometry(),
|
||||||
|
layer.getlocalToLatLon());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the the appropriate portion description for the warnedArea
|
||||||
|
* intersecting the countyOrZone.
|
||||||
|
*
|
||||||
|
* @param entityID
|
||||||
|
* @param countyOrZone
|
||||||
|
* @param warnedArea
|
||||||
|
* @param useExtreme
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public EnumSet<Direction> getPortions(String entityID,
|
||||||
|
Geometry countyOrZone, Geometry warnedArea, boolean useExtreme)
|
||||||
|
throws Exception {
|
||||||
|
countyOrZone.getUserData();
|
||||||
|
EntityData entityData = gridUtil.calculateGrids(countyOrZone,
|
||||||
|
warnedArea);
|
||||||
|
EnumSet<Direction> portions = getAreaDesc(entityData.getMeanMask(),
|
||||||
|
entityData.getCoverageMask(), entityData.getOctants(),
|
||||||
|
useExtreme);
|
||||||
|
return suppressPortions(entityID, portions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks up if the designated entity ID has an suppressed directions. For
|
||||||
|
* example, a county or zone may not need to include the north and sound
|
||||||
|
* direction description if it was included in the area.suppress file.
|
||||||
|
*
|
||||||
|
* @param entityID
|
||||||
|
* @param portions
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private EnumSet<Direction> suppressPortions(String entityID,
|
||||||
|
EnumSet<Direction> portions) {
|
||||||
|
Map<String, List<Direction>> suppressedCounties = SuppressMap
|
||||||
|
.getInstance().getAreas();
|
||||||
|
if (entityID != null && suppressedCounties != null
|
||||||
|
&& !suppressedCounties.isEmpty()) {
|
||||||
|
List<Direction> suppressedDirections = suppressedCounties
|
||||||
|
.get(entityID.toUpperCase());
|
||||||
|
if (suppressedDirections != null && !suppressedDirections.isEmpty()) {
|
||||||
|
portions.removeAll(suppressedDirections);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return portions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Port from A1 code of GeoEntityLookupTable::getAreaDesc.
|
||||||
|
*
|
||||||
|
* @param meanMask
|
||||||
|
* @param areaMask
|
||||||
|
* @param octants
|
||||||
|
* @param exYes
|
||||||
|
*/
|
||||||
|
private static EnumSet<Direction> getAreaDesc(int meanMask, int areaMask,
|
||||||
|
int octants, boolean exYes) {
|
||||||
|
EnumSet<Direction> portions = EnumSet.noneOf(Direction.class);
|
||||||
|
|
||||||
|
// Test for case where we cannot do portions
|
||||||
|
if (meanMask == 0 || areaMask == 0) {
|
||||||
|
return portions;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The next block of code is the original port of A1 code but prevented
|
||||||
|
// producing the correct result:
|
||||||
|
// Test for case where area is completely within one subsection.
|
||||||
|
// if (meanMask == areaMask) {
|
||||||
|
// return getPointDesc(meanMask, exYes);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Test for central by not being near adjacent borders.
|
||||||
|
if (octants == 0
|
||||||
|
|| ((octants & CoverageConstants.EXTREME_YES) == 0)
|
||||||
|
&& (meanMask & CoverageConstants.CENTER) == CoverageConstants.CENTER) {
|
||||||
|
portions.add(Direction.CENTRAL);
|
||||||
|
return portions;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((octants & 0xFFFF) == 0xFFFF) {
|
||||||
|
return portions;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Identify quadrants in use, q is typical, qq is diagonal.
|
||||||
|
int xoctant = octants >> 8;
|
||||||
|
int xxoctant = octants >> 16;
|
||||||
|
int nn, ss, ee, ww, ne, nw, se, sw;
|
||||||
|
nn = ss = ee = ww = ne = nw = se = sw = 0;
|
||||||
|
int omerge = xxoctant | xoctant | octants;
|
||||||
|
if ((omerge & (CoverageConstants.NNE | CoverageConstants.ENE)) > 0) {
|
||||||
|
ne = 1;
|
||||||
|
}
|
||||||
|
if ((omerge & (CoverageConstants.SSE | CoverageConstants.ESE)) > 0) {
|
||||||
|
se = 1;
|
||||||
|
}
|
||||||
|
if ((omerge & (CoverageConstants.NNW | CoverageConstants.WNW)) > 0) {
|
||||||
|
nw = 1;
|
||||||
|
}
|
||||||
|
if ((omerge & (CoverageConstants.SSW | CoverageConstants.WSW)) > 0) {
|
||||||
|
sw = 1;
|
||||||
|
}
|
||||||
|
if ((omerge & (CoverageConstants.NNE | CoverageConstants.NNW)) > 0) {
|
||||||
|
nn = 1;
|
||||||
|
}
|
||||||
|
if ((omerge & (CoverageConstants.SSE | CoverageConstants.SSW)) > 0) {
|
||||||
|
ss = 1;
|
||||||
|
}
|
||||||
|
if ((omerge & (CoverageConstants.WNW | CoverageConstants.WSW)) > 0) {
|
||||||
|
ww = 1;
|
||||||
|
}
|
||||||
|
if ((omerge & (CoverageConstants.ENE | CoverageConstants.ESE)) > 0) {
|
||||||
|
ee = 1;
|
||||||
|
}
|
||||||
|
if ((areaMask & CoverageConstants.NORTH_SOUTH) == 0) {
|
||||||
|
nn = ss = ne = nw = se = sw = 0;
|
||||||
|
}
|
||||||
|
if ((areaMask & CoverageConstants.EAST_WEST) == 0) {
|
||||||
|
ee = ww = ne = nw = se = sw = 0;
|
||||||
|
}
|
||||||
|
int q = ne + nw + se + sw;
|
||||||
|
int qq = nn + ss + ee + ww;
|
||||||
|
|
||||||
|
// Identify extremes in use.
|
||||||
|
int nnx, ssx, eex, wwx;
|
||||||
|
nnx = ssx = eex = wwx = 0;
|
||||||
|
if ((areaMask & CoverageConstants.XNORTH) > 0) {
|
||||||
|
nnx = 1;
|
||||||
|
}
|
||||||
|
if ((areaMask & CoverageConstants.XSOUTH) > 0) {
|
||||||
|
ssx = 1;
|
||||||
|
}
|
||||||
|
if ((areaMask & CoverageConstants.XWEST) > 0) {
|
||||||
|
wwx = 1;
|
||||||
|
}
|
||||||
|
if ((areaMask & CoverageConstants.XEAST) > 0) {
|
||||||
|
eex = 1;
|
||||||
|
}
|
||||||
|
int xxx = nnx + ssx + eex + wwx;
|
||||||
|
|
||||||
|
// Modify masks based on whether we can use extreme.
|
||||||
|
if ((octants & CoverageConstants.EXTREME_NO) > 0
|
||||||
|
&& (areaMask & CoverageConstants.EXTREME) > 0) {
|
||||||
|
areaMask &= CoverageConstants.NOT_EXTREME;
|
||||||
|
meanMask &= CoverageConstants.NOT_EXTREME;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Possible case of a stripe across the middle
|
||||||
|
if (q == 0) {
|
||||||
|
;// Only one direction encoded
|
||||||
|
} else if (q == 2 && nw == se || q == 2 && ne == sw || qq == 2
|
||||||
|
&& nn == ss || qq == 2 && ee == ww) {
|
||||||
|
if ((meanMask & CoverageConstants.CENTRAL) == CoverageConstants.CENTRAL
|
||||||
|
|| nnx == ssx && wwx == eex) {
|
||||||
|
portions.add(Direction.CENTRAL);
|
||||||
|
return portions;
|
||||||
|
}
|
||||||
|
return getPointDesc2(meanMask, exYes, nn, ss, ee, ww);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modify masks based on whether we can use central.
|
||||||
|
if (xxx > 2 || nnx != ssx && wwx != eex) {
|
||||||
|
areaMask &= CoverageConstants.NOT_CENTRAL;
|
||||||
|
meanMask &= CoverageConstants.NOT_CENTRAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Another possible case of a stripe across the middle.
|
||||||
|
if (q == 4 && (meanMask & CoverageConstants.CENTER) > 0) {
|
||||||
|
portions.add(Direction.CENTRAL);
|
||||||
|
return portions;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All quadrants in use.
|
||||||
|
if (q == 4 && qq == 4) {
|
||||||
|
return EnumSet.noneOf(Direction.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only one typical quadrant in use.
|
||||||
|
if (q == 1) {
|
||||||
|
// if (ne == 1) {
|
||||||
|
// portions.add(Direction.NORTH);
|
||||||
|
// portions.add(Direction.EAST);
|
||||||
|
// } else if (nw == 1) {
|
||||||
|
// portions.add(Direction.NORTH);
|
||||||
|
// portions.add(Direction.WEST);
|
||||||
|
// } else if (se == 1) {
|
||||||
|
// portions.add(Direction.SOUTH);
|
||||||
|
// portions.add(Direction.EAST);
|
||||||
|
// } else if (sw == 1) {
|
||||||
|
// portions.add(Direction.SOUTH);
|
||||||
|
// portions.add(Direction.WEST);
|
||||||
|
// }
|
||||||
|
// return portions;
|
||||||
|
return getPointDesc2(meanMask, exYes, nn, ss, ee, ww);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Further modify masks based on whether we can use central.
|
||||||
|
if (xxx >= 2) {
|
||||||
|
areaMask &= CoverageConstants.NOT_CENTRAL;
|
||||||
|
meanMask &= CoverageConstants.NOT_CENTRAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No more than two quadrants of any kind in use, or all quadrants.
|
||||||
|
if (q < 3 && qq < 3) {
|
||||||
|
if (nnx != ssx && wwx != eex
|
||||||
|
|| (meanMask & CoverageConstants.CENTRAL) > 0) {
|
||||||
|
return getPointDesc2(meanMask, exYes, nn, ss, ee, ww);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return getPointDesc2(areaMask, exYes, nn, ss, ee, ww);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Three typical quadrants in use.
|
||||||
|
if (q == 3 && qq != 3) {
|
||||||
|
|
||||||
|
if (ne == 0) {
|
||||||
|
// The next line is the original port of A1 code but prevented
|
||||||
|
// producing the correct result:
|
||||||
|
// if (ne == 0 && (xxoctant & (SSW | WSW)) > 0) {
|
||||||
|
portions.add(Direction.SOUTH);
|
||||||
|
portions.add(Direction.WEST);
|
||||||
|
|
||||||
|
} else if (se == 0) {
|
||||||
|
// The next line is the original port of A1 code but prevented
|
||||||
|
// producing the correct result:
|
||||||
|
// } else if (se == 0 && (xxoctant & (NNW | WNW)) > 0) {
|
||||||
|
portions.add(Direction.NORTH);
|
||||||
|
portions.add(Direction.WEST);
|
||||||
|
|
||||||
|
} else if (nw == 0) {
|
||||||
|
// The next line is the original port of A1 code but prevented
|
||||||
|
// producing the correct result:
|
||||||
|
// } else if (nw == 0 && (xxoctant & (SSE | ESE)) > 0) {
|
||||||
|
portions.add(Direction.SOUTH);
|
||||||
|
portions.add(Direction.EAST);
|
||||||
|
|
||||||
|
} else if (sw == 0) {
|
||||||
|
// The next line is the original port of A1 code but prevented
|
||||||
|
// producing the correct result:
|
||||||
|
// } else if (sw == 0 && (xxoctant & (NNE | ENE)) > 0) {
|
||||||
|
portions.add(Direction.NORTH);
|
||||||
|
portions.add(Direction.EAST);
|
||||||
|
}
|
||||||
|
// The next line is the original port of A1 code but prevented
|
||||||
|
// producing the correct result:
|
||||||
|
// return getPointDesc(meanMask, exYes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Three diagonal quadrants in use.
|
||||||
|
if (qq == 3 && portions.isEmpty()) {
|
||||||
|
if (nn == 0) {
|
||||||
|
portions.add(Direction.SOUTH);
|
||||||
|
} else if (ss == 0) {
|
||||||
|
portions.add(Direction.NORTH);
|
||||||
|
} else if (ww == 0) {
|
||||||
|
portions.add(Direction.EAST);
|
||||||
|
} else if (ee == 0) {
|
||||||
|
portions.add(Direction.WEST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add extreme for three quadrant case.
|
||||||
|
if (!portions.isEmpty()) {
|
||||||
|
if (exYes && ((areaMask & CoverageConstants.EXTREME)) > 0) {
|
||||||
|
portions.add(Direction.EXTREME);
|
||||||
|
}
|
||||||
|
return portions;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All of either type of quadrant in use.
|
||||||
|
if (q == 4 || qq == 4) {
|
||||||
|
return EnumSet.noneOf(Direction.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Case of a pure simple direction.
|
||||||
|
nn = areaMask & CoverageConstants.NORTHERN;
|
||||||
|
ss = areaMask & CoverageConstants.SOUTHERN;
|
||||||
|
ee = areaMask & CoverageConstants.EASTERN;
|
||||||
|
ww = areaMask & CoverageConstants.WESTERN;
|
||||||
|
if (ss > 0 && nn > 0 || q == 0) {
|
||||||
|
if (ee == 0 && ww > 0) {
|
||||||
|
portions.add(Direction.WEST);
|
||||||
|
}
|
||||||
|
if (ww == 0 && ee > 0) {
|
||||||
|
portions.add(Direction.EAST);
|
||||||
|
}
|
||||||
|
} else if (ee > 0 && ww > 0 || q == 0) {
|
||||||
|
if (nn == 0 && ss > 0) {
|
||||||
|
portions.add(Direction.SOUTH);
|
||||||
|
}
|
||||||
|
if (ss == 0 && nn > 0) {
|
||||||
|
portions.add(Direction.NORTH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add extreme for simple direction case.
|
||||||
|
if (!portions.isEmpty()) {
|
||||||
|
if (exYes && ((areaMask & CoverageConstants.EXTREME)) > 0) {
|
||||||
|
portions.add(Direction.EXTREME);
|
||||||
|
}
|
||||||
|
return portions;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Catch with the point descriptor one last time
|
||||||
|
return getPointDesc2(meanMask, exYes, nn, ss, ee, ww);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Port from A1 code of GeoEntityLookupTable::getPointDesc.
|
||||||
|
*
|
||||||
|
* @param mask
|
||||||
|
* @param exYes
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static EnumSet<Direction> getPointDesc(int mask, boolean exYes) {
|
||||||
|
EnumSet<Direction> portions = EnumSet.noneOf(Direction.class);
|
||||||
|
|
||||||
|
if (mask == 0) {
|
||||||
|
return portions;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cc = mask & CoverageConstants.CENTRAL;
|
||||||
|
if (cc == CoverageConstants.CENTRAL) {
|
||||||
|
portions.add(Direction.CENTRAL);
|
||||||
|
return portions;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mask & CoverageConstants.NORTH_SOUTH) == 0) {
|
||||||
|
;
|
||||||
|
} else if ((mask & CoverageConstants.SOUTHERN) == (mask & CoverageConstants.NORTH_SOUTH)) {
|
||||||
|
portions.add(Direction.SOUTH);
|
||||||
|
} else if ((mask & CoverageConstants.NORTHERN) == (mask & CoverageConstants.NORTH_SOUTH)) {
|
||||||
|
portions.add(Direction.NORTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mask & CoverageConstants.EAST_WEST) == 0) {
|
||||||
|
;
|
||||||
|
} else if ((mask & CoverageConstants.WESTERN) == (mask & CoverageConstants.EAST_WEST)) {
|
||||||
|
portions.add(Direction.WEST);
|
||||||
|
} else if ((mask & CoverageConstants.EASTERN) == (mask & CoverageConstants.EAST_WEST)) {
|
||||||
|
portions.add(Direction.EAST);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (portions.isEmpty()) {
|
||||||
|
return portions;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cc != 0) {
|
||||||
|
portions.add(Direction.CENTRAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exYes && ((int) (mask & CoverageConstants.EXTREME) > 0)) {
|
||||||
|
portions.add(Direction.EXTREME);
|
||||||
|
}
|
||||||
|
|
||||||
|
return portions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is not a direct port from A1. The original getPointDesc did
|
||||||
|
* not produce the expected results. This method is a modified version of
|
||||||
|
* getPointDesct that uses the calculated qq values instead of just the
|
||||||
|
* meanMask.
|
||||||
|
*
|
||||||
|
* @param mask
|
||||||
|
* @param exYes
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static EnumSet<Direction> getPointDesc2(int mask, boolean exYes,
|
||||||
|
int nn, int ss, int ee, int ww) {
|
||||||
|
EnumSet<Direction> portions = EnumSet.noneOf(Direction.class);
|
||||||
|
|
||||||
|
if (mask == 0) {
|
||||||
|
return portions;
|
||||||
|
}
|
||||||
|
|
||||||
|
int counter = 0;
|
||||||
|
if (nn > 0 && ss > 0) {
|
||||||
|
;
|
||||||
|
} else if (ss > 0) {
|
||||||
|
portions.add(Direction.SOUTH);
|
||||||
|
counter++;
|
||||||
|
} else if (nn > 0) {
|
||||||
|
portions.add(Direction.NORTH);
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ee > 0 && ww > 0) {
|
||||||
|
;
|
||||||
|
} else if (ww > 0) {
|
||||||
|
portions.add(Direction.WEST);
|
||||||
|
counter++;
|
||||||
|
} else if (ee > 0) {
|
||||||
|
portions.add(Direction.EAST);
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (portions.isEmpty()) {
|
||||||
|
return portions;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cc = mask & CoverageConstants.CENTRAL;
|
||||||
|
boolean useCentral = counter < 2;
|
||||||
|
if (useCentral && cc != 0) {
|
||||||
|
portions.add(Direction.CENTRAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exYes && ((int) (mask & CoverageConstants.EXTREME) > 0)) {
|
||||||
|
portions.add(Direction.EXTREME);
|
||||||
|
}
|
||||||
|
|
||||||
|
return portions;
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,7 +17,7 @@
|
||||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||||
* further licensing information.
|
* further licensing information.
|
||||||
**/
|
**/
|
||||||
package com.raytheon.viz.warngen.suppress;
|
package com.raytheon.viz.warngen.gis;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -25,7 +25,10 @@ import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
@ -38,9 +41,11 @@ import com.raytheon.uf.common.localization.PathManagerFactory;
|
||||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||||
import com.raytheon.uf.common.status.UFStatus;
|
import com.raytheon.uf.common.status.UFStatus;
|
||||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||||
|
import com.raytheon.uf.viz.core.localization.LocalizationManager;
|
||||||
|
import com.raytheon.viz.warngen.gis.GisUtil.Direction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO Add Description
|
* Creates a map of all the site's area suppress files.
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
*
|
*
|
||||||
|
@ -48,6 +53,7 @@ import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||||
* Date Ticket# Engineer Description
|
* Date Ticket# Engineer Description
|
||||||
* ------------ ---------- ----------- --------------------------
|
* ------------ ---------- ----------- --------------------------
|
||||||
* Aug 2, 2010 jsanchez Initial creation
|
* Aug 2, 2010 jsanchez Initial creation
|
||||||
|
* Aug 15,2013 2177 jsanchez Refactored.
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -66,16 +72,26 @@ public class SuppressMap {
|
||||||
private static final Pattern ugcPattern = Pattern
|
private static final Pattern ugcPattern = Pattern
|
||||||
.compile("[A-Z]{2}[CZ][0-9]{3}");
|
.compile("[A-Z]{2}[CZ][0-9]{3}");
|
||||||
|
|
||||||
public static final String NORTH_SOUTH = "NS";
|
private static final List<Direction> NORTH_SOUTH = Arrays.asList(
|
||||||
|
Direction.NORTH, Direction.SOUTH);
|
||||||
|
|
||||||
public static final String EAST_WEST = "EW";
|
private static final List<Direction> EAST_WEST = Arrays.asList(
|
||||||
|
Direction.EAST, Direction.WEST);
|
||||||
|
|
||||||
public static final String NONE = "NONE";
|
private static final List<Direction> ALL = Arrays.asList(Direction.NORTH,
|
||||||
|
Direction.SOUTH, Direction.EAST, Direction.WEST, Direction.CENTRAL,
|
||||||
|
Direction.EXTREME);
|
||||||
|
|
||||||
public static final String ALL = "ALL";
|
private static Map<String, Map<String, List<Direction>>> suppressMap = new HashMap<String, Map<String, List<Direction>>>();
|
||||||
|
|
||||||
private Map<String, String> suppressMap = new HashMap<String, String>();
|
private SuppressMap() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return an instance of the SuppressMap object.
|
||||||
|
*/
|
||||||
public static SuppressMap getInstance() {
|
public static SuppressMap getInstance() {
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
instance = new SuppressMap();
|
instance = new SuppressMap();
|
||||||
|
@ -83,64 +99,82 @@ public class SuppressMap {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SuppressMap() {
|
/**
|
||||||
readFile();
|
* Returns the suppressed area map for the current localized site.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Map<String, List<Direction>> getAreas() {
|
||||||
|
String threeLetterSiteID = LocalizationManager.getInstance()
|
||||||
|
.getCurrentSite();
|
||||||
|
Map<String, List<Direction>> areas = suppressMap.get(threeLetterSiteID);
|
||||||
|
|
||||||
|
if (areas == null) {
|
||||||
|
areas = new HashMap<String, List<Direction>>();
|
||||||
|
IPathManager pm = PathManagerFactory.getPathManager();
|
||||||
|
LocalizationContext lc = pm.getContext(
|
||||||
|
LocalizationType.COMMON_STATIC, LocalizationLevel.SITE);
|
||||||
|
File file = pm.getFile(lc, AREA_SUPPRESS_FILENAME);
|
||||||
|
loadFile(file, areas);
|
||||||
|
}
|
||||||
|
|
||||||
|
return areas;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readFile() {
|
/**
|
||||||
// load site
|
* Loads the areas map with the suppress information in the file
|
||||||
IPathManager pathMgr = PathManagerFactory.getPathManager();
|
*
|
||||||
LocalizationContext lc = pathMgr.getContext(
|
* @param file
|
||||||
LocalizationType.COMMON_STATIC, LocalizationLevel.SITE);
|
* @param areas
|
||||||
File file = pathMgr.getFile(lc, AREA_SUPPRESS_FILENAME);
|
*/
|
||||||
loadFile(file, suppressMap);
|
private void loadFile(File file, Map<String, List<Direction>> areas) {
|
||||||
}
|
|
||||||
|
|
||||||
private void loadFile(File file, Map<String, String> aliasMap) {
|
|
||||||
if ((file != null) && file.exists()) {
|
if ((file != null) && file.exists()) {
|
||||||
Matcher m = null;
|
Matcher m = null;
|
||||||
|
BufferedReader fis = null;
|
||||||
try {
|
try {
|
||||||
BufferedReader fis = new BufferedReader(new InputStreamReader(
|
fis = new BufferedReader(new InputStreamReader(
|
||||||
new FileInputStream(file)));
|
new FileInputStream(file)));
|
||||||
|
|
||||||
String line = null;
|
String line = null;
|
||||||
try {
|
try {
|
||||||
while ((line = fis.readLine()) != null) {
|
while ((line = fis.readLine()) != null) {
|
||||||
m = ugcPattern.matcher(line);
|
m = ugcPattern.matcher(line);
|
||||||
if (m.find()) {
|
if (m.find()) {
|
||||||
String dataKey = m.group();
|
List<Direction> suppressedDirections = new ArrayList<Direction>();
|
||||||
String data = ALL;
|
String ugc = m.group();
|
||||||
if (line.indexOf("ns") > 5) {
|
if (line.indexOf("ns") > 5) {
|
||||||
data = NORTH_SOUTH;
|
suppressedDirections = NORTH_SOUTH;
|
||||||
} else if (line.indexOf("ew") > 5) {
|
} else if (line.indexOf("ew") > 5) {
|
||||||
data = EAST_WEST;
|
suppressedDirections = EAST_WEST;
|
||||||
|
} else {
|
||||||
|
suppressedDirections = ALL;
|
||||||
}
|
}
|
||||||
aliasMap.put(dataKey, data);
|
areas.put(ugc, suppressedDirections);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// TODO Auto-generated catch block. Please revise as
|
|
||||||
// appropriate.
|
|
||||||
statusHandler.handle(Priority.PROBLEM,
|
statusHandler.handle(Priority.PROBLEM,
|
||||||
"Could not read counties file: "
|
"Could not read counties file: "
|
||||||
+ AREA_SUPPRESS_FILENAME, e);
|
+ AREA_SUPPRESS_FILENAME, e);
|
||||||
|
|
||||||
}
|
}
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
// TODO Auto-generated catch block. Please revise as
|
|
||||||
// appropriate.
|
|
||||||
statusHandler.handle(Priority.PROBLEM,
|
statusHandler.handle(Priority.PROBLEM,
|
||||||
"Failed to find counties file: "
|
"Failed to find counties file: "
|
||||||
+ AREA_SUPPRESS_FILENAME, e);
|
+ AREA_SUPPRESS_FILENAME, e);
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
|
||||||
|
if (fis != null) {
|
||||||
|
try {
|
||||||
|
fis.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
statusHandler.handle(Priority.PROBLEM,
|
||||||
|
"Error trying to close buffered reader ", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getType(String key) {
|
|
||||||
if (suppressMap.containsKey(key)) {
|
|
||||||
return suppressMap.get(key);
|
|
||||||
} else {
|
|
||||||
return NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -49,6 +49,9 @@ import org.eclipse.swt.graphics.RGB;
|
||||||
import org.eclipse.swt.widgets.Event;
|
import org.eclipse.swt.widgets.Event;
|
||||||
import org.eclipse.swt.widgets.Listener;
|
import org.eclipse.swt.widgets.Listener;
|
||||||
import org.eclipse.ui.PlatformUI;
|
import org.eclipse.ui.PlatformUI;
|
||||||
|
import org.geotools.coverage.grid.GeneralGridEnvelope;
|
||||||
|
import org.geotools.coverage.grid.GeneralGridGeometry;
|
||||||
|
import org.geotools.geometry.GeneralEnvelope;
|
||||||
import org.geotools.geometry.jts.JTS;
|
import org.geotools.geometry.jts.JTS;
|
||||||
import org.geotools.referencing.GeodeticCalculator;
|
import org.geotools.referencing.GeodeticCalculator;
|
||||||
import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
||||||
|
@ -57,7 +60,6 @@ import org.opengis.referencing.operation.MathTransform;
|
||||||
import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord;
|
import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord;
|
||||||
import com.raytheon.uf.common.dataplugin.warning.WarningRecord.WarningAction;
|
import com.raytheon.uf.common.dataplugin.warning.WarningRecord.WarningAction;
|
||||||
import com.raytheon.uf.common.dataplugin.warning.config.AreaSourceConfiguration;
|
import com.raytheon.uf.common.dataplugin.warning.config.AreaSourceConfiguration;
|
||||||
import com.raytheon.uf.common.dataplugin.warning.config.AreaSourceConfiguration.AreaType;
|
|
||||||
import com.raytheon.uf.common.dataplugin.warning.config.BulletActionGroup;
|
import com.raytheon.uf.common.dataplugin.warning.config.BulletActionGroup;
|
||||||
import com.raytheon.uf.common.dataplugin.warning.config.DialogConfiguration;
|
import com.raytheon.uf.common.dataplugin.warning.config.DialogConfiguration;
|
||||||
import com.raytheon.uf.common.dataplugin.warning.config.GridSpacing;
|
import com.raytheon.uf.common.dataplugin.warning.config.GridSpacing;
|
||||||
|
@ -185,6 +187,7 @@ import com.vividsolutions.jts.io.WKTReader;
|
||||||
* 07/26/2013 DR 16376 Qinglu Lin Moved adjustVertex() and computeSlope() to PolygonUtil; removed calculateDistance();
|
* 07/26/2013 DR 16376 Qinglu Lin Moved adjustVertex() and computeSlope() to PolygonUtil; removed calculateDistance();
|
||||||
* updated AreaHatcher's run().
|
* updated AreaHatcher's run().
|
||||||
* 07/26/2013 DR 16450 D. Friedman Fix logic errors when frame count is one.
|
* 07/26/2013 DR 16450 D. Friedman Fix logic errors when frame count is one.
|
||||||
|
* 08/19/2013 2177 jsanchez Set a GeneralGridGeometry object in the GeospatialDataList.
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @author mschenke
|
* @author mschenke
|
||||||
|
@ -212,24 +215,28 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
IExtent localExtent;
|
IExtent localExtent;
|
||||||
|
|
||||||
int nx, ny;
|
int nx, ny;
|
||||||
|
|
||||||
|
GeneralGridGeometry localGridGeometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class GeospatialDataAccessor {
|
private static class GeospatialDataAccessor {
|
||||||
GeospatialDataList geoData;
|
GeospatialDataList geoData;
|
||||||
|
|
||||||
AreaSourceConfiguration areaConfig;
|
AreaSourceConfiguration areaConfig;
|
||||||
|
|
||||||
public GeospatialDataAccessor(GeospatialDataList geoData,
|
public GeospatialDataAccessor(GeospatialDataList geoData,
|
||||||
AreaSourceConfiguration areaConfig) {
|
AreaSourceConfiguration areaConfig) {
|
||||||
if (geoData == null || areaConfig == null) {
|
if (geoData == null || areaConfig == null) {
|
||||||
throw new IllegalArgumentException("GeospatialDataAccessor must not be null");
|
throw new IllegalArgumentException(
|
||||||
|
"GeospatialDataAccessor must not be null");
|
||||||
}
|
}
|
||||||
this.geoData = geoData;
|
this.geoData = geoData;
|
||||||
this.areaConfig = areaConfig;
|
this.areaConfig = areaConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the geometry area that intersects the cwa filter for the polygon in
|
* Build the geometry area that intersects the cwa filter for the
|
||||||
* local projection space
|
* polygon in local projection space
|
||||||
*
|
*
|
||||||
* @param polygon
|
* @param polygon
|
||||||
* polygon to intersect with in lat/lon space
|
* polygon to intersect with in lat/lon space
|
||||||
|
@ -243,8 +250,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
PreparedGeometry prepGeom = (PreparedGeometry) r.attributes
|
PreparedGeometry prepGeom = (PreparedGeometry) r.attributes
|
||||||
.get(GeospatialDataList.LOCAL_PREP_GEOM);
|
.get(GeospatialDataList.LOCAL_PREP_GEOM);
|
||||||
try {
|
try {
|
||||||
Geometry intersection = GeometryUtil.intersection(polygon,
|
Geometry intersection = GeometryUtil.intersection(
|
||||||
prepGeom);
|
polygon, prepGeom);
|
||||||
if (intersection.isEmpty()) {
|
if (intersection.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -407,7 +414,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
warningPolygon = PolygonUtil.removeDuplicateCoordinate(warningPolygon);
|
warningPolygon = PolygonUtil
|
||||||
|
.removeDuplicateCoordinate(warningPolygon);
|
||||||
Polygon hatched = polygonUtil.hatchWarningArea(
|
Polygon hatched = polygonUtil.hatchWarningArea(
|
||||||
warningPolygon,
|
warningPolygon,
|
||||||
removeCounties(warningArea,
|
removeCounties(warningArea,
|
||||||
|
@ -425,27 +433,37 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
LinearRing lr = gf.createLinearRing(coords);
|
LinearRing lr = gf.createLinearRing(coords);
|
||||||
hatchedArea = gf.createPolygon(lr, null);
|
hatchedArea = gf.createPolygon(lr, null);
|
||||||
int adjustPolygon_counter = 0;
|
int adjustPolygon_counter = 0;
|
||||||
while (!hatchedArea.isValid() && adjustPolygon_counter < 1) {
|
while (!hatchedArea.isValid()
|
||||||
System.out.println("Calling adjustPolygon #" + adjustPolygon_counter);
|
&& adjustPolygon_counter < 1) {
|
||||||
|
System.out.println("Calling adjustPolygon #"
|
||||||
|
+ adjustPolygon_counter);
|
||||||
PolygonUtil.adjustPolygon(coords);
|
PolygonUtil.adjustPolygon(coords);
|
||||||
PolygonUtil.round(coords, 2);
|
PolygonUtil.round(coords, 2);
|
||||||
coords = PolygonUtil.removeDuplicateCoordinate(coords);
|
coords = PolygonUtil
|
||||||
coords = PolygonUtil.removeOverlaidLinesegments(coords);
|
.removeDuplicateCoordinate(coords);
|
||||||
|
coords = PolygonUtil
|
||||||
|
.removeOverlaidLinesegments(coords);
|
||||||
lr = gf.createLinearRing(coords);
|
lr = gf.createLinearRing(coords);
|
||||||
hatchedArea = gf.createPolygon(lr, null);
|
hatchedArea = gf.createPolygon(lr, null);
|
||||||
adjustPolygon_counter += 1;
|
adjustPolygon_counter += 1;
|
||||||
}
|
}
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
if (!hatchedArea.isValid() && counter < 2) {
|
if (!hatchedArea.isValid() && counter < 2) {
|
||||||
System.out.println("calling adjustVertex & alterVertexes: loop #" + counter);
|
System.out
|
||||||
|
.println("calling adjustVertex & alterVertexes: loop #"
|
||||||
|
+ counter);
|
||||||
int adjustVertex_counter = 0;
|
int adjustVertex_counter = 0;
|
||||||
lr = gf.createLinearRing(coords);
|
lr = gf.createLinearRing(coords);
|
||||||
hatchedArea = gf.createPolygon(lr, null);
|
hatchedArea = gf.createPolygon(lr, null);
|
||||||
while (!hatchedArea.isValid() && adjustVertex_counter < 5) {
|
while (!hatchedArea.isValid()
|
||||||
System.out.println(" Calling adjustVertex #" + adjustVertex_counter);
|
&& adjustVertex_counter < 5) {
|
||||||
|
System.out.println(" Calling adjustVertex #"
|
||||||
|
+ adjustVertex_counter);
|
||||||
coords = PolygonUtil.adjustVertex(coords);
|
coords = PolygonUtil.adjustVertex(coords);
|
||||||
coords = PolygonUtil.removeDuplicateCoordinate(coords);
|
coords = PolygonUtil
|
||||||
coords = PolygonUtil.removeOverlaidLinesegments(coords);
|
.removeDuplicateCoordinate(coords);
|
||||||
|
coords = PolygonUtil
|
||||||
|
.removeOverlaidLinesegments(coords);
|
||||||
lr = gf.createLinearRing(coords);
|
lr = gf.createLinearRing(coords);
|
||||||
hatchedArea = gf.createPolygon(lr, null);
|
hatchedArea = gf.createPolygon(lr, null);
|
||||||
adjustVertex_counter += 1;
|
adjustVertex_counter += 1;
|
||||||
|
@ -453,10 +471,14 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
int inner_counter = 0;
|
int inner_counter = 0;
|
||||||
System.out.println("");
|
System.out.println("");
|
||||||
while (!hatchedArea.isValid() && inner_counter < 5) {
|
while (!hatchedArea.isValid() && inner_counter < 5) {
|
||||||
System.out.println(" Calling alterVertexes #" + inner_counter);
|
System.out
|
||||||
|
.println(" Calling alterVertexes #"
|
||||||
|
+ inner_counter);
|
||||||
coords = PolygonUtil.alterVertexes(coords);
|
coords = PolygonUtil.alterVertexes(coords);
|
||||||
coords = PolygonUtil.removeDuplicateCoordinate(coords);
|
coords = PolygonUtil
|
||||||
coords = PolygonUtil.removeOverlaidLinesegments(coords);
|
.removeDuplicateCoordinate(coords);
|
||||||
|
coords = PolygonUtil
|
||||||
|
.removeOverlaidLinesegments(coords);
|
||||||
lr = gf.createLinearRing(coords);
|
lr = gf.createLinearRing(coords);
|
||||||
hatchedArea = gf.createPolygon(lr, null);
|
hatchedArea = gf.createPolygon(lr, null);
|
||||||
inner_counter += 1;
|
inner_counter += 1;
|
||||||
|
@ -674,8 +696,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
displayState.angle = 0;
|
displayState.angle = 0;
|
||||||
displayState.speed = 0;
|
displayState.speed = 0;
|
||||||
} else if (checkStormTrackData(data = ToolsDataManager
|
} else if (checkStormTrackData(data = ToolsDataManager
|
||||||
.getInstance()
|
.getInstance().getStormTrackData())) {
|
||||||
.getStormTrackData())) {
|
|
||||||
displayState.angle = adjustAngle(data.getMotionDirection());
|
displayState.angle = adjustAngle(data.getMotionDirection());
|
||||||
displayState.speed = knotToMeterPerSec.convert(data
|
displayState.speed = knotToMeterPerSec.convert(data
|
||||||
.getMotionSpeed());
|
.getMotionSpeed());
|
||||||
|
@ -995,8 +1016,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
}
|
}
|
||||||
if (config != null) {
|
if (config != null) {
|
||||||
init(config);
|
init(config);
|
||||||
displayState.setInitiallyMotionless(
|
displayState.setInitiallyMotionless(this.configuration
|
||||||
this.configuration.isTrackEnabled() == false
|
.isTrackEnabled() == false
|
||||||
|| this.configuration.getPathcastConfig() == null);
|
|| this.configuration.getPathcastConfig() == null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1044,9 +1065,11 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
+ (System.currentTimeMillis() - t0) + "ms");
|
+ (System.currentTimeMillis() - t0) + "ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Adds geospatial data to siteMap and timezoneMap for the given
|
/**
|
||||||
* template configuration. This must not have any site effects on the
|
* Adds geospatial data to siteMap and timezoneMap for the given template
|
||||||
* currently loaded template or the current product being edited.
|
* configuration. This must not have any site effects on the currently
|
||||||
|
* loaded template or the current product being edited.
|
||||||
|
*
|
||||||
* @param config
|
* @param config
|
||||||
*/
|
*/
|
||||||
private void loadGeodataForConfiguration(WarngenConfiguration config) {
|
private void loadGeodataForConfiguration(WarngenConfiguration config) {
|
||||||
|
@ -1083,7 +1106,6 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
Coordinate c = new GeometryFactory()
|
Coordinate c = new GeometryFactory()
|
||||||
.buildGeometry(geoms).getCentroid()
|
.buildGeometry(geoms).getCentroid()
|
||||||
.getCoordinate();
|
.getCoordinate();
|
||||||
|
|
||||||
gData.latLonToLocal = MapUtil
|
gData.latLonToLocal = MapUtil
|
||||||
.getTransformFromLatLon(MapUtil
|
.getTransformFromLatLon(MapUtil
|
||||||
.constructStereographic(
|
.constructStereographic(
|
||||||
|
@ -1146,6 +1168,18 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
gData.nx = nx;
|
gData.nx = nx;
|
||||||
gData.ny = ny;
|
gData.ny = ny;
|
||||||
|
|
||||||
|
GeneralGridEnvelope range = new GeneralGridEnvelope(
|
||||||
|
new int[] { 0, 0 }, new int[] { gData.nx,
|
||||||
|
gData.ny }, false);
|
||||||
|
GeneralEnvelope ge = new GeneralEnvelope(new double[] {
|
||||||
|
gData.localExtent.getMinX(),
|
||||||
|
gData.localExtent.getMaxY() }, new double[] {
|
||||||
|
gData.localExtent.getMaxX(),
|
||||||
|
gData.localExtent.getMinY() });
|
||||||
|
|
||||||
|
gData.localGridGeometry = new GeneralGridGeometry(
|
||||||
|
range, ge);
|
||||||
|
|
||||||
System.out.println("Time to lookup geospatial data "
|
System.out.println("Time to lookup geospatial data "
|
||||||
+ (System.currentTimeMillis() - tq0));
|
+ (System.currentTimeMillis() - tq0));
|
||||||
siteMap.put(currKey, gData);
|
siteMap.put(currKey, gData);
|
||||||
|
@ -1188,6 +1222,14 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
return new GeospatialData[0];
|
return new GeospatialData[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GeneralGridGeometry getLocalGridGeometry() {
|
||||||
|
return geoData.localGridGeometry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MathTransform getlocalToLatLon() {
|
||||||
|
return geoData.localToLatLon;
|
||||||
|
}
|
||||||
|
|
||||||
private GeospatialDataList getGeodataList(String areaSource,
|
private GeospatialDataList getGeodataList(String areaSource,
|
||||||
String localizedSite) {
|
String localizedSite) {
|
||||||
String key = areaSource + "." + localizedSite;
|
String key = areaSource + "." + localizedSite;
|
||||||
|
@ -1303,7 +1345,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
* Returns a set of UGCs for each area in the CWA that intersects the given
|
* Returns a set of UGCs for each area in the CWA that intersects the given
|
||||||
* polygon.
|
* polygon.
|
||||||
*/
|
*/
|
||||||
public Set<String> getUgcsForCountyWatches(Polygon polygon) throws Exception {
|
public Set<String> getUgcsForCountyWatches(Polygon polygon)
|
||||||
|
throws Exception {
|
||||||
GeospatialDataAccessor gda = getCountyGeospatialDataAcessor();
|
GeospatialDataAccessor gda = getCountyGeospatialDataAcessor();
|
||||||
Set<String> ugcs = new HashSet<String>();
|
Set<String> ugcs = new HashSet<String>();
|
||||||
for (String fips : gda.getAllFipsInArea(gda.buildArea(polygon))) {
|
for (String fips : gda.getAllFipsInArea(gda.buildArea(polygon))) {
|
||||||
|
@ -1321,17 +1364,20 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
return ugcs;
|
return ugcs;
|
||||||
}
|
}
|
||||||
|
|
||||||
private GeospatialDataAccessor getCountyGeospatialDataAcessor() throws Exception {
|
private GeospatialDataAccessor getCountyGeospatialDataAcessor()
|
||||||
|
throws Exception {
|
||||||
GeospatialDataList gdl = searchCountyGeospatialDataAccessor();
|
GeospatialDataList gdl = searchCountyGeospatialDataAccessor();
|
||||||
if (gdl == null) {
|
if (gdl == null) {
|
||||||
// Cause county geospatial data to be loaded
|
// Cause county geospatial data to be loaded
|
||||||
// TODO: Should not be referencing tornadoWarning.
|
// TODO: Should not be referencing tornadoWarning.
|
||||||
WarngenConfiguration torConfig = WarngenConfiguration.loadConfig("tornadoWarning", getLocalizedSite());
|
WarngenConfiguration torConfig = WarngenConfiguration.loadConfig(
|
||||||
|
"tornadoWarning", getLocalizedSite());
|
||||||
loadGeodataForConfiguration(torConfig);
|
loadGeodataForConfiguration(torConfig);
|
||||||
gdl = searchCountyGeospatialDataAccessor();
|
gdl = searchCountyGeospatialDataAccessor();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: There should be some way to get the "county" configuration by name
|
// TODO: There should be some way to get the "county" configuration by
|
||||||
|
// name
|
||||||
// independent of a template
|
// independent of a template
|
||||||
AreaSourceConfiguration areaConfig = new AreaSourceConfiguration();
|
AreaSourceConfiguration areaConfig = new AreaSourceConfiguration();
|
||||||
areaConfig.setFipsField("FIPS");
|
areaConfig.setFipsField("FIPS");
|
||||||
|
@ -1341,7 +1387,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
|
|
||||||
private GeospatialDataList searchCountyGeospatialDataAccessor() {
|
private GeospatialDataList searchCountyGeospatialDataAccessor() {
|
||||||
synchronized (siteMap) {
|
synchronized (siteMap) {
|
||||||
for (Map.Entry<String, GeospatialDataList> entry : siteMap.entrySet()) {
|
for (Map.Entry<String, GeospatialDataList> entry : siteMap
|
||||||
|
.entrySet()) {
|
||||||
String[] keyParts = entry.getKey().split("\\.");
|
String[] keyParts = entry.getKey().split("\\.");
|
||||||
if (keyParts.length == 2
|
if (keyParts.length == 2
|
||||||
&& "county".equalsIgnoreCase(keyParts[0])
|
&& "county".equalsIgnoreCase(keyParts[0])
|
||||||
|
@ -1938,8 +1985,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (warningAction == null || warningAction == WarningAction.NEW) {
|
if (warningAction == null || warningAction == WarningAction.NEW) {
|
||||||
if ((configuration.isTrackEnabled() == false ||
|
if ((configuration.isTrackEnabled() == false || configuration
|
||||||
configuration.getPathcastConfig() == null)
|
.getPathcastConfig() == null)
|
||||||
&& !this.displayState.isNonstationary()
|
&& !this.displayState.isNonstationary()
|
||||||
&& this.displayState.displayType != DisplayType.POLY) {
|
&& this.displayState.displayType != DisplayType.POLY) {
|
||||||
createSquare();
|
createSquare();
|
||||||
|
@ -2271,8 +2318,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
}
|
}
|
||||||
|
|
||||||
Point point = displayState.dragMePoint;
|
Point point = displayState.dragMePoint;
|
||||||
if (motdir != null && motspd != null &&
|
if (motdir != null && motspd != null
|
||||||
(motspd != 0 || configuration.isTrackEnabled())) {
|
&& (motspd != 0 || configuration.isTrackEnabled())) {
|
||||||
displayState.setInitiallyMotionless(false);
|
displayState.setInitiallyMotionless(false);
|
||||||
displayState.angle = adjustAngle(motdir);
|
displayState.angle = adjustAngle(motdir);
|
||||||
displayState.speed = knotToMeterPerSec.convert(motspd);
|
displayState.speed = knotToMeterPerSec.convert(motspd);
|
||||||
|
@ -2325,10 +2372,9 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
if (m.find()) {
|
if (m.find()) {
|
||||||
int hour = Integer.parseInt(m.group(1));
|
int hour = Integer.parseInt(m.group(1));
|
||||||
int minute = Integer.parseInt(m.group(2));
|
int minute = Integer.parseInt(m.group(2));
|
||||||
frameTime = TimeUtil.timeOfDayToAbsoluteTime(
|
frameTime = TimeUtil.timeOfDayToAbsoluteTime(hour
|
||||||
hour * TimeUtil.SECONDS_PER_HOUR +
|
* TimeUtil.SECONDS_PER_HOUR + minute
|
||||||
minute * TimeUtil.SECONDS_PER_MINUTE,
|
* TimeUtil.SECONDS_PER_MINUTE, warnRecord.getIssueTime());
|
||||||
warnRecord.getIssueTime());
|
|
||||||
} else {
|
} else {
|
||||||
frameTime = warnRecord.getIssueTime();
|
frameTime = warnRecord.getIssueTime();
|
||||||
}
|
}
|
||||||
|
@ -2376,8 +2422,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
FramesInfo info = descriptor.getFramesInfo();
|
FramesInfo info = descriptor.getFramesInfo();
|
||||||
int currentFrame = trackUtil.getCurrentFrame(info);
|
int currentFrame = trackUtil.getCurrentFrame(info);
|
||||||
int frameCount = trackUtil.getFrameCount(info);
|
int frameCount = trackUtil.getFrameCount(info);
|
||||||
if (currentFrame == frameCount - 1
|
if (currentFrame == frameCount - 1 || !displayState.isNonstationary()) {
|
||||||
|| ! displayState.isNonstationary()) {
|
|
||||||
return coordinate;
|
return coordinate;
|
||||||
}
|
}
|
||||||
DataTime[] datatimes = trackUtil.getDataTimes(info);
|
DataTime[] datatimes = trackUtil.getDataTimes(info);
|
||||||
|
@ -2686,7 +2731,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
getFips(f));
|
getFips(f));
|
||||||
if (tmp.isEmpty()) {
|
if (tmp.isEmpty()) {
|
||||||
String fip = getFips(f);
|
String fip = getFips(f);
|
||||||
if (fip != null && uniqueFip != null && fip.equals(uniqueFip)) {
|
if (fip != null && uniqueFip != null
|
||||||
|
&& fip.equals(uniqueFip)) {
|
||||||
updateWarnedAreas(true);
|
updateWarnedAreas(true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2769,8 +2815,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
||||||
if (areaHatcher != null) {
|
if (areaHatcher != null) {
|
||||||
Polygon polygon = state.getWarningPolygon();
|
Polygon polygon = state.getWarningPolygon();
|
||||||
polygon = tryToIntersectWithOriginalPolygon(polygon);
|
polygon = tryToIntersectWithOriginalPolygon(polygon);
|
||||||
areaHatcher.hatchArea(polygon,
|
areaHatcher.hatchArea(polygon, state.getWarningArea(),
|
||||||
state.getWarningArea(),
|
|
||||||
state.getOldWarningPolygon());
|
state.getOldWarningPolygon());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,6 +98,7 @@ import com.raytheon.viz.warngen.gis.Area;
|
||||||
import com.raytheon.viz.warngen.gis.ClosestPointComparator;
|
import com.raytheon.viz.warngen.gis.ClosestPointComparator;
|
||||||
import com.raytheon.viz.warngen.gis.GisUtil;
|
import com.raytheon.viz.warngen.gis.GisUtil;
|
||||||
import com.raytheon.viz.warngen.gis.PathCast;
|
import com.raytheon.viz.warngen.gis.PathCast;
|
||||||
|
import com.raytheon.viz.warngen.gis.PortionsUtil;
|
||||||
import com.raytheon.viz.warngen.gis.Wx;
|
import com.raytheon.viz.warngen.gis.Wx;
|
||||||
import com.raytheon.viz.warngen.gui.BackupData;
|
import com.raytheon.viz.warngen.gui.BackupData;
|
||||||
import com.raytheon.viz.warngen.gui.FollowupData;
|
import com.raytheon.viz.warngen.gui.FollowupData;
|
||||||
|
@ -154,6 +155,7 @@ import com.vividsolutions.jts.io.WKTReader;
|
||||||
* May 10, 2013 1951 rjpeter Updated ugcZones references
|
* May 10, 2013 1951 rjpeter Updated ugcZones references
|
||||||
* May 30, 2013 DR 16237 D. Friedman Fix watch query.
|
* May 30, 2013 DR 16237 D. Friedman Fix watch query.
|
||||||
* Jun 18, 2013 2118 njensen Only calculate pathcast if it's actually used
|
* Jun 18, 2013 2118 njensen Only calculate pathcast if it's actually used
|
||||||
|
* Aug 19, 2013 2177 jsanchez Passed PortionsUtil to Area class.
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @author njensen
|
* @author njensen
|
||||||
|
@ -301,17 +303,18 @@ public class TemplateRunner {
|
||||||
AffectedAreas[] cancelareas = null;
|
AffectedAreas[] cancelareas = null;
|
||||||
Map<String, Object> intersectAreas = null;
|
Map<String, Object> intersectAreas = null;
|
||||||
Wx wx = null;
|
Wx wx = null;
|
||||||
|
Area area = new Area(new PortionsUtil(warngenLayer));
|
||||||
long wwaMNDTime = 0l;
|
long wwaMNDTime = 0l;
|
||||||
try {
|
try {
|
||||||
t0 = System.currentTimeMillis();
|
t0 = System.currentTimeMillis();
|
||||||
areas = Area.findAffectedAreas(config, warnPolygon, warningArea,
|
areas = area.findAffectedAreas(config, warnPolygon, warningArea,
|
||||||
threeLetterSiteId);
|
threeLetterSiteId);
|
||||||
System.out.println("Time to get areas = "
|
System.out.println("Time to get areas = "
|
||||||
+ (System.currentTimeMillis() - t0));
|
+ (System.currentTimeMillis() - t0));
|
||||||
context.put(config.getHatchedAreaSource().getVariable(), areas);
|
context.put(config.getHatchedAreaSource().getVariable(), areas);
|
||||||
|
|
||||||
t0 = System.currentTimeMillis();
|
t0 = System.currentTimeMillis();
|
||||||
intersectAreas = Area.findInsectingAreas(config, warnPolygon,
|
intersectAreas = area.findInsectingAreas(config, warnPolygon,
|
||||||
warningArea, threeLetterSiteId, warngenLayer);
|
warningArea, threeLetterSiteId, warngenLayer);
|
||||||
System.out.println("Time to get intersecting areas = "
|
System.out.println("Time to get intersecting areas = "
|
||||||
+ (System.currentTimeMillis() - t0));
|
+ (System.currentTimeMillis() - t0));
|
||||||
|
@ -324,10 +327,11 @@ public class TemplateRunner {
|
||||||
double minSize = 1.0E-3d;
|
double minSize = 1.0E-3d;
|
||||||
if ((areas != null) && (areas.length > 0)) {
|
if ((areas != null) && (areas.length > 0)) {
|
||||||
Set<String> timeZones = new HashSet<String>();
|
Set<String> timeZones = new HashSet<String>();
|
||||||
for (AffectedAreas area : areas) {
|
for (AffectedAreas affectedAreas : areas) {
|
||||||
if (area.getTimezone() != null) {
|
if (affectedAreas.getTimezone() != null) {
|
||||||
// Handles counties that span two time zones
|
// Handles counties that span two time zones
|
||||||
String oneLetterTimeZones = area.getTimezone().trim();
|
String oneLetterTimeZones = affectedAreas.getTimezone()
|
||||||
|
.trim();
|
||||||
oneLetterTZ = new String[oneLetterTimeZones.length()];
|
oneLetterTZ = new String[oneLetterTimeZones.length()];
|
||||||
if (oneLetterTimeZones.length() == 1) {
|
if (oneLetterTimeZones.length() == 1) {
|
||||||
timeZones.add(String.valueOf(oneLetterTimeZones
|
timeZones.add(String.valueOf(oneLetterTimeZones
|
||||||
|
@ -799,14 +803,14 @@ public class TemplateRunner {
|
||||||
Geometry removedAreas = warngenLayer.getWarningAreaForGids(
|
Geometry removedAreas = warngenLayer.getWarningAreaForGids(
|
||||||
oldGids, oldWarningArea);
|
oldGids, oldWarningArea);
|
||||||
if (removedAreas.isEmpty() == false) {
|
if (removedAreas.isEmpty() == false) {
|
||||||
cancelareas = Area.findAffectedAreas(config,
|
cancelareas = area.findAffectedAreas(config,
|
||||||
oldWarn.getGeometry(), removedAreas,
|
oldWarn.getGeometry(), removedAreas,
|
||||||
threeLetterSiteId);
|
threeLetterSiteId);
|
||||||
for (int i = 0; i < cancelareas.length; i++) {
|
for (int i = 0; i < cancelareas.length; i++) {
|
||||||
for (AffectedAreas area : areas) {
|
for (AffectedAreas affectedAreas : areas) {
|
||||||
if ((cancelareas[i] != null)
|
if ((cancelareas[i] != null)
|
||||||
&& cancelareas[i].getFips().equals(
|
&& cancelareas[i].getFips().equals(
|
||||||
area.getFips())) {
|
affectedAreas.getFips())) {
|
||||||
cancelareas[i] = null;
|
cancelareas[i] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -824,7 +828,7 @@ public class TemplateRunner {
|
||||||
// This may not be efficient enough. Is it possible that
|
// This may not be efficient enough. Is it possible that
|
||||||
// a removed intersected county be in the affected
|
// a removed intersected county be in the affected
|
||||||
// intersected county. Need an example to fully test.
|
// intersected county. Need an example to fully test.
|
||||||
Map<String, Object> intersectRemovedAreas = Area
|
Map<String, Object> intersectRemovedAreas = area
|
||||||
.findInsectingAreas(config, warnPolygon,
|
.findInsectingAreas(config, warnPolygon,
|
||||||
removedAreas, threeLetterSiteId,
|
removedAreas, threeLetterSiteId,
|
||||||
warngenLayer);
|
warngenLayer);
|
||||||
|
|
Loading…
Add table
Reference in a new issue