From 0b425f94eb66a43e42e460c9b2f3eb14ed68cd0d Mon Sep 17 00:00:00 2001 From: Jordan Gerth Date: Mon, 15 Sep 2014 16:30:22 -0500 Subject: [PATCH] VLab Issue #4723 - Ingest LambertConformal projection with two standard parallels using RegionalSat; fixes #4723 Change-Id: I20b309f4e994259a54e6bdb2276bc09a6b60a885 Former-commit-id: baf75c177b595dcfb545436586c31d28080b8281 --- .../util/satellite/SatSpatialFactory.java | 56 +++++++++++++------ .../decoder/RegionalSatDecoder.java | 50 ++++++++++------- 2 files changed, 70 insertions(+), 36 deletions(-) diff --git a/edexOsgi/com.raytheon.edex.plugin.satellite/src/com/raytheon/edex/util/satellite/SatSpatialFactory.java b/edexOsgi/com.raytheon.edex.plugin.satellite/src/com/raytheon/edex/util/satellite/SatSpatialFactory.java index 525fff7d4e..d57a4f2c48 100644 --- a/edexOsgi/com.raytheon.edex.plugin.satellite/src/com/raytheon/edex/util/satellite/SatSpatialFactory.java +++ b/edexOsgi/com.raytheon.edex.plugin.satellite/src/com/raytheon/edex/util/satellite/SatSpatialFactory.java @@ -43,7 +43,7 @@ import com.vividsolutions.jts.geom.Envelope; * Sep 30, 2013 2333 mschenke Refactored to store points in crs space * Apr 15, 2014 3017 bsteffen Add new getCoverage methods to support * either one corner + dx/dy or two corners. - * + * Sep 15, 2014 DR 17303 jgerth Support for second standard latitude * */ public class SatSpatialFactory { @@ -141,18 +141,20 @@ public class SatSpatialFactory { * @param ny * the number of rows of data. * @param lov - * the longitude orientatition, used by + * the longitude orientation, used by * {@link #PROJ_CYLIN_EQUIDISTANT}, {@link #PROJ_LAMBERT}, * {@link #PROJ_POLAR}. * @param latin * the latitude at which the projection is tangent to the earths * surface, used by {@link #PROJ_CYLIN_EQUIDISTANT}, * {@link #PROJ_LAMBERT}, {@link #PROJ_MERCATOR}. + * @param latin2 + * the second standard latitude, used by {@link #PROJ_LAMBERT}. * @param la1 * the latitude of a corner of the grid, if dy is positive this * is an upper corner. * @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 * @param dx * the distance between columns measured in CRS meters. @@ -163,10 +165,10 @@ public class SatSpatialFactory { * @throws DecoderException */ 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 { try { - ProjectedCRS crs = createCRS(crsType, lov, latin, 0.0); + ProjectedCRS crs = createCRS(crsType, lov, latin, latin2, 0.0); DirectPosition2D corner = new DirectPosition2D(lo1, la1); MathTransform fromLatLon = MapUtil.getTransformFromLatLon(crs); 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 - * 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. * * @param crsType @@ -204,36 +215,38 @@ public class SatSpatialFactory { * {@link #PROJ_CYLIN_EQUIDISTANT}, {@link #PROJ_LAMBERT}, * {@link #PROJ_MERCATOR}, {@link #PROJ_POLAR}. * @param lov - * the longitude orientatition, used by + * the longitude orientation, used by * {@link #PROJ_CYLIN_EQUIDISTANT}, {@link #PROJ_LAMBERT}, * {@link #PROJ_POLAR}. * @param latin * the latitude at which the projection is tangent to the earths * surface, used by {@link #PROJ_CYLIN_EQUIDISTANT}, * {@link #PROJ_LAMBERT}, {@link #PROJ_MERCATOR}. + * @param latin2 + * the second standard latitude, used by {@link #PROJ_LAMBERT}. * @param la1 * the latitude of a corner of the grid. * @param lo1 - * the longitide of a corner of the grid. + * the longitude of a corner of the grid. * @param la2 * the latitude of a corner of the grid., should be opposite * corner from la1. * @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 * @return a {@link SatMapCoverage} matching these parameters that has been * loaded from or persisted to the database. * @throws DecoderException */ 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 { try { double cm = 0.0; if ((lo1 > 0.0) && (lo2 < 0.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 corner2 = new DirectPosition2D(lo2, la2); 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} */ private synchronized SatMapCoverage checkPersisted( SatMapCoverage mapCoverage) { @@ -294,25 +316,27 @@ public class SatSpatialFactory { * {@link #PROJ_CYLIN_EQUIDISTANT}, {@link #PROJ_LAMBERT}, * {@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_POLAR}. * @param latin * the latitude at which the projection is tangent to the earths * surface, used by {@link #PROJ_CYLIN_EQUIDISTANT}, * {@link #PROJ_LAMBERT}, {@link #PROJ_MERCATOR}. + * @param latin2 + * the second standard latitude, used by {@link #PROJ_LAMBERT}. * @param cm * the central meridian of the projection, only used by * {@link #PROJ_MERCATOR}. * @return */ private static ProjectedCRS createCRS(int crsType, double lov, - double latin, double cm) { + double latin, double latin2, double cm) { switch (crsType) { case PROJ_MERCATOR: return createMercatorCrs(latin, cm); case PROJ_LAMBERT: - return createLambertCrs(latin, lov); + return createLambertCrs(latin, latin2, lov); case PROJ_CYLIN_EQUIDISTANT: return createEqCylCrs(latin, lov); default: @@ -325,9 +349,9 @@ public class SatSpatialFactory { 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, - MapUtil.AWIPS_EARTH_RADIUS, latin, latin, lov); + MapUtil.AWIPS_EARTH_RADIUS, latin, latin2, lov); } private static ProjectedCRS createEqCylCrs(double latin, double lov) { diff --git a/ost/gov.noaa.nws.ost.edex.plugin.regionalsat/src/gov/noaa/nws/ost/edex/plugin/regionalsat/decoder/RegionalSatDecoder.java b/ost/gov.noaa.nws.ost.edex.plugin.regionalsat/src/gov/noaa/nws/ost/edex/plugin/regionalsat/decoder/RegionalSatDecoder.java index 803c1be345..5e8fc10905 100644 --- a/ost/gov.noaa.nws.ost.edex.plugin.regionalsat/src/gov/noaa/nws/ost/edex/plugin/regionalsat/decoder/RegionalSatDecoder.java +++ b/ost/gov.noaa.nws.ost.edex.plugin.regionalsat/src/gov/noaa/nws/ost/edex/plugin/regionalsat/decoder/RegionalSatDecoder.java @@ -61,6 +61,7 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools; * IDataRecord required by the SatelliteDao * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * Apr 15, 2014 3017 bsteffen Call new methods in SatSpatialFactory + * Sep 11, 2014 DR 17303 jgerth Support for second standard latitude * * * @author tk @@ -116,26 +117,26 @@ public class RegionalSatDecoder extends AbstractDecoder { netCdfFile = NetcdfFile.openInMemory(filename, data); // set the source; Alaska Region - if (source == null) { - source = "Source"; // use to look up source value; default of - // Source + String gaSourceStr = "Unknown"; + Attribute gaSource = netCdfFile.findGlobalAttribute("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 Attribute satName = netCdfFile.findGlobalAttribute("satelliteName"); - String entity = null; // "HRPT"; "GOESR-PG"; "Blended2"; if (satName != null) { - entity = satName.getStringValue(); + entity = satName.getStringValue().trim(); } if (entity != null) { String parsed = getCreatingEntity(entity); if ((parsed != null) && (parsed.length() > 0)) { - record.setCreatingEntity(parsed); + record.setCreatingEntity(parsed.replace("/", " ")); } else { - record.setCreatingEntity(entity); + record.setCreatingEntity(entity.replace("/", " ")); } } else { record.setCreatingEntity("Unknown"); @@ -156,9 +157,9 @@ public class RegionalSatDecoder extends AbstractDecoder { pev = getPhysicalElement(entity, channel); String element = pev.name; if (pev.name != null) { - record.setPhysicalElement(element); + record.setPhysicalElement(element.replace("/", " ")); } else { - record.setPhysicalElement(channel); + record.setPhysicalElement(channel.replace("/", " ")); } } else { 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 long time = netCdfFile.findVariable("validTime").readScalarLong(); // time - // in - // seconds + // in + // seconds calendar.setTimeInMillis(time * 1000); // need to convert seconds to - // milliseconds + // milliseconds /* * Date date = new Date(); // used for setting the test data time @@ -199,9 +200,10 @@ public class RegionalSatDecoder extends AbstractDecoder { .getNumericValue().floatValue(); int mapProjection = SatSpatialFactory.PROJ_POLAR; // STEREOGRAPHIC - // projection - // default + // projection + // default float latin = 0.0f; // set to zero for Stereographic projections + Attribute rot = netCdfFile.findGlobalAttribute("rotation"); float rotation = 0.0f; // read the projection @@ -214,6 +216,9 @@ public class RegionalSatDecoder extends AbstractDecoder { if (projection.equalsIgnoreCase("LAMBERT") || projection.equalsIgnoreCase("LAMBERT_CONFORMAL")) { mapProjection = SatSpatialFactory.PROJ_LAMBERT; + if (rot != null) { + rotation = rot.getNumericValue().floatValue(); + } } else if (projection.equalsIgnoreCase("MERCATOR")) { mapProjection = SatSpatialFactory.PROJ_MERCATOR; } else if (projection @@ -222,7 +227,6 @@ public class RegionalSatDecoder extends AbstractDecoder { } } else { - Attribute rot = netCdfFile.findGlobalAttribute("rotation"); if (rot != null) { rotation = rot.getNumericValue().floatValue(); // STEREOGRAPHIC projection add rotation to lov @@ -274,9 +278,15 @@ public class RegionalSatDecoder extends AbstractDecoder { "Unable to decode Satellite: Encountered Unknown projection"); } // end of if map projection block - SatMapCoverage mapCoverage = SatSpatialFactory.getInstance() - .getCoverageTwoCorners(mapProjection, nx, ny, lov, latin, - la1, lo1, la2, lo2); + SatMapCoverage mapCoverage; + if (mapProjection == SatSpatialFactory.PROJ_LAMBERT && rot != null && rotation != latin) + 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.setCoverage(mapCoverage); @@ -357,4 +367,4 @@ public class RegionalSatDecoder extends AbstractDecoder { this.filename = file; } -} +} \ No newline at end of file