diff --git a/cave/com.raytheon.viz.gfe/plugin.xml b/cave/com.raytheon.viz.gfe/plugin.xml index 8f927fefb0..4751c2243d 100644 --- a/cave/com.raytheon.viz.gfe/plugin.xml +++ b/cave/com.raytheon.viz.gfe/plugin.xml @@ -362,6 +362,12 @@ id="com.raytheon.viz.gfe.SiteActivation" name="GFE Site Activation"> + + + + @@ -1143,6 +1153,13 @@ label="Site Activation..." style="push"> + diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/actions/CoordinateConversionHandler.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/actions/CoordinateConversionHandler.java new file mode 100644 index 0000000000..9dcd8f7b9d --- /dev/null +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/actions/CoordinateConversionHandler.java @@ -0,0 +1,83 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.viz.gfe.actions; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; + +import com.raytheon.viz.gfe.core.DataManager; +import com.raytheon.viz.gfe.core.DataManagerUIFactory; +import com.raytheon.viz.gfe.dialogs.CoordinateConversionDialog; + +/** + * Handler to display the Coordinate Conversion Dialog + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * May 13, 2014  #3069     randerso    Added to help debug GeoTools 10.5 issues.
+ *                                     May partially address Dimensions DR 15463
+ *                                     plugin.xml menu entry commented out so can't be activated
+ * 
+ * 
+ * + * @author randerso + * @version 1.0 + */ + +public class CoordinateConversionHandler extends AbstractHandler { + + private CoordinateConversionDialog dialog; + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands. + * ExecutionEvent) + */ + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + DataManager dm = DataManagerUIFactory.getCurrentInstance(); + if (dm == null) { + return null; + } + + if ((dialog == null) || (dialog.getShell() == null) + || dialog.isDisposed()) { + Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow() + .getShell(); + + dialog = new CoordinateConversionDialog(shell, dm); + dialog.setBlockOnOpen(false); + dialog.open(); + } else { + dialog.bringToTop(); + } + return null; + } + +} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/CoordinateConversionDialog.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/CoordinateConversionDialog.java new file mode 100644 index 0000000000..1cc28641ee --- /dev/null +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/CoordinateConversionDialog.java @@ -0,0 +1,307 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.viz.gfe.dialogs; + +import java.text.DecimalFormat; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.opengis.metadata.spatial.PixelOrientation; + +import com.raytheon.uf.common.dataplugin.gfe.config.ProjectionData; +import com.raytheon.uf.common.dataplugin.gfe.db.objects.GridLocation; +import com.raytheon.uf.common.geospatial.MapUtil; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.viz.gfe.core.DataManager; +import com.raytheon.viz.ui.dialogs.CaveJFACEDialog; +import com.vividsolutions.jts.geom.Coordinate; + +/** + * Coordinate Conversion Dialog + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * May 13, 2014  #3069     randerso    Added to help debug GeoTools 10.5 issues.
+ *                                     May partially address Dimensions DR 15463.
+ *                                     plugin.xml menu entry comnmented out so can't be activated
+ * 
+ * 
+ * + * @author randerso + * @version 1.0 + */ + +public class CoordinateConversionDialog extends CaveJFACEDialog { + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(CoordinateConversionDialog.class); + + private DataManager dataMgr; + + private GridLocation gloc; + + private ProjectionData awipsProj; + + private DecimalFormat df; + + private Text lonText; + + private Text latText; + + private Text awipsXText; + + private Text awipsYText; + + private Text gfeXText; + + private Text gfeYText; + + /** + * @param parentShell + * @param dataMgr + */ + public CoordinateConversionDialog(Shell parentShell, DataManager dataMgr) { + super(parentShell); + this.dataMgr = dataMgr; + + gloc = this.dataMgr.getParmManager().compositeGridLocation(); + awipsProj = gloc.getProjection(); + + df = new DecimalFormat("###0.####;-###0.####"); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets + * .Shell) + */ + @Override + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + newShell.setText("Coordinate Conversion"); + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.viz.ui.dialogs.CaveJFACEDialog#createDialogArea(org.eclipse + * .swt.widgets.Composite) + */ + @Override + protected Control createDialogArea(Composite parent) { + Composite comp = (Composite) super.createDialogArea(parent); + ((GridLayout) comp.getLayout()).numColumns = 3; + + // listener to validate numeric entry and update computed fields + KeyListener keyListener = new KeyListener() { + + @Override + public void keyReleased(KeyEvent e) { + if (e.character != '.') { + Object source = e.getSource(); + if ((source == lonText) || (source == latText)) { + updateLonLat(); + } else if ((source == awipsXText) || (source == awipsYText)) { + updateAwips(); + } else if ((source == gfeXText) || (source == gfeYText)) { + updateGfe(); + } + } + } + + @Override + public void keyPressed(KeyEvent e) { + if (!Character.isISOControl(e.character)) { + Text source = (Text) e.getSource(); + String text = source.getText(); + Point selection = source.getSelection(); + text = text.substring(0, selection.x) + e.character + + text.substring(selection.y); + try { + Double.parseDouble(text); + } catch (NumberFormatException e1) { + e.doit = false; + getShell().getDisplay().beep(); + } + } + } + }; + + Label label = new Label(comp, SWT.RIGHT); + GridData layoutData = new GridData(SWT.FILL, SWT.CENTER, true, false); + label.setLayoutData(layoutData); + label.setText("Lon/Lat"); + + lonText = new Text(comp, SWT.RIGHT | SWT.SINGLE | SWT.BORDER); + layoutData = new GridData(SWT.FILL, SWT.CENTER, true, false); + lonText.setLayoutData(layoutData); + lonText.addKeyListener(keyListener); + + latText = new Text(comp, SWT.RIGHT | SWT.SINGLE | SWT.BORDER); + layoutData = new GridData(SWT.FILL, SWT.CENTER, true, false); + latText.setLayoutData(layoutData); + latText.addKeyListener(keyListener); + + label = new Label(comp, SWT.RIGHT); + layoutData = new GridData(SWT.FILL, SWT.CENTER, true, false); + label.setLayoutData(layoutData); + label.setText(gloc.getProjection().getProjectionID()); + + awipsXText = new Text(comp, SWT.RIGHT | SWT.SINGLE | SWT.BORDER); + layoutData = new GridData(SWT.FILL, SWT.CENTER, true, false); + awipsXText.setLayoutData(layoutData); + awipsXText.addKeyListener(keyListener); + + awipsYText = new Text(comp, SWT.RIGHT | SWT.SINGLE | SWT.BORDER); + layoutData = new GridData(SWT.FILL, SWT.CENTER, true, false); + awipsYText.setLayoutData(layoutData); + awipsYText.addKeyListener(keyListener); + + label = new Label(comp, SWT.RIGHT); + layoutData = new GridData(SWT.FILL, SWT.CENTER, true, false); + label.setLayoutData(layoutData); + label.setText(gloc.getSiteId()); + + gfeXText = new Text(comp, SWT.RIGHT | SWT.SINGLE | SWT.BORDER); + layoutData = new GridData(SWT.FILL, SWT.CENTER, true, false); + gfeXText.setLayoutData(layoutData); + gfeXText.addKeyListener(keyListener); + + gfeYText = new Text(comp, SWT.RIGHT | SWT.SINGLE | SWT.BORDER); + layoutData = new GridData(SWT.FILL, SWT.CENTER, true, false); + gfeYText.setLayoutData(layoutData); + gfeYText.addKeyListener(keyListener); + + gfeXText.setText("0"); + gfeYText.setText("0"); + + updateGfe(); + + return comp; + } + + private double getDoubleValue(Text text) { + String s = text.getText(); + if (s.isEmpty()) { + return 0; + } else { + return Double.parseDouble(s); + } + } + + private void updateLonLat() { + double lon = getDoubleValue(lonText); + double lat = getDoubleValue(latText); + Coordinate lonLat = new Coordinate(lon, lat); + // lonText.setText(df.format(lon)); + // latText.setText(df.format(lat)); + + try { + Coordinate gridCell = MapUtil.latLonToGridCoordinate(lonLat, + PixelOrientation.CENTER, gloc); + gfeXText.setText(df.format(gridCell.x)); + gfeYText.setText(df.format(gloc.getNy() - gridCell.y - 1)); + } catch (Exception e) { + statusHandler.error(e.getLocalizedMessage(), e); + gfeXText.setText(""); + gfeYText.setText(""); + } + + try { + Coordinate awips = awipsProj.latLonToGridCoordinate(lonLat); + awipsXText.setText(df.format(awips.x)); + awipsYText.setText(df.format(awips.y)); + } catch (Exception e) { + statusHandler.error(e.getLocalizedMessage(), e); + awipsXText.setText(""); + awipsYText.setText(""); + } + } + + private void updateAwips() { + double x = getDoubleValue(awipsXText); + double y = getDoubleValue(awipsYText); + // awipsXText.setText(df.format(x)); + // awipsYText.setText(df.format(y)); + + Coordinate awips = new Coordinate(x, y); + Coordinate lonLat; + try { + lonLat = awipsProj.gridCoordinateToLatLon(awips); + lonText.setText(df.format(lonLat.x)); + latText.setText(df.format(lonLat.y)); + + try { + Coordinate gridCell = MapUtil.latLonToGridCoordinate(lonLat, + PixelOrientation.CENTER, gloc); + gfeXText.setText(df.format(gridCell.x)); + gfeYText.setText(df.format(gloc.getNy() - gridCell.y - 1)); + } catch (Exception e) { + statusHandler.error(e.getLocalizedMessage(), e); + gfeXText.setText(""); + gfeYText.setText(""); + } + } catch (Exception e) { + statusHandler.error(e.getLocalizedMessage(), e); + lonText.setText(""); + latText.setText(""); + gfeXText.setText(""); + gfeYText.setText(""); + } + } + + private void updateGfe() { + double x = getDoubleValue(gfeXText); + double y = getDoubleValue(gfeYText); + Coordinate gridCell = new Coordinate(x, gloc.getNy() - y - 1); + // gfeXText.setText(df.format(x)); + // gfeYText.setText(df.format(y)); + + Coordinate lonLat = gloc.latLonCenter(gridCell); + lonText.setText(df.format(lonLat.x)); + latText.setText(df.format(lonLat.y)); + + try { + Coordinate awips = awipsProj.latLonToGridCoordinate(lonLat); + awipsXText.setText(df.format(awips.x)); + awipsYText.setText(df.format(awips.y)); + } catch (Exception e) { + statusHandler.error(e.getLocalizedMessage(), e); + awipsXText.setText(""); + awipsYText.setText(""); + } + } +} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/JTSRenderable.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/JTSRenderable.java index 1a45f3c2c6..48b2cbf1ef 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/JTSRenderable.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/JTSRenderable.java @@ -25,6 +25,7 @@ import org.eclipse.swt.graphics.RGB; import com.raytheon.uf.viz.core.IGraphicsTarget; import com.raytheon.uf.viz.core.IGraphicsTarget.LineStyle; +import com.raytheon.uf.viz.core.drawables.IDescriptor; import com.raytheon.uf.viz.core.drawables.IFont; import com.raytheon.uf.viz.core.drawables.IRenderable; import com.raytheon.uf.viz.core.drawables.IWireframeShape; @@ -46,6 +47,9 @@ import com.vividsolutions.jts.geom.Geometry; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * May 5, 2008 chammack Initial creation + * May 15, 2014 #3069 randerso Made labelSpacing settable. + * Fixed label coordinates after ReferencedGeometry + * was made non-destructive. * * * @@ -63,6 +67,8 @@ public class JTSRenderable implements IRenderable { private RGB color = ColorUtil.WHITE; + private int labelSpacing = 50; + /** * @return the color */ @@ -93,6 +99,10 @@ public class JTSRenderable implements IRenderable { this.lineWidth = lineWidth; } + public void setLabelSpacing(int labelSpacing) { + this.labelSpacing = labelSpacing; + } + private float lineWidth = 1.0f; public JTSRenderable() { @@ -127,17 +137,17 @@ public class JTSRenderable implements IRenderable { @Override public void paint(IGraphicsTarget target, PaintProperties paintProps) throws VizException { - EditToolPaintProperties etpp = (EditToolPaintProperties) paintProps; + IDescriptor descriptor = ((EditToolPaintProperties) paintProps) + .getDescriptor(); if (this.wireframeShape == null) { - this.wireframeShape = target.createWireframeShape(true, - etpp.getDescriptor()); + this.wireframeShape = target.createWireframeShape(true, descriptor); } if (!this.pendingGeometies.isEmpty()) { JTSCompiler jtsCompiler = new JTSCompiler(null, wireframeShape, - etpp.getDescriptor()); + descriptor); while (!this.pendingGeometies.isEmpty()) { Geometry geom = this.pendingGeometies.remove(); jtsCompiler.handle(geom); @@ -146,10 +156,11 @@ public class JTSRenderable implements IRenderable { String label = (String) geom.getUserData(); double[] coord = new double[2]; int numCoords = geom.getNumPoints(); - for (int j = 0; j < numCoords; j += 50) { + for (int j = 0; j < numCoords; j += this.labelSpacing) { Coordinate c = geom.getCoordinates()[j]; coord[0] = c.x; coord[1] = c.y; + coord = descriptor.worldToPixel(coord); this.wireframeShape.addLabel(label, coord); } } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/contour/ContourTool.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/contour/ContourTool.java index e5d5215721..de88952b25 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/contour/ContourTool.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/contour/ContourTool.java @@ -117,6 +117,8 @@ import com.vividsolutions.jts.geom.LineString; * drawing and calculating new grid. * Aug 08, 2012 #621 dgilling Fix ConcurrentModificationException * in handling of renderables field. + * May 15, 2014 #3069 randerso Changed to compute contour label spacing variable + * based on subsample setting * * * @@ -212,7 +214,7 @@ public class ContourTool extends AbstractFreeformTool implements Point gridSize = gloc.gridSize(); int newX = ((gridSize.x - 1) / subFactor) + 1; int newY = ((gridSize.y - 1) / subFactor) + 1; - if (newX <= 5 || newY <= 5) { + if ((newX <= 5) || (newY <= 5)) { int tmpX = gridSize.x / 5; int tmpY = gridSize.y / 5; subFactor = Math.min(tmpX, tmpY); @@ -228,14 +230,14 @@ public class ContourTool extends AbstractFreeformTool implements } private RemapGrid getToLowRes() { - if (toLowRes == null && currentGrid != null) { + if ((toLowRes == null) && (currentGrid != null)) { computeRemaps(); } return toLowRes; } private RemapGrid getToHiRes() { - if (toHiRes == null && currentGrid != null) { + if ((toHiRes == null) && (currentGrid != null)) { computeRemaps(); } return toHiRes; @@ -319,9 +321,6 @@ public class ContourTool extends AbstractFreeformTool implements refresh(); } - /** - * - */ private void replaceCLines(List contours) { clearRenderables(); @@ -335,6 +334,7 @@ public class ContourTool extends AbstractFreeformTool implements JTSRenderable renderable = new JTSRenderable(); renderable.setLineWidth(2.0f); renderable.setColor(contourColor); + renderable.setLabelSpacing(200 / subSample); for (CLine contour : contours) { LineString ls = contour.getLineString(); if (ls == null) { @@ -1141,8 +1141,8 @@ public class ContourTool extends AbstractFreeformTool implements sumLoc.x += coords.get(i).x; sumLoc.y += coords.get(i).y; } - sumLoc.x = sumLoc.x / (end - start + 1); - sumLoc.y = sumLoc.y / (end - start + 1); + sumLoc.x = sumLoc.x / ((end - start) + 1); + sumLoc.y = sumLoc.y / ((end - start) + 1); return sumLoc; } else { int i; @@ -1154,8 +1154,8 @@ public class ContourTool extends AbstractFreeformTool implements sumLoc.x += coords.get(i).x; sumLoc.y += coords.get(i).y; } - sumLoc.x = sumLoc.x / (start - end + 1); - sumLoc.y = sumLoc.y / (start - end + 1); + sumLoc.x = sumLoc.x / ((start - end) + 1); + sumLoc.y = sumLoc.y / ((start - end) + 1); return sumLoc; } } @@ -1182,7 +1182,7 @@ public class ContourTool extends AbstractFreeformTool implements double distance = line.getCoordinateN(0).distance( line.getCoordinateN(line.getNumPoints() - 1)); - if (distance < 3 * (cellSize.x + cellSize.y) / 2) { + if (distance < ((3 * (cellSize.x + cellSize.y)) / 2)) { return true; } @@ -1260,7 +1260,7 @@ public class ContourTool extends AbstractFreeformTool implements public void addContextMenuItems(IMenuManager menuManager, int x, int y) { Parm activeParm = dataManager.getSpatialDisplayManager() .getActivatedParm(); - if (activeParm != null + if ((activeParm != null) && activeParm.getGridInfo().getGridType() .equals(GridType.SCALAR)) { @@ -1668,7 +1668,7 @@ public class ContourTool extends AbstractFreeformTool implements @Override public void gridDataChanged(ParmID parmId, TimeRange validTime) { - if (currentGrid != null + if ((currentGrid != null) && currentGrid.getParm().getParmID().equals(parmId) && currentGrid.getGridTime().equals(validTime)) { initializeContourData(getGrid()); @@ -1681,7 +1681,7 @@ public class ContourTool extends AbstractFreeformTool implements @Override public void parmInventoryChanged(Parm parm, TimeRange affectedTimeRange) { - if (currentGrid != null + if ((currentGrid != null) && parm.getParmID().equals(currentGrid.getParm().getParmID()) && affectedTimeRange.contains(currentGrid.getGridTime())) { initializeContourData(getGrid()); diff --git a/edexOsgi/com.raytheon.edex.common/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.edex.common/META-INF/MANIFEST.MF index 7443dd8238..b2883bef29 100644 --- a/edexOsgi/com.raytheon.edex.common/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.edex.common/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Common Plug-in Bundle-SymbolicName: com.raytheon.edex.common -Bundle-Version: 1.12.1174.qualifier +Bundle-Version: 1.14.0 Bundle-Vendor: RAYTHEON Eclipse-BuddyPolicy: registered, ext, global Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization @@ -18,7 +18,6 @@ Export-Package: com.raytheon.edex.colormap, com.raytheon.edex.plugin.factory, com.raytheon.edex.site, com.raytheon.edex.subscription, - com.raytheon.edex.topo, com.raytheon.edex.urifilter, com.raytheon.edex.util, com.raytheon.edex.utility diff --git a/edexOsgi/com.raytheon.edex.common/unit-test/com/raytheon/edex/topo/GridLocation.java b/edexOsgi/com.raytheon.edex.common/unit-test/com/raytheon/edex/topo/GridLocation.java deleted file mode 100644 index fc350b4784..0000000000 --- a/edexOsgi/com.raytheon.edex.common/unit-test/com/raytheon/edex/topo/GridLocation.java +++ /dev/null @@ -1,178 +0,0 @@ -/** - * 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.edex.topo; - -import org.geotools.coverage.grid.GeneralGridEnvelope; -import org.geotools.coverage.grid.GridGeometry2D; -import org.geotools.geometry.GeneralEnvelope; -import org.geotools.referencing.CRS; -import org.geotools.referencing.operation.DefaultMathTransformFactory; -import org.opengis.metadata.spatial.PixelOrientation; -import org.opengis.referencing.FactoryException; -import org.opengis.referencing.crs.CoordinateReferenceSystem; -import org.opengis.referencing.operation.MathTransform; - -import com.raytheon.uf.common.geospatial.CRSCache; -import com.raytheon.uf.common.geospatial.ISpatialObject; -import com.raytheon.uf.common.geospatial.MapUtil; -import com.vividsolutions.jts.geom.Coordinate; -import com.vividsolutions.jts.geom.Polygon; - -public class GridLocation implements ISpatialObject { - - private CoordinateReferenceSystem crsObject; - - private Polygon geometry; - - private Integer nx; - - private Integer ny; - - private String crsWKT; - - private Coordinate extent; - - private Coordinate origin; - - private ProjectionData projection; - - /** - * @param data - * @param gridSize - * @param domainOrigin - * @param domainExtent - */ - public GridLocation(ProjectionData proj, java.awt.Point gridSize, - Coordinate domainOrigin, Coordinate domainExtent) { - try { - this.nx = gridSize.x; - this.ny = gridSize.y; - this.projection = proj; - this.origin = domainOrigin; - this.extent = domainExtent; - this.crsObject = proj.getCRS(); - this.crsWKT = this.crsObject.toWKT(); - - // transform the projection corner points to CRS units - MathTransform mt = MapUtil.getTransformFromLatLon(this.crsObject); - double[] output = new double[4]; - mt.transform( - new double[] { proj.getLatLonLL().x, proj.getLatLonLL().y, - proj.getLatLonUR().x, proj.getLatLonUR().y }, 0, - output, 0, 2); - - // create a grid geometry for the projection - GeneralEnvelope ge = new GeneralEnvelope(2); - ge.setCoordinateReferenceSystem(this.crsObject); - ge.setRange(0, Math.min(output[0], output[2]), - Math.max(output[0], output[2])); - ge.setRange(1, Math.min(output[1], output[3]), - Math.max(output[1], output[3])); - - GeneralGridEnvelope gr = new GeneralGridEnvelope(new int[] { - proj.getGridPointLL().x, proj.getGridPointLL().y }, - new int[] { proj.getGridPointUR().x + 1, - proj.getGridPointUR().y + 1 }, false); - - GridGeometry2D projGeom = new GridGeometry2D(gr, ge); - - DefaultMathTransformFactory dmtf = new DefaultMathTransformFactory(); - double[] latLon = new double[8]; - - // transform the grid corners from grid coordinates to CRS units - // need to adjust for the fact that AWIPS considers 1,1 to be in - // lower left and GeoTools considers 1,1 to be in upper left - Coordinate ll = new Coordinate(domainOrigin.x, - proj.getGridPointUR().y - domainOrigin.y - + proj.getGridPointLL().y); - Coordinate ur = new Coordinate(domainOrigin.x + domainExtent.x, - ll.y - domainExtent.y); - - mt.transform(new double[] { ll.x, ll.y, ur.x, ur.y }, 0, output, 0, - 2); - - mt = projGeom.getGridToCRS(PixelOrientation.UPPER_LEFT); - output = new double[4]; - mt.transform(new double[] { ll.x, ll.y, ur.x, ur.y }, 0, output, 0, - 2); - - // construct the grid geometry that covers the GFE grid - ge.setRange(0, Math.min(output[0], output[2]), - Math.max(output[0], output[2])); - ge.setRange(1, Math.min(output[1], output[3]), - Math.max(output[1], output[3])); - GridGeometry2D gridGeom = new GridGeometry2D( - new GeneralGridEnvelope(new int[] { 0, 0 }, new int[] { - this.nx, this.ny }, false), ge); - - // set up the transform from grid coordinates to lon/lat - mt = dmtf.createConcatenatedTransform( - gridGeom.getGridToCRS(PixelOrientation.CENTER), - MapUtil.getTransformToLatLon(crsObject)); - - // transform grid corner points to Lat/Lon - mt.transform(new double[] { -1.0, this.ny - 1, -1.0, -1.0, - this.nx - 1, -1.0, this.nx - 1, this.ny - 1 }, 0, latLon, - 0, 4); - - Coordinate[] corners = new Coordinate[] { - MapUtil.getCoordinate(latLon[0], latLon[1]), - MapUtil.getCoordinate(latLon[2], latLon[3]), - MapUtil.getCoordinate(latLon[4], latLon[5]), - MapUtil.getCoordinate(latLon[6], latLon[7]), - MapUtil.getCoordinate(latLon[0], latLon[1]) }; - - this.geometry = MapUtil.getPolygon(corners); - - // this.geometry = new Polygon(new LinearRing[] { shell }); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - @Override - public CoordinateReferenceSystem getCrs() { - if (crsObject == null) { - try { - crsObject = CRSCache.getInstance() - .getCoordinateReferenceSystem(crsWKT); - } catch (FactoryException e) { - crsObject = null; - } - } - return crsObject; - } - - @Override - public Polygon getGeometry() { - return geometry; - } - - @Override - public Integer getNx() { - return nx; - } - - @Override - public Integer getNy() { - return ny; - } -} diff --git a/edexOsgi/com.raytheon.edex.common/unit-test/com/raytheon/edex/topo/ProjectionData.java b/edexOsgi/com.raytheon.edex.common/unit-test/com/raytheon/edex/topo/ProjectionData.java deleted file mode 100644 index 4b8ac7e9b3..0000000000 --- a/edexOsgi/com.raytheon.edex.common/unit-test/com/raytheon/edex/topo/ProjectionData.java +++ /dev/null @@ -1,282 +0,0 @@ -/** - * 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.edex.topo; - -import java.awt.Point; - -import org.opengis.referencing.crs.CoordinateReferenceSystem; - -import com.raytheon.uf.common.geospatial.MapUtil; -import com.vividsolutions.jts.geom.Coordinate; - -public class ProjectionData { - - private static float COMPARISON_THRESHOLD = 0.005f; - - public static enum ProjectionType { - NONE, LAMBERT_CONFORMAL, MERCATOR, POLAR_STEREOGRAPHIC, LATLON - }; - - private String projectionID; - - private ProjectionType projectionType; - - private Coordinate latLonLL; - - private Coordinate latLonUR; - - private Coordinate latLonOrigin; - - private double stdParallelOne; - - private double stdParallelTwo; - - private Point gridPointLL; - - private Point gridPointUR; - - private double latIntersect; - - private double lonCenter; - - private double lonOrigin; - - public ProjectionData() { - latLonLL = new Coordinate(); - latLonUR = new Coordinate(); - latLonOrigin = new Coordinate(); - gridPointLL = new Point(); - gridPointUR = new Point(); - } - - public ProjectionData(String projID, int projType, Coordinate latLonLL, - Coordinate latLonUR, Coordinate latLonOrig, float stdPar1, - float stdPar2, Point gridLL, Point gridUR, float latInt, - float lonCenter, float lonOrig) { - this(); - - this.projectionID = projID; - this.projectionType = ProjectionType.values()[projType]; - this.latLonLL = latLonLL; - this.latLonUR = latLonUR; - this.latLonOrigin = latLonOrig; - this.stdParallelOne = stdPar1; - this.stdParallelTwo = stdPar2; - this.gridPointLL = gridLL; - this.gridPointUR = gridUR; - this.latIntersect = latInt; - this.lonCenter = lonCenter; - this.lonOrigin = lonOrig; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - String result = "{"; - - result += projectionType + ", "; - result += latLonLL + ", "; - result += latLonUR + ", "; - result += latLonOrigin + ", "; - result += stdParallelOne + ", "; - result += stdParallelTwo + ", "; - result += gridPointLL + ", "; - result += gridPointUR + ", "; - result += latIntersect + ", "; - result += lonCenter + ", "; - result += lonOrigin; - - result += "}"; - return result; - } - - /** - * @return - */ - public CoordinateReferenceSystem getCRS() { - // construct the appropriate CRS based on the projection type - CoordinateReferenceSystem crs = null; - switch (this.projectionType) { - case LAMBERT_CONFORMAL: - crs = MapUtil.constructLambertConformal(MapUtil.AWIPS_EARTH_RADIUS, - MapUtil.AWIPS_EARTH_RADIUS, this.stdParallelOne, - this.stdParallelTwo, this.latLonOrigin.x); - break; - - case MERCATOR: - crs = MapUtil.constructMercator(MapUtil.AWIPS_EARTH_RADIUS, - MapUtil.AWIPS_EARTH_RADIUS, this.stdParallelOne, - this.lonCenter); - break; - - case POLAR_STEREOGRAPHIC: - crs = MapUtil.constructNorthPolarStereo(MapUtil.AWIPS_EARTH_RADIUS, - MapUtil.AWIPS_EARTH_RADIUS, 60.0, this.lonOrigin); - break; - - case LATLON: - crs = MapUtil.LATLON_PROJECTION; - break; - - case NONE: - default: - System.out.println("ERROR: unknown projection type: " - + this.projectionType); - } - - return crs; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof ProjectionData)) { - return false; - } - - ProjectionData rhs = (ProjectionData) obj; - if (!this.getProjectionType().equals(rhs.getProjectionType())) { - return false; - } - - if (Math.abs(this.latLonLL.y - rhs.latLonLL.y) > COMPARISON_THRESHOLD - || Math.abs(this.latLonLL.x - rhs.latLonLL.x) > COMPARISON_THRESHOLD - || Math.abs(this.latLonUR.y - rhs.latLonUR.y) > COMPARISON_THRESHOLD - || Math.abs(this.latLonLL.x - rhs.latLonLL.x) > COMPARISON_THRESHOLD) { - return false; - } - - // specific projection comparisons - switch (this.projectionType) { - case LAMBERT_CONFORMAL: - return (Math.abs(this.latLonOrigin.y - rhs.latLonOrigin.y) < COMPARISON_THRESHOLD - || Math.abs(this.latLonOrigin.x - rhs.latLonOrigin.x) < COMPARISON_THRESHOLD - || Math.abs(this.stdParallelOne - rhs.stdParallelOne) < COMPARISON_THRESHOLD || Math - .abs(this.stdParallelTwo - rhs.stdParallelTwo) < COMPARISON_THRESHOLD); - case POLAR_STEREOGRAPHIC: - return (Math.abs(this.lonOrigin - rhs.lonOrigin) < COMPARISON_THRESHOLD); - case MERCATOR: - return (Math.abs(this.lonCenter - rhs.lonCenter) < COMPARISON_THRESHOLD); - case LATLON: - return true; - default: - return false; - } - } - - public String getProjectionID() { - return projectionID; - } - - public ProjectionType getProjectionType() { - return projectionType; - } - - public Coordinate getLatLonLL() { - return latLonLL; - } - - public Coordinate getLatLonUR() { - return latLonUR; - } - - public Coordinate getLatLonOrigin() { - return latLonOrigin; - } - - public double getStdParallelOne() { - return stdParallelOne; - } - - public double getStdParallelTwo() { - return stdParallelTwo; - } - - public Point getGridPointLL() { - return gridPointLL; - } - - public Point getGridPointUR() { - return gridPointUR; - } - - public double getLatIntersect() { - return latIntersect; - } - - public double getLonCenter() { - return lonCenter; - } - - public double getLonOrigin() { - return lonOrigin; - } - - public void setProjectionID(String projectionID) { - this.projectionID = projectionID; - } - - public void setProjectionType(ProjectionType projectionType) { - this.projectionType = projectionType; - } - - public void setLatLonLL(Coordinate latLonLL) { - this.latLonLL = latLonLL; - } - - public void setLatLonUR(Coordinate latLonUR) { - this.latLonUR = latLonUR; - } - - public void setLatLonOrigin(Coordinate latLonOrigin) { - this.latLonOrigin = latLonOrigin; - } - - public void setStdParallelOne(double stdParallelOne) { - this.stdParallelOne = stdParallelOne; - } - - public void setStdParallelTwo(double stdParallelTwo) { - this.stdParallelTwo = stdParallelTwo; - } - - public void setGridPointLL(Point gridPointLL) { - this.gridPointLL = gridPointLL; - } - - public void setGridPointUR(Point gridPointUR) { - this.gridPointUR = gridPointUR; - } - - public void setLatIntersect(double latIntersect) { - this.latIntersect = latIntersect; - } - - public void setLonCenter(double lonCenter) { - this.lonCenter = lonCenter; - } - - public void setLonOrigin(double lonOrigin) { - this.lonOrigin = lonOrigin; - } -} diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/smartinit/SmartInitTransactions.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/smartinit/SmartInitTransactions.java index 0f5817858a..f3de33bf3d 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/smartinit/SmartInitTransactions.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/smartinit/SmartInitTransactions.java @@ -37,13 +37,13 @@ import org.hibernate.criterion.Restrictions; import com.raytheon.edex.plugin.gfe.smartinit.SmartInitRecordPK.State; import com.raytheon.uf.edex.database.cluster.ClusterLockUtils; -import com.raytheon.uf.edex.database.cluster.ClusterTask; import com.raytheon.uf.edex.database.cluster.ClusterLockUtils.LockState; +import com.raytheon.uf.edex.database.cluster.ClusterTask; import com.raytheon.uf.edex.database.dao.CoreDao; import com.raytheon.uf.edex.database.dao.DaoConfig; /** - * TODO Add Description + * SmartInit Transactions * *
  * 
@@ -51,6 +51,8 @@ import com.raytheon.uf.edex.database.dao.DaoConfig;
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
  * Apr 12, 2010            njensen     Initial creation
+ * May 20, 2014 #3069      randerso    Added validTime to sort order when 
+ *                                     choosing next smartInit to run
  * 
  * 
* @@ -104,8 +106,8 @@ public class SmartInitTransactions { LockOptions.UPGRADE); // double check to make sure another process hasn't // already grabbed it and the run didn't finish - if (record != null - && record.getInsertTime().getTime() < timeOutCheck) { + if ((record != null) + && (record.getInsertTime().getTime() < timeOutCheck)) { logger.info("Running smartInit " + record.getId() + " timed out. Rerunning smartInit."); record.setInsertTime(new Date(System @@ -120,8 +122,9 @@ public class SmartInitTransactions { // query the pending table for available inits Criteria pendingCrit = sess.createCriteria(SmartInitRecord.class); - pendingCrit.addOrder(Order.asc("priority")).addOrder( - Order.asc("insertTime")); + pendingCrit.addOrder(Order.asc("priority")) + .addOrder(Order.asc("insertTime")) + .addOrder(Order.asc("id.validTime")); long pendingTimeRest = System.currentTimeMillis() - pendingInitMinTimeMillis; @@ -151,8 +154,8 @@ public class SmartInitTransactions { record.getId(), LockOptions.UPGRADE); // double check its still valid - if (record != null - && record.getInsertTime().getTime() <= pendingTimeRest) { + if ((record != null) + && (record.getInsertTime().getTime() <= pendingTimeRest)) { sess.delete(record); // can we update primary key in place?? or do we need to // delete then add diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/config/ProjectionData.java b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/config/ProjectionData.java index 2d0b1203b0..3f727c93b3 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/config/ProjectionData.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/config/ProjectionData.java @@ -20,7 +20,6 @@ package com.raytheon.uf.common.dataplugin.gfe.config; import java.awt.Point; -import java.util.HashMap; import javax.persistence.Column; import javax.persistence.Embeddable; @@ -29,14 +28,15 @@ import javax.persistence.Enumerated; import javax.persistence.Transient; import org.geotools.coverage.grid.GeneralGridEnvelope; -import org.geotools.coverage.grid.GridGeometry2D; import org.geotools.geometry.GeneralEnvelope; import org.geotools.referencing.operation.DefaultMathTransformFactory; import org.geotools.referencing.operation.builder.GridToEnvelopeMapper; -import org.opengis.metadata.spatial.PixelOrientation; +import org.opengis.referencing.FactoryException; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.datum.PixelInCell; import org.opengis.referencing.operation.MathTransform; +import org.opengis.referencing.operation.NoninvertibleTransformException; +import org.opengis.referencing.operation.TransformException; import com.raytheon.uf.common.geospatial.MapUtil; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; @@ -58,6 +58,9 @@ import com.vividsolutions.jts.geom.Coordinate; * 08/06/13 #1571 randerso Added hibernate annotations * Removed constructor with int for ProjectionType * 10/22/13 #2361 njensen Remove XML annotations + * 05/14/2014 #3069 randerso Changed to store math transforms and CRS instead of + * GridGeometry2D since GeoTools now changes the supplied + * math transform when creating GridGeometry2D * * * @@ -145,22 +148,13 @@ public class ProjectionData { private CoordinateReferenceSystem crs; @Transient - private GridGeometry2D gridGeometry; + private MathTransform gridToLatLon; @Transient - private MathTransform crsToLatLon; + private MathTransform latLonToGrid; @Transient - private MathTransform latLonToCrs; - - @Transient - private HashMap gridToLatLon; - - @Transient - private HashMap latLonToGrid; - - @Transient - private HashMap gridToCrs; + private MathTransform gridToCrs; @Transient private boolean initialized; @@ -175,10 +169,6 @@ public class ProjectionData { gridPointLL = new Point(); gridPointUR = new Point(); - gridToLatLon = new HashMap(); - latLonToGrid = new HashMap(); - gridToCrs = new HashMap(); - initialized = false; } @@ -255,24 +245,25 @@ public class ProjectionData { ge.setRange(1, Math.min(output[1], output[3]), Math.max(output[1], output[3])); - // NOTE: the LL + 1 is a kludge to work around an apparent geotools - // issue + // GeoTools 10.5 kludge to say upper right is non-inclusive GeneralGridEnvelope gr = new GeneralGridEnvelope(new int[] { - getGridPointLL().x + 1, getGridPointLL().y + 1 }, - new int[] { getGridPointUR().x, getGridPointUR().y }, true); + getGridPointLL().x, getGridPointLL().y }, new int[] { + getGridPointUR().x, getGridPointUR().y }, false); + // GeoTools 10.5 kludge to use CELL_CORNER instead of CELL_CENTER GridToEnvelopeMapper mapper = new GridToEnvelopeMapper(); mapper.setEnvelope(ge); mapper.setGridRange(gr); - mapper.setPixelAnchor(PixelInCell.CELL_CENTER); + mapper.setPixelAnchor(PixelInCell.CELL_CORNER); mapper.setReverseAxis(new boolean[] { false, false }); - mt = mapper.createTransform(); + gridToCrs = mapper.createTransform(); - gridGeometry = new GridGeometry2D(PixelInCell.CELL_CORNER, mt, ge, - null); + MathTransform crsToLatLon = MapUtil.getTransformToLatLon(getCrs()); - crsToLatLon = MapUtil.getTransformToLatLon(getCrs()); - latLonToCrs = MapUtil.getTransformFromLatLon(getCrs()); + DefaultMathTransformFactory dmtf = new DefaultMathTransformFactory(); + gridToLatLon = dmtf.createConcatenatedTransform(gridToCrs, + crsToLatLon); + latLonToGrid = getGridToLatLon().inverse(); initialized = true; @@ -388,71 +379,96 @@ public class ProjectionData { } /** - * Return the lat/lon of the specified corner or center of a grid cell + * Return the lat/lon of the specified grid cell * * @param gridCoord * coordinates of the grid cell - * @param orientation - * desired corner or center * @return the lat/lon + * @throws FactoryException + * @throws TransformException */ - public Coordinate gridCoordinateToLatLon(Coordinate gridCoord, - PixelOrientation orientation) { + public Coordinate gridCoordinateToLatLon(Coordinate gridCoord) + throws FactoryException, TransformException { Coordinate latLon = new Coordinate(); - MathTransform mt = gridToLatLon.get(orientation); - try { - if (mt == null) { - init(); - DefaultMathTransformFactory dmtf = new DefaultMathTransformFactory(); - mt = dmtf.createConcatenatedTransform( - gridGeometry.getGridToCRS(orientation), crsToLatLon); - gridToLatLon.put(orientation, mt); - } - - double[] output = new double[2]; - mt.transform(new double[] { gridCoord.x, gridCoord.y }, 0, output, - 0, 1); - latLon.x = output[0]; - latLon.y = output[1]; - } catch (Exception e) { - statusHandler.error( - "Error computing grid coordinate to lat/lon transform", e); - } + MathTransform mt = getGridToLatLon(); + double[] output = new double[2]; + mt.transform(new double[] { gridCoord.x, gridCoord.y }, 0, output, 0, 1); + latLon.x = output[0]; + latLon.y = output[1]; return latLon; } /** - * Return the math transform from grid coordinate to the specified corner or - * center lat/lon + * Return the grid coordinate of the specified lat/lon * - * @param orientation - * desired corner or center - * @return the transform + * @param latLon + * lat/lon to be converted + * @return the grid coordinate + * @throws FactoryException + * @throws TransformException */ - public MathTransform getGridToCrs(PixelOrientation orientation) { - MathTransform mt = gridToCrs.get(orientation); - if (mt == null) { - init(); - mt = gridGeometry.getGridToCRS(orientation); - gridToCrs.put(orientation, mt); - } - return mt; + public Coordinate latLonToGridCoordinate(Coordinate latLon) + throws FactoryException, TransformException { + Coordinate gridCoord = new Coordinate(); + MathTransform mt = getLatLonToGrid(); + double[] output = new double[2]; + mt.transform(new double[] { latLon.x, latLon.y }, 0, output, 0, 1); + gridCoord.x = output[0]; + gridCoord.y = output[1]; + return gridCoord; } /** - * Convert a grid cell coordinate to the native CRS coordinate of this - * projection + * Return the math transform from grid coordinate to lat/lon + * + * @return the transform + * @throws FactoryException + */ + public MathTransform getGridToLatLon() throws FactoryException { + if (gridToLatLon == null) { + init(); + } + return gridToLatLon; + } + + /** + * Return the math transform from lat/lon to grid coordinate + * + * @return the transform + * @throws FactoryException + * @throws NoninvertibleTransformException + */ + public MathTransform getLatLonToGrid() throws FactoryException, + NoninvertibleTransformException { + + if (latLonToGrid == null) { + init(); + } + return latLonToGrid; + } + + /** + * Return the math transform from grid coordinate to the native CRS + * + * @return the transform + */ + public MathTransform getGridToCrs() { + if (gridToCrs == null) { + init(); + } + return gridToCrs; + } + + /** + * Convert a grid cell coordinate to the native CRS of this projection * * @param gridCoord * grid cell coordinate - * @param orientation - * desired corner or center of the grid cell * @return native CRS coordinate */ - public Coordinate gridCoordinateToCrs(Coordinate gridCoord, - PixelOrientation orientation) { + public Coordinate gridCoordinateToCrs(Coordinate gridCoord) { Coordinate crsCoordinate = new Coordinate(); - MathTransform mt = getGridToCrs(orientation); + MathTransform mt = getGridToCrs(); try { double[] output = new double[2]; mt.transform(new double[] { gridCoord.x, gridCoord.y }, 0, output, diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/db/objects/GridLocation.java b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/db/objects/GridLocation.java index b867eb2bf3..f940a64616 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/db/objects/GridLocation.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/db/objects/GridLocation.java @@ -100,6 +100,9 @@ import com.vividsolutions.jts.simplify.TopologyPreservingSimplifier; * 09/30/13 #2333 mschenke Added method to construct from {@link IGridGeometryProvider} * 10/22/13 #2361 njensen Remove XML annotations * 04/11/14 #2947 bsteffen Remove ISpatialObject constructor. + * 05/14/2014 #3069 randerso Changed to store math transforms and CRS instead of + * GridGeometry2D since GeoTools now changes the supplied + * math transform when creating GridGeometry2D * * * @@ -121,7 +124,7 @@ public class GridLocation extends PersistableDataObject implements * reshaped using numpy for performance * */ - private static class PythonNumpyLatLonGrid implements INumpyable { + static class PythonNumpyLatLonGrid implements INumpyable { private float[] data; public PythonNumpyLatLonGrid(int nx, int ny, float[] data) { @@ -276,10 +279,8 @@ public class GridLocation extends PersistableDataObject implements Coordinate ur = new Coordinate(this.origin.x + this.extent.x, this.origin.y + this.extent.y); - Coordinate llCrs = this.projection.gridCoordinateToCrs(ll, - PixelOrientation.CENTER); - Coordinate urCrs = this.projection.gridCoordinateToCrs(ur, - PixelOrientation.CENTER); + Coordinate llCrs = this.projection.gridCoordinateToCrs(ll); + Coordinate urCrs = this.projection.gridCoordinateToCrs(ur); // construct the grid geometry that covers the GFE grid GeneralEnvelope ge = new GeneralEnvelope(2); @@ -289,29 +290,29 @@ public class GridLocation extends PersistableDataObject implements ge.setRange(1, Math.min(llCrs.y, urCrs.y), Math.max(llCrs.y, urCrs.y)); + // GeoTools 10.5 kludge to use nx-1, ny-1 non-inclusive GeneralGridEnvelope gr = new GeneralGridEnvelope( - new int[] { 1, 1 }, new int[] { this.nx, this.ny }, false); + new int[] { 0, 0 }, new int[] { this.nx - 1, this.ny - 1 }, + false); + // GeoTools 10.5 kludge to use CELL_CORNER instead of CELL_CENTER GridToEnvelopeMapper mapper = new GridToEnvelopeMapper(); mapper.setEnvelope(ge); mapper.setGridRange(gr); - mapper.setPixelAnchor(PixelInCell.CELL_CENTER); - mapper.setReverseAxis(new boolean[] { false, false }); - MathTransform mt = mapper.createTransform(); - - GridGeometry2D gridGeom = new GridGeometry2D( - PixelInCell.CELL_CORNER, mt, ge, null); + mapper.setPixelAnchor(PixelInCell.CELL_CORNER); + mapper.setReverseAxis(new boolean[] { false, true }); + MathTransform gridToCrs = mapper.createTransform(); // set up the transform from grid coordinates to lon/lat DefaultMathTransformFactory dmtf = new DefaultMathTransformFactory(); - mt = dmtf.createConcatenatedTransform( - gridGeom.getGridToCRS(PixelOrientation.UPPER_LEFT), - MapUtil.getTransformToLatLon(crsObject)); - + MathTransform gridToLatLon = dmtf.createConcatenatedTransform( + gridToCrs, MapUtil.getTransformToLatLon(crsObject)); // transform grid corner points to Lat/Lon double[] latLon = new double[8]; - mt.transform(new double[] { 0, this.ny, 0, 0, this.nx, 0, this.nx, - this.ny }, 0, latLon, 0, 4); + double[] gridCells = new double[] { -0.5, -0.5, -0.5, + this.ny - 0.5, this.nx - 0.5, this.ny - 0.5, this.nx - 0.5, + -0.5 }; + gridToLatLon.transform(gridCells, 0, latLon, 0, 4); Coordinate[] corners = new Coordinate[] { MapUtil.getCoordinate(latLon[0], latLon[1]), @@ -700,9 +701,7 @@ public class GridLocation extends PersistableDataObject implements public String toString() { String s = "[SiteID =" + siteId + ",ProjID=" + getCrs().getName().getCode() + ",gridSize=(" + nx + ',' + ny - + "),loc=" + this.geometry.getGeometryType(); - // if (proj()) - // s += "," + proj()->pdata(); + + "), loc=[o=" + this.origin + ", e=" + this.extent + "]"; s += ']'; return s; } @@ -1008,43 +1007,56 @@ public class GridLocation extends PersistableDataObject implements // new Coordinate(9, 9), "CST6CDT"); GridLocation gloc = new GridLocation("OAX", grid211, - new Point(145, 145), new Coordinate(45.0, 30.0), - new Coordinate(9, 9), "CST6CDT"); + new Point(417, 289), new Coordinate(41.0, 29.0), + new Coordinate(13, 9), "CST6CDT"); System.out.println(gloc.getSiteId()); Coordinate gridCoord = new Coordinate(); Coordinate latLon = new Coordinate(); - PixelOrientation orientation = PixelOrientation.CENTER; - gridCoord.x = 0; - gridCoord.y = 0; - latLon = MapUtil.gridCoordinateToLatLon(gridCoord, orientation, gloc); - System.out.println(gridCoord.x + "," + gridCoord.y + " " + latLon); + System.out.println("geometry: " + gloc.getGeometry()); - gridCoord.x = 0; - gridCoord.y = gloc.getNy() - 1; - latLon = MapUtil.gridCoordinateToLatLon(gridCoord, orientation, gloc); - System.out.println(gridCoord.x + "," + gridCoord.y + " " + latLon); + try { + gridCoord.x = 0; + gridCoord.y = 0; + latLon = MapUtil.gridCoordinateToLatLon(gridCoord, + PixelOrientation.CENTER, gloc); + System.out.println(gridCoord.x + "," + gridCoord.y + " " + latLon); - gridCoord.x = gloc.getNx() - 1; - gridCoord.y = gloc.getNy() - 1; - latLon = MapUtil.gridCoordinateToLatLon(gridCoord, orientation, gloc); - System.out.println(gridCoord.x + "," + gridCoord.y + " " + latLon); + gridCoord.x = 0; + gridCoord.y = gloc.getNy() - 1; + latLon = MapUtil.gridCoordinateToLatLon(gridCoord, + PixelOrientation.CENTER, gloc); + System.out.println(gridCoord.x + "," + gridCoord.y + " " + latLon); - gridCoord.x = gloc.getNx() - 1; - gridCoord.y = 0; - latLon = MapUtil.gridCoordinateToLatLon(gridCoord, orientation, gloc); - System.out.println(gridCoord.x + "," + gridCoord.y + " " + latLon); + gridCoord.x = gloc.getNx() - 1; + gridCoord.y = gloc.getNy() - 1; + latLon = MapUtil.gridCoordinateToLatLon(gridCoord, + PixelOrientation.CENTER, gloc); + System.out.println(gridCoord.x + "," + gridCoord.y + " " + latLon); - PythonNumpyLatLonGrid latLonGrid = gloc.getLatLonGrid(); - float[] data = (float[]) latLonGrid.getNumpy()[0]; - for (int x = 0; x < gloc.getNx(); x++) { - for (int y = 0; y < gloc.getNy(); y++) { - int idx = 2 * ((x * gloc.ny) + y); - float lon = data[idx]; - float lat = data[idx + 1]; - System.out.println(x + "," + y + " " + lon + ", " + lat); + gridCoord.x = gloc.getNx() - 1; + gridCoord.y = 0; + latLon = MapUtil.gridCoordinateToLatLon(gridCoord, + PixelOrientation.CENTER, gloc); + System.out.println(gridCoord.x + "," + gridCoord.y + " " + latLon); + + GridGeometry2D gridGeometry = MapUtil.getGridGeometry(gloc); + System.out.println(gridGeometry.getEnvelope2D().toString()); + System.out.println(gridGeometry.toString()); + + PythonNumpyLatLonGrid latLonGrid = gloc.getLatLonGrid(); + float[] data = (float[]) latLonGrid.getNumpy()[0]; + for (int x = 0; x < gloc.getNx(); x++) { + for (int y = 0; y < gloc.getNy(); y++) { + int idx = 2 * ((x * gloc.ny) + y); + float lon = data[idx]; + float lat = data[idx + 1]; + System.out.println(x + "," + y + " " + lon + ", " + lat); + } } + } catch (Exception e) { + e.printStackTrace(); } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/test/com/raytheon/uf/common/dataplugin/gfe/db/objects/GridLocationTest.java b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/test/com/raytheon/uf/common/dataplugin/gfe/db/objects/GridLocationTest.java new file mode 100644 index 0000000000..13bdddb485 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/test/com/raytheon/uf/common/dataplugin/gfe/db/objects/GridLocationTest.java @@ -0,0 +1,120 @@ +/** + * 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.dataplugin.gfe.db.objects; + +import java.awt.Point; + +import org.geotools.coverage.grid.GridGeometry2D; +import org.opengis.metadata.spatial.PixelOrientation; + +import com.raytheon.uf.common.dataplugin.gfe.config.ProjectionData; +import com.raytheon.uf.common.dataplugin.gfe.config.ProjectionData.ProjectionType; +import com.raytheon.uf.common.dataplugin.gfe.db.objects.GridLocation.PythonNumpyLatLonGrid; +import com.raytheon.uf.common.geospatial.MapUtil; +import com.vividsolutions.jts.geom.Coordinate; + +/** + * GridLocation unit test + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * May 20, 2014  #3069     randerso    Initial creation
+ * 
+ * 
+ * + * @author randerso + * @version 1.0 + */ + +public class GridLocationTest { + + /** + * @param args + */ + public static void main(String[] args) { + ProjectionData grid211 = new ProjectionData("Grid211", + ProjectionType.LAMBERT_CONFORMAL, new Coordinate(-133.459, + 12.190), new Coordinate(-49.385, 57.290), + new Coordinate(-95.0, 25.0), 25.0f, 25.0f, new Point(1, 1), + new Point(93, 65), 0.0f, 0.0f, 0.0f); + + // GridLocation gloc = new GridLocation("ABR", grid211, + // new Point(145, 145), new Coordinate(45.0, 35.0), + // new Coordinate(9, 9), "CST6CDT"); + + GridLocation gloc = new GridLocation("OAX", grid211, + new Point(417, 289), new Coordinate(41.0, 29.0), + new Coordinate(13, 9), "CST6CDT"); + + System.out.println(gloc.getSiteId()); + Coordinate gridCoord = new Coordinate(); + Coordinate latLon = new Coordinate(); + + System.out.println("geometry: " + gloc.getGeometry()); + + try { + gridCoord.x = 0; + gridCoord.y = 0; + latLon = MapUtil.gridCoordinateToLatLon(gridCoord, + PixelOrientation.CENTER, gloc); + System.out.println(gridCoord.x + "," + gridCoord.y + " " + latLon); + + gridCoord.x = 0; + gridCoord.y = gloc.getNy() - 1; + latLon = MapUtil.gridCoordinateToLatLon(gridCoord, + PixelOrientation.CENTER, gloc); + System.out.println(gridCoord.x + "," + gridCoord.y + " " + latLon); + + gridCoord.x = gloc.getNx() - 1; + gridCoord.y = gloc.getNy() - 1; + latLon = MapUtil.gridCoordinateToLatLon(gridCoord, + PixelOrientation.CENTER, gloc); + System.out.println(gridCoord.x + "," + gridCoord.y + " " + latLon); + + gridCoord.x = gloc.getNx() - 1; + gridCoord.y = 0; + latLon = MapUtil.gridCoordinateToLatLon(gridCoord, + PixelOrientation.CENTER, gloc); + System.out.println(gridCoord.x + "," + gridCoord.y + " " + latLon); + + GridGeometry2D gridGeometry = MapUtil.getGridGeometry(gloc); + System.out.println(gridGeometry.getEnvelope2D().toString()); + System.out.println(gridGeometry.toString()); + + PythonNumpyLatLonGrid latLonGrid = gloc.getLatLonGrid(); + float[] data = (float[]) latLonGrid.getNumpy()[0]; + for (int x = 0; x < gloc.getNx(); x++) { + for (int y = 0; y < gloc.getNy(); y++) { + int idx = 2 * ((x * gloc.ny) + y); + float lon = data[idx]; + float lat = data[idx + 1]; + System.out.println(x + "," + y + " " + lon + ", " + lat); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/edexOsgi/com.raytheon.uf.common.topo/src/com/raytheon/uf/common/topo/TopoQuery.java b/edexOsgi/com.raytheon.uf.common.topo/src/com/raytheon/uf/common/topo/TopoQuery.java index bb2463d5fd..6d7a8e4192 100644 --- a/edexOsgi/com.raytheon.uf.common.topo/src/com/raytheon/uf/common/topo/TopoQuery.java +++ b/edexOsgi/com.raytheon.uf.common.topo/src/com/raytheon/uf/common/topo/TopoQuery.java @@ -90,6 +90,9 @@ import com.vividsolutions.jts.geom.Coordinate; * Aug 06, 2013 2235 bsteffen Added Caching version of TopoQuery. * Feb 10, 2014 2788 randerso Removed override of CRS from Topo file. * Fixed handling of fill values (missing data) + * May 19, 2014 3069 randerso Changed to store math transforms and CRS instead of + * GridGeometry2D since GeoTools now changes the supplied + * math transform when creating GridGeometry2D * * * @@ -149,11 +152,13 @@ public class TopoQuery { protected Rectangle worldRect; - private GridGeometry2D worldGeomPM; + // private GridGeometry2D worldGeomPM; + private MathTransform worldToCRSPM; private MathTransform worldToLLPM; - private GridGeometry2D worldGeomDL; + // private GridGeometry2D worldGeomDL; + private MathTransform worldToCRSDL; private MathTransform llToWorldPM; @@ -163,6 +168,10 @@ public class TopoQuery { private int numLevels; + private CoordinateReferenceSystem crsPM; + + private CoordinateReferenceSystem crsDL; + TopoQuery(File hdf5File) throws TopoException { this(hdf5File, 0); } @@ -197,17 +206,17 @@ public class TopoQuery { worldRect = new Rectangle(0, 0, width, height); // construct the grid geometry that covers the topo grid - CoordinateReferenceSystem crs = CRSCache.getInstance() - .getCoordinateReferenceSystem(crsString); + crsPM = CRSCache.getInstance().getCoordinateReferenceSystem( + crsString); double[] input = new double[] { ulLon, ulLat, lrLon, lrLat }; double[] output = new double[4]; - MathTransform llToCrsPM = MapUtil.getTransformFromLatLon(crs); + MathTransform llToCrsPM = MapUtil.getTransformFromLatLon(crsPM); llToCrsPM.transform(input, 0, output, 0, 2); GeneralEnvelope ge = new GeneralEnvelope(2); - ge.setCoordinateReferenceSystem(crs); + ge.setCoordinateReferenceSystem(crsPM); ge.setRange(0, output[0], output[2]); ge.setRange(1, output[3], output[1]); @@ -219,29 +228,24 @@ public class TopoQuery { mapper.setGridRange(gr); mapper.setPixelAnchor(PixelInCell.CELL_CENTER); mapper.setReverseAxis(new boolean[] { false, true }); - MathTransform mt = mapper.createTransform(); - - worldGeomPM = new GridGeometry2D(PixelInCell.CELL_CORNER, mt, ge, - null); + worldToCRSPM = mapper.createTransform(); // set up the transform from grid coordinates to lon/lat - MathTransform worldToCRSPM = worldGeomPM - .getGridToCRS(PixelOrientation.UPPER_LEFT); - MathTransform crsToLL = MapUtil.getTransformToLatLon(crs); + MathTransform crsToLL = MapUtil.getTransformToLatLon(crsPM); worldToLLPM = dmtf.createConcatenatedTransform(worldToCRSPM, crsToLL); llToWorldPM = worldToLLPM.inverse(); - crs = MapUtil.constructEquidistantCylindrical( + crsDL = MapUtil.constructEquidistantCylindrical( MapUtil.AWIPS_EARTH_RADIUS, MapUtil.AWIPS_EARTH_RADIUS, 180, 0); input = new double[] { 180 + ulLon, ulLat, 180 + lrLon, lrLat }; - MathTransform llToCrsDL = MapUtil.getTransformFromLatLon(crs); + MathTransform llToCrsDL = MapUtil.getTransformFromLatLon(crsDL); llToCrsDL.transform(input, 0, output, 0, 2); ge = new GeneralEnvelope(2); - ge.setCoordinateReferenceSystem(crs); + ge.setCoordinateReferenceSystem(crsDL); ge.setRange(0, output[0], output[2]); ge.setRange(1, output[3], output[1]); @@ -252,10 +256,7 @@ public class TopoQuery { mapper.setGridRange(gr); mapper.setPixelAnchor(PixelInCell.CELL_CENTER); mapper.setReverseAxis(new boolean[] { false, true }); - mt = mapper.createTransform(); - - worldGeomDL = new GridGeometry2D(PixelInCell.CELL_CORNER, mt, ge, - null); + worldToCRSDL = mapper.createTransform(); } catch (Exception e) { throw new TopoException("Error initializing TopoQuery from " @@ -545,18 +546,16 @@ public class TopoQuery { worldRect.getMaxY() }; double[] crsCorners = new double[worldCorners.length]; GeneralEnvelope env = new GeneralEnvelope(2); - if (worldCorners[2] > (worldGeomPM.getGridRange().getHigh(0) + 1)) { - worldGeomDL.getGridToCRS(PixelInCell.CELL_CORNER) - .transform(worldCorners, 0, crsCorners, 0, - worldCorners.length / 2); - env.setCoordinateReferenceSystem(worldGeomDL.getEnvelope() - .getCoordinateReferenceSystem()); + if (worldCorners[2] > (this.worldRect.width)) { + worldToCRSDL.transform(worldCorners, 0, crsCorners, 0, + worldCorners.length / 2); + env.setCoordinateReferenceSystem(crsDL); } else { - worldGeomPM.getGridToCRS(PixelInCell.CELL_CORNER) - .transform(worldCorners, 0, crsCorners, 0, - worldCorners.length / 2); - env.setCoordinateReferenceSystem(worldGeomPM.getEnvelope() - .getCoordinateReferenceSystem()); + worldToCRSPM + + .transform(worldCorners, 0, crsCorners, 0, + worldCorners.length / 2); + env.setCoordinateReferenceSystem(crsPM); } double minX = Double.POSITIVE_INFINITY;