Issue #2333 Refactored satellite to store table values in CRS space instead of lat/lon for GOES-R readiness

Amend: Accepted ticket.

Change-Id: Ib8171694869f60b46fb38634e71de61eb0e76830

Former-commit-id: fe7051816e [formerly 780ac0129f] [formerly e3f6b1ea21] [formerly 866c851b47 [formerly e3f6b1ea21 [formerly 384b8e6a02d4fffa0688993b2a2b53e974ecf493]]]
Former-commit-id: 866c851b47
Former-commit-id: 00101432c385c23ffd439ab94c020a849e2c2d13 [formerly ba25f56dbe]
Former-commit-id: 43b7cb3107
This commit is contained in:
Max Schenkelberg 2013-10-01 14:36:00 -05:00
parent 075a394152
commit 9e14571020
37 changed files with 1012 additions and 1167 deletions

View file

@ -34,13 +34,15 @@ import javax.measure.unit.SI;
import javax.measure.unit.Unit; import javax.measure.unit.Unit;
import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.graphics.RGB;
import org.opengis.metadata.spatial.PixelOrientation; import org.geotools.coverage.grid.GridGeometry2D;
import org.opengis.referencing.datum.PixelInCell;
import org.opengis.referencing.operation.MathTransform;
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters; import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
import com.raytheon.uf.common.dataplugin.grid.GridConstants; import com.raytheon.uf.common.dataplugin.grid.GridConstants;
import com.raytheon.uf.common.geospatial.ISpatialObject; import com.raytheon.uf.common.geospatial.IGridGeometryProvider;
import com.raytheon.uf.common.geospatial.MapUtil;
import com.raytheon.uf.common.geospatial.ReferencedCoordinate; import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
import com.raytheon.uf.common.geospatial.TransformFactory;
import com.raytheon.uf.common.sounding.VerticalSounding; import com.raytheon.uf.common.sounding.VerticalSounding;
import com.raytheon.uf.common.sounding.WxMath; import com.raytheon.uf.common.sounding.WxMath;
import com.raytheon.uf.common.sounding.adapter.IVerticalSoundingProvider; import com.raytheon.uf.common.sounding.adapter.IVerticalSoundingProvider;
@ -76,7 +78,8 @@ import com.vividsolutions.jts.geom.Coordinate;
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Jul 18, 2011 2190 mschenke Initial creation * Jul 18, 2011 2190 mschenke Initial creation
* Oct 2, 2013 2333 mschenke Converted to use IGridGeometryProvider
* *
* </pre> * </pre>
* *
@ -417,12 +420,15 @@ public class CloudHeightResource extends
.interrogate(new ReferencedCoordinate(location)); .interrogate(new ReferencedCoordinate(location));
if (interMap != null if (interMap != null
&& interMap.get(SATELLITE_DATA_INTERROGATE_ID) instanceof Measure && interMap.get(SATELLITE_DATA_INTERROGATE_ID) instanceof Measure
&& interMap && interMap.containsKey(IGridGeometryProvider.class
.containsKey(ISpatialObject.class.toString())) { .toString())) {
// Extract temperature values from the resource // Extract temperature values from the resource
float[] rscTemps = extractTemps(location, resource, float[] rscTemps = extractTemps(
(ISpatialObject) interMap.get(ISpatialObject.class location,
.toString())); resource,
((IGridGeometryProvider) interMap
.get(IGridGeometryProvider.class.toString()))
.getGridGeometry());
boolean good = true; boolean good = true;
for (int i = 0; i < rscTemps.length; ++i) { for (int i = 0; i < rscTemps.length; ++i) {
if (Float.isNaN(rscTemps[i])) { if (Float.isNaN(rscTemps[i])) {
@ -441,14 +447,39 @@ public class CloudHeightResource extends
return temps; return temps;
} }
private Coordinate convert(MathTransform mt, double[] point) {
try {
double[] out = new double[point.length];
mt.transform(point, 0, out, 0, 1);
return new Coordinate(out[0], out[1]);
} catch (Exception e) {
// Ingore and return null
}
return null;
}
private float[] extractTemps(Coordinate latLon, private float[] extractTemps(Coordinate latLon,
AbstractVizResource<?, ?> rsc, ISpatialObject spatialObject) { AbstractVizResource<?, ?> rsc, GridGeometry2D gridGeometry) {
// Method loosely ported from SatPVImageDepict.C::interogate // Method loosely ported from SatPVImageDepict.C::interogate
float[] temps = new float[] { Float.NaN, Float.NaN, Float.NaN, float[] temps = new float[] { Float.NaN, Float.NaN, Float.NaN,
Float.NaN }; Float.NaN };
Coordinate c = MapUtil.latLonToGridCoordinate(latLon, MathTransform gridToLatLon, latLonToGrid;
PixelOrientation.CENTER, spatialObject); try {
gridToLatLon = TransformFactory.gridToLatLon(gridGeometry,
PixelInCell.CELL_CENTER);
latLonToGrid = gridToLatLon.inverse();
} catch (Exception e) {
// Ignore and return early
return temps;
}
Coordinate c = convert(latLonToGrid,
new double[] { latLon.x, latLon.y });
if (c == null) {
return temps;
}
int x = (int) c.x; int x = (int) c.x;
int y = (int) c.y; int y = (int) c.y;
@ -471,8 +502,8 @@ public class CloudHeightResource extends
jj = y + j; jj = y + j;
for (i = xStart; i < xEnd; i++) { for (i = xStart; i < xEnd; i++) {
ii = x + i; ii = x + i;
elements[numElements++] = getTemperature(rsc, spatialObject, elements[numElements++] = getTemperature(rsc, gridToLatLon, ii,
ii, jj); jj);
} }
} }
@ -490,21 +521,20 @@ public class CloudHeightResource extends
} }
/** /**
* Interrogates the resource at the spatial object's gridX,gridY location * Interrogates the resource at the gridToLatLon transform, gridX,gridY
* and reads out the temperature value converting to * location and reads out the temperature value converting to
* {@link CloudHeightCalculatorPorted#ALGORITHM_UNIT} * {@link CloudHeightCalculatorPorted#ALGORITHM_UNIT}
* *
* @param resource * @param resource
* @param spatialObject * @param gridToLatLon
* @param gridX * @param gridX
* @param gridY * @param gridY
* @return * @return
*/ */
private double getTemperature(AbstractVizResource<?, ?> resource, private double getTemperature(AbstractVizResource<?, ?> resource,
ISpatialObject spatialObject, int gridX, int gridY) { MathTransform gridToLatLon, int gridX, int gridY) {
Coordinate latLon = MapUtil.gridCoordinateToLatLon(new Coordinate( return getTemperature(resource,
gridX, gridY), PixelOrientation.CENTER, spatialObject); convert(gridToLatLon, new double[] { gridX, gridY }));
return getTemperature(resource, latLon);
} }
/** /**
@ -521,16 +551,18 @@ public class CloudHeightResource extends
private double getTemperature(AbstractVizResource<?, ?> resource, private double getTemperature(AbstractVizResource<?, ?> resource,
Coordinate latLon) { Coordinate latLon) {
double temperature = Double.NaN; double temperature = Double.NaN;
try { if (latLon != null) {
Map<String, Object> dataMap = resource try {
.interrogate(new ReferencedCoordinate(latLon)); Map<String, Object> dataMap = resource
Object obj = dataMap.get(SATELLITE_DATA_INTERROGATE_ID); .interrogate(new ReferencedCoordinate(latLon));
if (obj instanceof Measure) { Object obj = dataMap.get(SATELLITE_DATA_INTERROGATE_ID);
temperature = getDataValue((Measure<?, ?>) obj, if (obj instanceof Measure) {
CloudHeightCalculatorPorted.ALGORITHM_UNIT); temperature = getDataValue((Measure<?, ?>) obj,
CloudHeightCalculatorPorted.ALGORITHM_UNIT);
}
} catch (VizException e) {
// Ignore
} }
} catch (VizException e) {
// Ignore
} }
return temperature; return temperature;
} }

View file

@ -46,17 +46,17 @@ import com.raytheon.uf.common.dataplugin.npp.viirs.VIIRSDataRecord;
import com.raytheon.uf.common.datastorage.Request; import com.raytheon.uf.common.datastorage.Request;
import com.raytheon.uf.common.datastorage.records.IDataRecord; import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.datastorage.records.ShortDataRecord; import com.raytheon.uf.common.datastorage.records.ShortDataRecord;
import com.raytheon.uf.common.geospatial.ISpatialObject; import com.raytheon.uf.common.geospatial.IGridGeometryProvider;
import com.raytheon.uf.common.geospatial.ReferencedCoordinate; import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
import com.raytheon.uf.common.geospatial.util.EnvelopeIntersection; import com.raytheon.uf.common.geospatial.util.EnvelopeIntersection;
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.common.style.LabelingPreferences; import com.raytheon.uf.common.style.LabelingPreferences;
import com.raytheon.uf.common.style.StyleException;
import com.raytheon.uf.common.style.StyleManager; import com.raytheon.uf.common.style.StyleManager;
import com.raytheon.uf.common.style.StyleManager.StyleType; import com.raytheon.uf.common.style.StyleManager.StyleType;
import com.raytheon.uf.common.style.StyleRule; import com.raytheon.uf.common.style.StyleRule;
import com.raytheon.uf.common.style.StyleException;
import com.raytheon.uf.common.style.image.DataScale; import com.raytheon.uf.common.style.image.DataScale;
import com.raytheon.uf.common.style.image.ImagePreferences; import com.raytheon.uf.common.style.image.ImagePreferences;
import com.raytheon.uf.common.time.DataTime; import com.raytheon.uf.common.time.DataTime;
@ -683,8 +683,7 @@ public class VIIRSResource extends
bestValue); bestValue);
} }
if (bestRecord != null) { if (bestRecord != null) {
interMap.put(ISpatialObject.class.toString(), interMap.put(IGridGeometryProvider.class.toString(), bestRecord);
bestRecord.getSpatialObject());
} }
} }

View file

@ -44,6 +44,7 @@ import org.geotools.coverage.grid.GridCoverageFactory;
import org.geotools.coverage.grid.GridGeometry2D; import org.geotools.coverage.grid.GridGeometry2D;
import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.satellite.SatMapCoverage;
import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord; import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint; import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType; import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType;
@ -246,16 +247,15 @@ public class SatelliteDataCubeAdapter extends DefaultDataCubeAdapter {
* used in derived parameter * used in derived parameter
*/ */
GridGeometry2D geo = null; GridGeometry2D geo = null;
if (!records.get(0).getSpatialObject().getNx() if (!records.get(0).getCoverage().getNx()
.equals(records.get(1).getSpatialObject().getNx()) .equals(records.get(1).getCoverage().getNx())
|| !records.get(0).getSpatialObject().getNy() || !records.get(0).getCoverage().getNy()
.equals(records.get(1).getSpatialObject().getNy())) { .equals(records.get(1).getCoverage().getNy())) {
interpolate = true; interpolate = true;
geo = MapUtil.getGridGeometry(records.get(largestRecIdx) SatMapCoverage coverage = records.get(largestRecIdx).getCoverage();
.getSpatialObject()); geo = coverage.getGridGeometry();
targetWidth = records.get(largestRecIdx).getSpatialObject().getNx(); targetWidth = coverage.getNx();
targetHeight = records.get(largestRecIdx).getSpatialObject() targetHeight = coverage.getNy();
.getNy();
} }
try { try {

View file

@ -38,11 +38,12 @@ import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters.PersistedParameters; import com.raytheon.uf.common.colormap.prefs.ColorMapParameters.PersistedParameters;
import com.raytheon.uf.common.colormap.prefs.DataMappingPreferences; import com.raytheon.uf.common.colormap.prefs.DataMappingPreferences;
import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.satellite.SatMapCoverage;
import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord; import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord;
import com.raytheon.uf.common.dataplugin.satellite.units.SatelliteUnits; import com.raytheon.uf.common.dataplugin.satellite.units.SatelliteUnits;
import com.raytheon.uf.common.dataplugin.satellite.units.generic.GenericPixel; import com.raytheon.uf.common.dataplugin.satellite.units.generic.GenericPixel;
import com.raytheon.uf.common.dataplugin.satellite.units.water.BlendedTPWPixel; import com.raytheon.uf.common.dataplugin.satellite.units.water.BlendedTPWPixel;
import com.raytheon.uf.common.geospatial.ISpatialObject; import com.raytheon.uf.common.geospatial.IGridGeometryProvider;
import com.raytheon.uf.common.geospatial.ReferencedCoordinate; import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
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;
@ -133,7 +134,7 @@ public class SatResource extends
private class SatRenderable implements IRenderable { private class SatRenderable implements IRenderable {
private Map<ISpatialObject, SatTileSetRenderable> tileMap = new HashMap<ISpatialObject, SatTileSetRenderable>(); private Map<SatMapCoverage, SatTileSetRenderable> tileMap = new HashMap<SatMapCoverage, SatTileSetRenderable>();
private DataTime renderableTime; private DataTime renderableTime;
@ -167,8 +168,8 @@ public class SatResource extends
public void addRecord(SatelliteRecord record) { public void addRecord(SatelliteRecord record) {
synchronized (tileMap) { synchronized (tileMap) {
SatTileSetRenderable tileSet = tileMap.get(record SatTileSetRenderable tileSet = tileMap
.getSpatialObject()); .get(record.getCoverage());
if (tileSet != null) { if (tileSet != null) {
SatelliteRecord existingRecord = tileSet SatelliteRecord existingRecord = tileSet
.getSatelliteRecord(); .getSatelliteRecord();
@ -192,7 +193,7 @@ public class SatResource extends
if (tileSet == null) { if (tileSet == null) {
tileSet = new SatTileSetRenderable(SatResource.this, record); tileSet = new SatTileSetRenderable(SatResource.this, record);
tileSet.project(descriptor.getGridGeometry()); tileSet.project(descriptor.getGridGeometry());
tileMap.put(record.getSpatialObject(), tileSet); tileMap.put(record.getCoverage(), tileSet);
} }
} }
} }
@ -394,8 +395,8 @@ public class SatResource extends
.asLatLon()); .asLatLon());
if (result != null) { if (result != null) {
dataValue = result.getValue(); dataValue = result.getValue();
dataMap.put(ISpatialObject.class.toString(), result dataMap.put(IGridGeometryProvider.class.toString(), result
.getRecord().getSpatialObject()); .getRecord().getCoverage());
} }
} catch (Exception e) { } catch (Exception e) {
throw new VizException("Error interrogating raw data", e); throw new VizException("Error interrogating raw data", e);

View file

@ -58,7 +58,7 @@ public class SatTileSetRenderable extends RecordTileSetRenderable {
public SatTileSetRenderable(AbstractVizResource<?, ?> resource, public SatTileSetRenderable(AbstractVizResource<?, ?> resource,
SatelliteRecord record) { SatelliteRecord record) {
// Total levels = Number of interpolation levels + base level // Total levels = Number of interpolation levels + base level
super(resource, record, record.getSpatialObject(), record super(resource, record, record.getGridGeometry(), record
.getInterpolationLevels() + 1); .getInterpolationLevels() + 1);
this.resource = resource; this.resource = resource;
} }
@ -68,8 +68,6 @@ public class SatTileSetRenderable extends RecordTileSetRenderable {
return new SatDataRetriever((SatelliteRecord) record, tile.tileLevel, return new SatDataRetriever((SatelliteRecord) record, tile.tileLevel,
tile.getRectangle()).getColorMapData(); tile.getRectangle()).getColorMapData();
} }
@Override @Override
protected void issueRefresh(IGraphicsTarget target) { protected void issueRefresh(IGraphicsTarget target) {

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.raytheon.uf.edex.upgrade.satellitespatial</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,7 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

View file

@ -0,0 +1,10 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Satellite Spatial Upgrade
Bundle-SymbolicName: com.raytheon.uf.edex.upgrade.satellitespatial
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: RAYTHEON
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Require-Bundle: org.postgres;bundle-version="9.2.0",
com.raytheon.uf.common.geospatial;bundle-version="1.12.1174",
com.raytheon.uf.common.serialization;bundle-version="1.12.1174"

View file

@ -0,0 +1,4 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.

View file

@ -0,0 +1,262 @@
/**
* 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.uf.edex.upgrade.satellitespatial;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.geotools.coverage.grid.GridEnvelope2D;
import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.geometry.Envelope2D;
import org.geotools.referencing.CRS;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.raytheon.uf.common.geospatial.ISpatialObject;
import com.raytheon.uf.common.geospatial.MapUtil;
import com.raytheon.uf.common.geospatial.util.EnvelopeIntersection;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.io.WKBReader;
/**
* Java application to update the satellite spatial table. Converts old spatial
* format into new format using crs space
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Sep 30, 2013 2333 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class UpdateSatSpatial {
private static final String SATELLITE_SPATIAL_TABLE = "satellite_spatial";
private static final String SATELLITE_SPATIAL_GID = "gid";
private static final String SATELLITE_SPATIAL_CRSWKT = "crswkt";
private static final String SATELLITE_SPATIAL_GEOM = "the_geom";
private static final String SATELLITE_SPATIAL_NX = "nx";
private static final String SATELLITE_SPATIAL_NY = "ny";
private static final String SATELLITE_SPATIAL_DX = "dx";
private static final String SATELLITE_SPATIAL_DY = "dy";
private static final String SATELLITE_SPATIAL_MINX = "minx";
private static final String SATELLITE_SPATIAL_MINY = "miny";
private static final String HOST_ARGUMENT = "-host";
private static final String DEFAULT_HOST = "localhost";
private static final String PORT_ARGUMENT = "-port";
private static final String DEFAULT_PORT = "5432";
private static final String USER_ARGUMENT = "-user";
private static final String DEFAULT_USER = "awips";
private static final String PASSWORD_ARGUMENT = "-password";
private static final String DEFAULT_PASSWORD = "awips";
private static final String DATABASE_ARGUMENT = "-database";
private static final String DEFAULT_DATABASE = "metadata";
private static final String JDBC_CONNECTION_FORMAT_STRING = "jdbc:postgresql://%s:%s/%s";
private static final String USER_PROPERTY = "user";
private static final String PASSWORD_PROPERTY = "password";
private static Map<String, Object> argumentMap = new HashMap<String, Object>();
private static class SpatialObject implements ISpatialObject {
private static final long serialVersionUID = 1L;
private final int nx;
private final int ny;
private final Geometry geometry;
private final CoordinateReferenceSystem crs;
public SpatialObject(int nx, int ny, Geometry geometry,
CoordinateReferenceSystem crs) {
this.nx = nx;
this.ny = ny;
this.geometry = geometry;
this.crs = crs;
}
@Override
public Geometry getGeometry() {
return geometry;
}
@Override
public CoordinateReferenceSystem getCrs() {
return crs;
}
@Override
public Integer getNx() {
return nx;
}
@Override
public Integer getNy() {
return ny;
}
}
public static void main(String[] args) throws Exception {
// Parse arguments
parseArguments(args);
Connection conn = openConnection();
Statement query = conn.createStatement();
ResultSet results = query.executeQuery("SELECT "
+ SATELLITE_SPATIAL_GID + ", " + SATELLITE_SPATIAL_CRSWKT
+ ", " + SATELLITE_SPATIAL_NX + ", " + SATELLITE_SPATIAL_NY
+ ", " + SATELLITE_SPATIAL_DX + ", " + SATELLITE_SPATIAL_DY
+ ", AsBinary(" + SATELLITE_SPATIAL_GEOM + ") as "
+ SATELLITE_SPATIAL_GEOM + " FROM " + SATELLITE_SPATIAL_TABLE);
String updateStatement = "UPDATE " + SATELLITE_SPATIAL_TABLE + " SET ("
+ SATELLITE_SPATIAL_MINX + ", " + SATELLITE_SPATIAL_MINY + ", "
+ SATELLITE_SPATIAL_DX + ", " + SATELLITE_SPATIAL_DY + ", "
+ SATELLITE_SPATIAL_GEOM
+ ") = (?, ?, ?, ?, GeomFromText(? , -1)) WHERE "
+ SATELLITE_SPATIAL_GID + " = ?";
while (results.next()) {
int gid = results.getInt(SATELLITE_SPATIAL_GID);
Geometry geometry = new WKBReader().read(results
.getBytes(SATELLITE_SPATIAL_GEOM));
CoordinateReferenceSystem crs = CRS.parseWKT(results
.getString(SATELLITE_SPATIAL_CRSWKT));
int nx = results.getInt(SATELLITE_SPATIAL_NX);
int ny = results.getInt(SATELLITE_SPATIAL_NY);
double dx = results.getDouble(SATELLITE_SPATIAL_DX);
double dy = results.getDouble(SATELLITE_SPATIAL_DY);
ISpatialObject object = new SpatialObject(nx, ny, geometry, crs);
GridGeometry2D resultGeom = MapUtil.getGridGeometry(object);
Envelope2D env = resultGeom.getEnvelope2D();
GridEnvelope2D grid = resultGeom.getGridRange2D();
double minX = env.getMinX();
double minY = env.getMinY();
if (dx == 0.0) {
dx = env.getWidth() / grid.width;
}
if (dy == 0.0) {
dy = env.getHeight() / grid.height;
}
Geometry newGeom = EnvelopeIntersection.createEnvelopeIntersection(
resultGeom.getEnvelope(),
new Envelope2D(DefaultGeographicCRS.WGS84, -180, -90, 360,
180), 1.0, 10, 10).getEnvelope();
PreparedStatement update = conn.prepareStatement(updateStatement);
int index = 1;
update.setDouble(index++, minX);
update.setDouble(index++, minY);
update.setDouble(index++, dx);
update.setDouble(index++, dy);
update.setString(index++, newGeom.toText());
update.setInt(index++, gid);
update.execute();
}
conn.close();
}
private static Connection openConnection() throws SQLException {
String host = getString(HOST_ARGUMENT, DEFAULT_HOST);
String port = getString(PORT_ARGUMENT, DEFAULT_PORT);
String database = getString(DATABASE_ARGUMENT, DEFAULT_DATABASE);
String user = getString(USER_ARGUMENT, DEFAULT_USER);
String password = getString(PASSWORD_ARGUMENT, DEFAULT_PASSWORD);
DriverManager.registerDriver(new org.postgresql.Driver());
String connectionURL = String.format(JDBC_CONNECTION_FORMAT_STRING,
host, port, database);
Properties props = new Properties();
props.setProperty(USER_PROPERTY, user);
props.setProperty(PASSWORD_PROPERTY, password);
return DriverManager.getConnection(connectionURL, props);
}
private static void parseArguments(String[] args) {
for (int i = 0; i < args.length; ++i) {
String arg = args[i];
if (arg.startsWith("-")) {
// we have a key
if (args.length > (i + 1)
&& args[i + 1].startsWith("-") == false) {
argumentMap.put(arg, args[i + 1]);
++i;
} else {
argumentMap.put(arg, true);
}
}
}
}
private static String getString(String key, String defaultValue) {
Object val = argumentMap.get(key);
if (val != null) {
return val.toString();
}
return defaultValue;
}
}

View file

@ -0,0 +1,16 @@
#!/bin/bash
# This script is needed for DR 2333 for GOES-R readiness. The satellite spatial table needed to be refactored to store data to construct
# GridGeometry2D in CRS space instead of lat/lon due to the geostationary projection corner points not being valid in lat/lon space.
DIR=`dirname $0`
PSQL="/awips2/psql/bin/psql"
JAVA="/awips2/java/bin/java"
# Update columns on tables for satellite
${PSQL} -U awips -d metadata -c "ALTER TABLE satellite DROP COLUMN upperrightlat, DROP COLUMN upperrightlon;"
${PSQL} -U awips -d metadata -c "ALTER TABLE satellite_spatial DROP COLUMN la1, DROP COLUMN la2, DROP COLUMN latin, DROP COLUMN lo1, DROP COLUMN lo2, DROP COLUMN lov;"
${PSQL} -U awips -d metadata -c "ALTER TABLE satellite_spatial ADD COLUMN minx double precision, ADD COLUMN miny double precision;"
# Run application to convert sat spatial entries to use crs space
${JAVA} -jar update_satellite_spatial.jar

View file

@ -238,7 +238,7 @@ public class D2DSatParm {
physicalElement, timeRanges); physicalElement, timeRanges);
for (int i = 0; i < satRecords.size(); i++) { for (int i = 0; i < satRecords.size(); i++) {
GridLocation satGridLoc = new GridLocation(this.pid.toString(), GridLocation satGridLoc = new GridLocation(this.pid.toString(),
satRecords.get(i).getCoverage()); satRecords.get(i));
ByteDataRecord hdf5Record = (ByteDataRecord) satRecords.get(i) ByteDataRecord hdf5Record = (ByteDataRecord) satRecords.get(i)
.getMessageData(); .getMessageData();
Grid2DByte rawData = new Grid2DByte( Grid2DByte rawData = new Grid2DByte(

View file

@ -22,9 +22,6 @@ Require-Bundle: com.raytheon.uf.common.dataplugin;bundle-version="1.12.1174",
com.raytheon.uf.common.awipstools;bundle-version="1.12.1174", com.raytheon.uf.common.awipstools;bundle-version="1.12.1174",
com.raytheon.uf.edex.core;bundle-version="1.12.1174", com.raytheon.uf.edex.core;bundle-version="1.12.1174",
com.raytheon.uf.edex.database;bundle-version="1.0.0", com.raytheon.uf.edex.database;bundle-version="1.0.0",
com.raytheon.uf.edex.menus;bundle-version="1.0.0", com.raytheon.uf.edex.menus;bundle-version="1.0.0"
org.springframework;bundle-version="3.1.4",
javax.persistence;bundle-version="1.0.0",
org.hibernate;bundle-version="1.0.0"
Import-Package: com.raytheon.edex.exception, Import-Package: com.raytheon.edex.exception,
org.apache.commons.logging org.apache.commons.logging

View file

@ -345,21 +345,11 @@ public class SatelliteDecoder {
// get the scanning mode // get the scanning mode
scanMode = byteBuffer.get(37); scanMode = byteBuffer.get(37);
// Get latitude of upper right hand corner
byteBuffer.position(55);
byteBuffer.get(threeBytesArray, 0, 3);
record.setUpperRightLat(transformLatitude(threeBytesArray));
// Get longitude of upper right hand corner
byteBuffer.position(58);
byteBuffer.get(threeBytesArray, 0, 3);
record.setUpperRightLon(transformLongitude(threeBytesArray));
float dx = 0.0f, dy = 0.0f, lov = 0.0f, lo2 = 0.0f, la2 = 0.0f; float dx = 0.0f, dy = 0.0f, lov = 0.0f, lo2 = 0.0f, la2 = 0.0f;
// Do specialized decoding and retrieve spatial data for Lambert // Do specialized decoding and retrieve spatial data for Lambert
// Conformal and Polar Stereographic projections // Conformal and Polar Stereographic projections
if ((mapProjection == SatMapCoverage.PROJ_LAMBERT) if ((mapProjection == SatSpatialFactory.PROJ_LAMBERT)
|| (mapProjection == SatMapCoverage.PROJ_POLAR_STEREO)) { || (mapProjection == SatSpatialFactory.PROJ_POLAR)) {
byteBuffer.position(30); byteBuffer.position(30);
byteBuffer.get(threeBytesArray, 0, 3); byteBuffer.get(threeBytesArray, 0, 3);
dx = byteArrayToFloat(threeBytesArray) / 10; dx = byteArrayToFloat(threeBytesArray) / 10;
@ -372,11 +362,9 @@ public class SatelliteDecoder {
byteBuffer.get(threeBytesArray, 0, 3); byteBuffer.get(threeBytesArray, 0, 3);
lov = transformLongitude(threeBytesArray); lov = transformLongitude(threeBytesArray);
} }
// Do specialized decoding and retrieve spatial data for // Do specialized decoding and retrieve spatial data for
// Mercator // Mercator projection
// projection else if (mapProjection == SatSpatialFactory.PROJ_MERCATOR) {
else if (mapProjection == SatMapCoverage.PROJ_MERCATOR) {
dx = byteBuffer.getShort(33); dx = byteBuffer.getShort(33);
dy = byteBuffer.getShort(35); dy = byteBuffer.getShort(35);
@ -400,7 +388,7 @@ public class SatelliteDecoder {
* This is a temporary workaround for DR14724, hopefully to * This is a temporary workaround for DR14724, hopefully to
* be removed after NESDIS changes the product header * be removed after NESDIS changes the product header
*/ */
if ((mapProjection == SatMapCoverage.PROJ_LAMBERT) if ((mapProjection == SatSpatialFactory.PROJ_LAMBERT)
&& (record.getPhysicalElement() && (record.getPhysicalElement()
.equalsIgnoreCase("Imager 13 micron (IR)")) .equalsIgnoreCase("Imager 13 micron (IR)"))
&& (record.getSectorID() && (record.getSectorID()

View file

@ -27,7 +27,6 @@ import com.raytheon.uf.common.dataplugin.satellite.SatMapCoverage;
import com.raytheon.uf.edex.database.DataAccessLayerException; import com.raytheon.uf.edex.database.DataAccessLayerException;
import com.raytheon.uf.edex.database.dao.CoreDao; import com.raytheon.uf.edex.database.dao.CoreDao;
import com.raytheon.uf.edex.database.dao.DaoConfig; import com.raytheon.uf.edex.database.dao.DaoConfig;
import com.raytheon.uf.edex.database.query.DatabaseQuery;
/** /**
* The dao implementation associated with the SatelliteMapCoverage class used * The dao implementation associated with the SatelliteMapCoverage class used
@ -41,8 +40,9 @@ import com.raytheon.uf.edex.database.query.DatabaseQuery;
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* 7/24/07 353 bphillip Initial Check in * 7/24/07 353 bphillip Initial Check in
* - AWIPS2 Baseline Repository -------- * - AWIPS2 Baseline Repository --------
* 06/27/2012 798 jkorman Corrected id query type. * 06/27/2012 798 jkorman Corrected id query type.
* * 10/02/2013 2333 mschenke Removed unused code
*
* </pre> * </pre>
* *
* @author bphillip * @author bphillip
@ -105,81 +105,4 @@ public class SatMapCoverageDao extends CoreDao {
return (List<SatMapCoverage>) queryByCriteria(fields, values); return (List<SatMapCoverage>) queryByCriteria(fields, values);
} }
/**
* Retrieves a map projection based on the given criteria
*
* @param mapProjection
* The map projection 1=Mercator 3=Lambert Conformal 5=Polar
* Stereographic
* @param nx
* Number of points along the x-axis
* @param ny
* Number of points along the y-axis
* @param dx
* The horizontal resolution of the grid
* @param dy
* The vertical resolution of the grid
* @param lov
* The orientation of the grid
* @param latin
* The tangent latitude
* @param la1
* The latitude of the first grid point
* @param lo1
* The longitude of the first grid point
* @param la2
* The latitude of the last grid point (only used with Mercator
* projection)
* @param lo2
* The longitude of the last grid opint (only used with Mercaotr
* projection)
* @return The SatMapCoverage object matching the given criteria
*/
@SuppressWarnings("unchecked")
public SatMapCoverage getSatCoverage(Integer mapProjection, Integer nx,
Integer ny, Float dx, Float dy, Float lov, Float latin, Float la1,
Float lo1, Float la2, Float lo2) throws DataAccessLayerException{
List<SatMapCoverage> queryResults = null;
List<String> fields = new ArrayList<String>();
List<Object> values = new ArrayList<Object>();
DatabaseQuery query = new DatabaseQuery(daoClass.getName());
query.addQueryParam("projection", mapProjection);
query.addQueryParam("nx",nx);
query.addQueryParam("ny",ny);
query.addQueryParam("dx",dx);
query.addQueryParam("dy",dy);
query.addQueryParam("lov",lov);
query.addQueryParam("latin",latin);
query.addQueryParam("la1",la1);
query.addQueryParam("lo1",lo1);
if (mapProjection == SatMapCoverage.PROJ_MERCATOR) {
query.addQueryParam("la2",la2);
query.addQueryParam("lo2",lo2);
}
queryResults = (List<SatMapCoverage>) queryByCriteria(query);
if (queryResults != null) {
if (queryResults.size() > 1) {
StringBuffer out = new StringBuffer();
out
.append("Multiple map coverages return using the following criteria: [");
for (int i = 0; i < fields.size(); i++) {
out.append(fields.get(i)).append("=").append(values.get(i))
.append(" ");
}
out.append("] -- Using first result");
logger.debug(out.toString());
}
if (queryResults.size() >= 1) {
return queryResults.get(0);
} else {
return null;
}
} else {
return null;
}
}
} }

View file

@ -46,7 +46,6 @@ import com.raytheon.uf.common.datastorage.StorageProperties;
import com.raytheon.uf.common.datastorage.records.ByteDataRecord; import com.raytheon.uf.common.datastorage.records.ByteDataRecord;
import com.raytheon.uf.common.datastorage.records.IDataRecord; import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.datastorage.records.ShortDataRecord; import com.raytheon.uf.common.datastorage.records.ShortDataRecord;
import com.raytheon.uf.common.geospatial.MapUtil;
import com.raytheon.uf.common.geospatial.interpolation.GridDownscaler; import com.raytheon.uf.common.geospatial.interpolation.GridDownscaler;
import com.raytheon.uf.common.geospatial.interpolation.data.AbstractDataWrapper; import com.raytheon.uf.common.geospatial.interpolation.data.AbstractDataWrapper;
import com.raytheon.uf.common.geospatial.interpolation.data.ByteArrayWrapper; import com.raytheon.uf.common.geospatial.interpolation.data.ByteArrayWrapper;
@ -152,7 +151,7 @@ public class SatelliteDao extends PluginDao {
coverage.getNx(), coverage.getNy()); coverage.getNx(), coverage.getNy());
dataSource.setFillValue(fillValue); dataSource.setFillValue(fillValue);
GridDownscaler downScaler = new GridDownscaler( GridDownscaler downScaler = new GridDownscaler(
MapUtil.getGridGeometry(coverage)); coverage.getGridGeometry());
// How many interpolation levels do we need for this data? // How many interpolation levels do we need for this data?
int levels = downScaler.getNumberOfDownscaleLevels(); int levels = downScaler.getNumberOfDownscaleLevels();

View file

@ -23,6 +23,7 @@ package com.raytheon.edex.util.satellite;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.geotools.geometry.DirectPosition2D; import org.geotools.geometry.DirectPosition2D;
import org.geotools.geometry.jts.JTS;
import org.opengis.referencing.crs.ProjectedCRS; import org.opengis.referencing.crs.ProjectedCRS;
import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.MathTransform;
@ -30,8 +31,10 @@ import com.raytheon.edex.plugin.satellite.dao.SatMapCoverageDao;
import com.raytheon.uf.common.dataplugin.satellite.SatMapCoverage; import com.raytheon.uf.common.dataplugin.satellite.SatMapCoverage;
import com.raytheon.uf.common.geospatial.MapUtil; import com.raytheon.uf.common.geospatial.MapUtil;
import com.raytheon.uf.edex.database.DataAccessLayerException; import com.raytheon.uf.edex.database.DataAccessLayerException;
import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.io.WKTReader; import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Polygon;
/** /**
* *
@ -43,18 +46,34 @@ import com.vividsolutions.jts.io.WKTReader;
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* 12/19/07 439 bphillip Initial creation * 12/19/07 439 bphillip Initial creation
* - AWIPS2 Baseline Repository -------- * - AWIPS2 Baseline Repository --------
* 07/12/2012 798 jkorman Changed projection "magic" numbers * 07/12/2012 798 jkorman Changed projection "magic" numbers
* * 09/30/2013 2333 mschenke Refactored to store points in crs space
* </pre> * </pre>
*/ */
public class SatSpatialFactory { public class SatSpatialFactory {
// TODO: These constants should be in the GINI decoder since they are only
// related to the GINI format and should not be stored in SatMapCoverage.
// Can't do this now as ncep has code that checks projection number to
// determine how code should flow.
public static final int PROJ_MERCATOR = 1;
public static final int PROJ_LAMBERT = 3;
public static final int PROJ_POLAR = 5;
public static final int PROJ_CYLIN_EQUIDISTANT = 7;
public static final int UNDEFINED = -1;
/** The logger */ /** The logger */
private Log logger = LogFactory.getLog(getClass()); private Log logger = LogFactory.getLog(getClass());
/** The singleton instance */ /** The singleton instance */
private static SatSpatialFactory instance; private static SatSpatialFactory instance;
private SatMapCoverageDao satDao = new SatMapCoverageDao();
/** /**
* Gets the singleton instance * Gets the singleton instance
* *
@ -98,39 +117,24 @@ public class SatSpatialFactory {
* If errors occur during db interaction or creation of the * If errors occur during db interaction or creation of the
* coverage object * coverage object
*/ */
public synchronized SatMapCoverage getMapCoverage( public synchronized SatMapCoverage getMapCoverage(Integer mapProjection,
Integer mapProjection, Integer nx, Integer ny, Float dx, Float dy, Integer nx, Integer ny, Float dx, Float dy, Float lov, Float latin,
Float lov, Float latin, Float la1, Float lo1, Float la2, Float lo2) Float la1, Float lo1, Float la2, Float lo2) throws Exception {
throws Exception {
SatMapCoverage mapCoverage = null;
SatMapCoverageDao satDao = new SatMapCoverageDao();
try { try {
// Check the database to see if a coverage already exists SatMapCoverage mapCoverage = createMapCoverage(mapProjection, nx,
mapCoverage = satDao.getSatCoverage(mapProjection, nx, ny, dx, dy, ny, dx, dy, lov, latin, la1, lo1, la2, lo2);
lov, latin, la1, lo1, la2, lo2); SatMapCoverage persisted = satDao
.queryByMapId(mapCoverage.getGid());
// If the database does not contain an existing sat map coverage for if (persisted == null) {
// the given values, create one persisted = mapCoverage;
if (mapCoverage == null) { satDao.persist(persisted);
mapCoverage = createMapCoverage(mapProjection, nx, ny, dx, dy,
lov, latin, la1, lo1, la2, lo2);
// Persist the new coverage to the database
satDao.persist(mapCoverage);
} }
return persisted;
} catch (Exception e) { } catch (Exception e) {
throw new DataAccessLayerException( throw new DataAccessLayerException(
"Unable to retrieve or construct valid Satellite Map Coverage", "Unable to retrieve or construct valid Satellite Map Coverage",
e); e);
} }
if (mapCoverage == null) {
throw new DataAccessLayerException(
"Unable to retrieve or construct valid Satellite Map Coverage");
}
return mapCoverage;
} }
/** /**
@ -173,16 +177,20 @@ public class SatSpatialFactory {
ProjectedCRS crs = null; ProjectedCRS crs = null;
// Get the correct CRS // Get the correct CRS
if (mapProjection == SatMapCoverage.PROJ_MERCATOR) { if (mapProjection == PROJ_MERCATOR) {
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;
} }
crs = MapUtil.constructMercator(MapUtil.AWIPS_EARTH_RADIUS, crs = MapUtil.constructMercator(MapUtil.AWIPS_EARTH_RADIUS,
MapUtil.AWIPS_EARTH_RADIUS, latin, cm); MapUtil.AWIPS_EARTH_RADIUS, latin, cm);
} else if (mapProjection == 3) { } else if (mapProjection == PROJ_LAMBERT) {
crs = MapUtil.constructLambertConformal(MapUtil.AWIPS_EARTH_RADIUS, crs = MapUtil.constructLambertConformal(MapUtil.AWIPS_EARTH_RADIUS,
MapUtil.AWIPS_EARTH_RADIUS, latin, latin, lov); MapUtil.AWIPS_EARTH_RADIUS, latin, latin, lov);
} else if (mapProjection == SatSpatialFactory.PROJ_CYLIN_EQUIDISTANT) {
crs = MapUtil.constructEquidistantCylindrical(
MapUtil.AWIPS_EARTH_RADIUS, MapUtil.AWIPS_EARTH_RADIUS,
lov, latin);
} else { } else {
crs = MapUtil.constructNorthPolarStereo(MapUtil.AWIPS_EARTH_RADIUS, crs = MapUtil.constructNorthPolarStereo(MapUtil.AWIPS_EARTH_RADIUS,
MapUtil.AWIPS_EARTH_RADIUS, 60, lov); MapUtil.AWIPS_EARTH_RADIUS, 60, lov);
@ -201,7 +209,7 @@ public class SatSpatialFactory {
* Projection is Mercator. Determine corner points from la1,lo1,la2,lo2 * Projection is Mercator. Determine corner points from la1,lo1,la2,lo2
* provided in the satellite file * provided in the satellite file
*/ */
if (mapProjection == SatMapCoverage.PROJ_MERCATOR) { if (mapProjection == PROJ_MERCATOR) {
logger.debug("Determining corner points for Mercator projection"); logger.debug("Determining corner points for Mercator projection");
corner1.x = lo1; corner1.x = lo1;
corner1.y = la1; corner1.y = la1;
@ -214,15 +222,13 @@ public class SatSpatialFactory {
corner4.x = lo1; corner4.x = lo1;
corner4.y = la2; corner4.y = la2;
} }
/* /*
* Projection is Lambert Conformal or Polar Stereographic. Therefore, * Projection is Lambert Conformal or Polar Stereographic. Therefore,
* the corner points must be calculated * the corner points must be calculated
*/ */
else { else {
logger logger.debug("Determining corner points for Lambert Conformal or Polar Stereographic projection");
.debug("Determining corner points for Lambert Conformal or Polar Stereographic projection");
// Get the transforms to be used to convert between meters and // Get the transforms to be used to convert between meters and
// lat/lon // lat/lon
@ -235,12 +241,12 @@ public class SatSpatialFactory {
// Determine the 3 other corner points using the given dx,dy,nx, and // Determine the 3 other corner points using the given dx,dy,nx, and
// ny in meters // ny in meters
secondPosition = new DirectPosition2D(dx * nx + firstPosition.x, secondPosition = new DirectPosition2D(firstPosition.x + (dx * nx),
firstPosition.y); firstPosition.y);
thirdPosition = new DirectPosition2D(dx * nx + firstPosition.x, dy thirdPosition = new DirectPosition2D(secondPosition.x,
* ny + firstPosition.y); firstPosition.y + (dy * ny));
fourthPosition = new DirectPosition2D(firstPosition.x, dx * ny fourthPosition = new DirectPosition2D(firstPosition.x,
+ firstPosition.y); thirdPosition.y);
// Convert the corner points from meters to lat/lon // Convert the corner points from meters to lat/lon
toLatLon.transform(firstPosition, corner1); toLatLon.transform(firstPosition, corner1);
@ -249,23 +255,31 @@ public class SatSpatialFactory {
toLatLon.transform(fourthPosition, corner4); toLatLon.transform(fourthPosition, corner4);
} }
// Construct the polygon constructor String double[] c = corner1.getCoordinate();
StringBuffer buffer = new StringBuffer(); Coordinate c1 = new Coordinate(c[0], c[1]);
buffer.append("POLYGON(("); c = corner2.getCoordinate();
buffer.append(corner1.x + " " + corner1.y + ","); Coordinate c2 = new Coordinate(c[0], c[1]);
buffer.append(corner2.x + " " + corner2.y + ","); c = corner3.getCoordinate();
buffer.append(corner3.x + " " + corner3.y + ","); Coordinate c3 = new Coordinate(c[0], c[1]);
buffer.append(corner4.x + " " + corner4.y + ","); c = corner4.getCoordinate();
buffer.append(corner1.x + " " + corner1.y); Coordinate c4 = new Coordinate(c[0], c[1]);
buffer.append("))");
// Create the geometry from the constructed String // Go from lat/lon to crs space to get minX,minY in crs space
Geometry geometry = new WKTReader().read(buffer.toString()); GeometryFactory gf = new GeometryFactory();
Polygon polygon = gf.createPolygon(
gf.createLinearRing(new Coordinate[] { c1, c2, c3, c4, c1 }),
null);
MathTransform fromLatLon = MapUtil.getTransformFromLatLon(crs);
SatMapCoverage mapCoverage = new SatMapCoverage(mapProjection, polygon = (Polygon) JTS.transform(polygon, fromLatLon);
nx, ny, dx, dy, lov, latin, la1, lo1, la2, lo2, crs, geometry); Envelope env = polygon.getEnvelopeInternal();
if (mapProjection == PROJ_MERCATOR) {
return mapCoverage; // Calculate dx/dy in mercator crs space
dx = (float) (env.getWidth() / nx);
dy = (float) (env.getHeight() / ny);
}
return new SatMapCoverage(mapProjection, env.getMinX(), env.getMinY(),
nx, ny, dx, dy, crs);
} }
} }

View file

@ -46,7 +46,9 @@ import jep.INumpyable;
import org.geotools.coverage.grid.GeneralGridEnvelope; import org.geotools.coverage.grid.GeneralGridEnvelope;
import org.geotools.coverage.grid.GridGeometry2D; import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.geometry.Envelope2D;
import org.geotools.geometry.GeneralEnvelope; import org.geotools.geometry.GeneralEnvelope;
import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.GeodeticCalculator; import org.geotools.referencing.GeodeticCalculator;
import org.geotools.referencing.operation.DefaultMathTransformFactory; import org.geotools.referencing.operation.DefaultMathTransformFactory;
import org.geotools.referencing.operation.builder.GridToEnvelopeMapper; import org.geotools.referencing.operation.builder.GridToEnvelopeMapper;
@ -68,6 +70,7 @@ import com.raytheon.uf.common.dataplugin.gfe.reference.ReferenceData.CoordinateT
import com.raytheon.uf.common.dataplugin.gfe.reference.ReferenceID; import com.raytheon.uf.common.dataplugin.gfe.reference.ReferenceID;
import com.raytheon.uf.common.dataplugin.persist.PersistableDataObject; import com.raytheon.uf.common.dataplugin.persist.PersistableDataObject;
import com.raytheon.uf.common.geospatial.CRSCache; import com.raytheon.uf.common.geospatial.CRSCache;
import com.raytheon.uf.common.geospatial.IGridGeometryProvider;
import com.raytheon.uf.common.geospatial.ISpatialObject; import com.raytheon.uf.common.geospatial.ISpatialObject;
import com.raytheon.uf.common.geospatial.MapUtil; import com.raytheon.uf.common.geospatial.MapUtil;
import com.raytheon.uf.common.serialization.ISerializableObject; import com.raytheon.uf.common.serialization.ISerializableObject;
@ -102,6 +105,7 @@ import com.vividsolutions.jts.simplify.TopologyPreservingSimplifier;
* spatial * spatial
* 08/06/13 #1571 randerso Added hibernate annotations, javadoc cleanup, * 08/06/13 #1571 randerso Added hibernate annotations, javadoc cleanup,
* made init method public for use in GFEDao * made init method public for use in GFEDao
* 09/30/13 #2333 mschenke Added method to construct from {@link IGridGeometryProvider}
* *
* *
* </pre> * </pre>
@ -372,6 +376,36 @@ public class GridLocation extends PersistableDataObject<String> implements
this.ny = coverage.getNy(); this.ny = coverage.getNy();
} }
/**
* @param id
* @param provider
*/
public GridLocation(String id, IGridGeometryProvider provider) {
this.siteId = id;
GridGeometry2D gridGeometry = provider.getGridGeometry();
this.crsObject = gridGeometry.getCoordinateReferenceSystem();
this.crsWKT = this.crsObject.toWKT();
this.nx = gridGeometry.getGridRange().getSpan(0);
this.ny = gridGeometry.getGridRange().getSpan(1);
Envelope2D envelope = gridGeometry.getEnvelope2D();
Coordinate ul = new Coordinate(envelope.getMinX(), envelope.getMinY());
Coordinate ur = new Coordinate(envelope.getMaxX(), envelope.getMinY());
Coordinate lr = new Coordinate(envelope.getMaxX(), envelope.getMaxY());
Coordinate ll = new Coordinate(envelope.getMinX(), envelope.getMaxY());
GeometryFactory gf = new GeometryFactory();
Geometry crsPolygon = gf.createPolygon(
gf.createLinearRing(new Coordinate[] { ul, ur, lr, ll, ul }),
null);
try {
MathTransform crsToLL = MapUtil.getTransformToLatLon(crsObject);
this.geometry = (Polygon) JTS.transform(crsPolygon, crsToLL);
} catch (Exception e) {
throw new IllegalArgumentException(
"GridGeometry provided does not support conversion to lat/lon");
}
}
/** /**
* @param id * @param id
* @param gloc * @param gloc

View file

@ -33,14 +33,14 @@ import javax.persistence.SequenceGenerator;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.UniqueConstraint; import javax.persistence.UniqueConstraint;
import org.geotools.coverage.grid.GridGeometry2D;
import org.hibernate.annotations.Index; import org.hibernate.annotations.Index;
import com.raytheon.uf.common.dataplugin.IDecoderGettable; import com.raytheon.uf.common.dataplugin.IDecoderGettable;
import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.annotations.DataURI; import com.raytheon.uf.common.dataplugin.annotations.DataURI;
import com.raytheon.uf.common.dataplugin.persist.PersistablePluginDataObject; import com.raytheon.uf.common.dataplugin.persist.PersistablePluginDataObject;
import com.raytheon.uf.common.geospatial.ISpatialEnabled; import com.raytheon.uf.common.geospatial.IGridGeometryProvider;
import com.raytheon.uf.common.geospatial.ISpatialObject;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
@ -77,7 +77,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
"refTime", "forecastTime" }) }) "refTime", "forecastTime" }) })
@DynamicSerialize @DynamicSerialize
public class VIIRSDataRecord extends PersistablePluginDataObject implements public class VIIRSDataRecord extends PersistablePluginDataObject implements
ISpatialEnabled { IGridGeometryProvider {
public static final String MISSING_VALUE_ID = "missing_value"; public static final String MISSING_VALUE_ID = "missing_value";
@ -130,11 +130,12 @@ public class VIIRSDataRecord extends PersistablePluginDataObject implements
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see com.raytheon.uf.common.geospatial.ISpatialEnabled#getSpatialObject() * @see
* com.raytheon.uf.common.geospatial.IGridGeometryProvider#getGridGeometry()
*/ */
@Override @Override
public ISpatialObject getSpatialObject() { public GridGeometry2D getGridGeometry() {
return coverage; return coverage != null ? coverage.getGridGeometry() : null;
} }
/** /**

View file

@ -31,13 +31,13 @@ import javax.persistence.Transient;
import org.geotools.coverage.grid.GeneralGridEnvelope; import org.geotools.coverage.grid.GeneralGridEnvelope;
import org.geotools.coverage.grid.GridGeometry2D; import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.geometry.GeneralEnvelope; import org.geotools.geometry.GeneralEnvelope;
import org.hibernate.annotations.Index;
import org.opengis.referencing.FactoryException; import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.hibernate.annotations.Index;
import com.raytheon.uf.common.dataplugin.npp.viirs.projection.VIIRSMapProjectionFactory; import com.raytheon.uf.common.dataplugin.npp.viirs.projection.VIIRSMapProjectionFactory;
import com.raytheon.uf.common.dataplugin.persist.PersistableDataObject; import com.raytheon.uf.common.dataplugin.persist.PersistableDataObject;
import com.raytheon.uf.common.geospatial.ISpatialObject; import com.raytheon.uf.common.geospatial.IGridGeometryProvider;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
import com.raytheon.uf.common.time.DataTime; import com.raytheon.uf.common.time.DataTime;
@ -67,15 +67,11 @@ import com.vividsolutions.jts.geom.Geometry;
* Both refTime and forecastTime are included in the refTimeIndex since * Both refTime and forecastTime are included in the refTimeIndex since
* forecastTime is unlikely to be used. * forecastTime is unlikely to be used.
*/ */
@org.hibernate.annotations.Table( @org.hibernate.annotations.Table(appliesTo = "viirs_spatial", indexes = { @Index(name = "viirs_spatial_refTimeIndex", columnNames = {
appliesTo = "viirs_spatial", "refTime", "forecastTime" }) })
indexes = {
@Index(name = "viirs_spatial_refTimeIndex", columnNames = { "refTime", "forecastTime" } )
}
)
@DynamicSerialize @DynamicSerialize
public class VIIRSSpatialCoverage extends PersistableDataObject implements public class VIIRSSpatialCoverage extends PersistableDataObject implements
ISpatialObject { IGridGeometryProvider {
private static final long serialVersionUID = -2532225158997059309L; private static final long serialVersionUID = -2532225158997059309L;
@ -127,22 +123,6 @@ public class VIIRSSpatialCoverage extends PersistableDataObject implements
@DynamicSerializeElement @DynamicSerializeElement
private Geometry envelope; private Geometry envelope;
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.common.geospatial.ISpatialObject#getGeometry()
*/
@Override
public Geometry getGeometry() {
return envelope;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.common.geospatial.ISpatialObject#getCrs()
*/
@Override
public CoordinateReferenceSystem getCrs() { public CoordinateReferenceSystem getCrs() {
if (crs == null) { if (crs == null) {
try { try {
@ -210,22 +190,16 @@ public class VIIRSSpatialCoverage extends PersistableDataObject implements
this.directions = directions; this.directions = directions;
} }
/* /**
* (non-Javadoc) * @return the nx
*
* @see com.raytheon.uf.common.geospatial.ISpatialObject#getNx()
*/ */
@Override
public Integer getNx() { public Integer getNx() {
return nx; return nx;
} }
/* /**
* (non-Javadoc) * @return the ny
*
* @see com.raytheon.uf.common.geospatial.ISpatialObject#getNy()
*/ */
@Override
public Integer getNy() { public Integer getNy() {
return ny; return ny;
} }

View file

@ -4,7 +4,7 @@ Bundle-Name: Satellite Common
Bundle-SymbolicName: com.raytheon.uf.common.dataplugin.satellite Bundle-SymbolicName: com.raytheon.uf.common.dataplugin.satellite
Bundle-Version: 1.0.0.qualifier Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: RAYTHEON Bundle-Vendor: RAYTHEON
Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization, com.raytheon.uf.viz.core Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization
Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Require-Bundle: com.raytheon.uf.common.dataplugin;bundle-version="1.12.1174", Require-Bundle: com.raytheon.uf.common.dataplugin;bundle-version="1.12.1174",
com.raytheon.uf.common.serialization;bundle-version="1.12.1174", com.raytheon.uf.common.serialization;bundle-version="1.12.1174",

View file

@ -20,8 +20,9 @@
package com.raytheon.uf.common.dataplugin.satellite; package com.raytheon.uf.common.dataplugin.satellite;
import java.awt.geom.Rectangle2D;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.Table; import javax.persistence.Table;
@ -32,18 +33,26 @@ import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.HashCodeBuilder;
import org.geotools.coverage.grid.GridEnvelope2D;
import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.geometry.Envelope2D;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.hibernate.annotations.Type; import org.hibernate.annotations.Type;
import org.opengis.coverage.grid.GridEnvelope;
import org.opengis.geometry.Envelope;
import org.opengis.referencing.FactoryException; import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.raytheon.uf.common.dataplugin.annotations.DataURI; import com.raytheon.uf.common.dataplugin.annotations.DataURI;
import com.raytheon.uf.common.dataplugin.persist.PersistableDataObject; import com.raytheon.uf.common.dataplugin.persist.PersistableDataObject;
import com.raytheon.uf.common.geospatial.CRSCache; import com.raytheon.uf.common.geospatial.CRSCache;
import com.raytheon.uf.common.geospatial.ISpatialObject; import com.raytheon.uf.common.geospatial.IGridGeometryProvider;
import com.raytheon.uf.common.geospatial.util.EnvelopeIntersection;
import com.raytheon.uf.common.serialization.adapters.GeometryAdapter; import com.raytheon.uf.common.serialization.adapters.GeometryAdapter;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Polygon; import com.vividsolutions.jts.geom.Polygon;
/** /**
@ -62,6 +71,7 @@ import com.vividsolutions.jts.geom.Polygon;
* Jul 12, 2012 798 jkorman Changed projection "magic" numbers * Jul 12, 2012 798 jkorman Changed projection "magic" numbers
* Jul 16, 2013 2181 bsteffen Convert geometry types to use hibernate- * Jul 16, 2013 2181 bsteffen Convert geometry types to use hibernate-
* spatial * spatial
* Sep 30, 2013 2333 mschenke Refactored to store coordinates in CRS space
* *
* </pre> * </pre>
*/ */
@ -69,321 +79,349 @@ import com.vividsolutions.jts.geom.Polygon;
@Table(name = "satellite_spatial") @Table(name = "satellite_spatial")
@XmlAccessorType(XmlAccessType.NONE) @XmlAccessorType(XmlAccessType.NONE)
@DynamicSerialize @DynamicSerialize
@Embeddable public class SatMapCoverage extends PersistableDataObject<Object> implements
public class SatMapCoverage extends PersistableDataObject implements IGridGeometryProvider {
ISpatialObject {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public static final int PROJ_MERCATOR = 1; @Id
@DynamicSerializeElement
public static final int PROJ_LAMBERT = 3;
public static final int PROJ_POLAR_STEREO = 5;
public static final int PROJ_CYLIN_EQUIDISTANT = 7;
@Id
@DynamicSerializeElement
@DataURI(position = 0) @DataURI(position = 0)
private int gid; private int gid;
/** /**
* The projection of the map coverage 1=Mercator, 3=Lambert Conformal * The projection of the map coverage 1=Mercator, 3=Lambert Conformal
* 5=Polar Stereographic * 5=Polar Stereographic
*/ *
@Column * @deprecated This field is only useful for GINI satellite format decoding
@XmlAttribute * and should not be in the coverage object
@DynamicSerializeElement */
private Integer projection; @Column
@XmlAttribute
@DynamicSerializeElement
@Deprecated
private Integer projection;
/** Number of points along the x-axis */ /** Minimum x coordinate in crs space */
@XmlAttribute @XmlAttribute
@DynamicSerializeElement @DynamicSerializeElement
@Column @Column
protected Integer nx; private double minX;
/** Number of points along the y-axis */ /** Minimum y coordinate in crs space */
@XmlAttribute @XmlAttribute
@DynamicSerializeElement @DynamicSerializeElement
@Column @Column
protected Integer ny; private double minY;
/** The horizontal resolution of the grid */ /** Number of points along the x-axis */
@Column @XmlAttribute
@XmlAttribute @DynamicSerializeElement
@DynamicSerializeElement @Column
private Float dx; private Integer nx;
/** The vertical resolution of the grid */ /** Number of points along the y-axis */
@Column @XmlAttribute
@XmlAttribute @DynamicSerializeElement
@DynamicSerializeElement @Column
private Float dy; private Integer ny;
/** /** The horizontal resolution of the grid */
* The orientation of the grid; i.e, the east longitude value of the @Column
* meridian which is parallel to the y-axis (or columns of the grid) along @XmlAttribute
* which latitude increases as the y-coordinate increases (Note: the @DynamicSerializeElement
* orientation longitude may or may not appear withing a particular grid.) private double dx;
*/
@Column
@XmlAttribute
@DynamicSerializeElement
private Float lov;
/** /** The vertical resolution of the grid */
* The latitude at which the Lambert projection cone is tangent to the @Column
* earth. Polar Stereographic this value is set to 0. For Mercator this is @XmlAttribute
* The latitude at which the Mercator projection cylinder intersects the @DynamicSerializeElement
* earth. private double dy;
*/
@Column
@XmlAttribute
@DynamicSerializeElement
private Float latin;
/** The latitude of the first grid point */ @Column(length = 2047)
@Column @XmlAttribute
@XmlAttribute @DynamicSerializeElement
@DynamicSerializeElement private String crsWKT;
private Float la1;
/** The longitude of the first grid point */ @Transient
@Column private CoordinateReferenceSystem crsObject;
@XmlAttribute
@DynamicSerializeElement
private Float lo1;
/** The latitude of the last grid point (only used with Mercator projection) */ /** The map coverage */
@Column
@XmlAttribute
@DynamicSerializeElement
private Float la2;
/**
* The longitude of the last grid point (only used with Mercator projection)
*/
@Column
@XmlAttribute
@DynamicSerializeElement
private Float lo2;
@Column(length = 2047)
@XmlAttribute
@DynamicSerializeElement
private String crsWKT;
@Transient
private CoordinateReferenceSystem crsObject;
/** The map coverage */
@Column(name = "the_geom") @Column(name = "the_geom")
@Type(type = "org.hibernatespatial.GeometryUserType") @Type(type = "org.hibernatespatial.GeometryUserType")
@XmlJavaTypeAdapter(value = GeometryAdapter.class) @XmlJavaTypeAdapter(value = GeometryAdapter.class)
@DynamicSerializeElement @DynamicSerializeElement
private Polygon location; private Geometry location;
public SatMapCoverage() { public SatMapCoverage() {
super(); super();
} }
/** /**
* Constructs a new SatMapCoverage Object * Constructs a new SatMapCoverage Object
* *
* @param projection * @param projection
* @param nx * the projection id value
* The number of horizontal scan lines * @param minX
* @param ny * minimum x value in crs space
* The number vertical scan lines * @param minY
* @param dx * minimum y value in crs space
* The horizontal resolution * @param nx
* @param dy * number of x points in the satellite grid
* The vertical resolution * @param ny
* @param lov * number of y points in the satellite grid
* The orientation of the grid * @param dx
* @param latin * spacing between grid cells in crs x space
* The tangent latitude * @param dy
* @param la1 * spacing between grid cells in crs y space
* The latitude of the first grid point * @param crs
* @param lo1 * the satellite data crs
* The longitude of the first grid point */
* @param la2 public SatMapCoverage(int projection, double minX, double minY, int nx,
* The latitude of the last grid point (null for Lambert int ny, double dx, double dy, CoordinateReferenceSystem crs) {
* Conformal or Polar Stereographic) this(projection, minX, minY, nx, ny, dx, dy, crs, null);
* @param lo2 }
* The longitude of the last grid point (null for Lambert
* Conformal or Polar Stereographic)
* @param crs
* The coordinate reference system
* @param geometry
* The geometry
*/
public SatMapCoverage(Integer projection, Integer nx, Integer ny, Float dx,
Float dy, Float lov, Float latin, Float la1, Float lo1, Float la2,
Float lo2, CoordinateReferenceSystem crs, Geometry geometry) {
this.projection = projection; /**
this.nx = nx; * Constructs a new SatMapCoverage Object
this.ny = ny; *
this.dx = dx; * @param projection
this.dy = dy; * the projection id value
this.lov = lov; * @param minX
this.latin = latin; * minimum x value in crs space
this.la1 = la1; * @param minY
this.lo1 = lo1; * minimum y value in crs space
this.la2 = la2; * @param nx
this.lo2 = lo2; * number of x points in the satellite grid
this.crsObject = crs; * @param ny
this.crsWKT = crsObject.toWKT(); * number of y points in the satellite grid
this.location = (Polygon) geometry; * @param dx
gid = this.hashCode(); * spacing between grid cells in crs x space
} * @param dy
* spacing between grid cells in crs y space
* @param crs
* the satellite data crs
* @param latLonGeometry
* A Geometry representing the satellite bounds in lat/lon space
*/
public SatMapCoverage(int projection, double minX, double minY, int nx,
int ny, double dx, double dy, CoordinateReferenceSystem crs,
Geometry latLonGeometry) {
this.projection = projection;
this.minX = minX;
this.minY = minY;
this.nx = nx;
this.ny = ny;
this.dx = dx;
this.dy = dy;
this.crsObject = crs;
this.gid = hashCode();
if (latLonGeometry == null) {
try {
latLonGeometry = EnvelopeIntersection
.createEnvelopeIntersection(
getGridGeometry().getEnvelope(),
new Envelope2D(DefaultGeographicCRS.WGS84,
-180, -90, 360, 180), 1.0, 10, 10)
.getEnvelope();
} catch (Exception e) {
// Ignore exception, null location
}
}
this.location = latLonGeometry;
}
public int hashCode() { /**
HashCodeBuilder hashBuilder = new HashCodeBuilder(); * @deprecated This field is only useful for GINI satellite format decoding
hashBuilder.append(projection); * and should not be in the coverage object
hashBuilder.append(nx); * @return
hashBuilder.append(ny); */
hashBuilder.append(dx); @Deprecated
hashBuilder.append(dy); public Integer getProjection() {
hashBuilder.append(lov); return projection;
hashBuilder.append(latin); }
hashBuilder.append(la1);
hashBuilder.append(la2);
hashBuilder.append(lo1);
hashBuilder.append(lo2);
return hashBuilder.toHashCode();
}
@Override /**
public Polygon getGeometry() { * @deprecated This field is only useful for GINI satellite format decoding
return location; * and should not be in the coverage object
} * @param projection
*/
@Deprecated
public void setProjection(Integer projection) {
this.projection = projection;
}
@Override public int getGid() {
public CoordinateReferenceSystem getCrs() { return gid;
if (crsObject == null) { }
try {
crsObject = CRSCache.getInstance()
.getCoordinateReferenceSystem(crsWKT);
} catch (FactoryException e) {
crsObject = null;
}
}
return crsObject;
}
public Float getDx() { public void setGid(int gid) {
return dx; this.gid = gid;
} }
public void setDx(Float dx) { public double getMinX() {
this.dx = dx; return minX;
} }
public Float getDy() { public void setMinX(double minX) {
return dy; this.minX = minX;
} }
public void setDy(Float dy) { public double getMinY() {
this.dy = dy; return minY;
} }
public Float getLov() { public void setMinY(double minY) {
return lov; this.minY = minY;
} }
public void setLov(Float lov) { public Integer getNx() {
this.lov = lov; return nx;
} }
public Float getLatin() { public void setNx(Integer nx) {
return latin; this.nx = nx;
} }
public void setLatin(Float latin) { public Integer getNy() {
this.latin = latin; return ny;
} }
public Float getLa1() { public void setNy(Integer ny) {
return la1; this.ny = ny;
} }
public void setLa1(Float la1) { public double getDx() {
this.la1 = la1; return dx;
} }
public Float getLo1() { public void setDx(double dx) {
return lo1; this.dx = dx;
} }
public void setLo1(Float lo1) { public double getDy() {
this.lo1 = lo1; return dy;
} }
public Float getLa2() { public void setDy(double dy) {
return la2; this.dy = dy;
} }
public void setLa2(Float la2) { public String getCrsWKT() {
this.la2 = la2; if (crsWKT == null && crsObject != null) {
} crsWKT = crsObject.toWKT();
}
return crsWKT;
}
public Float getLo2() { public void setCrsWKT(String crsWKT) {
return lo2; this.crsWKT = crsWKT;
} if (crsObject != null) {
crsObject = null;
}
}
public void setLo2(Float lo2) { public Geometry getLocation() {
this.lo2 = lo2; if (location == null) {
} location = generateLocation();
if (location == null) {
// Default to empty MultiPolygon so various Geometry methods
// still work
location = new GeometryFactory()
.createMultiPolygon(new Polygon[0]);
}
}
return location;
}
public Integer getProjection() { public void setLocation(Geometry location) {
return projection; this.location = location;
} }
public void setProjection(Integer projection) { /**
this.projection = projection; * Generates the lat/lon bounding geometry for the spatial record
} *
* @return lat/lon bounding geometry or null if none could be generated
*/
private Geometry generateLocation() {
try {
return EnvelopeIntersection.createEnvelopeIntersection(
getGridGeometry().getEnvelope(),
new Envelope2D(DefaultGeographicCRS.WGS84, -180, -90, 360,
180), 1.0, 10, 10).getEnvelope();
} catch (Exception e) {
// Ignore exception, null location
}
return null;
}
public int getGid() { public CoordinateReferenceSystem getCrs() {
return gid; if (crsObject == null && crsWKT != null) {
} try {
crsObject = CRSCache.getInstance()
.getCoordinateReferenceSystem(crsWKT);
} catch (FactoryException e) {
crsObject = null;
}
}
return crsObject;
}
public void setGid(int gid) { @Override
this.gid = gid; public GridGeometry2D getGridGeometry() {
} GridEnvelope gridRange = new GridEnvelope2D(0, 0, getNx(), getNy());
Envelope crsRange = new Envelope2D(getCrs(), new Rectangle2D.Double(
minX, minY, getNx() * getDx(), getNy() * getDy()));
return new GridGeometry2D(gridRange, crsRange);
}
public Integer getNx() { @Override
return nx; public int hashCode() {
} HashCodeBuilder builder = new HashCodeBuilder();
builder.append(projection);
builder.append(getCrsWKT());
builder.append(minX);
builder.append(minY);
builder.append(dx);
builder.append(dy);
builder.append(nx);
builder.append(ny);
return builder.toHashCode();
}
public void setNx(Integer nx) { @Override
this.nx = nx; public boolean equals(Object obj) {
} if (this == obj)
return true;
public Integer getNy() { if (obj == null)
return ny; return false;
} if (getClass() != obj.getClass())
return false;
public void setNy(Integer ny) { SatMapCoverage other = (SatMapCoverage) obj;
this.ny = ny; if (projection != other.projection)
} return false;
String crsWKT = getCrsWKT();
public String getCrsWKT() { String otherCrsWKT = other.getCrsWKT();
return crsWKT; if (crsWKT == null) {
} if (otherCrsWKT != null)
return false;
public void setCrsWKT(String crsWKT) { } else if (!crsWKT.equals(otherCrsWKT))
this.crsWKT = crsWKT; return false;
} if (Double.doubleToLongBits(dx) != Double.doubleToLongBits(other.dx))
return false;
public Polygon getLocation() { if (Double.doubleToLongBits(dy) != Double.doubleToLongBits(other.dy))
return location; return false;
} if (Double.doubleToLongBits(minX) != Double
.doubleToLongBits(other.minX))
public void setLocation(Polygon location) { return false;
this.location = location; if (Double.doubleToLongBits(minY) != Double
} .doubleToLongBits(other.minY))
return false;
if (nx != other.nx)
return false;
if (ny != other.ny)
return false;
return true;
}
} }

View file

@ -35,6 +35,7 @@ import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
import org.geotools.coverage.grid.GridGeometry2D;
import org.hibernate.annotations.Index; import org.hibernate.annotations.Index;
import com.raytheon.uf.common.dataplugin.IDecoderGettable; import com.raytheon.uf.common.dataplugin.IDecoderGettable;
@ -43,7 +44,7 @@ import com.raytheon.uf.common.dataplugin.annotations.DataURI;
import com.raytheon.uf.common.dataplugin.persist.PersistablePluginDataObject; import com.raytheon.uf.common.dataplugin.persist.PersistablePluginDataObject;
import com.raytheon.uf.common.datastorage.DataStoreFactory; import com.raytheon.uf.common.datastorage.DataStoreFactory;
import com.raytheon.uf.common.datastorage.records.IDataRecord; import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.geospatial.ISpatialEnabled; import com.raytheon.uf.common.geospatial.IGridGeometryProvider;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
@ -91,7 +92,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
@XmlAccessorType(XmlAccessType.NONE) @XmlAccessorType(XmlAccessType.NONE)
@DynamicSerialize @DynamicSerialize
public class SatelliteRecord extends PersistablePluginDataObject implements public class SatelliteRecord extends PersistablePluginDataObject implements
ISpatialEnabled { IGridGeometryProvider {
public static final String PLUGIN_ID = "satellite"; public static final String PLUGIN_ID = "satellite";
@ -176,16 +177,6 @@ public class SatelliteRecord extends PersistablePluginDataObject implements
@DynamicSerializeElement @DynamicSerializeElement
private Float satSubPointLon; private Float satSubPointLon;
/** The upper right hand latitude */
@Column
@DynamicSerializeElement
private Float upperRightLat;
/** The upper right hand longitude */
@Column
@DynamicSerializeElement
private Float upperRightLon;
/** Height of the satellite in km */ /** Height of the satellite in km */
@Column @Column
@DynamicSerializeElement @DynamicSerializeElement
@ -229,8 +220,8 @@ public class SatelliteRecord extends PersistablePluginDataObject implements
} }
@Override @Override
public SatMapCoverage getSpatialObject() { public GridGeometry2D getGridGeometry() {
return coverage; return coverage != null ? coverage.getGridGeometry() : null;
} }
public SatMapCoverage getCoverage() { public SatMapCoverage getCoverage() {
@ -257,22 +248,6 @@ public class SatelliteRecord extends PersistablePluginDataObject implements
this.satSubPointLon = satSubPointLon; this.satSubPointLon = satSubPointLon;
} }
public Float getUpperRightLat() {
return upperRightLat;
}
public void setUpperRightLat(Float upperRightLat) {
this.upperRightLat = upperRightLat;
}
public Float getUpperRightLon() {
return upperRightLon;
}
public void setUpperRightLon(Float upperRightLon) {
this.upperRightLon = upperRightLon;
}
public Integer getNumRecords() { public Integer getNumRecords() {
return numRecords; return numRecords;
} }

View file

@ -0,0 +1,45 @@
/**
* 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.uf.common.geospatial;
import org.geotools.coverage.grid.GridGeometry2D;
/**
* Interface indicating object can provide a {@link GridGeometry2D}
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Sep 25, 2013 2333 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public interface IGridGeometryProvider {
public GridGeometry2D getGridGeometry();
}

View file

@ -39,7 +39,9 @@ import org.opengis.referencing.FactoryException;
import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.MathTransform;
/** /**
* Geostationary map projection. Earth as viewed from space. * Geostationary map projection. Earth as viewed from space. Based on
* Coordination Group for Meteorological Satellites LRIT/HRIT Global
* Specification
* *
* TODO Add support latitude of origin != 0.0 * TODO Add support latitude of origin != 0.0
* *
@ -49,7 +51,8 @@ import org.opengis.referencing.operation.MathTransform;
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Jun 27, 2013 mschenke Initial creation * Jun 27, 2013 mschenke Initial creation
* Oct 02, 2013 2333 mschenke Converted from libproj to CGMS algorithm
* *
* </pre> * </pre>
* *
@ -63,17 +66,25 @@ public class Geostationary extends MapProjection {
public static final String PROJECTION_NAME = "Geostationary"; public static final String PROJECTION_NAME = "Geostationary";
public static final String PERSPECTIVE_HEIGHT = "perspective_height"; public static final String ORBITAL_HEIGHT = "orbital_height";
public static final String SWEEP_AXIS = "sweep_axis"; public static final String SWEEP_AXIS = "sweep_axis";
static final double DEFAULT_PERSPECTIVE_HEIGHT = 35800000.0; static final double DEFAULT_PERSPECTIVE_HEIGHT = 35800000.0;
private double perspectiveHeight = DEFAULT_PERSPECTIVE_HEIGHT; private double orbitalHeight;
private double perspectiveHeight;
private boolean swapAxis = false; private boolean swapAxis = false;
private double radius_g, radius_g_1, radius_p, radius_p2, radius_p_inv2, C; private double rEq, rEq2;
private double rPol, rPol2;
private double height_ratio;
private double e2;
/** /**
* @param values * @param values
@ -82,23 +93,18 @@ public class Geostationary extends MapProjection {
protected Geostationary(ParameterValueGroup values) protected Geostationary(ParameterValueGroup values)
throws ParameterNotFoundException { throws ParameterNotFoundException {
super(values); super(values);
this.perspectiveHeight = Provider.getValue(Provider.PERSPECTIVE_HEIGHT, this.orbitalHeight = Provider.getValue(Provider.ORBITAL_HEIGHT, values);
values); this.perspectiveHeight = orbitalHeight + semiMajor;
double sweepValue = Provider.getValue(Provider.SWEEP_AXIS, values); double sweepValue = Provider.getValue(Provider.SWEEP_AXIS, values);
this.swapAxis = sweepValue == 1.0; this.swapAxis = sweepValue == 1.0;
double h = perspectiveHeight;
double a = semiMajor;
double b = semiMinor;
double es = 1.0 - (b * b) / (a * a);
double one_es = 1.0 - es;
double rone_es = 1.0 / one_es;
radius_g_1 = h / a; this.rEq = semiMajor;
radius_g = 1 + radius_g_1; this.rEq2 = rEq * rEq;
radius_p2 = one_es; this.rPol = semiMinor;
radius_p_inv2 = rone_es; this.rPol2 = rPol * rPol;
radius_p = Math.sqrt(radius_p2); this.e2 = (rEq2 - rPol2) / rEq2;
C = radius_g * radius_g - 1.0;
this.height_ratio = rEq / orbitalHeight;
} }
/* /*
@ -112,6 +118,16 @@ public class Geostationary extends MapProjection {
return Provider.PARAMETERS; return Provider.PARAMETERS;
} }
@Override
public ParameterValueGroup getParameterValues() {
ParameterValueGroup values = super.getParameterValues();
values.parameter(Provider.ORBITAL_HEIGHT.getName().getCode()).setValue(
orbitalHeight);
values.parameter(Provider.SWEEP_AXIS.getName().getCode()).setValue(
swapAxis ? 1.0 : 0.0);
return values;
}
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
@ -121,38 +137,30 @@ public class Geostationary extends MapProjection {
@Override @Override
protected Point2D inverseTransformNormalized(double x, double y, protected Point2D inverseTransformNormalized(double x, double y,
Point2D ptDst) throws ProjectionException { Point2D ptDst) throws ProjectionException {
double lam, phi; double lam = Double.NaN, phi = Double.NaN;
double Vx, Vy, Vz, a, b, det, k; x *= height_ratio;
y *= height_ratio;
/* Setting three components of vector from satellite to position. */ double sinX = Math.sin(x);
Vx = -1.0; double cosX = Math.cos(x);
if (swapAxis) {
Vz = Math.tan(y / radius_g_1); double sinY = Math.sin(y);
Vy = Math.tan(x / radius_g_1) * Math.hypot(1.0, Vz); double cosY = Math.cos(y);
} else {
Vy = Math.tan(x / radius_g_1); double a = sinX * sinX + cosX * cosX
Vz = Math.tan(y / radius_g_1) * Math.hypot(1.0, Vy); * (cosY * cosY + (rEq2 / rPol2) * sinY * sinY);
} double b = -2 * perspectiveHeight * cosX * cosY;
/* Calculation of terms in cubic equation and determinant. */ double c = perspectiveHeight * perspectiveHeight - rEq2;
a = Vz / radius_p;
a = Vy * Vy + a * a + Vx * Vx; double Vl = (-b - Math.sqrt(b * b - 4 * a * c)) / 2 * a;
b = 2 * radius_g * Vx; double Vx = Vl * cosX * cosY;
if ((det = (b * b) - 4 * a * C) < 0.) { double Vy = Vl * sinX;
lam = phi = Double.NaN; double Vz = Vl * sinY * cosX;
} else {
/* double s1 = perspectiveHeight - Vx;
* Calculation of three components of vector from satellite to
* position. lam = Math.atan(Vy / s1);
*/ phi = Math.atan((rEq2 / rPol2) * (Vz / Math.sqrt(s1 * s1 + Vy * Vy)));
k = (-b - Math.sqrt(det)) / (2. * a);
Vx = radius_g + k * Vx;
Vy *= k;
Vz *= k;
/* Calculation of longitude and latitude. */
lam = Math.atan2(Vy, Vx);
phi = Math.atan(Vz * Math.cos(lam) / Vx);
phi = Math.atan(radius_p_inv2 * Math.tan(phi));
}
if (ptDst == null) { if (ptDst == null) {
ptDst = new Point2D.Double(); ptDst = new Point2D.Double();
@ -170,38 +178,37 @@ public class Geostationary extends MapProjection {
@Override @Override
protected Point2D transformNormalized(double lam, double phi, Point2D ptDst) protected Point2D transformNormalized(double lam, double phi, Point2D ptDst)
throws ProjectionException { throws ProjectionException {
double x, y; double x = Double.NaN, y = Double.NaN;
double r, Vx, Vy, Vz, tmp;
/* Calculation of geocentric latitude. */ double cPhi = Math.atan((rPol2 / rEq2) * Math.tan(phi));
phi = Math.atan(radius_p2 * Math.tan(phi)); double cosPhi = Math.cos(cPhi);
/*
* Calculation of the three components of the vector from satellite to* double rs = rPol / Math.sqrt(1 - e2 * cosPhi * cosPhi);
* position on earth surface (lon,lat). double rPhi = rs * cosPhi;
*/
r = (radius_p) / Math.hypot(radius_p * Math.cos(phi), Math.sin(phi)); double Vx = perspectiveHeight - rPhi * Math.cos(lam);
Vx = r * Math.cos(lam) * Math.cos(phi); double Vy = rPhi * Math.sin(lam);
Vy = r * Math.sin(lam) * Math.cos(phi); double Vz = rs * Math.sin(cPhi);
Vz = r * Math.sin(phi); double Vn = Math.sqrt(Vx * Vx + Vy * Vy + Vz * Vz);
/* Check visibility. */
if (((radius_g - Vx) * Vx - Vy * Vy - Vz * Vz * radius_p_inv2) < 0.) { if ((perspectiveHeight * (perspectiveHeight - Vx)) < (Vy * Vy + (rEq2 / rPol2)
* Vz * Vz)) {
x = y = Double.NaN; x = y = Double.NaN;
} else { } else {
/* Calculation based on view angles from satellite. */ // Altered for x sweeping axis
tmp = radius_g - Vx;
if (swapAxis) { if (swapAxis) {
x = radius_g_1 * Math.atan(Vy / Math.hypot(Vz, tmp)); x = Math.atan(Vy / Vx);
y = radius_g_1 * Math.atan(Vz / tmp); y = Math.asin(Vz / Vn);
} else { } else {
x = radius_g_1 * Math.atan(Vy / tmp); x = Math.asin(Vy / Vn);
y = radius_g_1 * Math.atan(Vz / Math.hypot(Vy, tmp)); y = Math.atan(Vz / Vx);
} }
} }
if (ptDst == null) { if (ptDst == null) {
ptDst = new Point2D.Double(); ptDst = new Point2D.Double();
} }
ptDst.setLocation(x, y); ptDst.setLocation(x / height_ratio, y / height_ratio);
return ptDst; return ptDst;
} }
@ -209,8 +216,8 @@ public class Geostationary extends MapProjection {
private static final long serialVersionUID = 3868187206568280453L; private static final long serialVersionUID = 3868187206568280453L;
static final ParameterDescriptor<Double> PERSPECTIVE_HEIGHT = DefaultParameterDescriptor static final ParameterDescriptor<Double> ORBITAL_HEIGHT = DefaultParameterDescriptor
.create(Geostationary.PERSPECTIVE_HEIGHT, .create(Geostationary.ORBITAL_HEIGHT,
DEFAULT_PERSPECTIVE_HEIGHT, 0, Double.MAX_VALUE, DEFAULT_PERSPECTIVE_HEIGHT, 0, Double.MAX_VALUE,
SI.METER); SI.METER);
@ -218,10 +225,10 @@ public class Geostationary extends MapProjection {
.create(Geostationary.SWEEP_AXIS, 0.0, 0.0, 1.0, Unit.ONE); .create(Geostationary.SWEEP_AXIS, 0.0, 0.0, 1.0, Unit.ONE);
static final ParameterDescriptorGroup PARAMETERS = new DefaultParameterDescriptorGroup( static final ParameterDescriptorGroup PARAMETERS = new DefaultParameterDescriptorGroup(
PROJECTION_NAME, new ParameterDescriptor[] { PROJECTION_NAME, new ParameterDescriptor[] { SEMI_MAJOR,
SEMI_MAJOR, SEMI_MINOR, CENTRAL_MERIDIAN, SEMI_MINOR, CENTRAL_MERIDIAN, LATITUDE_OF_ORIGIN,
LATITUDE_OF_ORIGIN, FALSE_EASTING, FALSE_NORTHING, FALSE_EASTING, FALSE_NORTHING, ORBITAL_HEIGHT,
PERSPECTIVE_HEIGHT, SWEEP_AXIS }); SWEEP_AXIS });
public Provider() { public Provider() {
super(PARAMETERS); super(PARAMETERS);

View file

@ -81,7 +81,6 @@ public class EnvelopeIntersection {
public static Geometry createEnvelopeIntersection(Envelope sourceEnvelope, public static Geometry createEnvelopeIntersection(Envelope sourceEnvelope,
Envelope targetEnvelope, double threshold, int maxHorDivisions, Envelope targetEnvelope, double threshold, int maxHorDivisions,
int maxVertDivisions) throws TransformException, FactoryException { int maxVertDivisions) throws TransformException, FactoryException {
long t0 = System.currentTimeMillis();
ReferencedEnvelope sourceREnvelope = reference(sourceEnvelope); ReferencedEnvelope sourceREnvelope = reference(sourceEnvelope);
ReferencedEnvelope targetREnvelope = reference(targetEnvelope); ReferencedEnvelope targetREnvelope = reference(targetEnvelope);
Geometry border = null; Geometry border = null;
@ -242,7 +241,6 @@ public class EnvelopeIntersection {
// intersections in collection // intersections in collection
Coordinate[] borderCorners = { ul, ur, lr, ll }; Coordinate[] borderCorners = { ul, ur, lr, ll };
// First, world wrap correct the line strings // First, world wrap correct the line strings
List<LineString> corrected = new ArrayList<LineString>(); List<LineString> corrected = new ArrayList<LineString>();
for (LineString ls : lineStrings) { for (LineString ls : lineStrings) {
@ -507,8 +505,6 @@ public class EnvelopeIntersection {
} }
} }
System.out.println("Time to create EnvelopeIntersection: "
+ (System.currentTimeMillis() - t0) + "ms");
return border; return border;
} }

View file

@ -20,8 +20,6 @@
package com.raytheon.uf.edex.plugin.fog; package com.raytheon.uf.edex.plugin.fog;
import org.geotools.coverage.grid.GridGeometry2D; import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.geometry.GeneralEnvelope;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.raytheon.edex.plugin.satellite.dao.SatelliteDao; import com.raytheon.edex.plugin.satellite.dao.SatelliteDao;
import com.raytheon.uf.common.dataplugin.PluginException; import com.raytheon.uf.common.dataplugin.PluginException;
@ -30,11 +28,7 @@ import com.raytheon.uf.common.datastorage.IDataStore;
import com.raytheon.uf.common.datastorage.Request; import com.raytheon.uf.common.datastorage.Request;
import com.raytheon.uf.common.datastorage.records.ByteDataRecord; import com.raytheon.uf.common.datastorage.records.ByteDataRecord;
import com.raytheon.uf.common.datastorage.records.IDataRecord; import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.geospatial.MapUtil;
import com.raytheon.uf.edex.database.plugin.PluginFactory; import com.raytheon.uf.edex.database.plugin.PluginFactory;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
public class FogDbUtils { public class FogDbUtils {
@ -94,67 +88,7 @@ public class FogDbUtils {
* @return * @return
*/ */
public static GridGeometry2D getGridGeometry(SatelliteRecord rec) { public static GridGeometry2D getGridGeometry(SatelliteRecord rec) {
return MapUtil.getGridGeometry(rec.getSpatialObject()); return rec.getGridGeometry();
}
/**
* Creates the Grid Geometry for the Fog Display grid
*
* @param geo
* @param crs
* @param nx
* @param ny
* @return
*/
public static GeneralEnvelope getEnvelope(Geometry geo, CoordinateReferenceSystem crs) {
GeneralEnvelope env2 = null;
try {
Point[] points = new Point[((Polygon) geo).getExteriorRing().getNumPoints()];
for (int i = 0; i < points.length; i++) {
points[i] = ((Polygon) geo).getExteriorRing().getPointN(i);
}
env2 = MapUtil.extractProjectedEnvelope(crs, points, MapUtil
.getTransformFromLatLon(crs));
}
catch (Exception e) {
e.printStackTrace();
}
return env2;
}
/**
* Used to re size raster IR sat grids to VIS size
*
* @param inputGrid
* @param outputGridSize
* @param nx
* @param ny
* @return
*/
public static float[] reSizeFloatGrid(float[] inputGrid, int outputGridSize, int nx, int ny) {
float[] outputGrid = new float[outputGridSize];
// decimate
// (SK) i => x j => y
for (int j = 0; j < ny; j++) {
for (int i = 0; i < nx; i++) {
float avValue = 0;
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
// average the grid values
avValue += inputGrid[nx * (j * 4 + y) + i * 4 + x];
}
}
outputGrid[nx * j + i] = avValue / 16;
}
}
return outputGrid;
} }
/** /**

View file

@ -292,8 +292,7 @@ public class FogConfig {
* @return * @return
*/ */
private void setDx(SatelliteRecord rec) { private void setDx(SatelliteRecord rec) {
dx = (float) rec.getCoverage().getDx();
dx = rec.getCoverage().getDx();
} }
/** /**
@ -312,8 +311,7 @@ public class FogConfig {
* @return * @return
*/ */
private void setDy(SatelliteRecord rec) { private void setDy(SatelliteRecord rec) {
dy = (float) rec.getCoverage().getDy();
dy = rec.getCoverage().getDy();
} }
/** /**

View file

@ -323,7 +323,7 @@ public class McidasSatelliteDecoder {
lo2 = (float) prnlon(lo2); lo2 = (float) prnlon(lo2);
result = SatSpatialFactory.getInstance().getMapCoverage( result = SatSpatialFactory.getInstance().getMapCoverage(
SatMapCoverage.PROJ_MERCATOR, nx, ny, (float) dx, SatSpatialFactory.PROJ_MERCATOR, nx, ny, (float) dx,
(float) dy, (float) clon, (float) clat, la1, lo1, la2, lo2); (float) dy, (float) clon, (float) clat, la1, lo1, la2, lo2);
} else { } else {
unimplemented(String.format("navigation type \"%s\"", navType)); unimplemented(String.format("navigation type \"%s\"", navType));

View file

@ -61,6 +61,7 @@ import gov.noaa.nws.ncep.common.dataplugin.ncgrib.spatial.projections.PolarStere
* Added getGridNavigationContent, float2File, * Added getGridNavigationContent, float2File,
* serialize2File, data2File, flipData * serialize2File, data2File, flipData
* 09/14/2010 284 mgamazaychikov Add addHours method * 09/14/2010 284 mgamazaychikov Add addHours method
* 10/02/2013 2333 mschenke Removed unused function getSatHdrContent
* </pre> * </pre>
* *
* @author mgamazaychikov * @author mgamazaychikov
@ -295,45 +296,6 @@ public class GempakConvert {
return inputStrings; return inputStrings;
} }
/*
* Construct the satellite header string
*/
public static String getSatHdrContent(ISpatialObject obj) throws JAXBException {
SatMapCoverage mapCoverage = (SatMapCoverage)obj;
StringBuffer resultsBuf = new StringBuffer();
resultsBuf.append(mapCoverage.getProjection());
resultsBuf.append(";");
resultsBuf.append(mapCoverage.getNx());
resultsBuf.append(";");
resultsBuf.append(mapCoverage.getNy());
resultsBuf.append(";");
Float dummy = mapCoverage.getLa1()*10000;
resultsBuf.append(dummy.intValue());
resultsBuf.append(";");
dummy = mapCoverage.getLa2()*10000;
resultsBuf.append(dummy.intValue());
resultsBuf.append(";");
dummy = mapCoverage.getLo1()*10000;
resultsBuf.append(dummy.intValue());
resultsBuf.append(";");
dummy = mapCoverage.getLo2()*10000;
resultsBuf.append(dummy.intValue());
resultsBuf.append(";");
dummy = mapCoverage.getLatin()*10000;
resultsBuf.append(dummy.intValue());
resultsBuf.append(";");
dummy = mapCoverage.getLov()*10000;
resultsBuf.append(dummy.intValue());
resultsBuf.append(";");
resultsBuf.append(mapCoverage.getDx().intValue());
resultsBuf.append(";");
resultsBuf.append(mapCoverage.getDy().intValue());
String content = resultsBuf.toString();
return content;
}
/* /*
* Converts AWIPS2 date time string into GEMPAK DATTIM string * Converts AWIPS2 date time string into GEMPAK DATTIM string
*/ */

View file

@ -80,7 +80,7 @@ public class GiniAreaProviderFactory implements INcAreaProviderFactory {
if( proj == 1 || proj == 3 || proj == 5 ) { // MER, LCC or STR if( proj == 1 || proj == 3 || proj == 5 ) { // MER, LCC or STR
// for remapped projections such as MER, LCC, STR // for remapped projections such as MER, LCC, STR
gridGeom = MapUtil.getGridGeometry( satRec.getSpatialObject() ); gridGeom = satRec.getGridGeometry();
} }
else { else {
System.out.println("Unable to get Coverage for projection "+ proj+ "." ); System.out.println("Unable to get Coverage for projection "+ proj+ "." );

View file

@ -12,7 +12,6 @@ package gov.noaa.nws.ost.edex.plugin.regionalsat.decoder;
import gov.noaa.nws.ost.edex.plugin.regionalsat.util.RegionalSatLookups; import gov.noaa.nws.ost.edex.plugin.regionalsat.util.RegionalSatLookups;
import gov.noaa.nws.ost.edex.plugin.regionalsat.util.RegionalSatLookups.PhysicalElementValue; import gov.noaa.nws.ost.edex.plugin.regionalsat.util.RegionalSatLookups.PhysicalElementValue;
import gov.noaa.nws.ost.edex.plugin.regionalsat.util.RegionalSatSpatialFactory;
import java.util.Calendar; import java.util.Calendar;
import java.util.TimeZone; import java.util.TimeZone;
@ -22,6 +21,7 @@ import ucar.nc2.NetcdfFile;
import com.raytheon.edex.exception.DecoderException; import com.raytheon.edex.exception.DecoderException;
import com.raytheon.edex.plugin.AbstractDecoder; import com.raytheon.edex.plugin.AbstractDecoder;
import com.raytheon.edex.util.satellite.SatSpatialFactory;
import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.satellite.SatMapCoverage; import com.raytheon.uf.common.dataplugin.satellite.SatMapCoverage;
import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord; import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord;
@ -200,7 +200,7 @@ public class RegionalSatDecoder extends AbstractDecoder {
float lov = netCdfFile.findGlobalAttribute("centralLon") float lov = netCdfFile.findGlobalAttribute("centralLon")
.getNumericValue().floatValue(); .getNumericValue().floatValue();
int mapProjection = SatMapCoverage.PROJ_POLAR_STEREO; // 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
@ -215,12 +215,12 @@ public class RegionalSatDecoder extends AbstractDecoder {
.getNumericValue().floatValue(); .getNumericValue().floatValue();
if (projection.equalsIgnoreCase("LAMBERT") if (projection.equalsIgnoreCase("LAMBERT")
|| projection.equalsIgnoreCase("LAMBERT_CONFORMAL")) { || projection.equalsIgnoreCase("LAMBERT_CONFORMAL")) {
mapProjection = SatMapCoverage.PROJ_LAMBERT; mapProjection = SatSpatialFactory.PROJ_LAMBERT;
} else if (projection.equalsIgnoreCase("MERCATOR")) { } else if (projection.equalsIgnoreCase("MERCATOR")) {
mapProjection = SatMapCoverage.PROJ_MERCATOR; mapProjection = SatSpatialFactory.PROJ_MERCATOR;
} else if (projection } else if (projection
.equalsIgnoreCase("CYLINDRICAL_EQUIDISTANT")) { .equalsIgnoreCase("CYLINDRICAL_EQUIDISTANT")) {
mapProjection = SatMapCoverage.PROJ_CYLIN_EQUIDISTANT; mapProjection = SatSpatialFactory.PROJ_CYLIN_EQUIDISTANT;
} }
} else { } else {
@ -237,10 +237,10 @@ public class RegionalSatDecoder extends AbstractDecoder {
int nx = 0, ny = 0; int nx = 0, ny = 0;
// Do specialized decoding and retrieve spatial data for projections // Do specialized decoding and retrieve spatial data for projections
if ((mapProjection == SatMapCoverage.PROJ_MERCATOR) if ((mapProjection == SatSpatialFactory.PROJ_MERCATOR)
|| (mapProjection == SatMapCoverage.PROJ_LAMBERT) || (mapProjection == SatSpatialFactory.PROJ_LAMBERT)
|| (mapProjection == SatMapCoverage.PROJ_POLAR_STEREO) || (mapProjection == SatSpatialFactory.PROJ_POLAR)
|| (mapProjection == SatMapCoverage.PROJ_CYLIN_EQUIDISTANT)) { || (mapProjection == SatSpatialFactory.PROJ_CYLIN_EQUIDISTANT)) {
// set number of points along x-axis // set number of points along x-axis
nx = recordSize; nx = recordSize;
@ -276,20 +276,10 @@ 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
// Get latitude of upper right hand corner
float urLat = 0; // not used so set to zero, if required get and set
// value
record.setUpperRightLat(urLat);
// Get longitude of upper right hand corner
float urLon = 0; // not used so set to zero, if required get and set
// value
record.setUpperRightLon(urLon);
SatMapCoverage mapCoverage = null; SatMapCoverage mapCoverage = null;
try { try {
mapCoverage = RegionalSatSpatialFactory.getInstance() mapCoverage = SatSpatialFactory.getInstance()
.getMapCoverage(mapProjection, nx, ny, dx, dy, lov, .getMapCoverage(mapProjection, nx, ny, dx, dy, lov,
latin, la1, lo1, la2, lo2); latin, la1, lo1, la2, lo2);
} catch (Exception e) { } catch (Exception e) {
@ -316,7 +306,6 @@ public class RegionalSatDecoder extends AbstractDecoder {
record.setCoverage(mapCoverage); record.setCoverage(mapCoverage);
record.setPersistenceTime(TimeTools.getSystemCalendar() record.setPersistenceTime(TimeTools.getSystemCalendar()
.getTime()); .getTime());
record.constructDataURI();
// Set the data into the IDataRecord // Set the data into the IDataRecord
IDataRecord dataRec = SatelliteRecord.getDataRecord(record); IDataRecord dataRec = SatelliteRecord.getDataRecord(record);

View file

@ -1,393 +0,0 @@
/**
*
* gov.noaa.nws.ost.edex.plugin.regionalsat.util.RegionalSatSpatialFactory
*
* 12-01-11
*
* This code has been developed by the NWS/OST/SEC for use in the AWIPS2 system.
*
**/
package gov.noaa.nws.ost.edex.plugin.regionalsat.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.geotools.geometry.DirectPosition2D;
import org.opengis.referencing.crs.ProjectedCRS;
import org.opengis.referencing.operation.MathTransform;
import com.raytheon.edex.plugin.satellite.dao.SatMapCoverageDao;
import com.raytheon.uf.common.dataplugin.satellite.SatMapCoverage;
import com.raytheon.uf.common.geospatial.MapUtil;
import com.raytheon.uf.edex.database.DataAccessLayerException;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.io.WKTReader;
/**
* The RegionalSatSpatialFactory class is responsible for creating a SatMapCoverage object.
* This class is based on the SatSpatialFactory class. TODO; The class needs to be refactored
* to reduce code duplication. The class should use the Abstract Factory Method design pattern,
* but the code refactor requires changes to the base code. A TTR has been submitted to refactor
* the Satellite spatial factory classes in edex.
*
* <pre>
*
* SOFTWARE HISTORY
*
* date Ticket# Engineer Description
* ----------- ---------- ----------- --------------------------
* 7/15/11 tk Initial Creation
* - AWIPS2 Baseline Repository --------
* 07/12/2012 798 jkorman Changed projection "magic" numbers
* </pre>
*
* @author tk
* @version 1.0
*/
public class RegionalSatSpatialFactory {
/** The logger */
private Log logger = LogFactory.getLog(getClass());
/** The singleton instance */
private static RegionalSatSpatialFactory instance;
/**
* Gets the singleton instance
*
* @return The singleton instance
*/
public static synchronized RegionalSatSpatialFactory getInstance() {
if (instance == null) {
instance = new RegionalSatSpatialFactory();
}
return instance;
}
/**
* make default constructor private to disable
* object creation from outside the class
*
*/
private RegionalSatSpatialFactory() {
}
/**
* Retrieves or generates a satellite map coverage object
*
* @param mapProjection
* The projection
* @param nx
* The number of columns
* @param ny
* The number of rows
* @param dx
* The distance between x points
* @param dy
* The distance between y points
* @param lov
* The orientation of the grid
* @param latin
* The latitude at which the Lambert projection cone is tangent
* to the earth
* @param la1
* Latitude of first point
* @param lo1
* Longitude of first point
* @param la2
* Latitude of last point
* @param lo2
* Longitude of last point
* @return A SatMapCoverage object with the given values
* @throws Exception
* If errors occur during db interaction or creation of the
* coverage object
*/
public synchronized SatMapCoverage getMapCoverage(
Integer mapProjection, Integer nx, Integer ny, Float dx, Float dy,
Float lov, Float latin, Float la1, Float lo1, Float la2, Float lo2)
throws Exception {
SatMapCoverage mapCoverage = null;
SatMapCoverageDao satDao = new SatMapCoverageDao();
try {
// Check the database to see if a coverage already exists
mapCoverage = satDao.getSatCoverage(mapProjection, nx, ny, dx, dy,
lov, latin, la1, lo1, la2, lo2);
// If the database does not contain an existing sat map coverage for
// the given values, create one
if (mapCoverage == null) {
mapCoverage = createMapCoverage(mapProjection, nx, ny, dx, dy,
lov, latin, la1, lo1, la2, lo2);
// Persist the new coverage to the database
satDao.persist(mapCoverage);
}
} catch (Exception e) {
throw new DataAccessLayerException(
"Unable to retrieve or construct valid Satellite Map Coverage",
e);
}
if (mapCoverage == null) {
throw new DataAccessLayerException(
"Unable to retrieve or construct valid Satellite Map Coverage");
}
return mapCoverage;
}
/**
* Creates a new SatMapCoverage object from scratch with the given
* parameters
*
* @param mapProjection
* The projection
* @param nx
* The number of columns
* @param ny
* The number of rows
* @param dx
* The distance between x points
* @param dy
* The distance between y points
* @param lov
* The orientation of the grid
* @param latin
* The latitude at which the Lambert projection cone is tangent
* to the earth
* @param la1
* Latitude of first point
* @param lo1
* Longitude of first point
* @param la2
* Latitude of last point
* @param lo2
* Longitude of last point
* @return A SatMapCoverage object with the given values
* @throws Exception
* If errors occur during generation of the coverage object
*/
private synchronized SatMapCoverage createMapCoverage(
Integer mapProjection, Integer nx, Integer ny, Float dx, Float dy,
Float lov, Float latin, Float la1, Float lo1, Float la2, Float lo2)
throws Exception {
logger.debug("Creating map coverage object");
ProjectedCRS crs = null;
// Get the correct CRS
if (mapProjection == SatMapCoverage.PROJ_MERCATOR) {
crs = MapUtil.constructMercator(MapUtil.AWIPS_EARTH_RADIUS,
MapUtil.AWIPS_EARTH_RADIUS, latin, lov);
} else if (mapProjection == SatMapCoverage.PROJ_LAMBERT) {
crs = MapUtil.constructLambertConformal(MapUtil.AWIPS_EARTH_RADIUS,
MapUtil.AWIPS_EARTH_RADIUS, latin, latin, lov);
} else if (mapProjection == SatMapCoverage.PROJ_CYLIN_EQUIDISTANT) {
crs = MapUtil.constructEquidistantCylindrical(MapUtil.AWIPS_EARTH_RADIUS,
MapUtil.AWIPS_EARTH_RADIUS, lov, latin);
} else {
crs = MapUtil.constructNorthPolarStereo(MapUtil.AWIPS_EARTH_RADIUS,
MapUtil.AWIPS_EARTH_RADIUS, 60, lov);
}
DirectPosition2D firstPosition = null;
DirectPosition2D secondPosition = null;
DirectPosition2D thirdPosition = null;
DirectPosition2D fourthPosition = null;
DirectPosition2D corner1 = new DirectPosition2D();
DirectPosition2D corner2 = new DirectPosition2D();
DirectPosition2D corner3 = new DirectPosition2D();
DirectPosition2D corner4 = new DirectPosition2D();
/*
* Projection is Mercator. Determine corner points from la1,lo1,la2,lo2
* provided in the satellite file. Image starts with ul corner
*/
if (mapProjection == 1) {
logger.debug("Determining corner points for Mercator projection");
corner4.x = lo1;
corner4.y = la1;
corner2.x = lo2;
corner2.y = la2;
corner3.x = lo2;
corner3.y = la1;
corner1.x = lo1;
corner1.y = la2;
}
else {
/*
* Projection is for Polar Stereographic, EquidistantCylindrical or "
* "Lambert Conformal. Therefore,the corner points must be calculated
*/
logger.debug("Determining corner points for Polar Stereographic, " +
"EquidistantCylindrical or Lambert Conformal");
// make lon values positive since -170 is the same as +190 degrees
double lon1 = 0.0f;
if (lo1 < 0.0f) {
lon1 = (180.0 + lo1) + 180.0;
} else {
lon1 = lo1;
}
double lon2 = 0.0f;
if (lo2 < 0.0f) {
lon2 = (180.0 + lo2) + 180.0;
} else {
lon2 = lo1;
}
// Get the transforms to be used to convert between meters and
// lat/lon
MathTransform fromLatLon = MapUtil.getTransformFromLatLon(crs);
MathTransform toLatLon = fromLatLon.inverse();
if (la2 < la1) {
if (lon2 < lon1) {
// Use la2 and lo2 to specify the first point starting with ll corner
logger.debug("Starting with lower left corner Fourth Position");
fourthPosition = new DirectPosition2D();
fromLatLon.transform(new DirectPosition2D(lo2, la2), fourthPosition);
logger.debug("Fourth Position:x,y " + fourthPosition.x + ", " + fourthPosition.y);
secondPosition = new DirectPosition2D();
fromLatLon.transform(new DirectPosition2D(lo1, la1), secondPosition);
logger.debug("Second Position:x,y " + secondPosition.x + ", " + secondPosition.y);
firstPosition = new DirectPosition2D(secondPosition.x, fourthPosition.y);
logger.debug(" First Position:x,y " + firstPosition.x + ", " + firstPosition.y);
thirdPosition = new DirectPosition2D(fourthPosition.x, secondPosition.y);
logger.debug("Third Position:x,y " + thirdPosition.x + ", " + thirdPosition.y);
} else {
// Use la2 and lo2 to specify the fourth point starting with lr corner
logger.debug("Polorsterographic for Alaska start with lower right corner " +
"Third Position");
thirdPosition = new DirectPosition2D();
fromLatLon.transform(new DirectPosition2D(lo2, la2), thirdPosition);
logger.debug("Third Position:x,y " + thirdPosition.x + ", " + thirdPosition.y);
firstPosition = new DirectPosition2D();
fromLatLon.transform(new DirectPosition2D(lo1, la1), firstPosition);
logger.debug("First Position:x,y " + firstPosition.x + ", " + firstPosition.y);
fourthPosition = new DirectPosition2D(thirdPosition.x, firstPosition.y);
logger.debug("Fourth Position:x,y " + fourthPosition.x + ", " + fourthPosition.y);
secondPosition = new DirectPosition2D(firstPosition.x, thirdPosition.y);
logger.debug("Second Position:x,y " + secondPosition.x + ", " + secondPosition.y);
}
} else {
if (lon2 < lon1) {
// Use la2 and lo2 to specify the first point starting with ul corner
logger.debug("Starting with lower upper left Fourth Position");
firstPosition = new DirectPosition2D();
fromLatLon.transform(new DirectPosition2D(lo2, la2), firstPosition);
logger.debug("First Position:x,y " + firstPosition.x + ", " + firstPosition.y);
thirdPosition = new DirectPosition2D();
fromLatLon.transform(new DirectPosition2D(lo1, la1), thirdPosition);
logger.debug("Third Position:x,y " + thirdPosition.x + ", " + thirdPosition.y);
secondPosition = new DirectPosition2D(firstPosition.x, thirdPosition.y);
logger.debug("Second Position:x,y " + secondPosition.x + ", " + secondPosition.y);
fourthPosition = new DirectPosition2D(thirdPosition.x, firstPosition.y);
logger.debug("Fourth Position:x,y " + fourthPosition.x + ", " + fourthPosition.y);
} else {
// Use la2 and lo2 to specify the fourth point starting with ur corner
logger.debug("Starting with lower right corner Fourth Position");
secondPosition = new DirectPosition2D();
fromLatLon.transform(new DirectPosition2D(lo2, la2), secondPosition);
logger.debug("Second Position:x,y " + secondPosition.x + ", " + secondPosition.y);
fourthPosition = new DirectPosition2D();
fromLatLon.transform(new DirectPosition2D(lo1, la1), fourthPosition);
logger.debug("Fourth Position:x,y " + fourthPosition.x + ", " + fourthPosition.y);
firstPosition = new DirectPosition2D(secondPosition.x, fourthPosition.y);
logger.debug("First Position:x,y " + firstPosition.x + ", " + firstPosition.y);
thirdPosition = new DirectPosition2D(fourthPosition.x, secondPosition.y);
logger.debug("Third Position:x,y " + thirdPosition.x + ", " + thirdPosition.y);
}
}
// Convert the corner points from meters to lat/lon
toLatLon.transform(firstPosition, corner1);
toLatLon.transform(secondPosition, corner2);
toLatLon.transform(thirdPosition, corner3);
toLatLon.transform(fourthPosition, corner4);
logger.debug("First Corner:" + corner1.toString());
logger.debug("Second Corner:" + corner2.toString());
logger.debug("Third Corner:" + corner3.toString());
logger.debug("Fourth Corner:" + corner4.toString());
}
/*
* Projection is EquidistantCylindrical or Polar Stereographic. Therefore,
* the corner points must be calculated
*/
// Construct the polygon constructor String
StringBuffer buffer = new StringBuffer();
buffer.append("POLYGON((");
buffer.append(corner4.x + " " + corner4.y + ",");
buffer.append(corner1.x + " " + corner1.y + ",");
buffer.append(corner2.x + " " + corner2.y + ",");
buffer.append(corner3.x + " " + corner3.y + ",");
buffer.append(corner4.x + " " + corner4.y);
buffer.append("))");
logger.debug("Polygon: " + buffer.toString());
// Create the geometry from the constructed String
Geometry geometry = new WKTReader().read(buffer.toString());
la2 = (float)corner2.y;
lo2 = (float)corner2.x;
la1 = (float)corner4.y;
lo1 = (float)corner4.x;
logger.debug("(Lo1, La1),(lo2, La2) (" + lo1 + ", " + la1 + "), (" + lo2 + ", " + la2 +")");
SatMapCoverage mapCoverage = new SatMapCoverage(mapProjection,
nx, ny, dx, dy, lov, latin, la1, lo1, la2, lo2, crs, geometry);
return mapCoverage;
}
}