From 7a38489e53c61dd41fa4860417d93b1c6c91b07e Mon Sep 17 00:00:00 2001 From: ucar-tmeyer Date: Mon, 6 Feb 2023 20:59:04 +0000 Subject: [PATCH] Updated Obs/Surface Menu -Changed the menu name from "Obs" to "Surface" -Added in previous java code to plot/display the Surface Temps -Added in previous bundles -Combined the METAR/Synoptic plots to one menu (like in v18) -Removed local data -Removed mping (local data) -Added in previous svg files needed for plotting --- .../com.raytheon.uf.viz.d2d.ui.obs/plugin.xml | 37 +- .../menus/app-obs/baseCollectDissem.xml | 31 - .../localization/menus/app-obs/index.xml | 28 - .../localization/bundles/15minSurfacePlot.xml | 4 + .../localization/bundles/ColoredASOSPlot.xml | 460 +++++++++++ .../bundles/ColoredMaritimePlot_Wind.xml | 327 ++++++++ .../bundles/ColoredStationPlot_CV.xml | 299 ++++++++ .../bundles/ColoredStationPlot_Wind.xml | 222 ++++++ .../localization/bundles/MetarPlot.xml | 14 - .../localization/bundles/MetarPrecipPlot.xml | 3 +- .../localization/bundles/SeaStatePlot.xml | 7 +- .../localization/bundles/SurfaceColorTemp.xml | 37 + .../localization/bundles/SurfaceMSLP.xml | 55 ++ .../localization/bundles/SurfacePlotMetar.xml | 42 + .../localization/bundles/SurfacePlotWinds.xml | 37 + .../bundles/maritimeFixedBuoy.xml | 46 ++ .../localization/menus/mping/baseMPing.xml | 173 ----- .../localization/menus/mping/index.xml | 29 - .../localization/menus/obs/baseLocalData.xml | 122 --- .../localization/menus/obs/baseSurface.xml | 221 +++++- .../localization/menus/obs/index.xml | 3 +- .../localization/plotModels/colorTemp.svg | 48 ++ .../localization/plotModels/mslp.svg | 49 ++ .../localization/plotModels/windDesign.svg | 86 +++ .../viz/pointdata/rsc/MetarTempResource.java | 724 ++++++++++++++++++ .../pointdata/rsc/MetarTempResourceData.java | 77 ++ .../util/MetarTempDataContainer.java | 344 +++++++++ 27 files changed, 3061 insertions(+), 464 deletions(-) delete mode 100644 cave/com.raytheon.viz.hydro/localization/menus/app-obs/baseCollectDissem.xml delete mode 100644 cave/com.raytheon.viz.hydro/localization/menus/app-obs/index.xml create mode 100644 cave/com.raytheon.viz.pointdata/localization/bundles/ColoredASOSPlot.xml create mode 100755 cave/com.raytheon.viz.pointdata/localization/bundles/ColoredMaritimePlot_Wind.xml create mode 100755 cave/com.raytheon.viz.pointdata/localization/bundles/ColoredStationPlot_CV.xml create mode 100755 cave/com.raytheon.viz.pointdata/localization/bundles/ColoredStationPlot_Wind.xml create mode 100644 cave/com.raytheon.viz.pointdata/localization/bundles/SurfaceColorTemp.xml create mode 100644 cave/com.raytheon.viz.pointdata/localization/bundles/SurfaceMSLP.xml create mode 100644 cave/com.raytheon.viz.pointdata/localization/bundles/SurfacePlotMetar.xml create mode 100644 cave/com.raytheon.viz.pointdata/localization/bundles/SurfacePlotWinds.xml delete mode 100644 cave/com.raytheon.viz.pointdata/localization/menus/mping/baseMPing.xml delete mode 100755 cave/com.raytheon.viz.pointdata/localization/menus/mping/index.xml delete mode 100644 cave/com.raytheon.viz.pointdata/localization/menus/obs/baseLocalData.xml create mode 100644 cave/com.raytheon.viz.pointdata/localization/plotModels/colorTemp.svg create mode 100644 cave/com.raytheon.viz.pointdata/localization/plotModels/mslp.svg create mode 100644 cave/com.raytheon.viz.pointdata/localization/plotModels/windDesign.svg create mode 100644 cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/MetarTempResource.java create mode 100644 cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/MetarTempResourceData.java create mode 100644 cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/util/MetarTempDataContainer.java diff --git a/cave/com.raytheon.uf.viz.d2d.ui.obs/plugin.xml b/cave/com.raytheon.uf.viz.d2d.ui.obs/plugin.xml index 498eb883ba..df6f87d7d6 100644 --- a/cave/com.raytheon.uf.viz.d2d.ui.obs/plugin.xml +++ b/cave/com.raytheon.uf.viz.d2d.ui.obs/plugin.xml @@ -22,7 +22,7 @@ - + @@ -32,45 +32,12 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + diff --git a/cave/com.raytheon.viz.hydro/localization/menus/app-obs/baseCollectDissem.xml b/cave/com.raytheon.viz.hydro/localization/menus/app-obs/baseCollectDissem.xml deleted file mode 100644 index 53114f2a47..0000000000 --- a/cave/com.raytheon.viz.hydro/localization/menus/app-obs/baseCollectDissem.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/cave/com.raytheon.viz.hydro/localization/menus/app-obs/index.xml b/cave/com.raytheon.viz.hydro/localization/menus/app-obs/index.xml deleted file mode 100644 index b986fdc89b..0000000000 --- a/cave/com.raytheon.viz.hydro/localization/menus/app-obs/index.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/cave/com.raytheon.viz.pointdata/localization/bundles/15minSurfacePlot.xml b/cave/com.raytheon.viz.pointdata/localization/bundles/15minSurfacePlot.xml index 6b6664c582..01529a19f9 100644 --- a/cave/com.raytheon.viz.pointdata/localization/bundles/15minSurfacePlot.xml +++ b/cave/com.raytheon.viz.pointdata/localization/bundles/15minSurfacePlot.xml @@ -44,6 +44,10 @@ + + + diff --git a/cave/com.raytheon.viz.pointdata/localization/bundles/ColoredASOSPlot.xml b/cave/com.raytheon.viz.pointdata/localization/bundles/ColoredASOSPlot.xml new file mode 100644 index 0000000000..6463d43865 --- /dev/null +++ b/cave/com.raytheon.viz.pointdata/localization/bundles/ColoredASOSPlot.xml @@ -0,0 +1,460 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cave/com.raytheon.viz.pointdata/localization/bundles/ColoredMaritimePlot_Wind.xml b/cave/com.raytheon.viz.pointdata/localization/bundles/ColoredMaritimePlot_Wind.xml new file mode 100755 index 0000000000..c708560ec9 --- /dev/null +++ b/cave/com.raytheon.viz.pointdata/localization/bundles/ColoredMaritimePlot_Wind.xml @@ -0,0 +1,327 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cave/com.raytheon.viz.pointdata/localization/bundles/ColoredStationPlot_CV.xml b/cave/com.raytheon.viz.pointdata/localization/bundles/ColoredStationPlot_CV.xml new file mode 100755 index 0000000000..5e30130357 --- /dev/null +++ b/cave/com.raytheon.viz.pointdata/localization/bundles/ColoredStationPlot_CV.xml @@ -0,0 +1,299 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cave/com.raytheon.viz.pointdata/localization/bundles/ColoredStationPlot_Wind.xml b/cave/com.raytheon.viz.pointdata/localization/bundles/ColoredStationPlot_Wind.xml new file mode 100755 index 0000000000..40e4c75b82 --- /dev/null +++ b/cave/com.raytheon.viz.pointdata/localization/bundles/ColoredStationPlot_Wind.xml @@ -0,0 +1,222 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cave/com.raytheon.viz.pointdata/localization/bundles/MetarPlot.xml b/cave/com.raytheon.viz.pointdata/localization/bundles/MetarPlot.xml index bfb4b42a8c..00c122614a 100644 --- a/cave/com.raytheon.viz.pointdata/localization/bundles/MetarPlot.xml +++ b/cave/com.raytheon.viz.pointdata/localization/bundles/MetarPlot.xml @@ -28,20 +28,6 @@ - - - - - - - - - basemaps/MTR.spi - METAR Station Locations - - diff --git a/cave/com.raytheon.viz.pointdata/localization/bundles/MetarPrecipPlot.xml b/cave/com.raytheon.viz.pointdata/localization/bundles/MetarPrecipPlot.xml index 5f56185472..5188413764 100644 --- a/cave/com.raytheon.viz.pointdata/localization/bundles/MetarPrecipPlot.xml +++ b/cave/com.raytheon.viz.pointdata/localization/bundles/MetarPrecipPlot.xml @@ -36,8 +36,7 @@ isBlinking="false" isMapLayer="false" isHoverOn="false" isVisible="true" /> - + + + + + + diff --git a/cave/com.raytheon.viz.pointdata/localization/bundles/SurfaceColorTemp.xml b/cave/com.raytheon.viz.pointdata/localization/bundles/SurfaceColorTemp.xml new file mode 100644 index 0000000000..d4798ecb2e --- /dev/null +++ b/cave/com.raytheon.viz.pointdata/localization/bundles/SurfaceColorTemp.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cave/com.raytheon.viz.pointdata/localization/bundles/SurfaceMSLP.xml b/cave/com.raytheon.viz.pointdata/localization/bundles/SurfaceMSLP.xml new file mode 100644 index 0000000000..3cf032e21d --- /dev/null +++ b/cave/com.raytheon.viz.pointdata/localization/bundles/SurfaceMSLP.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cave/com.raytheon.viz.pointdata/localization/bundles/SurfacePlotMetar.xml b/cave/com.raytheon.viz.pointdata/localization/bundles/SurfacePlotMetar.xml new file mode 100644 index 0000000000..91fd7c9038 --- /dev/null +++ b/cave/com.raytheon.viz.pointdata/localization/bundles/SurfacePlotMetar.xml @@ -0,0 +1,42 @@ + + + + + + + + + + PLAIN_VIEW + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cave/com.raytheon.viz.pointdata/localization/bundles/SurfacePlotWinds.xml b/cave/com.raytheon.viz.pointdata/localization/bundles/SurfacePlotWinds.xml new file mode 100644 index 0000000000..5d73f6391c --- /dev/null +++ b/cave/com.raytheon.viz.pointdata/localization/bundles/SurfacePlotWinds.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cave/com.raytheon.viz.pointdata/localization/bundles/maritimeFixedBuoy.xml b/cave/com.raytheon.viz.pointdata/localization/bundles/maritimeFixedBuoy.xml index bdf766d4b5..410e458d4e 100644 --- a/cave/com.raytheon.viz.pointdata/localization/bundles/maritimeFixedBuoy.xml +++ b/cave/com.raytheon.viz.pointdata/localization/bundles/maritimeFixedBuoy.xml @@ -80,6 +80,52 @@ Fixed Buoy Locations + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cave/com.raytheon.viz.pointdata/localization/menus/mping/baseMPing.xml b/cave/com.raytheon.viz.pointdata/localization/menus/mping/baseMPing.xml deleted file mode 100644 index 3134e49301..0000000000 --- a/cave/com.raytheon.viz.pointdata/localization/menus/mping/baseMPing.xml +++ /dev/null @@ -1,173 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/cave/com.raytheon.viz.pointdata/localization/menus/mping/index.xml b/cave/com.raytheon.viz.pointdata/localization/menus/mping/index.xml deleted file mode 100755 index c0630aff58..0000000000 --- a/cave/com.raytheon.viz.pointdata/localization/menus/mping/index.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/cave/com.raytheon.viz.pointdata/localization/menus/obs/baseLocalData.xml b/cave/com.raytheon.viz.pointdata/localization/menus/obs/baseLocalData.xml deleted file mode 100644 index 5f976f49f8..0000000000 --- a/cave/com.raytheon.viz.pointdata/localization/menus/obs/baseLocalData.xml +++ /dev/null @@ -1,122 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/cave/com.raytheon.viz.pointdata/localization/menus/obs/baseSurface.xml b/cave/com.raytheon.viz.pointdata/localization/menus/obs/baseSurface.xml index f6e4f5cf8d..a0459170ce 100644 --- a/cave/com.raytheon.viz.pointdata/localization/menus/obs/baseSurface.xml +++ b/cave/com.raytheon.viz.pointdata/localization/menus/obs/baseSurface.xml @@ -1,29 +1,196 @@ - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /obs/% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cave/com.raytheon.viz.pointdata/localization/menus/obs/index.xml b/cave/com.raytheon.viz.pointdata/localization/menus/obs/index.xml index b110c7d75d..f6348ce57d 100644 --- a/cave/com.raytheon.viz.pointdata/localization/menus/obs/index.xml +++ b/cave/com.raytheon.viz.pointdata/localization/menus/obs/index.xml @@ -27,6 +27,5 @@ - - \ No newline at end of file + diff --git a/cave/com.raytheon.viz.pointdata/localization/plotModels/colorTemp.svg b/cave/com.raytheon.viz.pointdata/localization/plotModels/colorTemp.svg new file mode 100644 index 0000000000..24101198fd --- /dev/null +++ b/cave/com.raytheon.viz.pointdata/localization/plotModels/colorTemp.svg @@ -0,0 +1,48 @@ + + + + + + + + 75 + + + + diff --git a/cave/com.raytheon.viz.pointdata/localization/plotModels/mslp.svg b/cave/com.raytheon.viz.pointdata/localization/plotModels/mslp.svg new file mode 100644 index 0000000000..12f6ac631b --- /dev/null +++ b/cave/com.raytheon.viz.pointdata/localization/plotModels/mslp.svg @@ -0,0 +1,49 @@ + + + + + + + + 75 + + + + + \ No newline at end of file diff --git a/cave/com.raytheon.viz.pointdata/localization/plotModels/windDesign.svg b/cave/com.raytheon.viz.pointdata/localization/plotModels/windDesign.svg new file mode 100644 index 0000000000..fe2fefe25e --- /dev/null +++ b/cave/com.raytheon.viz.pointdata/localization/plotModels/windDesign.svg @@ -0,0 +1,86 @@ + + + + + + + + 0 + + arrow + + + + + diff --git a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/MetarTempResource.java b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/MetarTempResource.java new file mode 100644 index 0000000000..f8b0c0911b --- /dev/null +++ b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/MetarTempResource.java @@ -0,0 +1,724 @@ +/** + * 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.pointdata.rsc; + +import java.awt.Font; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.LinkedBlockingQueue; + +import javax.measure.Unit; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.swt.graphics.RGB; +import org.geotools.coverage.grid.GridEnvelope2D; +import org.geotools.coverage.grid.GridGeometry2D; +import org.geotools.geometry.DirectPosition2D; +import org.geotools.geometry.Envelope2D; +import org.opengis.geometry.DirectPosition; +import org.opengis.referencing.FactoryException; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.operation.MathTransform; +import org.opengis.referencing.operation.TransformException; + +import com.raytheon.uf.common.colormap.Color; +import com.raytheon.uf.common.colormap.ColorMapException; +import com.raytheon.uf.common.colormap.ColorMapLoader; +import com.raytheon.uf.common.colormap.prefs.ColorMapParameters; +import com.raytheon.uf.common.colormap.prefs.DataMappingPreferences; +import com.raytheon.uf.common.colormap.prefs.DataMappingPreferences.DataMappingEntry; +import com.raytheon.uf.common.dataplugin.PluginDataObject; +import com.raytheon.uf.common.dataplugin.annotations.DataURIUtil; +import com.raytheon.uf.common.dataquery.requests.RequestConstraint; +import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType; +import com.raytheon.uf.common.geospatial.MapUtil; +import com.raytheon.uf.common.geospatial.ReferencedCoordinate; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.common.time.DataTime; +import com.raytheon.uf.viz.core.DrawableString; +import com.raytheon.uf.viz.core.IExtent; +import com.raytheon.uf.viz.core.IGraphicsTarget; +import com.raytheon.uf.viz.core.IGraphicsTarget.HorizontalAlignment; +import com.raytheon.uf.viz.core.IGraphicsTarget.VerticalAlignment; +import com.raytheon.uf.viz.core.drawables.IDescriptor.FramesInfo; +import com.raytheon.uf.viz.core.drawables.IFont; +import com.raytheon.uf.viz.core.drawables.IFont.Style; +import com.raytheon.uf.viz.core.drawables.IRenderableDisplay; +import com.raytheon.uf.viz.core.drawables.PaintProperties; +import com.raytheon.uf.viz.core.exception.VizException; +import com.raytheon.uf.viz.core.map.IMapDescriptor; +import com.raytheon.uf.viz.core.rsc.AbstractVizResource; +import com.raytheon.uf.viz.core.rsc.IResourceDataChanged.ChangeType; +import com.raytheon.uf.viz.core.rsc.LoadProperties; +import com.raytheon.uf.viz.core.rsc.capabilities.ColorMapCapability; +import com.raytheon.uf.viz.core.rsc.capabilities.DensityCapability; +import com.raytheon.uf.viz.core.rsc.capabilities.MagnificationCapability; +import com.raytheon.viz.pointdata.rsc.progdisc.GenericProgressiveDisclosure; +import com.raytheon.viz.pointdata.rsc.progdisc.GenericProgressiveDisclosure.PlotItem; +import com.raytheon.viz.pointdata.util.MetarTempDataContainer; +import com.raytheon.viz.pointdata.util.MetarTempDataContainer.TempData; + +import tec.uom.se.AbstractUnit; + +import org.locationtech.jts.geom.Coordinate; + +/** + * + * Resource for displaying colored Metar Temp values. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date          Ticket#  Engineer  Description
+ * ------------- -------- --------- --------------------------------------------
+ * Aug 05, 2016           mjames   Copied from MetarPrecipResource
+ * Feb 06, 2019           mjames   Updated for reprojection, default color map.
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ +public class MetarTempResource extends AbstractVizResource { + + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(MetarTempResource.class); + + private RGB color = new RGB(126, 126, 126); + + public RGB getColorByValue(float value) { + ColorMapParameters parameters = getCapability(ColorMapCapability.class).getColorMapParameters(); + if (parameters != null) { + Color color = parameters.getColorByValue(value); + if (color != null) { + return new RGB((int) (color.getRed() * 255), + (int) (color.getGreen() * 255), + (int) (color.getBlue() * 255)); + } + } + return getColor(); + } + + public RGB getColor() { + return color; + } + + public void setColor(RGB color) { + this.color = color; + } + private static final int PLOT_PIXEL_SIZE = 30; + + private class RenderableTempData extends TempData implements PlotItem { + + public final DrawableString string; + + public RenderableTempData(TempData data, DrawableString string) { + super(data.getTimeObs(), data.getStationName(), + data.getTempValue(), data.getLatLon().x, data.getLatLon().y); + this.string = string; + } + + @Override + public Coordinate getLocation() { + return new Coordinate(string.basics.x, string.basics.y); + } + + } + + // To avoid synchronization issues with data request, updates, and removals + // do it all on this thread. + private Job dataProcessJob = new Job("Loading Sfc Temps") { + + @Override + protected IStatus run(IProgressMonitor monitor) { + processNewFrames(monitor); + if (monitor.isCanceled()) { + return Status.CANCEL_STATUS; + } + processUpdates(monitor); + + if (monitor.isCanceled()) { + return Status.CANCEL_STATUS; + } + processRemoves(); + return Status.OK_STATUS; + } + + }; + + private LinkedBlockingQueue updates = new LinkedBlockingQueue(); + + private LinkedBlockingQueue removes = new LinkedBlockingQueue(); + + private boolean reproject = false; + + private Map> data = new HashMap<>(); + + private IFont font = null; + + protected MetarTempResource(MetarTempResourceData resourceData, + LoadProperties loadProperties) { + super(resourceData, loadProperties, false); + + } + + @Override + protected void disposeInternal() { + if (font != null) { + font.dispose(); + font = null; + } + dataProcessJob.cancel(); + } + + @Override + protected void paintInternal(IGraphicsTarget target, + PaintProperties paintProps) throws VizException { + DataTime time = paintProps.getDataTime(); + if (time == null) { + return; + } + GenericProgressiveDisclosure disclosure = null; + synchronized (data) { + disclosure = data.get(time); + } + if (disclosure == null) { + dataProcessJob.schedule(); + return; + } + IExtent extent = paintProps.getView().getExtent(); + Double magnification = getCapability(MagnificationCapability.class) + .getMagnification(); + Double density = getCapability(DensityCapability.class).getDensity(); + double threshold = (PLOT_PIXEL_SIZE * magnification) / density; + threshold = (threshold * extent.getWidth()) + / paintProps.getCanvasBounds().width; + Collection temps = disclosure.runDisclosure( + extent, threshold); + if (temps.isEmpty()) { + return; + } + + if (font == null) { + font = target.initializeFont(Font.DIALOG, 8, + new Style[] { Style.BOLD }); + font.setMagnification(magnification.floatValue()); + } + + List strings = new ArrayList(); + + for (RenderableTempData data : temps) { + data.string.font = this.font; + strings.add(data.string); + } + + target.drawStrings(strings); + } + + private List getTempsData(DataTime time) { + GenericProgressiveDisclosure currData = null; + synchronized (data) { + currData = data.get(time); + } + if (currData != null) { + return currData.getAll(); + } + return null; + } + + @Override + protected void initInternal(IGraphicsTarget target) throws VizException { + dataProcessJob.schedule(); + ColorMapParameters params = new ColorMapParameters(); + + try { + params.setColorMap(ColorMapLoader.loadColorMap("Grid/gridded data")); + } catch (ColorMapException e) { + throw new VizException(e); + } + + DataMappingPreferences preferences = new DataMappingPreferences(); + + DataMappingEntry entry = new DataMappingEntry(); + entry.setDisplayValue(-50.); + entry.setPixelValue(0.0); + preferences.addEntry(entry); + + entry = new DataMappingEntry(); + entry.setDisplayValue(-40.); + entry.setPixelValue(1.0); + preferences.addEntry(entry); + + entry = new DataMappingEntry(); + entry.setDisplayValue(-30.); + entry.setPixelValue(2.0); + preferences.addEntry(entry); + + entry = new DataMappingEntry(); + entry.setDisplayValue(-20.); + entry.setPixelValue(3.0); + preferences.addEntry(entry); + + entry = new DataMappingEntry(); + entry.setDisplayValue(-10.); + entry.setPixelValue(4.0); + preferences.addEntry(entry); + + entry = new DataMappingEntry(); + entry.setDisplayValue(0.0); + entry.setPixelValue(5.0); + preferences.addEntry(entry); + + entry = new DataMappingEntry(); + entry.setDisplayValue(10.); + entry.setPixelValue(6.0); + preferences.addEntry(entry); + + entry = new DataMappingEntry(); + entry.setDisplayValue(20.); + entry.setPixelValue(7.0); + preferences.addEntry(entry); + + entry = new DataMappingEntry(); + entry.setDisplayValue(30.); + entry.setPixelValue(8.0); + preferences.addEntry(entry); + + entry = new DataMappingEntry(); + entry.setDisplayValue(40.); + entry.setPixelValue(9.0); + preferences.addEntry(entry); + + entry = new DataMappingEntry(); + entry.setDisplayValue(50.); + entry.setPixelValue(10.0); + preferences.addEntry(entry); + + entry = new DataMappingEntry(); + entry.setDisplayValue(60.); + entry.setPixelValue(11.0); + preferences.addEntry(entry); + + entry = new DataMappingEntry(); + entry.setDisplayValue(70.); + entry.setPixelValue(12.0); + preferences.addEntry(entry); + + entry = new DataMappingEntry(); + entry.setDisplayValue(80.); + entry.setPixelValue(13.0); + preferences.addEntry(entry); + + entry = new DataMappingEntry(); + entry.setDisplayValue(90.); + entry.setPixelValue(14.0); + preferences.addEntry(entry); + + entry = new DataMappingEntry(); + entry.setDisplayValue(100.); + entry.setPixelValue(15.0); + preferences.addEntry(entry); + + entry = new DataMappingEntry(); + entry.setDisplayValue(110.); + entry.setPixelValue(16.0); + preferences.addEntry(entry); + + params.setDisplayUnit(AbstractUnit.ONE); + params.setDataMapping(preferences); + params.setColorMapMin(0); + params.setColorMapMax(17); + + getCapability(ColorMapCapability.class).setColorMapParameters(params); + + } + + @Override + protected void resourceDataChanged(ChangeType type, Object object) { + super.resourceDataChanged(type, object); + if (type == ChangeType.CAPABILITY) { + if (object instanceof MagnificationCapability) { + if (font != null) { + font.dispose(); + font = null; + } + } + issueRefresh(); + } else if (type == ChangeType.DATA_UPDATE) { + if (object instanceof PluginDataObject[]) { + PluginDataObject[] pdos = (PluginDataObject[]) object; + for (PluginDataObject pdo : pdos) { + updates.offer(pdo); + dataProcessJob.schedule(); + } + } + } + } + + @Override + public String getName() { + return "Surface Temps [F]"; + } + + @Override + public void remove(DataTime dataTime) { + // This will be handled asynchronously by the update job + removes.offer(dataTime); + dataProcessJob.schedule(); + } + + @Override + public void project(CoordinateReferenceSystem crs) throws VizException { + // This will be handled asynchronously by the update job + reproject = true; + dataProcessJob.schedule(); + } + + @Override + public String inspect(ReferencedCoordinate coord) throws VizException { + Coordinate pixel = null; + try { + pixel = coord.asPixel(descriptor.getGridGeometry()); + } catch (TransformException e) { + throw new VizException(e); + } catch (FactoryException e) { + throw new VizException(e); + } + + Double magnification = getCapability(MagnificationCapability.class) + .getMagnification(); + + List temps = getTempsData(descriptor + .getTimeForResource(this)); + + if ((temps == null) || temps.isEmpty()) { + return null; + } + + IRenderableDisplay rDisplay = descriptor.getRenderableDisplay(); + + double bestDist = PLOT_PIXEL_SIZE * magnification; + if (rDisplay != null) { + bestDist *= rDisplay.getView().getExtent().getWidth() + / rDisplay.getBounds().width; + } else { + bestDist *= 100; + } + + TempData bestData = null; + + for (RenderableTempData temp : temps) { + double xDist = temp.string.basics.x - pixel.x; + double yDist = temp.string.basics.y - pixel.y; + double dist = Math.hypot(xDist, yDist); + if (dist < bestDist) { + bestDist = dist; + bestData = temp; + } + } + if (bestData != null) { + return bestData.getStationName(); + } + return "No Data"; + } + + /** + * + * Re-project to the new crs. Returns true to reload the frame. + * + * @return boolean + */ + private boolean processReproject() { + + if (reproject) { + reproject = false; + + GridEnvelope2D envelope = GridGeometry2D.wrap( + descriptor.getGridGeometry()).getGridRange2D(); + + synchronized (data) { + for (GenericProgressiveDisclosure disclosure : data + .values()) { + List dataList = disclosure.getAll(); + Iterator it = dataList.iterator(); + while (it.hasNext()) { + RenderableTempData temp = it.next(); + Coordinate latLon = temp.getLatLon(); + double[] px = descriptor.worldToPixel(new double[] { + latLon.x, latLon.y }); + if (envelope.contains(px[0], px[1])) { + temp.string.setCoordinates(px[0], px[1], px[2]); + } else { + it.remove(); + } + } + } + } + + return true; + } + issueRefresh(); + return false; + } + + private void processRemoves() { + synchronized (data) { + while (!removes.isEmpty()) { + DataTime toRemove = removes.poll(); + this.dataTimes.remove(toRemove); + this.data.remove(toRemove); + } + } + } + + private void processUpdates(IProgressMonitor monitor) { + if (updates.isEmpty()) { + return; + } + HashMap rcMap = resourceData + .getMetadataMap(); + rcMap = new HashMap(rcMap); + RequestConstraint rc = new RequestConstraint(null, ConstraintType.IN); + long earliestTime = Long.MAX_VALUE; + Set newStations = new HashSet(); + // Get the envelope and math transform to ensure we only bother + // processing updates on screen. + MathTransform toDescriptor = null; + try { + toDescriptor = MapUtil.getTransformFromLatLon(descriptor.getCRS()); + } catch (FactoryException e) { + statusHandler + .handle(Priority.PROBLEM, + "Error processing updates for MetarTemps, Ignoring all updates.", + e); + updates.clear(); + return; + } + + Envelope2D envelope = new Envelope2D(descriptor.getGridGeometry() + .getEnvelope()); + + while (!updates.isEmpty()) { + PluginDataObject pdo = updates.poll(); + try { + Map map = DataURIUtil.createDataURIMap(pdo); + double lon = ((Number) map.get("location.longitude")).doubleValue(); + double lat = ((Number) map.get("location.latitude")).doubleValue(); + DirectPosition2D dp = new DirectPosition2D(lon, lat); + toDescriptor.transform(dp, dp); + if (envelope.contains((DirectPosition) dp)) { + newStations.add(map.get("location.stationId").toString()); + long validTime = pdo.getDataTime().getMatchValid(); + if (validTime < earliestTime) { + earliestTime = validTime; + } + } + } catch (Exception e) { + statusHandler.handle(Priority.PROBLEM, + "Error processing updates for MetarTemps, Ignoring an update.", e); + } + } + + if (newStations.isEmpty()) { + return; + } + + rc.setConstraintValueList(newStations.toArray(new String[0])); + + rcMap.put("location.stationId", rc); + + MetarTempDataContainer container = new MetarTempDataContainer( + rcMap); + + for (Entry> entry : data + .entrySet()) { + DataTime time = entry.getKey(); + if (time.getMatchValid() < earliestTime) { + // No need to reprocess times after the earliest update. + continue; + } + GenericProgressiveDisclosure newValue = new GenericProgressiveDisclosure<>(); + for (RenderableTempData data : entry.getValue().getAll()) { + if (!newStations.contains(data.getStationName())) { + newValue.add(data); + } + } + entry.setValue(newValue); + addData(time, container.getBaseTempData(time)); + if (monitor.isCanceled()) { + return; + } + } + } + + private void processNewFrames(IProgressMonitor monitor) { + // load data in two steps, first load base data then any derived data. + // Always try to load the current frame, then nearby frames. + MetarTempDataContainer container = new MetarTempDataContainer( + resourceData.getMetadataMap(), + descriptor.getGridGeometry().getEnvelope()); + Set reprojectedFrames = new HashSet(); + Set baseOnly = new HashSet(); + boolean modified = true; + while (modified) { + // don't want to miss a reproject if retrieval takes awhile. + + if (processReproject()) { + // We must create a new container and re request all the data + // for the new area. + data.clear(); + reprojectedFrames = new HashSet(data.keySet()); + container = new MetarTempDataContainer( + resourceData.getMetadataMap(), descriptor + .getGridGeometry().getEnvelope()); + } + + if (monitor.isCanceled()) { + return; + } + modified = false; + // If the current frame changes while we are processing we will + // begin requesting data for the new frame + FramesInfo frameInfo = descriptor.getFramesInfo(); + DataTime[] times = frameInfo.getTimeMap().get( + MetarTempResource.this); + if (times == null) { + return; + } + int curIndex = frameInfo.getFrameIndex(); + int count = frameInfo.getFrameCount(); + // This will generate the number series 0, -1, 1, -2, 2, -3, 3... + for (int i = 0; i < ((count / 2) + 1); i = i < 0 ? -i : -i - 1) { + int index = (count + curIndex + i) % count; + DataTime next = times[index]; + if (next != null) { + if (!data.containsKey(next) + || reprojectedFrames.contains(next)) { + List baseData = container + .getBaseTempData(next); + addData(next, baseData); + baseOnly.add(next); + modified = true; + break; + } + if (baseOnly.contains(next)) { + List derivedData = container + .getBaseTempData(next); + addData(next, derivedData); + baseOnly.remove(next); + reprojectedFrames.remove(next); + modified = true; + break; + } + } + } + issueRefresh(); + } + + synchronized (data) { + // This will only happen if frames were removed while we were + // processing. Don't leave any half created frames + for (DataTime time : baseOnly) { + this.dataTimes.remove(time); + this.data.remove(time); + } + } + } + + private void addData(DataTime time, List temps) { + if (temps.isEmpty()) { + if (dataTimes.add(time)) { + GenericProgressiveDisclosure disclosure = + new GenericProgressiveDisclosure(); + synchronized (data) { + data.put(time, disclosure); + } + } + } + if (data.containsKey(time)) { + temps = new ArrayList(temps); + temps.addAll(getTempsData(time)); + } + Collections.sort(temps, new Comparator() { + + @Override + public int compare(TempData o1, TempData o2) { + return o2.getTempValue().compareTo(o1.getTempValue()); + } + + }); + + GenericProgressiveDisclosure newTemps = new GenericProgressiveDisclosure(); + + //RGB color = getCapability(ColorableCapability.class).getColor(); + + GridEnvelope2D envelope = GridGeometry2D.wrap( + descriptor.getGridGeometry()).getGridRange2D(); + + for (int i = 0; i < temps.size(); i++) { + TempData tempFromTenths = temps.get(i); + RenderableTempData data = null; + if (tempFromTenths instanceof RenderableTempData) { + data = (RenderableTempData) tempFromTenths; + } else { + double[] px = descriptor.worldToPixel(new double[] { + tempFromTenths.getLatLon().x, tempFromTenths.getLatLon().y }); + if (!envelope.contains(px[0], px[1])) { + continue; + } + Float amount = temps.get(i).getTempValue().floatValue(); + RGB rgbval = getColorByValue(amount); + DrawableString string = new DrawableString(formatValues(temps + .get(i).getTempValue()), rgbval); + string.setCoordinates(px[0], px[1], px[2]); + string.verticallAlignment = VerticalAlignment.MIDDLE; + string.horizontalAlignment = HorizontalAlignment.CENTER; + data = new RenderableTempData(tempFromTenths, string); + } + newTemps.add(data); + } + synchronized (data) { + data.put(time, newTemps); + dataTimes.add(time); + } + issueRefresh(); + } + + + private String formatValues(Double tempValue) { + return String.format("%6.0f", tempValue).substring(1); + } + +} \ No newline at end of file diff --git a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/MetarTempResourceData.java b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/MetarTempResourceData.java new file mode 100644 index 0000000000..7afdaa585e --- /dev/null +++ b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/MetarTempResourceData.java @@ -0,0 +1,77 @@ +/** + * 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.pointdata.rsc; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; + +import com.raytheon.uf.common.dataplugin.PluginDataObject; +import com.raytheon.uf.viz.core.exception.VizException; +import com.raytheon.uf.viz.core.rsc.AbstractRequestableResourceData; +import com.raytheon.uf.viz.core.rsc.AbstractVizResource; +import com.raytheon.uf.viz.core.rsc.LoadProperties; + +/** + * + * TODO Add Description + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 05, 2016            mjames    Copied from MetarPrecipResourceData
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ +@XmlAccessorType(XmlAccessType.NONE) +public class MetarTempResourceData extends PlotResourceData { + + @Override + protected AbstractVizResource constructResource( + LoadProperties loadProperties, PluginDataObject[] objects) { + return new MetarTempResource(this, loadProperties); + } + + @Override + public boolean isUpdatingOnMetadataOnly() { + return true; + } + + @Override + public boolean isRetrieveData() { + return false; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result; + return result; + } + + +} diff --git a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/util/MetarTempDataContainer.java b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/util/MetarTempDataContainer.java new file mode 100644 index 0000000000..ec8e659f27 --- /dev/null +++ b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/util/MetarTempDataContainer.java @@ -0,0 +1,344 @@ +/** + * 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.pointdata.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.geotools.geometry.jts.ReferencedEnvelope; + +import com.raytheon.uf.common.inventory.exception.DataCubeException; +import com.raytheon.uf.common.dataquery.requests.RequestConstraint; +import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType; +import com.raytheon.uf.common.geospatial.MapUtil; +import com.raytheon.uf.common.geospatial.util.EnvelopeIntersection; +import com.raytheon.uf.common.pointdata.PointDataContainer; +import com.raytheon.uf.common.pointdata.PointDataView; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.common.time.DataTime; +import com.raytheon.uf.viz.datacube.DataCubeContainer; +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.Envelope; +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.geom.GeometryCollection; + +/** + * + * Container for requesting and caching metar temp data. This container can be + * reused to request data for multiple times. getBaseTempData is used to quickly + * retrieve data for all metar stations which have the data directly available. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 05, 2016            mjames      Copied from MetarPrecipDataContainer
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ +@SuppressWarnings("unchecked") +public class MetarTempDataContainer { + + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(MetarTempDataContainer.class); + + /* + * Envelope which contains the whole world in LatLon projection. Used for + * intersections/conversion since this is the valid area for metar records. + */ + private static final ReferencedEnvelope WORLD_LAT_LON_ENVELOPE = new ReferencedEnvelope( + -180, 180, -90, 90, MapUtil.LATLON_PROJECTION); + + public static class TempData { + + private final long timeObs; + + private final String stationName; + + private final Double tempValue; + + private final Coordinate latLon; + + public TempData(long timeObs, String stationName, Double tempValue, + Double longitude, Double latitude) { + super(); + this.timeObs = timeObs; + this.stationName = stationName; + this.tempValue = getFahrenheitTemp(tempValue); + this.latLon = new Coordinate(longitude, latitude); + } + + public Double getTempValue() { + return tempValue; + } + + public Coordinate getLatLon() { + return latLon; + } + + public String getStationName() { + return stationName; + } + + public long getTimeObs() { + return timeObs; + } + + } + + private static final String LAT_KEY = "latitude"; + + private static final String LON_KEY = "longitude"; + + private static final String NAME_KEY = "stationName"; + + private static final String TIME_KEY = "timeObs"; + + private static final String TEMP_KEY = "temperature"; + + private static final long TEN_MIN = 10 * 60 * 1000l; + + private final Map rcMap; + + private final org.opengis.geometry.Envelope descriptorEnvelope; + + private List latLonEnvelopes; + + private final Map> baseStations = new HashMap>(); + + /** + * Consturct a container with geospatially filtering to only request data in + * the area of descriptorEnvelope + * + * @param rcMap + * @param descriptorEnvelope + */ + public MetarTempDataContainer(HashMap rcMap, + org.opengis.geometry.Envelope descriptorEnvelope) { + this.rcMap = rcMap; + this.descriptorEnvelope = descriptorEnvelope; + } + + /** + * This will construct a container with no geospatial constraints, use it + * only for updates where the rcMap already has stationIds that are + * geospatially filtered. + * + * @param rcMap + */ + public MetarTempDataContainer(Map rcMap) { + this.rcMap = rcMap; + this.descriptorEnvelope = null; + this.latLonEnvelopes = Arrays. asList(WORLD_LAT_LON_ENVELOPE); + } + + /** + * Get the base temp data from all metar stations + * + * @param time + * @return + */ + public List getBaseTempData(DataTime time) { + Map tempMap = new HashMap(); + long validTime = time.getMatchValid(); + + PointDataContainer pdc = requestPointData(rcMap, validTime, TEMP_KEY); + if (pdc != null) { + tempMap = createTempData(pdc, validTime - TEN_MIN, + validTime + TEN_MIN, TEMP_KEY); + } + + if (tempMap == null) { + tempMap = new HashMap(); + } + baseStations.put(time, tempMap.keySet()); + ArrayList result = new ArrayList( + tempMap.values()); + return result; + } + + /** + * build TempData objects for every station in a PointDataContainer + * + * @param pdc + * @param startTime + * @param latestTime + * @param tempKey + * @return + */ + private Map createTempData(PointDataContainer pdc, + long startTime, long latestTime, String tempKey) { + Map tempMap = new HashMap(); + for (int i = 0; i < pdc.getCurrentSz(); i++) { + PointDataView pdv = pdc.readRandom(i); + Number latitude = pdv.getNumber(LAT_KEY); + Number longitude = pdv.getNumber(LON_KEY); + String stationName = pdv.getString(NAME_KEY); + long timeObs = pdv.getLong(TIME_KEY); + Number tempValue = pdv.getNumber(tempKey); + if (timeObs > latestTime || timeObs <= startTime) { + continue; + } + + TempData data = tempMap.get(stationName); + if (data == null) { + data = new TempData(timeObs, stationName, + tempValue.doubleValue(), longitude.doubleValue(), + latitude.doubleValue()); + if (tempValue.doubleValue() > -100.){ + tempMap.put(stationName, data); + } + } else { + if (timeObs > data.getTimeObs()) { + data = new TempData(timeObs, stationName, + tempValue.doubleValue(), longitude.doubleValue(), + latitude.doubleValue()); + tempMap.put(stationName, data); + } + } + } + return tempMap; + } + + /** + * This function perfroms the request to edex for point data. + * + * @param rcMap + * @param time + * @param tempKeys + * @return + */ + private PointDataContainer requestPointData( + Map rcMap, long time, + String... tempKeys) { + List parameters = new ArrayList( + Arrays.asList(tempKeys)); + parameters.add(LAT_KEY); + parameters.add(LON_KEY); + parameters.add(NAME_KEY); + parameters.add(TIME_KEY); + rcMap = new HashMap(rcMap); + Calendar validTime = Calendar.getInstance(); + validTime.setTimeInMillis(time); + validTime.add(Calendar.MINUTE, 0); + DataTime end = new DataTime(validTime); + validTime = (Calendar) end.getValidTime().clone(); + validTime.add(Calendar.HOUR, -1); + validTime.add(Calendar.MINUTE, 1); + DataTime start = new DataTime(validTime); + RequestConstraint timeRC = new RequestConstraint(null, + ConstraintType.BETWEEN); + timeRC.setBetweenValueList(new String[] { start.toString(), + end.toString() }); + rcMap.put("dataTime", timeRC); + PointDataContainer pdc = null; + // Over the dateline there might be an envelope on either side. + for (Envelope latLonEnvelope : getLatLonEnvelopes()) { + PointDataContainer tmppdc = null; + RequestConstraint lonRC = new RequestConstraint(null, + ConstraintType.BETWEEN); + Double minLon = latLonEnvelope.getMinX(); + Double maxLon = latLonEnvelope.getMaxX(); + lonRC.setBetweenValueList(new String[] { minLon.toString(), + maxLon.toString() }); + rcMap.put("location.longitude", lonRC); + RequestConstraint latRC = new RequestConstraint(null, + ConstraintType.BETWEEN); + Double minLat = latLonEnvelope.getMinY(); + Double maxLat = latLonEnvelope.getMaxY(); + latRC.setBetweenValueList(new String[] { minLat.toString(), + maxLat.toString() }); + rcMap.put("location.latitude", latRC); + try { + tmppdc = DataCubeContainer.getPointData("obs", + parameters.toArray(new String[0]), rcMap); + } catch (DataCubeException e) { + statusHandler + .handle(Priority.ERROR, + "Error getting temp data, some obs will not display.", + e); + } + if (tmppdc != null) { + tmppdc.setCurrentSz(tmppdc.getAllocatedSz()); + if (pdc != null) { + pdc.combine(tmppdc); + pdc.setCurrentSz(pdc.getAllocatedSz()); + } else { + pdc = tmppdc; + } + } + } + return pdc; + } + + /** + * Get envelopes describing the latlon area that should be used to constrain + * all queries + * + * @return + */ + private List getLatLonEnvelopes() { + if (latLonEnvelopes == null) { + this.latLonEnvelopes = new ArrayList(2); + try { + Geometry intersection = EnvelopeIntersection + .createEnvelopeIntersection(descriptorEnvelope, + WORLD_LAT_LON_ENVELOPE, 0.1, 180, 180); + if (intersection instanceof GeometryCollection) { + GeometryCollection gc = (GeometryCollection) intersection; + for (int n = 0; n < gc.getNumGeometries(); n += 1) { + latLonEnvelopes.add(gc.getGeometryN(n) + .getEnvelopeInternal()); + } + } else { + latLonEnvelopes.add(intersection.getEnvelopeInternal()); + } + } catch (Exception e) { + statusHandler.handle(Priority.VERBOSE, e.getLocalizedMessage(), + e); + this.latLonEnvelopes.add(WORLD_LAT_LON_ENVELOPE); + } + } + return latLonEnvelopes; + } + + public static Double getFahrenheitTemp(Double val){ + if (val > -100.) { + return (val * 1.8) + 32.; + } else { + return val; + } + + } + + +}