VLab Issue #4723 - Ingest LambertConformal projection with two standard parallels using RegionalSat; fixes #4723

Change-Id: I20b309f4e994259a54e6bdb2276bc09a6b60a885

Former-commit-id: baf75c177b595dcfb545436586c31d28080b8281
This commit is contained in:
Jordan Gerth 2014-09-15 16:30:22 -05:00
parent 088ebd2ca2
commit 0b425f94eb
2 changed files with 70 additions and 36 deletions

View file

@ -43,7 +43,7 @@ import com.vividsolutions.jts.geom.Envelope;
* Sep 30, 2013 2333 mschenke Refactored to store points in crs space * Sep 30, 2013 2333 mschenke Refactored to store points in crs space
* Apr 15, 2014 3017 bsteffen Add new getCoverage methods to support * Apr 15, 2014 3017 bsteffen Add new getCoverage methods to support
* either one corner + dx/dy or two corners. * either one corner + dx/dy or two corners.
* * Sep 15, 2014 DR 17303 jgerth Support for second standard latitude
* </pre> * </pre>
*/ */
public class SatSpatialFactory { public class SatSpatialFactory {
@ -141,18 +141,20 @@ public class SatSpatialFactory {
* @param ny * @param ny
* the number of rows of data. * the number of rows of data.
* @param lov * @param lov
* the longitude orientatition, used by * the longitude orientation, used by
* {@link #PROJ_CYLIN_EQUIDISTANT}, {@link #PROJ_LAMBERT}, * {@link #PROJ_CYLIN_EQUIDISTANT}, {@link #PROJ_LAMBERT},
* {@link #PROJ_POLAR}. * {@link #PROJ_POLAR}.
* @param latin * @param latin
* the latitude at which the projection is tangent to the earths * the latitude at which the projection is tangent to the earths
* surface, used by {@link #PROJ_CYLIN_EQUIDISTANT}, * surface, used by {@link #PROJ_CYLIN_EQUIDISTANT},
* {@link #PROJ_LAMBERT}, {@link #PROJ_MERCATOR}. * {@link #PROJ_LAMBERT}, {@link #PROJ_MERCATOR}.
* @param latin2
* the second standard latitude, used by {@link #PROJ_LAMBERT}.
* @param la1 * @param la1
* the latitude of a corner of the grid, if dy is positive this * the latitude of a corner of the grid, if dy is positive this
* is an upper corner. * is an upper corner.
* @param lo1 * @param lo1
* the longitide of a corner of the grid, if dx is positive this * the longitude of a corner of the grid, if dx is positive this
* is a left corner * is a left corner
* @param dx * @param dx
* the distance between columns measured in CRS meters. * the distance between columns measured in CRS meters.
@ -163,10 +165,10 @@ public class SatSpatialFactory {
* @throws DecoderException * @throws DecoderException
*/ */
public SatMapCoverage getCoverageSingleCorner(int crsType, int nx, int ny, public SatMapCoverage getCoverageSingleCorner(int crsType, int nx, int ny,
double lov, double latin, double la1, double lo1, double dx, double lov, double latin, double latin2, double la1, double lo1, double dx,
double dy) throws DecoderException { double dy) throws DecoderException {
try { try {
ProjectedCRS crs = createCRS(crsType, lov, latin, 0.0); ProjectedCRS crs = createCRS(crsType, lov, latin, latin2, 0.0);
DirectPosition2D corner = new DirectPosition2D(lo1, la1); DirectPosition2D corner = new DirectPosition2D(lo1, la1);
MathTransform fromLatLon = MapUtil.getTransformFromLatLon(crs); MathTransform fromLatLon = MapUtil.getTransformFromLatLon(crs);
fromLatLon.transform(corner, corner); fromLatLon.transform(corner, corner);
@ -193,10 +195,19 @@ public class SatSpatialFactory {
} }
} }
/**
* @see {@link #getCoverageSingleCorner(int, int, int, double, double, double, double, double, double, double)}
*/
public SatMapCoverage getCoverageSingleCorner(int crsType, int nx, int ny,
double lov, double latin, double la1, double lo1, double dx,
double dy) throws DecoderException {
return getCoverageSingleCorner(crsType, nx, ny, lov, latin, latin, la1, lo1, dx, dy);
}
/** /**
* *
* Create a {@link SatMapCoverage} with an area defined by two corners. The * Create a {@link SatMapCoverage} with an area defined by two corners. The
* two corners must be opposite(diagnol) from eachother. They caan be either * two corners must be opposite (diagonal) from each other. They can be either
* the upper left and lower right or the upper right and lower left corners. * the upper left and lower right or the upper right and lower left corners.
* *
* @param crsType * @param crsType
@ -204,36 +215,38 @@ public class SatSpatialFactory {
* {@link #PROJ_CYLIN_EQUIDISTANT}, {@link #PROJ_LAMBERT}, * {@link #PROJ_CYLIN_EQUIDISTANT}, {@link #PROJ_LAMBERT},
* {@link #PROJ_MERCATOR}, {@link #PROJ_POLAR}. * {@link #PROJ_MERCATOR}, {@link #PROJ_POLAR}.
* @param lov * @param lov
* the longitude orientatition, used by * the longitude orientation, used by
* {@link #PROJ_CYLIN_EQUIDISTANT}, {@link #PROJ_LAMBERT}, * {@link #PROJ_CYLIN_EQUIDISTANT}, {@link #PROJ_LAMBERT},
* {@link #PROJ_POLAR}. * {@link #PROJ_POLAR}.
* @param latin * @param latin
* the latitude at which the projection is tangent to the earths * the latitude at which the projection is tangent to the earths
* surface, used by {@link #PROJ_CYLIN_EQUIDISTANT}, * surface, used by {@link #PROJ_CYLIN_EQUIDISTANT},
* {@link #PROJ_LAMBERT}, {@link #PROJ_MERCATOR}. * {@link #PROJ_LAMBERT}, {@link #PROJ_MERCATOR}.
* @param latin2
* the second standard latitude, used by {@link #PROJ_LAMBERT}.
* @param la1 * @param la1
* the latitude of a corner of the grid. * the latitude of a corner of the grid.
* @param lo1 * @param lo1
* the longitide of a corner of the grid. * the longitude of a corner of the grid.
* @param la2 * @param la2
* the latitude of a corner of the grid., should be opposite * the latitude of a corner of the grid., should be opposite
* corner from la1. * corner from la1.
* @param lo2 * @param lo2
* the longitide of a corner of the grid, should be opposite * the longitude of a corner of the grid, should be opposite
* corner from lo1 * corner from lo1
* @return a {@link SatMapCoverage} matching these parameters that has been * @return a {@link SatMapCoverage} matching these parameters that has been
* loaded from or persisted to the database. * loaded from or persisted to the database.
* @throws DecoderException * @throws DecoderException
*/ */
public SatMapCoverage getCoverageTwoCorners(int crsType, int nx, int ny, public SatMapCoverage getCoverageTwoCorners(int crsType, int nx, int ny,
double lov, double latin, double la1, double lo1, double la2, double lov, double latin, double latin2, double la1, double lo1, double la2,
double lo2) throws DecoderException { double lo2) throws DecoderException {
try { try {
double cm = 0.0; double cm = 0.0;
if ((lo1 > 0.0) && (lo2 < 0.0)) { if ((lo1 > 0.0) && (lo2 < 0.0)) {
cm = 180.0; cm = 180.0;
} }
ProjectedCRS crs = createCRS(crsType, lov, latin, cm); ProjectedCRS crs = createCRS(crsType, lov, latin, latin2, cm);
DirectPosition2D corner1 = new DirectPosition2D(lo1, la1); DirectPosition2D corner1 = new DirectPosition2D(lo1, la1);
DirectPosition2D corner2 = new DirectPosition2D(lo2, la2); DirectPosition2D corner2 = new DirectPosition2D(lo2, la2);
MathTransform fromLatLon = MapUtil.getTransformFromLatLon(crs); MathTransform fromLatLon = MapUtil.getTransformFromLatLon(crs);
@ -262,6 +275,15 @@ public class SatSpatialFactory {
} }
} }
/**
* @see {@link #getCoverageTwoCorners(int, int, int, double, double, double, double, double, double, double)}
*/
public SatMapCoverage getCoverageTwoCorners(int crsType, int nx, int ny,
double lov, double latin, double la1, double lo1, double la2,
double lo2) throws DecoderException {
return getCoverageTwoCorners(crsType, nx, ny, lov, latin, latin, la1, lo1, la2, lo2);
}
/** Load or persist a {@link SatMapCoverage} */ /** Load or persist a {@link SatMapCoverage} */
private synchronized SatMapCoverage checkPersisted( private synchronized SatMapCoverage checkPersisted(
SatMapCoverage mapCoverage) { SatMapCoverage mapCoverage) {
@ -294,25 +316,27 @@ public class SatSpatialFactory {
* {@link #PROJ_CYLIN_EQUIDISTANT}, {@link #PROJ_LAMBERT}, * {@link #PROJ_CYLIN_EQUIDISTANT}, {@link #PROJ_LAMBERT},
* {@link #PROJ_MERCATOR}, {@link #PROJ_POLAR}. * @param lov * {@link #PROJ_MERCATOR}, {@link #PROJ_POLAR}. * @param lov
* @param lov * @param lov
* the longitude orientatition, used by * the longitude orientation, used by
* {@link #PROJ_CYLIN_EQUIDISTANT}, {@link #PROJ_LAMBERT}, * {@link #PROJ_CYLIN_EQUIDISTANT}, {@link #PROJ_LAMBERT},
* {@link #PROJ_POLAR}. * {@link #PROJ_POLAR}.
* @param latin * @param latin
* the latitude at which the projection is tangent to the earths * the latitude at which the projection is tangent to the earths
* surface, used by {@link #PROJ_CYLIN_EQUIDISTANT}, * surface, used by {@link #PROJ_CYLIN_EQUIDISTANT},
* {@link #PROJ_LAMBERT}, {@link #PROJ_MERCATOR}. * {@link #PROJ_LAMBERT}, {@link #PROJ_MERCATOR}.
* @param latin2
* the second standard latitude, used by {@link #PROJ_LAMBERT}.
* @param cm * @param cm
* the central meridian of the projection, only used by * the central meridian of the projection, only used by
* {@link #PROJ_MERCATOR}. * {@link #PROJ_MERCATOR}.
* @return * @return
*/ */
private static ProjectedCRS createCRS(int crsType, double lov, private static ProjectedCRS createCRS(int crsType, double lov,
double latin, double cm) { double latin, double latin2, double cm) {
switch (crsType) { switch (crsType) {
case PROJ_MERCATOR: case PROJ_MERCATOR:
return createMercatorCrs(latin, cm); return createMercatorCrs(latin, cm);
case PROJ_LAMBERT: case PROJ_LAMBERT:
return createLambertCrs(latin, lov); return createLambertCrs(latin, latin2, lov);
case PROJ_CYLIN_EQUIDISTANT: case PROJ_CYLIN_EQUIDISTANT:
return createEqCylCrs(latin, lov); return createEqCylCrs(latin, lov);
default: default:
@ -325,9 +349,9 @@ public class SatSpatialFactory {
MapUtil.AWIPS_EARTH_RADIUS, latin, cm); MapUtil.AWIPS_EARTH_RADIUS, latin, cm);
} }
private static ProjectedCRS createLambertCrs(double latin, double lov) { private static ProjectedCRS createLambertCrs(double latin, double latin2, double lov) {
return MapUtil.constructLambertConformal(MapUtil.AWIPS_EARTH_RADIUS, return MapUtil.constructLambertConformal(MapUtil.AWIPS_EARTH_RADIUS,
MapUtil.AWIPS_EARTH_RADIUS, latin, latin, lov); MapUtil.AWIPS_EARTH_RADIUS, latin, latin2, lov);
} }
private static ProjectedCRS createEqCylCrs(double latin, double lov) { private static ProjectedCRS createEqCylCrs(double latin, double lov) {

View file

@ -61,6 +61,7 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools;
* IDataRecord required by the SatelliteDao * IDataRecord required by the SatelliteDao
* Aug 30, 2013 2298 rjpeter Make getPluginName abstract * Aug 30, 2013 2298 rjpeter Make getPluginName abstract
* Apr 15, 2014 3017 bsteffen Call new methods in SatSpatialFactory * Apr 15, 2014 3017 bsteffen Call new methods in SatSpatialFactory
* Sep 11, 2014 DR 17303 jgerth Support for second standard latitude
* </pre> * </pre>
* *
* @author tk * @author tk
@ -116,26 +117,26 @@ public class RegionalSatDecoder extends AbstractDecoder {
netCdfFile = NetcdfFile.openInMemory(filename, data); netCdfFile = NetcdfFile.openInMemory(filename, data);
// set the source; Alaska Region // set the source; Alaska Region
if (source == null) { String gaSourceStr = "Unknown";
source = "Source"; // use to look up source value; default of Attribute gaSource = netCdfFile.findGlobalAttribute("source");
// Source if (gaSource != null) {
gaSourceStr = gaSource.getStringValue().trim();
} }
record.setSource(getSource(source)); // lookup source value record.setSource(getSource(gaSourceStr).replace("/", " ")); // lookup source value
// set the creating entity // set the creating entity
Attribute satName = netCdfFile.findGlobalAttribute("satelliteName"); Attribute satName = netCdfFile.findGlobalAttribute("satelliteName");
String entity = null; // "HRPT"; "GOESR-PG"; "Blended2"; String entity = null; // "HRPT"; "GOESR-PG"; "Blended2";
if (satName != null) { if (satName != null) {
entity = satName.getStringValue(); entity = satName.getStringValue().trim();
} }
if (entity != null) { if (entity != null) {
String parsed = getCreatingEntity(entity); String parsed = getCreatingEntity(entity);
if ((parsed != null) && (parsed.length() > 0)) { if ((parsed != null) && (parsed.length() > 0)) {
record.setCreatingEntity(parsed); record.setCreatingEntity(parsed.replace("/", " "));
} else { } else {
record.setCreatingEntity(entity); record.setCreatingEntity(entity.replace("/", " "));
} }
} else { } else {
record.setCreatingEntity("Unknown"); record.setCreatingEntity("Unknown");
@ -156,9 +157,9 @@ public class RegionalSatDecoder extends AbstractDecoder {
pev = getPhysicalElement(entity, channel); pev = getPhysicalElement(entity, channel);
String element = pev.name; String element = pev.name;
if (pev.name != null) { if (pev.name != null) {
record.setPhysicalElement(element); record.setPhysicalElement(element.replace("/", " "));
} else { } else {
record.setPhysicalElement(channel); record.setPhysicalElement(channel.replace("/", " "));
} }
} else { } else {
record.setPhysicalElement("Imager Visible"); record.setPhysicalElement("Imager Visible");
@ -181,10 +182,10 @@ public class RegionalSatDecoder extends AbstractDecoder {
// read the valid time in seconds and store the time in milliseconds // read the valid time in seconds and store the time in milliseconds
long time = netCdfFile.findVariable("validTime").readScalarLong(); // time long time = netCdfFile.findVariable("validTime").readScalarLong(); // time
// in // in
// seconds // seconds
calendar.setTimeInMillis(time * 1000); // need to convert seconds to calendar.setTimeInMillis(time * 1000); // need to convert seconds to
// milliseconds // milliseconds
/* /*
* Date date = new Date(); // used for setting the test data time * Date date = new Date(); // used for setting the test data time
@ -199,9 +200,10 @@ public class RegionalSatDecoder extends AbstractDecoder {
.getNumericValue().floatValue(); .getNumericValue().floatValue();
int mapProjection = SatSpatialFactory.PROJ_POLAR; // STEREOGRAPHIC int mapProjection = SatSpatialFactory.PROJ_POLAR; // STEREOGRAPHIC
// projection // projection
// default // default
float latin = 0.0f; // set to zero for Stereographic projections float latin = 0.0f; // set to zero for Stereographic projections
Attribute rot = netCdfFile.findGlobalAttribute("rotation");
float rotation = 0.0f; float rotation = 0.0f;
// read the projection // read the projection
@ -214,6 +216,9 @@ public class RegionalSatDecoder extends AbstractDecoder {
if (projection.equalsIgnoreCase("LAMBERT") if (projection.equalsIgnoreCase("LAMBERT")
|| projection.equalsIgnoreCase("LAMBERT_CONFORMAL")) { || projection.equalsIgnoreCase("LAMBERT_CONFORMAL")) {
mapProjection = SatSpatialFactory.PROJ_LAMBERT; mapProjection = SatSpatialFactory.PROJ_LAMBERT;
if (rot != null) {
rotation = rot.getNumericValue().floatValue();
}
} else if (projection.equalsIgnoreCase("MERCATOR")) { } else if (projection.equalsIgnoreCase("MERCATOR")) {
mapProjection = SatSpatialFactory.PROJ_MERCATOR; mapProjection = SatSpatialFactory.PROJ_MERCATOR;
} else if (projection } else if (projection
@ -222,7 +227,6 @@ public class RegionalSatDecoder extends AbstractDecoder {
} }
} else { } else {
Attribute rot = netCdfFile.findGlobalAttribute("rotation");
if (rot != null) { if (rot != null) {
rotation = rot.getNumericValue().floatValue(); rotation = rot.getNumericValue().floatValue();
// STEREOGRAPHIC projection add rotation to lov // STEREOGRAPHIC projection add rotation to lov
@ -274,9 +278,15 @@ public class RegionalSatDecoder extends AbstractDecoder {
"Unable to decode Satellite: Encountered Unknown projection"); "Unable to decode Satellite: Encountered Unknown projection");
} // end of if map projection block } // end of if map projection block
SatMapCoverage mapCoverage = SatSpatialFactory.getInstance() SatMapCoverage mapCoverage;
.getCoverageTwoCorners(mapProjection, nx, ny, lov, latin, if (mapProjection == SatSpatialFactory.PROJ_LAMBERT && rot != null && rotation != latin)
la1, lo1, la2, lo2); mapCoverage = SatSpatialFactory.getInstance()
.getCoverageTwoCorners(mapProjection, nx, ny, lov, latin, rotation,
la1, lo1, la2, lo2);
else
mapCoverage = SatSpatialFactory.getInstance()
.getCoverageTwoCorners(mapProjection, nx, ny, lov, latin,
la1, lo1, la2, lo2);
record.setTraceId(traceId); record.setTraceId(traceId);
record.setCoverage(mapCoverage); record.setCoverage(mapCoverage);
@ -357,4 +367,4 @@ public class RegionalSatDecoder extends AbstractDecoder {
this.filename = file; this.filename = file;
} }
} }