12.10.1-3 baseline
Former-commit-id:de1639aea2
[formerly21f430062b
] [formerlyde1639aea2
[formerly21f430062b
] [formerly969e7e6dfd
[formerly 1a94c1ca3674c8e4dbb8847de5190efe33da371c]]] Former-commit-id:969e7e6dfd
Former-commit-id:f376a4b4db
[formerly438d139fdd
] Former-commit-id:faadb51529
This commit is contained in:
parent
5684a84a46
commit
5030894212
184 changed files with 13677 additions and 3204 deletions
|
@ -112,6 +112,10 @@
|
|||
<copy todir="${buildDirectory}/plugins">
|
||||
<fileset dir="${buildDirectory}/../../../" includes="edu.*/**"/>
|
||||
</copy>
|
||||
<echo message="de.*/**"/>
|
||||
<copy todir="${buildDirectory}/plugins">
|
||||
<fileset dir="${buildDirectory}/../../../" includes="de.*/**"/>
|
||||
</copy>
|
||||
<antcall target="getBaseComponents" />
|
||||
</target>
|
||||
|
||||
|
|
|
@ -107,6 +107,12 @@
|
|||
<fileset dir="${workspace.dir}"
|
||||
includes="edu.*/**" />
|
||||
</copy>
|
||||
|
||||
<echo message="PLUGINS: de.*/**" />
|
||||
<copy todir="${basedir}/cave/p2/plugins">
|
||||
<fileset dir="${workspace.dir}"
|
||||
includes="de.*/**" />
|
||||
</copy>
|
||||
<!-- END: Copy The Plugins -->
|
||||
|
||||
<!-- Copy The Features -->
|
||||
|
@ -266,7 +272,11 @@
|
|||
<param name="feature"
|
||||
value="com.raytheon.uf.viz.thinclient.feature" />
|
||||
</antcall>
|
||||
|
||||
<antcall target="p2.build.repo">
|
||||
<param name="feature"
|
||||
value="com.raytheon.uf.viz.kml.export.feature" />
|
||||
</antcall>
|
||||
|
||||
<antcall target="cleanup.features" />
|
||||
</target>
|
||||
|
||||
|
|
|
@ -0,0 +1,307 @@
|
|||
# ----------------------------------------------------------------------------
|
||||
# This software is in the public domain, furnished "as is", without technical
|
||||
# support, and with no warranty, express or implied, as to its usefulness for
|
||||
# any purpose.
|
||||
#
|
||||
# MakeHazard.py
|
||||
#
|
||||
# SOFTWARE HISTORY
|
||||
# Date Ticket# Engineer Description
|
||||
# ------------ ---------- ----------- --------------------------
|
||||
# Apr 03,2012 436 randerso Converted to Python procedure to allow some
|
||||
# level of site customization
|
||||
# Apr 09,2012 436 randerso Merged RNK's MakeHazards_Elevation procedure
|
||||
#
|
||||
# Author: randerso
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# The MenuItems list defines the GFE menu item(s) under which the
|
||||
# Procedure is to appear.
|
||||
# Possible items are: Populate, Edit, Consistency, Verify, Hazards
|
||||
MenuItems = ["Hazards"]
|
||||
|
||||
|
||||
import SmartScript
|
||||
import time, string, sys
|
||||
import HazardUtils
|
||||
import re
|
||||
import numpy
|
||||
import LogStream
|
||||
import JUtil
|
||||
|
||||
class Procedure (SmartScript.SmartScript):
|
||||
def __init__(self, dbss):
|
||||
SmartScript.SmartScript.__init__(self, dbss)
|
||||
|
||||
self._dataManager = dbss
|
||||
self._afterInit = 0 #flag indicating init is done.
|
||||
|
||||
self._tropicalHaz = ['HU.W','HU.A','HU.S','TR.W','TR.A']
|
||||
self._natlBaseETN = 1001
|
||||
|
||||
|
||||
def setUpUI(self):
|
||||
if sys.modules.has_key("MakeHazardConfig"):
|
||||
sys.modules.__delitem__("MakeHazardConfig")
|
||||
import MakeHazardConfig
|
||||
|
||||
args = {}
|
||||
args['dataManager'] = self._dataManager
|
||||
args['selectedTimeRange'] = self.selectedTimeRange
|
||||
args['mapColor'] = MakeHazardConfig.mapColor
|
||||
args['defaultMapWidth'] = MakeHazardConfig.defaultMapWidth
|
||||
args['timeScaleEndTime'] = MakeHazardConfig.timeScaleEndTime
|
||||
args['areaThreshold'] = MakeHazardConfig.areaThreshold
|
||||
args['defaultHazardType'] = MakeHazardConfig.defaultHazardType
|
||||
args['mapNames'] = MakeHazardConfig.mapNames
|
||||
args['hazardDict'] = MakeHazardConfig.hazardDict
|
||||
args['tcmList'] = MakeHazardConfig.tcmList
|
||||
args['tropicalHaz'] = self._tropicalHaz
|
||||
args['natlBaseETN'] = self._natlBaseETN
|
||||
|
||||
if not hasattr(MakeHazardConfig, 'localEffectAreas') or \
|
||||
MakeHazardConfig.localEffectAreas is None:
|
||||
args['localEffectAreas'] = {}
|
||||
else:
|
||||
args['localEffectAreas'] = MakeHazardConfig.localEffectAreas
|
||||
|
||||
if not hasattr(MakeHazardConfig, 'localAreaData') or \
|
||||
MakeHazardConfig.localAreaData is None:
|
||||
args['localAreaData'] = {}
|
||||
else:
|
||||
args['localAreaData'] = MakeHazardConfig.localAreaData
|
||||
|
||||
# create the Java/SWT dialog and open it
|
||||
from com.raytheon.viz.gfe.makehazard import MakeHazardDialog
|
||||
self.__dlg = MakeHazardDialog.createFromPython(
|
||||
JUtil.pyValToJavaObj(args)
|
||||
)
|
||||
self.__dlg.openFromPython()
|
||||
|
||||
# run the Java/SWT event loop
|
||||
try:
|
||||
dismiss = False
|
||||
while not dismiss:
|
||||
args = JUtil.javaObjToPyVal(self.__dlg.runFromPython(), converter)
|
||||
dismiss = True;
|
||||
# if args is None, then Cancel was pressed
|
||||
if args is not None:
|
||||
# dismiss is True if the Run/Dismiss button is pressed,
|
||||
# false if Run is pressed
|
||||
dismiss = args["dismiss"]
|
||||
del args["dismiss"]
|
||||
|
||||
if self.makeHazardGrid(**args) != 1:
|
||||
dismiss = False
|
||||
finally:
|
||||
# close the Java/SWT dialog when Cancelled, Dismissed or exception occurs
|
||||
self.__dlg.closeFromPython()
|
||||
|
||||
# RJM modified this routine from the HazardUtility file
|
||||
# returns a Numeric mask where each zone in zoneList is set to 1
|
||||
def _makeMask(self, zoneList, hazLocalEffect):
|
||||
|
||||
# RJM had to modify this next line to point to the hazUtils
|
||||
# for the getGridSize routine.
|
||||
gridSize = self._hazUtils._getGridSize()
|
||||
mask = numpy.zeros(gridSize)
|
||||
eaList = self.editAreaList()
|
||||
|
||||
# Get the elevation from the GUI input. We'll do this by clipping
|
||||
# of any numerical digits from the local effect.
|
||||
# elevation_string = re.findall("\d+", hazLocalEffect)
|
||||
# print "re elevation=", elevation_string, "xxx"
|
||||
# try:
|
||||
# elevation = elevation_string[0]
|
||||
# except:
|
||||
# elevation = "None"
|
||||
# print "re elevation=", elevation, "xxx"
|
||||
for z in zoneList:
|
||||
print "in _makeMask processing zone ", z
|
||||
|
||||
if z in eaList:
|
||||
zoneArea = self.getEditArea(z)
|
||||
zoneMask = self.encodeEditArea(zoneArea)
|
||||
|
||||
# Code added by RJM. This checks to see if the local effect
|
||||
# area was specified and is a valid edit area. If so,
|
||||
# make a mask from it, and then do an intersection with
|
||||
# the zone mask.
|
||||
if hazLocalEffect in eaList:
|
||||
print "Masking",z,"with",hazLocalEffect
|
||||
localEffectArea = self.getEditArea(hazLocalEffect)
|
||||
localEffectMask = self.encodeEditArea(localEffectArea)
|
||||
zoneMask = numpy.logical_and(zoneMask, localEffectMask)
|
||||
|
||||
mask = numpy.logical_or(mask, zoneMask)
|
||||
# else:
|
||||
# if z in eaList:
|
||||
# zoneArea = self.getEditArea(z)
|
||||
# zoneMask = self.encodeEditArea(zoneArea)
|
||||
# mask = numpy.logical_or(mask, zoneMask)
|
||||
|
||||
return mask
|
||||
|
||||
# Creates the hazard grid based on the dialog input
|
||||
def makeHazardGrid(self, selectedHazard, timeRange, areaList, segmentNumber,
|
||||
selectedTimeRange, defaultAreaList, defaultHazard, defaultSegment,
|
||||
hazLocalEffect):
|
||||
siteID = self.getSiteID()
|
||||
usingHazLocalEffect = (hazLocalEffect != 'None')
|
||||
|
||||
if len(areaList) == 0:
|
||||
editArea = self.getActiveEditArea()
|
||||
mask = self.encodeEditArea(editArea)
|
||||
else:
|
||||
# make the mask based on the list selections
|
||||
if not usingHazLocalEffect:
|
||||
mask = self._hazUtils._makeMask(areaList)
|
||||
else:
|
||||
mask = self._makeMask(areaList, hazLocalEffect)
|
||||
|
||||
if usingHazLocalEffect:
|
||||
# get the segment number and filter for valid characters
|
||||
segNum = segmentNumber
|
||||
|
||||
# get the hazards currently defined as temporary grids
|
||||
hazParms = self.getHazardParmNames()
|
||||
|
||||
# look through the list of grids and create a list of
|
||||
# segment numbers (if any) that are already in use
|
||||
# for the current hazard
|
||||
# if len(hazParms) == 0:
|
||||
# self.statusBarMsg("No temporary grids to merge.", "S")
|
||||
# return 0
|
||||
segList = []
|
||||
print "selectedHazard=", selectedHazard
|
||||
selectedPhen = selectedHazard[0:2]
|
||||
selectedSig = selectedHazard[3]
|
||||
print "selectedPhen,selectedSig=", selectedPhen, ".", selectedSig
|
||||
for hazParm in hazParms:
|
||||
print "hazParm=", hazParm
|
||||
trList = self._hazUtils._getWEInventory(hazParm)
|
||||
for tr in trList:
|
||||
print " tr=", tr, timeRange
|
||||
intersect_hours = tr.intersection(timeRange).duration()
|
||||
print " intersect=", intersect_hours
|
||||
intersect_percent = intersect_hours / timeRange.duration() * 100.0
|
||||
print " intersect %=", intersect_percent
|
||||
phen = hazParm[3:5]
|
||||
sig = hazParm[5:6]
|
||||
print "phen,sig=", phen, ".", sig
|
||||
if len(hazParm) > 6:
|
||||
if hazParm[6:].isdigit():
|
||||
seg = int(hazParm[6:])
|
||||
print " seg=", seg
|
||||
if phen == selectedPhen and sig == selectedSig:
|
||||
segList.append(seg)
|
||||
print "appending ", seg
|
||||
else:
|
||||
seg = 0
|
||||
segList.sort()
|
||||
|
||||
# print "looping through segList"
|
||||
# for seg in segList:
|
||||
# print " seg=", seg," elev=", elevation
|
||||
# if str(elevation) == str(seg):
|
||||
# print "adding 1 to elevation"
|
||||
# elevation += 1
|
||||
#
|
||||
# if elevation > 400:
|
||||
# print "using elevation for segNum"
|
||||
# segNum = elevation
|
||||
# # replace the segmentNumber field with the elevation +/- the Above/Below indicator.
|
||||
# self.__dlg.setSegmentNumber(elevation)
|
||||
# segmentNumber = str(elevation)
|
||||
# print "*** segmentNumber=", segmentNumber
|
||||
|
||||
index = string.find(selectedHazard, " ")
|
||||
if index != -1:
|
||||
selectedHazard = selectedHazard[0:index]
|
||||
if len(segmentNumber) > 0:
|
||||
hazardKey = selectedHazard + ":" + segmentNumber
|
||||
else:
|
||||
hazardKey = selectedHazard
|
||||
|
||||
defaultHazKey = ""
|
||||
if len(defaultSegment) > 0 and defaultHazard is not None:
|
||||
defaultHazKey = defaultHazard + ":" + defaultSegment
|
||||
|
||||
weName = self._hazUtils._makeTempWEName(hazardKey)
|
||||
|
||||
# if we're modifying, remove the old grid first
|
||||
if defaultAreaList != [] and hazardKey == defaultHazKey:
|
||||
self.deleteCmd([weName], self.selectedTimeRange)
|
||||
|
||||
# if we have no selection prevent user from making an empty hazard
|
||||
if 1 not in mask:
|
||||
self.statusBarMsg("NO EDIT AREA SELECTED: \n Select area from map or load edit area in GFE!", "S")
|
||||
return 0
|
||||
|
||||
self._hazUtils._addHazard(weName, timeRange, hazardKey, mask)
|
||||
LogStream.logUse("Set: ", weName,
|
||||
self._hazUtils._printTime(timeRange.startTime().unixTime()),
|
||||
self._hazUtils._printTime(timeRange.endTime().unixTime()), hazardKey,
|
||||
self._hazUtils._printAreas(areaList))
|
||||
|
||||
return 1
|
||||
|
||||
def getHazardParmNames(self):
|
||||
# get the list of loaded temporary hazard parms
|
||||
parms = self.loadedParms()
|
||||
hazParms = []
|
||||
for weName, level, dbID in parms:
|
||||
if "haz" in weName:
|
||||
key = self._hazUtils._tempWENameToKey(weName)
|
||||
index = string.find(key, ":")
|
||||
if index != -1:
|
||||
mkey = key[0:index]
|
||||
segNum = key[index+1:]
|
||||
else:
|
||||
mkey = key
|
||||
segNum = ""
|
||||
|
||||
# append the hazard and a description
|
||||
parmName = "haz" + key
|
||||
parmName = string.replace(parmName, ".", "")
|
||||
parmName = string.replace(parmName, ":", "")
|
||||
hazParms.append(parmName)
|
||||
|
||||
return hazParms
|
||||
|
||||
def execute(self, timeRange):
|
||||
#self._hazUtils = HazardUtils.HazardUtils(self._dataManager, self.eaMgr())
|
||||
self._hazUtils = HazardUtils.HazardUtils(self._dataManager, None)
|
||||
# save the selected timeRange
|
||||
self.selectedTimeRange = timeRange
|
||||
|
||||
self.setToolType("numeric")
|
||||
|
||||
# see if the Hazards WE is loaded in the GFE, if not abort the tool
|
||||
if not self._hazUtils._hazardsLoaded():
|
||||
self.statusBarMsg("Hazards Weather Element must be loaded in " + \
|
||||
"the GFE before running MakeHazard", "S")
|
||||
self.cancel()
|
||||
|
||||
|
||||
# always separate the Hazards grid first
|
||||
self._hazUtils._separateHazardGrids()
|
||||
|
||||
self.setUpUI()
|
||||
|
||||
self._afterInit = 1 #initialization done
|
||||
|
||||
return
|
||||
|
||||
def converter(obj):
|
||||
import AbsTime
|
||||
import TimeRange
|
||||
retVal = None
|
||||
|
||||
objtype = obj.jclassname
|
||||
if objtype == "java.util.Date":
|
||||
retVal = AbsTime.AbsTime(obj)
|
||||
elif objtype == "com.raytheon.uf.common.time.TimeRange":
|
||||
retVal = TimeRange.TimeRange(obj)
|
||||
return retVal
|
||||
|
|
@ -1,157 +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.
|
||||
##
|
||||
|
||||
# AWIPS1 imports SmartScript to retrieve the site ID below, but
|
||||
# since all we need is just that site ID, it makes more sense to
|
||||
# import DataManager directly to get that rather than all of the
|
||||
# SmartScript module
|
||||
# import SmartScript
|
||||
from com.raytheon.viz.gfe.core import DataManager
|
||||
|
||||
def sortHazardList(dict):
|
||||
#sorts the entries in the menus in alphabetical order, returns sorted
|
||||
#dictionary
|
||||
import VTECTable
|
||||
for ent in dict.keys():
|
||||
values = dict[ent]
|
||||
# get the descriptive word for this phen/sig
|
||||
items = []
|
||||
for v in values:
|
||||
desc = VTECTable.VTECTable.get(v,'')
|
||||
items.append((desc, v))
|
||||
items.sort() #sorts by description
|
||||
#extract out the sorted phen/sig
|
||||
phensig = []
|
||||
for desc, v in items:
|
||||
phensig.append(v)
|
||||
dict[ent] = phensig
|
||||
return dict
|
||||
|
||||
|
||||
###########################################################
|
||||
############## ###############
|
||||
############## CONFIGURATION SECTION ###############
|
||||
############## ###############
|
||||
|
||||
# Lists of hazards organized by type in a dictionary
|
||||
# Set these to value you use for your site. To minimize scrolling,
|
||||
# change the order so that the most common values your site uses are
|
||||
# near the front of each list. The key is the menu entry on the
|
||||
# Make Hazard dialog, the values are the key values for Hazards.
|
||||
siteID = DataManager.getCurrentInstance().getSiteID()
|
||||
if siteID == "GUM":
|
||||
hazardDict = {
|
||||
'Hydrology' : ["FF.A", "FA.A"],
|
||||
'Fire Weather' : ["FW.A", "FW.W"],
|
||||
'Coastal Flood' : ["CF.S", "LS.S", "CF.Y", "CF.W", "CF.A",
|
||||
"SU.Y", "SU.W", "LS.Y", "LS.W", "LS.A", "RP.S"],
|
||||
'Non-Precipitation' : ["AF.W", "AF.Y", "AQ.Y", "AS.O", "AS.Y", "DU.Y",
|
||||
"DS.W", "EH.W", "EH.A", "EC.W", "EC.A", "FG.Y", "FZ.W", "FZ.A",
|
||||
"HZ.W", "HZ.A", "ZF.Y", "FR.Y", "HT.Y", "HW.W", "HW.A",
|
||||
"LW.Y", "SM.Y", "WI.Y"],
|
||||
'Marine' : ["MA.S", "MH.W", "MH.Y", "BW.Y", "UP.Y", "MF.Y",
|
||||
"GL.A", "GL.W", "SE.A", "SE.W", "UP.A", "UP.W", "HF.A", "HF.W", "LO.Y", "SC.Y", "SW.Y",
|
||||
"RB.Y", "SI.Y", "MS.Y", "SR.A", "SR.W"],
|
||||
'Typhoon' : ["TY.A", "TY.W", "TR.A", "TR.W", "HU.S"],
|
||||
'Tsunami' : ["TS.A", "TS.W"],
|
||||
|
||||
#'Local' : ["TEST"], #example of adding local hazards
|
||||
# you can define your own groups of hazards by adding new categories
|
||||
}
|
||||
else:
|
||||
hazardDict = {
|
||||
'Winter Weather' : ["BZ.W", "BZ.A", "ZR.Y",
|
||||
"IS.W", "LE.Y", "LE.W", "LE.A",
|
||||
"WC.Y", "WC.W", "WC.A", "WS.W", "WS.A", "WW.Y"],
|
||||
'Hydrology' : ["FF.A", "FA.A"],
|
||||
'Fire Weather' : ["FW.A", "FW.W"],
|
||||
'Convective Watches' : ["SV.A", "TO.A"],
|
||||
'Coastal Flood' : ["CF.S", "LS.S", "CF.Y", "CF.W", "CF.A",
|
||||
"SU.Y", "SU.W", "LS.Y", "LS.W", "LS.A", "RP.S"],
|
||||
'Non-Precipitation' : ["AF.W", "AF.Y", "AQ.Y", "AS.O", "AS.Y", "DU.Y",
|
||||
"DS.W", "EH.W", "EH.A", "EC.W", "EC.A", "FG.Y", "FZ.W", "FZ.A",
|
||||
"HZ.W", "HZ.A", "ZF.Y", "FR.Y", "HT.Y", "HW.W", "HW.A",
|
||||
"LW.Y", "SM.Y", "WI.Y"],
|
||||
'Marine' : ["MA.S", "MH.W", "MH.Y", "BW.Y", "UP.Y", "MF.Y",
|
||||
"GL.A", "GL.W", "SE.A", "SE.W", "UP.A", "UP.W", "HF.A", "HF.W", "LO.Y", "SC.Y", "SW.Y",
|
||||
"RB.Y", "SI.Y", "MS.Y", "SR.A", "SR.W"],
|
||||
'Tropical Cyclone' : ["HU.W", "HU.A", "HU.S", "TR.W", "TR.A"],
|
||||
'Tsunami' : ["TS.A", "TS.W"],
|
||||
|
||||
#'Local' : ["TEST"], #example of adding local hazards
|
||||
# you can define your own groups of hazards by adding new categories
|
||||
}
|
||||
|
||||
|
||||
# This function sorts the hazards in the hazardDict by description.
|
||||
# Comment it out if this is not desired.
|
||||
hazardDict = sortHazardList(hazardDict)
|
||||
|
||||
# Dictionary of map categories and the map names. The "<site>" is
|
||||
# substituted with your site name. The names of the map must match
|
||||
# those defined in the ifpServer. The keys in mapNames must match
|
||||
# the keys in hazardDict.
|
||||
|
||||
mapNames = {
|
||||
'Fire Weather' : ["FireWxZones_<site>"],
|
||||
'Hydrology' : ["Zones_<site>"],
|
||||
'Coastal Flood': ["Zones_<site>"],
|
||||
'Convective Watches' : ["Marine_Zones_<site>","FIPS_<site>"],
|
||||
'Non-Precipitation' : ["Zones_<site>"],
|
||||
'Tropical Cyclone' : ["Offshore_Marine_Zones_<site>",
|
||||
"Marine_Zones_<site>","Zones_<site>"],
|
||||
'Typhoon' : ["Offshore_Marine_Zones_<site>",
|
||||
"Marine_Zones_<site>","Zones_<site>"],
|
||||
'Tsunami' : ["Offshore_Marine_Zones_<site>",
|
||||
"Marine_Zones_<site>","Zones_<site>"],
|
||||
'Winter Weather' : ["Zones_<site>"],
|
||||
'Marine' : ["Offshore_Marine_Zones_<site>",
|
||||
"Marine_Zones_<site>"],
|
||||
#'Local' : ["Zones_<site>"], #example of adding local class
|
||||
}
|
||||
|
||||
# The hazard type chosen when MakeHazard opens
|
||||
defaultHazardType = "Non-Precipitation"
|
||||
|
||||
# this is the color for the selected areas in the map
|
||||
mapColor = "red"
|
||||
|
||||
# initial map width
|
||||
defaultMapWidth = 400;
|
||||
|
||||
# the percentage that an area must be covered to default to selected
|
||||
areaThreshold = 0.10
|
||||
|
||||
# End time in hours of the time scales
|
||||
timeScaleEndTime = 96
|
||||
|
||||
# Define the tropical product used to identify the particular storm
|
||||
tcmList = [] # Comment out for HLS sites
|
||||
|
||||
# Uncomment line below for Atlantic basin sites
|
||||
#tcmList = ["TCMAT1", "TCMAT2", "TCMAT3", "TCMAT4", "TCMAT5"]
|
||||
|
||||
# Uncomment line below for EPac basin sites
|
||||
#tcmList = ["TCMEP1", "TCMEP2", "TCMEP3", "TCMEP4", "TCMEP5"]
|
||||
|
||||
# Uncomment line below for CPac basin sites
|
||||
#self.tcmList = ["TCMCP1", "TCMCP2", "TCMCP3", "TCMCP4", "TCMCP5"]
|
||||
|
||||
#################### END CONFIGURATION SECTION #################
|
|
@ -1061,10 +1061,7 @@ class HazardUtils(SmartScript.SmartScript):
|
|||
|
||||
#print areas, from dictionary
|
||||
def _printAreas(self, areas):
|
||||
ara = []
|
||||
for a in areas.keys():
|
||||
if areas[a] == 1:
|
||||
ara.append(a)
|
||||
ara = list(areas)
|
||||
ara.sort()
|
||||
return ara
|
||||
|
||||
|
|
|
@ -0,0 +1,182 @@
|
|||
# ----------------------------------------------------------------------------
|
||||
# This software is in the public domain, furnished "as is", without technical
|
||||
# support, and with no warranty, express or implied, as to its usefulness for
|
||||
# any purpose.
|
||||
#
|
||||
# MakeHazard.py
|
||||
#
|
||||
# SOFTWARE HISTORY
|
||||
# Date Ticket# Engineer Description
|
||||
# ------------ ---------- ----------- --------------------------
|
||||
# Jul 10,2012 436 randerso Separated configuration data from the
|
||||
# MakeHazard procedure
|
||||
#
|
||||
# Author: randerso
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
def sortHazardList(dict):
|
||||
#sorts the entries in the menus in alphabetical order, returns sorted
|
||||
#dictionary
|
||||
import VTECTable
|
||||
for ent in dict.keys():
|
||||
values = dict[ent]
|
||||
# get the descriptive word for this phen/sig
|
||||
items = []
|
||||
for v in values:
|
||||
desc = VTECTable.VTECTable.get(v,'')
|
||||
items.append((desc, v))
|
||||
items.sort() #sorts by description
|
||||
#extract out the sorted phen/sig
|
||||
phensig = []
|
||||
for desc, v in items:
|
||||
phensig.append(v)
|
||||
dict[ent] = phensig
|
||||
|
||||
return dict
|
||||
|
||||
# Lists of hazards organized by type in a dictionary
|
||||
# Set these to value you use for your site. To minimize scrolling,
|
||||
# change the order so that the most common values your site uses are
|
||||
# near the front of each list. The key is the menu entry on the
|
||||
# Make Hazard dialog, the values are the key values for Hazards.
|
||||
|
||||
# Using OrderedDict allows you to control the order in which the
|
||||
# Hazard Types are displayed in the dialog
|
||||
#
|
||||
from collections import OrderedDict
|
||||
hazardDict = OrderedDict([
|
||||
('Winter Weather', ["BZ.W", "BZ.A", "ZR.Y",
|
||||
"IS.W", "LE.Y", "LE.W", "LE.A",
|
||||
"WC.Y", "WC.W", "WC.A", "WS.W", "WS.A", "WW.Y"]),
|
||||
('Hydrology', ["FF.A", "FA.A"]),
|
||||
('Fire Weather', ["FW.A", "FW.W"]),
|
||||
('Convective Watches', ["SV.A", "TO.A"]),
|
||||
('Coastal Flood', ["CF.S", "LS.S", "CF.Y", "CF.W", "CF.A",
|
||||
"SU.Y", "SU.W", "LS.Y", "LS.W", "LS.A", "RP.S"]),
|
||||
('Non-Precipitation', ["AF.W", "AF.Y", "AQ.Y", "AS.O", "AS.Y", "DU.Y",
|
||||
"DS.W", "EH.W", "EH.A", "EC.W", "EC.A", "FG.Y", "FZ.W", "FZ.A",
|
||||
"HZ.W", "HZ.A", "ZF.Y", "FR.Y", "HT.Y", "HW.W", "HW.A",
|
||||
"LW.Y", "SM.Y", "WI.Y"]),
|
||||
('Marine', ["MA.S", "MH.W", "MH.Y", "BW.Y", "UP.Y", "MF.Y",
|
||||
"GL.A", "GL.W", "SE.A", "SE.W", "UP.A", "UP.W", "HF.A", "HF.W", "LO.Y", "SC.Y", "SW.Y",
|
||||
"RB.Y", "SI.Y", "MS.Y", "SR.A", "SR.W"]),
|
||||
('Tropical Cyclone', ["HU.W", "HU.A", "HU.S", "TR.W", "TR.A"]),
|
||||
('Tsunami', ["TS.A", "TS.W"]),
|
||||
|
||||
# ('Local', ["TEST"]), #example of adding local hazards
|
||||
# you can define your own groups of hazards by adding new categories
|
||||
])
|
||||
|
||||
# for GUM use comment out the above definition and uncomment the one below
|
||||
|
||||
#hazardDict = OrderedDict([
|
||||
# ('Hydrology', ["FF.A", "FA.A"]),
|
||||
# ('Fire Weather', ["FW.A", "FW.W"]),
|
||||
# ('Coastal Flood', ["CF.S", "LS.S", "CF.Y", "CF.W", "CF.A",
|
||||
# "SU.Y", "SU.W", "LS.Y", "LS.W", "LS.A", "RP.S"]),
|
||||
# ('Non-Precipitation', ["AF.W", "AF.Y", "AQ.Y", "AS.O", "AS.Y", "DU.Y",
|
||||
# "DS.W", "EH.W", "EH.A", "EC.W", "EC.A", "FG.Y", "FZ.W", "FZ.A",
|
||||
# "HZ.W", "HZ.A", "ZF.Y", "FR.Y", "HT.Y", "HW.W", "HW.A",
|
||||
# "LW.Y", "SM.Y", "WI.Y"]),
|
||||
# ('Marine', ["MA.S", "MH.W", "MH.Y", "BW.Y", "UP.Y", "MF.Y",
|
||||
# "GL.A", "GL.W", "SE.A", "SE.W", "UP.A", "UP.W", "HF.A", "HF.W", "LO.Y", "SC.Y", "SW.Y",
|
||||
# "RB.Y", "SI.Y", "MS.Y", "SR.A", "SR.W"]),
|
||||
# ('Typhoon', ["TY.A", "TY.W", "TR.A", "TR.W", "HU.S"]),
|
||||
# ('Tsunami', ["TS.A", "TS.W"]),
|
||||
#
|
||||
# # ('Local', ["TEST"]), #example of adding local hazards
|
||||
# # you can define your own groups of hazards by adding new categories
|
||||
# ])
|
||||
|
||||
|
||||
# This function sorts the hazards in the hazardDict by description.
|
||||
# Comment it out if this is not desired.
|
||||
hazardDict = sortHazardList(hazardDict)
|
||||
|
||||
# Dictionary of map categories and the map names. The "<site>" is
|
||||
# substituted with your site name. The names of the map must match
|
||||
# those defined in the ifpServer. The keys in mapNames must match
|
||||
# the keys in hazardDict.
|
||||
|
||||
mapNames = {
|
||||
'Fire Weather' : ["FireWxZones_<site>"],
|
||||
'Hydrology' : ["Zones_<site>"],
|
||||
'Coastal Flood': ["Zones_<site>"],
|
||||
'Convective Watches' : ["Marine_Zones_<site>","FIPS_<site>"],
|
||||
'Non-Precipitation' : ["Zones_<site>"],
|
||||
'Tropical Cyclone' : ["Offshore_Marine_Zones_<site>",
|
||||
"Marine_Zones_<site>","Zones_<site>"],
|
||||
'Typhoon' : ["Offshore_Marine_Zones_<site>",
|
||||
"Marine_Zones_<site>","Zones_<site>"],
|
||||
'Tsunami' : ["Offshore_Marine_Zones_<site>",
|
||||
"Marine_Zones_<site>","Zones_<site>"],
|
||||
'Winter Weather' : ["Zones_<site>"],
|
||||
'Marine' : ["Offshore_Marine_Zones_<site>",
|
||||
"Marine_Zones_<site>"],
|
||||
#'Local' : ["Zones_<site>"], #example of adding local class
|
||||
}
|
||||
|
||||
# The defaultHazardType - selected when the tool is first run. This
|
||||
# must be one of the categories (keys) in the mapNames and hazardDict.
|
||||
defaultHazardType = "Non-Precipitation"
|
||||
|
||||
# this is the color for the selected areas in the map
|
||||
mapColor = "red" # color of selected areas
|
||||
|
||||
# initial map width
|
||||
defaultMapWidth = 400;
|
||||
|
||||
# the percentage that an area must be covered to default to selected
|
||||
areaThreshold = 0.10
|
||||
|
||||
# End time in hours of the time scales
|
||||
timeScaleEndTime = 96
|
||||
|
||||
# Define the tropical product used to identify the particular storm
|
||||
tcmList = [] # Comment out for HLS sites
|
||||
|
||||
# Uncomment line below for Atlantic basin sites
|
||||
#tcmList = ["TCMAT1", "TCMAT2", "TCMAT3", "TCMAT4", "TCMAT5"]
|
||||
|
||||
# Uncomment line below for EPac basin sites
|
||||
#tcmList = ["TCMEP1", "TCMEP2", "TCMEP3", "TCMEP4", "TCMEP5"]
|
||||
|
||||
# Uncomment line below for CPac basin sites
|
||||
#tcmList = ["TCMCP1", "TCMCP2", "TCMCP3", "TCMCP4", "TCMCP5"]
|
||||
|
||||
# Dictionary mapping Hazard Types to applicable local effect areas
|
||||
# that can be intersected with the zone edit areas.
|
||||
# You should not define localEffectAreas entries for Tropical Cyclone
|
||||
# or Convective Watches.
|
||||
localEffectAreas = {}
|
||||
|
||||
#localEffectAreas = {
|
||||
# 'Winter Weather' : ["Below_1000","Below_1500","Below_2000","Below_2500","Below_3000","Below_3500","Below_4000",
|
||||
# "Above_1000","Above_1500","Above_2000","Above_2500","Above_3000","Above_3500"],
|
||||
# }
|
||||
|
||||
# Dictionary associating local Effect Area names with a corresponding
|
||||
# segment number, display name, and list of zones to be auto-selected
|
||||
# If you do not wish to auto-select zones you should supply an empty list
|
||||
#
|
||||
# The display name allows you to display a "pretty" string in the UI rather
|
||||
# than the edit area name. If the display name is empty ("") the edit area
|
||||
# name will be used.
|
||||
localAreaData = {}
|
||||
|
||||
#localAreaData = {
|
||||
# "Below_1000" : ( 999, "", []),
|
||||
# "Below_1500" : (1499, "", []),
|
||||
# "Below_2000" : (1999, "", []),
|
||||
# "Below_2500" : (2499, "", []),
|
||||
# "Below_3000" : (2999, "", []),
|
||||
# "Below_3500" : (3499, "", []),
|
||||
# "Below_4000" : (3999, "", []),
|
||||
# "Above_1000" : (1000, "", []),
|
||||
# "Above_1500" : (1500, "", []),
|
||||
# "Above_2000" : (2000, "", []),
|
||||
# "Above_2500" : (2500, "", []),
|
||||
# "Above_3000" : (3000, "", []),
|
||||
# "Above_3500" : (3500, "", []),
|
||||
# }
|
||||
|
|
@ -1,126 +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.
|
||||
##
|
||||
# ----------------------------------------------------------------------------
|
||||
# This software is in the public domain, furnished "as is", without technical
|
||||
# support, and with no warranty, express or implied, as to its usefulness for
|
||||
# any purpose.
|
||||
#
|
||||
# MakeHazard.py
|
||||
#
|
||||
# Author: wdougherty
|
||||
# ----------------------------------------------------------------------------
|
||||
import numpy
|
||||
import JUtil
|
||||
import LogStream
|
||||
import TimeRange
|
||||
from HazardUtils import HazardUtils
|
||||
from HazardUtils import ELEMENT
|
||||
from HazardUtils import MODEL
|
||||
from HazardUtils import LEVEL
|
||||
from HazardUtils import SUCCESS
|
||||
from HazardUtils import FAIL_REDUNDANT
|
||||
|
||||
def makeHazard(hazard, dbss, timeRange, zones, segment, selectedTimeRange, defaultAreaList, defaultHazard, defaultSegment):
|
||||
hazardUtils = HazardUtils(dbss, None)
|
||||
# hazard has already been validated
|
||||
# timeRange has already been validated
|
||||
|
||||
# convert zones to a Python list
|
||||
if zones is None:
|
||||
zones = []
|
||||
if defaultAreaList is None:
|
||||
defaultAreaList = []
|
||||
|
||||
if not isinstance(zones, list):
|
||||
zones = JUtil.javaStringListToPylist(zones)
|
||||
if not isinstance(defaultAreaList, list):
|
||||
defaultAreaList = JUtil.javaStringListToPylist(defaultAreaList)
|
||||
|
||||
# Find the mask that describes the area covered by the hazard
|
||||
if [] == zones:
|
||||
ea = hazardUtils.getActiveEditArea()
|
||||
if ea is None:
|
||||
mask = None
|
||||
else:
|
||||
mask = hazardUtils.encodeEditArea(ea)
|
||||
else:
|
||||
mask = hazardUtils._makeMask(zones)
|
||||
|
||||
# Hazards need to be separated for makeHazard's temp hazard grid.
|
||||
# If the user hasn't already separated them, it's up to us.
|
||||
if hazardUtils._tempWELoaded():
|
||||
pass # Hazards are already separated
|
||||
else:
|
||||
hazParm = hazardUtils.getParm(MODEL,ELEMENT,LEVEL)
|
||||
# If the inventory span is invalid, the hazards grid is empty.
|
||||
if hazParm.getInventorySpan().isValid():
|
||||
if SUCCESS != hazardUtils._separateHazardGrids():
|
||||
return False
|
||||
|
||||
# Build the hazard key
|
||||
hazardKey = hazard
|
||||
defaultHazardKey = defaultHazard
|
||||
|
||||
if segment is None:
|
||||
segment = ""
|
||||
if defaultSegment is None:
|
||||
defaultSegment = ""
|
||||
|
||||
segment = segment.strip()
|
||||
defaultSegment = defaultSegment.strip()
|
||||
|
||||
if "" != segment:
|
||||
hazardKey = hazardKey + ":" + segment
|
||||
if "" != defaultSegment and defaultHazardKey is not None:
|
||||
defaultHazardKey = defaultHazardKey + ":" + defaultSegment
|
||||
|
||||
# Create the name of the temp weather element from hazardKey
|
||||
weName = hazardUtils._makeTempWEName(hazardKey)
|
||||
|
||||
# if we're modifying, remove the old grid first
|
||||
if defaultAreaList != [] and hazardKey == defaultHazardKey:
|
||||
hazardUtils.deleteCmd([weName], selectedTimeRange)
|
||||
|
||||
# Don't allow the user to create an empty hazard grid
|
||||
if not numpy.any(mask):
|
||||
hazardUtils.statusBarMsg(
|
||||
"NO EDIT AREA SELECTED: \n Select area from map or load edit area in GFE!",
|
||||
"S", "GHG Status")
|
||||
return False
|
||||
|
||||
# Create the temporary hazard grid
|
||||
hazardUtils._addHazard(weName, timeRange, hazardKey, mask)
|
||||
|
||||
# convert timeRange to Python for logging
|
||||
timeRange = TimeRange.TimeRange(timeRange)
|
||||
# log the creation of the temp hazard
|
||||
LogStream.logEvent("Set: " + weName + " " +
|
||||
hazardUtils._printTime(timeRange.startTime().unixTime()) + " " +
|
||||
hazardUtils._printTime(timeRange.endTime().unixTime()) + " " +
|
||||
hazardKey + " " + str(zones))
|
||||
return True
|
||||
|
||||
##
|
||||
#
|
||||
def ensureSeparated(dbss):
|
||||
hazardUtils = HazardUtils(dbss, None)
|
||||
rtnCode = hazardUtils._separateHazardGrids()
|
||||
separated = rtnCode in [SUCCESS, FAIL_REDUNDANT]
|
||||
return separated
|
|
@ -1,250 +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.
|
||||
##
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
import string, time
|
||||
from com.raytheon.uf.common.status import UFStatus
|
||||
from com.raytheon.uf.common.status import UFStatus_Priority as Priority
|
||||
|
||||
|
||||
### New class for fetching ETN from TCM header for tropical hazards
|
||||
class TCMDecoder:
|
||||
def __init__(self):
|
||||
self.pos = 0
|
||||
# key words in TCM products from NCEP
|
||||
self.keyWordDict = {"NATIONAL HURRICANE CENTER" : self.decodeAltFilename,
|
||||
}
|
||||
|
||||
self.fcstList = [] # a place to store all of the forecasts
|
||||
|
||||
self.text = [] # the text product
|
||||
|
||||
self.currentFcst = {} # the current forecast we are docoding
|
||||
|
||||
self.baseProductTime = 0
|
||||
|
||||
self.altFilename = ""
|
||||
|
||||
self._handler = UFStatus.getHandler("GFE", 'GFE')
|
||||
|
||||
def stripText(self):
|
||||
endStr = chr(13) + chr(13) + chr(10)
|
||||
for i in range(len(self.text)):
|
||||
self.text[i] = string.replace(self.text[i], endStr, "")
|
||||
return
|
||||
|
||||
def getFcstList(self):
|
||||
return self.fcstList
|
||||
|
||||
def getBaseProductTime(self):
|
||||
return self.baseProductTime
|
||||
|
||||
def getAltInfoFilename(self):
|
||||
return self.altFilename
|
||||
|
||||
def currentLine(self):
|
||||
return self.text[self.pos]
|
||||
|
||||
def nextLine(self):
|
||||
self.pos = self.pos + 1
|
||||
if self.pos < len(self.text):
|
||||
return self.text[self.pos]
|
||||
else:
|
||||
return ""
|
||||
|
||||
def monthNum(self, monthStr):
|
||||
monthList = ["JAN", "FEB", "MAR", "APR", "MAY", "JUN",
|
||||
"JUL", "AUG", "SEP", "OCT", "NOV", "DEC"]
|
||||
|
||||
try:
|
||||
return monthList.index(monthStr) + 1
|
||||
except ValueError:
|
||||
return 0
|
||||
|
||||
def convertBaseTime(self, timeStr):
|
||||
# timeStr format: "HHMM UTC DAY MON DD YYYY"
|
||||
try:
|
||||
baseTime = time.strptime(timeStr, "%H%M UTC %a %b %d %Y")
|
||||
print "baseTime is", baseTime
|
||||
return baseTime
|
||||
except ValueError:
|
||||
return
|
||||
|
||||
|
||||
# extract time parts from the str
|
||||
# strList = string.split(timeStr)
|
||||
# if len(strList) != 6:
|
||||
# print "Invalid time string:", timeStr
|
||||
# print "Format should be of the form HHMM UTC DAY MON DD YYYY"
|
||||
# return
|
||||
#
|
||||
# hour = int(timeStr[0:2])
|
||||
# minute = int(timeStr[2:4])
|
||||
# monthStr = strList[3]
|
||||
# month = self.monthNum(monthStr)
|
||||
# day = int(strList[4])
|
||||
# year = int(strList[5])
|
||||
#
|
||||
# # time.mktime returns time in seconds but in local time
|
||||
# baseTime = time.mktime((year, month, day, hour, minute, 0, 0, 0, 0))
|
||||
# print "month is", month
|
||||
# print "baseTime is", baseTime
|
||||
|
||||
## # Adjust to UTC
|
||||
## diffTime = time.mktime(time.gmtime()) - time.mktime(time.localtime())
|
||||
## print "diffTime is", diffTime
|
||||
|
||||
## # subtract timeZone and round to the nearest hour
|
||||
## roundedTime = int((baseTime - diffTime) / 3600) * 3600
|
||||
##
|
||||
# return baseTime
|
||||
|
||||
def convert_ddhhmm(self, ddhhmmStr, baseTime):
|
||||
|
||||
# remove the slash if present
|
||||
ddhhmmStr = string.replace(ddhhmmStr, "/", "")
|
||||
|
||||
if baseTime == 0:
|
||||
baseTime = time.time()
|
||||
|
||||
# extract the time parts
|
||||
dayStr = ddhhmmStr[0:2]
|
||||
hourStr = ddhhmmStr[2:4]
|
||||
minStr = ddhhmmStr[4:6]
|
||||
day = int(dayStr)
|
||||
hour = int(hourStr)
|
||||
minute = int(minStr)
|
||||
tupleTime = time.gmtime(baseTime)
|
||||
year = tupleTime[0]
|
||||
month = tupleTime[1]
|
||||
# see if we crossed over to a new month
|
||||
if tupleTime[2] > day:
|
||||
month = month + 1
|
||||
if month > 12:
|
||||
month = 1
|
||||
year = year + 1
|
||||
|
||||
newTuple = (year, month, day, hour, minute, tupleTime[5],
|
||||
tupleTime[6], tupleTime[7], tupleTime[8])
|
||||
|
||||
secondsTime = time.mktime(newTuple)
|
||||
# Adjustment to UTC
|
||||
diffTime = time.mktime(time.gmtime()) - time.mktime(time.localtime())
|
||||
return secondsTime - diffTime # subtract timeZone
|
||||
|
||||
def decodeProductTime(self):
|
||||
# Time of the product found on the next line
|
||||
timeStr = self.nextLine()
|
||||
print "the time string is:", timeStr
|
||||
|
||||
# sanity check for the time string
|
||||
hhmm = timeStr[0:4]
|
||||
for c in hhmm:
|
||||
if not c in string.digits:
|
||||
return
|
||||
|
||||
baseTime = self.convertBaseTime(timeStr)
|
||||
self.baseProductTime = baseTime
|
||||
|
||||
return
|
||||
|
||||
def decodeAltFilename(self):
|
||||
nameStr = self.currentLine()
|
||||
parts = string.split(nameStr)
|
||||
|
||||
self.altFilename = parts[-1] # grab the last string token
|
||||
return
|
||||
|
||||
def decodeTCMProduct(self, TCMProduct):
|
||||
self.text = TCMProduct
|
||||
self.pos = 0
|
||||
self.fcstList = []
|
||||
## self.defaultEyeDiameter = eyeDiameter
|
||||
|
||||
self.stripText()
|
||||
while self.pos < len(TCMProduct):
|
||||
line = self.currentLine()
|
||||
for k in self.keyWordDict.keys():
|
||||
if string.find(line, k) > -1:
|
||||
self.keyWordDict[k]()
|
||||
break
|
||||
self.pos = self.pos + 1
|
||||
|
||||
# store the last forecast in the list of forecasts
|
||||
if self.currentFcst != {}:
|
||||
self.fcstList.append(self.currentFcst)
|
||||
self.currentFcst = {} # reset
|
||||
|
||||
return
|
||||
## End TCM decoder class
|
||||
|
||||
### New methods to pull ETN from TCM if grid is not initialized with ETN
|
||||
def tcmETNforTrop(tcmProduct):
|
||||
tcmProd = tcmProduct
|
||||
# print "chosen TCM is", tcmProd
|
||||
tcmDecoder = TCMDecoder()
|
||||
TCMProduct = getTextProductFromDB(tcmProd)
|
||||
if len(TCMProduct) < 3:
|
||||
msg = tcmProd + " could not be retrieved from the text database."
|
||||
statusBarMsg(msg, "S")
|
||||
return None # Just return if no TCM is found. Something's really wrong
|
||||
else:
|
||||
tcmDecoder.decodeTCMProduct(TCMProduct)
|
||||
altFileName = tcmDecoder.getAltInfoFilename()
|
||||
stormNum = altFileName[2:4]
|
||||
## print "storm number is", stormNum
|
||||
nationalBase = "10"
|
||||
tropicalETN = nationalBase + stormNum
|
||||
## print "Tropical ETN is: ", tropicalETN
|
||||
## print "lenth of tropical ETN is:", len(tropicalETN)
|
||||
return tropicalETN
|
||||
|
||||
def getTextProductFromDB(productID):
|
||||
from com.raytheon.viz.gfe import Activator
|
||||
from com.raytheon.viz.gfe.core import DataManager
|
||||
from com.raytheon.viz.gfe.product import TextDBUtil
|
||||
|
||||
prefStore = Activator.getDefault().getPreferenceStore()
|
||||
if prefStore.contains("TestVTECDecode"):
|
||||
testVtec = prefStore.getBoolean("TestVTECDecode")
|
||||
else:
|
||||
testVtec = False
|
||||
gfeMode = (DataManager.getCurrentInstance().getOpMode().name() == "OPERATIONAL")
|
||||
opMode = testVtec or gfeMode
|
||||
fullText = TextDBUtil.retrieveProduct(productID, opMode)
|
||||
textList = fullText.splitlines(True)
|
||||
return textList
|
||||
|
||||
def statusBarMsg(message, status, category="GFE"):
|
||||
from com.raytheon.uf.common.status import UFStatus
|
||||
from com.raytheon.uf.common.status import UFStatus_Priority as Priority
|
||||
from com.raytheon.viz.gfe import Activator
|
||||
from com.raytheon.viz.gfe.constants import StatusConstants
|
||||
|
||||
if "A" == status:
|
||||
importance = Priority.PROBLEM
|
||||
elif "R" == status:
|
||||
importance = Priority.EVENTA
|
||||
elif "U" == status:
|
||||
importance = Priority.CRITICAL
|
||||
else:
|
||||
importance = Priority.SIGNIFICANT
|
||||
|
||||
self._handler.handle(importance,message)
|
|
@ -24,6 +24,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -63,6 +64,7 @@ import com.vividsolutions.jts.geom.Point;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Sep 22, 2009 3072 bsteffen Initial creation
|
||||
* Aug 23, 2012 1096 njensen Fixed memory leaks
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -161,8 +163,10 @@ public class CcfpResource extends
|
|||
}
|
||||
|
||||
private void disposeFrames() {
|
||||
for (DisplayFrame frame : frames.values()) {
|
||||
frame.dispose();
|
||||
synchronized (frames) {
|
||||
for (DisplayFrame frame : frames.values()) {
|
||||
frame.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,11 +184,15 @@ public class CcfpResource extends
|
|||
|
||||
@Override
|
||||
public String inspect(ReferencedCoordinate coord) throws VizException {
|
||||
if (frames.get(this.displayedDataTime) == null) {
|
||||
DisplayFrame frame = null;
|
||||
synchronized (frames) {
|
||||
frame = frames.get(this.displayedDataTime);
|
||||
}
|
||||
if (frame == null) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder res = new StringBuilder();
|
||||
for (CcfpRecord record : frames.get(this.displayedDataTime).records) {
|
||||
for (CcfpRecord record : frame.records) {
|
||||
// Check if we have an area we are rendering
|
||||
if (isPaintingArea(record)) {
|
||||
try {
|
||||
|
@ -216,15 +224,20 @@ public class CcfpResource extends
|
|||
*/
|
||||
private void updateRecords(IGraphicsTarget target,
|
||||
PaintProperties paintProps) throws VizException {
|
||||
DisplayFrame frame = frames.get(this.displayedDataTime);
|
||||
if (frame == null) {
|
||||
frame = new DisplayFrame();
|
||||
frames.put(this.displayedDataTime, frame);
|
||||
DisplayFrame frame = null;
|
||||
synchronized (frames) {
|
||||
frame = frames.get(this.displayedDataTime);
|
||||
if (frame == null) {
|
||||
frame = new DisplayFrame();
|
||||
frames.put(this.displayedDataTime, frame);
|
||||
}
|
||||
}
|
||||
|
||||
// Add all the new Records
|
||||
Collection<CcfpRecord> newRecords = unprocessedRecords
|
||||
.get(this.displayedDataTime);
|
||||
Collection<CcfpRecord> newRecords = null;
|
||||
synchronized (unprocessedRecords) {
|
||||
newRecords = unprocessedRecords.get(this.displayedDataTime);
|
||||
}
|
||||
for (CcfpRecord record : newRecords) {
|
||||
// If we need to draw anything for this record then keep it
|
||||
if (isPaintingArea(record) || isPaintingMovement(record)
|
||||
|
@ -259,14 +272,19 @@ public class CcfpResource extends
|
|||
this.displayedDataTime = paintProps.getDataTime();
|
||||
|
||||
// First check to see if we need to process new data
|
||||
Collection<CcfpRecord> unprocessed = unprocessedRecords
|
||||
.get(this.displayedDataTime);
|
||||
Collection<CcfpRecord> unprocessed = null;
|
||||
synchronized (unprocessedRecords) {
|
||||
unprocessed = unprocessedRecords.get(this.displayedDataTime);
|
||||
}
|
||||
if (unprocessed != null && unprocessed.size() > 0) {
|
||||
updateRecords(target, paintProps);
|
||||
}
|
||||
|
||||
// Hopefully we now have some data to display, if not bail
|
||||
DisplayFrame frame = frames.get(this.displayedDataTime);
|
||||
DisplayFrame frame = null;
|
||||
synchronized (frames) {
|
||||
frame = frames.get(this.displayedDataTime);
|
||||
}
|
||||
if (frame == null) {
|
||||
this.displayedDataTime = null;
|
||||
return;
|
||||
|
@ -509,14 +527,24 @@ public class CcfpResource extends
|
|||
*/
|
||||
protected void addRecord(CcfpRecord obj) {
|
||||
DataTime dataTime = obj.getDataTime();
|
||||
Collection<CcfpRecord> records = unprocessedRecords.get(dataTime);
|
||||
if (records == null) {
|
||||
records = new ArrayList<CcfpRecord>();
|
||||
unprocessedRecords.put(dataTime, records);
|
||||
this.dataTimes.add(dataTime);
|
||||
Collections.sort(this.dataTimes);
|
||||
if (resourceData.durationMatches(dataTime)) {
|
||||
Collection<CcfpRecord> records = null;
|
||||
boolean brandNew = false;
|
||||
synchronized (unprocessedRecords) {
|
||||
records = unprocessedRecords.get(dataTime);
|
||||
if (records == null) {
|
||||
records = new HashSet<CcfpRecord>();
|
||||
unprocessedRecords.put(dataTime, records);
|
||||
brandNew = true;
|
||||
}
|
||||
}
|
||||
if (brandNew) {
|
||||
this.dataTimes.add(dataTime);
|
||||
Collections.sort(this.dataTimes);
|
||||
}
|
||||
|
||||
records.add(obj);
|
||||
}
|
||||
records.add(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -677,16 +705,40 @@ public class CcfpResource extends
|
|||
|
||||
@Override
|
||||
public void project(CoordinateReferenceSystem crs) throws VizException {
|
||||
disposeFrames();
|
||||
// add as unprocessed to make sure frames created
|
||||
for (DataTime time : frames.keySet()) {
|
||||
DisplayFrame frame = frames.get(time);
|
||||
if (frame != null) {
|
||||
List<CcfpRecord> copyList = new ArrayList<CcfpRecord>(
|
||||
frame.records);
|
||||
unprocessedRecords.put(time, copyList);
|
||||
synchronized (frames) {
|
||||
disposeFrames();
|
||||
// add as unprocessed to make sure frames created
|
||||
for (DataTime time : frames.keySet()) {
|
||||
DisplayFrame frame = frames.get(time);
|
||||
if (frame != null) {
|
||||
List<CcfpRecord> copyList = new ArrayList<CcfpRecord>(
|
||||
frame.records);
|
||||
synchronized (unprocessedRecords) {
|
||||
unprocessedRecords.put(time, copyList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(DataTime time) {
|
||||
super.remove(time);
|
||||
Collection<CcfpRecord> notNeeded = null;
|
||||
synchronized (unprocessedRecords) {
|
||||
notNeeded = unprocessedRecords.remove(time);
|
||||
}
|
||||
if (notNeeded != null) {
|
||||
notNeeded.clear();
|
||||
}
|
||||
|
||||
DisplayFrame frame = null;
|
||||
synchronized (frames) {
|
||||
frame = frames.remove(time);
|
||||
}
|
||||
if (frame != null) {
|
||||
frame.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,12 +31,10 @@ 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.ccfp.Activator;
|
||||
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;
|
||||
import com.raytheon.uf.viz.core.status.StatusConstants;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -56,8 +54,9 @@ import com.raytheon.uf.viz.core.status.StatusConstants;
|
|||
*/
|
||||
@XmlAccessorType(XmlAccessType.NONE)
|
||||
public class CcfpResourceData extends AbstractRequestableResourceData {
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus.getHandler(CcfpResourceData.class);
|
||||
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(CcfpResourceData.class);
|
||||
|
||||
// This flag determnies if we draw lines and polygons
|
||||
@XmlAttribute
|
||||
private boolean displayArea = true;
|
||||
|
@ -69,35 +68,34 @@ public class CcfpResourceData extends AbstractRequestableResourceData {
|
|||
// This flag determines if we display text boxes
|
||||
@XmlAttribute
|
||||
private boolean displayText = true;
|
||||
|
||||
|
||||
// Filter by coverage
|
||||
@XmlAttribute
|
||||
private int coverageFilter = 0;
|
||||
|
||||
|
||||
|
||||
@XmlAttribute
|
||||
private int validDuration = 0;
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!super.equals(obj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (obj instanceof CcfpResourceData == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
CcfpResourceData other = (CcfpResourceData) obj;
|
||||
|
||||
if (other.coverageFilter != this.coverageFilter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (other.validDuration != this.validDuration) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (other.displayText != this.displayText) {
|
||||
return false;
|
||||
}
|
||||
|
@ -109,7 +107,7 @@ public class CcfpResourceData extends AbstractRequestableResourceData {
|
|||
if (other.displayMovement != this.displayMovement) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -122,7 +120,7 @@ public class CcfpResourceData extends AbstractRequestableResourceData {
|
|||
DataTime[] originalTimes = super.getAvailableTimes();
|
||||
ArrayList<DataTime> newTimes = new ArrayList<DataTime>();
|
||||
for (DataTime time : originalTimes) {
|
||||
if (time.getValidPeriod().getDuration() == validDuration * 1000) {
|
||||
if (durationMatches(time)) {
|
||||
newTimes.add(time);
|
||||
}
|
||||
}
|
||||
|
@ -147,6 +145,18 @@ public class CcfpResourceData extends AbstractRequestableResourceData {
|
|||
return nr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a DataTime's valid period matches the duration of the resource
|
||||
* data
|
||||
*
|
||||
* @param time
|
||||
* the time to check
|
||||
* @return true if the durations are equal, otherwise false
|
||||
*/
|
||||
protected boolean durationMatches(DataTime time) {
|
||||
return time.getValidPeriod().getDuration() == validDuration * 1000;
|
||||
}
|
||||
|
||||
public boolean isDisplayArea() {
|
||||
return displayArea;
|
||||
}
|
||||
|
@ -185,6 +195,6 @@ public class CcfpResourceData extends AbstractRequestableResourceData {
|
|||
|
||||
public void setValidDuration(int validDuration) {
|
||||
this.validDuration = validDuration;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ com.raytheon.uf.viz.core.rsc.capabilities.LabelableCapability
|
|||
com.raytheon.uf.viz.core.rsc.capabilities.DensityCapability
|
||||
com.raytheon.uf.viz.core.rsc.capabilities.DisplayTypeCapability
|
||||
com.raytheon.uf.viz.core.rsc.capabilities.MagnificationCapability
|
||||
com.raytheon.uf.viz.core.rsc.capabilities.MultiChannelCapability
|
||||
com.raytheon.uf.viz.core.rsc.capabilities.PointCapability
|
||||
com.raytheon.uf.viz.core.rsc.capabilities.TimeMatchBasisCapability
|
||||
com.raytheon.uf.viz.core.rsc.GenericResourceData
|
||||
|
|
|
@ -187,6 +187,8 @@ public class ColorMapParameters implements Cloneable, ISerializableObject {
|
|||
|
||||
private boolean mirror;
|
||||
|
||||
private double noDataValue = Double.NaN;
|
||||
|
||||
@XmlElement
|
||||
private PersistedParameters persisted = new PersistedParameters();
|
||||
|
||||
|
@ -1009,4 +1011,20 @@ public class ColorMapParameters implements Cloneable, ISerializableObject {
|
|||
this.colorMapMax = params.colorMapMax;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the noDataValue
|
||||
*/
|
||||
public double getNoDataValue() {
|
||||
return noDataValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param noDataValue
|
||||
* the noDataValue to set
|
||||
*/
|
||||
public void setNoDataValue(double noDataValue) {
|
||||
this.noDataValue = noDataValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -124,7 +124,7 @@ public class ImagingSupport {
|
|||
bulk.toArray(new DrawableImage[bulk.size()]));
|
||||
}
|
||||
|
||||
return rval & skipped;
|
||||
return rval & !skipped;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,104 +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.uf.viz.core.drawables.ext.colormap;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.raytheon.uf.viz.core.data.IColorMapDataRetrievalCallback;
|
||||
import com.raytheon.uf.viz.core.drawables.ColorMapParameters;
|
||||
import com.raytheon.uf.viz.core.drawables.IColormappedImage;
|
||||
import com.raytheon.uf.viz.core.drawables.IImage;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.IImagingExtension;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
|
||||
/**
|
||||
* {@link IImagingExtension} used to create and draw multi-channel R,G,B images
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jul 5, 2012 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public interface IMultiChannelImageExtension extends IImagingExtension {
|
||||
|
||||
public static enum Channel {
|
||||
RED, GREEN, BLUE;
|
||||
}
|
||||
|
||||
public static class ChannelData {
|
||||
public String name;
|
||||
|
||||
public ColorMapParameters parameters;
|
||||
|
||||
public boolean invert;
|
||||
|
||||
public ChannelData(String name, ColorMapParameters params,
|
||||
boolean invert) {
|
||||
this.name = name;
|
||||
this.parameters = params;
|
||||
}
|
||||
}
|
||||
|
||||
public static interface IMultiChannelImage extends IImage {
|
||||
|
||||
public Map<Channel, IImageChannel> getImageMapping();
|
||||
|
||||
public void setImageMapping(Map<Channel, IImageChannel> mapping);
|
||||
|
||||
}
|
||||
|
||||
public static interface IImageChannel extends IColormappedImage {
|
||||
|
||||
public void setInverted(boolean inverted);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a true color image, this
|
||||
*
|
||||
* @param channelMap
|
||||
* @return
|
||||
* @throws VizException
|
||||
*/
|
||||
public IMultiChannelImage constructImage(
|
||||
Map<Channel, IImageChannel> imageMapping) throws VizException;
|
||||
|
||||
/**
|
||||
* Construct a IImageChannel for a IMultiChannelImage
|
||||
*
|
||||
* @param callback
|
||||
* @param inverted
|
||||
* @return
|
||||
* @throws VizException
|
||||
*/
|
||||
public IImageChannel constructImage(
|
||||
IColorMapDataRetrievalCallback callback, ChannelData channelData)
|
||||
throws VizException;
|
||||
|
||||
}
|
|
@ -158,6 +158,18 @@ public class ResourceList extends CopyOnWriteArrayList<ResourcePair> implements
|
|||
return add(rp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function for determining if the {@link ResourcePair} can be added to the
|
||||
* list. Default checks if the pair is already in the list and returns false
|
||||
* if so
|
||||
*
|
||||
* @param e
|
||||
* @return
|
||||
*/
|
||||
protected boolean canAdd(ResourcePair e) {
|
||||
return contains(e) == false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
|
@ -165,7 +177,7 @@ public class ResourceList extends CopyOnWriteArrayList<ResourcePair> implements
|
|||
*/
|
||||
@Override
|
||||
public boolean add(ResourcePair e) {
|
||||
if (e == null || contains(e)) {
|
||||
if (e == null || canAdd(e) == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -263,7 +275,7 @@ public class ResourceList extends CopyOnWriteArrayList<ResourcePair> implements
|
|||
}
|
||||
|
||||
synchronized (this) {
|
||||
if (contains(e)) {
|
||||
if (canAdd(e) == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -276,9 +288,7 @@ public class ResourceList extends CopyOnWriteArrayList<ResourcePair> implements
|
|||
|
||||
super.add(i >= 0 ? (i + 1) : 0, e);
|
||||
synchronized (resourcesToInstantiate) {
|
||||
if (resourcesToInstantiate.contains(e) == false) {
|
||||
resourcesToInstantiate.add(e);
|
||||
}
|
||||
resourcesToInstantiate.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,7 +310,7 @@ public class ResourceList extends CopyOnWriteArrayList<ResourcePair> implements
|
|||
if (rp.getResource() == null) {
|
||||
Validate.notNull(rp.getResourceData());
|
||||
}
|
||||
if (contains(rp) == false) {
|
||||
if (canAdd(rp)) {
|
||||
toAdd.add(rp);
|
||||
}
|
||||
}
|
||||
|
@ -400,7 +410,13 @@ public class ResourceList extends CopyOnWriteArrayList<ResourcePair> implements
|
|||
|
||||
super.remove(index);
|
||||
synchronized (resourcesToInstantiate) {
|
||||
resourcesToInstantiate.remove(rp);
|
||||
// Ensure rp is removed from list entirely
|
||||
Iterator<ResourcePair> iter = resourcesToInstantiate.iterator();
|
||||
while (iter.hasNext()) {
|
||||
if (iter.next() == rp) {
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
@ -1,313 +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.uf.viz.core.rsc.capabilities;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.adapters.XmlAdapter;
|
||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
|
||||
import com.raytheon.uf.viz.core.drawables.ColorMapParameters;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.colormap.IMultiChannelImageExtension.Channel;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.colormap.IMultiChannelImageExtension.ChannelData;
|
||||
|
||||
/**
|
||||
* Capability for multi channel imagery
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Dec 20, 2011 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.NONE)
|
||||
public class MultiChannelCapability extends AbstractCapability {
|
||||
|
||||
@XmlAccessorType(XmlAccessType.NONE)
|
||||
public static class ChannelSerializable {
|
||||
|
||||
@XmlAttribute
|
||||
private String name;
|
||||
|
||||
@XmlAttribute
|
||||
private Channel channel;
|
||||
|
||||
@XmlAttribute
|
||||
private boolean invert;
|
||||
|
||||
@XmlElement
|
||||
private float dataMin;
|
||||
|
||||
@XmlElement
|
||||
private float dataMax;
|
||||
|
||||
@XmlElement
|
||||
private float cmapMin;
|
||||
|
||||
@XmlElement
|
||||
private float cmapMax;
|
||||
|
||||
public ChannelSerializable() {
|
||||
|
||||
}
|
||||
|
||||
public ChannelSerializable(Channel channel, ChannelData channelData) {
|
||||
this.channel = channel;
|
||||
this.name = channelData.name;
|
||||
this.invert = channelData.invert;
|
||||
ColorMapParameters params = channelData.parameters;
|
||||
this.dataMin = params.getDataMin();
|
||||
this.dataMax = params.getDataMax();
|
||||
this.cmapMin = params.getColorMapMin();
|
||||
this.cmapMax = params.getColorMapMax();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* the name to set
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the channel
|
||||
*/
|
||||
public Channel getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param channel
|
||||
* the channel to set
|
||||
*/
|
||||
public void setChannel(Channel channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the dataMin
|
||||
*/
|
||||
public float getDataMin() {
|
||||
return dataMin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dataMin
|
||||
* the dataMin to set
|
||||
*/
|
||||
public void setDataMin(float dataMin) {
|
||||
this.dataMin = dataMin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the dataMax
|
||||
*/
|
||||
public float getDataMax() {
|
||||
return dataMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dataMax
|
||||
* the dataMax to set
|
||||
*/
|
||||
public void setDataMax(float dataMax) {
|
||||
this.dataMax = dataMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the cmapMin
|
||||
*/
|
||||
public float getCmapMin() {
|
||||
return cmapMin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cmapMin
|
||||
* the cmapMin to set
|
||||
*/
|
||||
public void setCmapMin(float cmapMin) {
|
||||
this.cmapMin = cmapMin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the cmapMax
|
||||
*/
|
||||
public float getCmapMax() {
|
||||
return cmapMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cmapMax
|
||||
* the cmapMax to set
|
||||
*/
|
||||
public void setCmapMax(float cmapMax) {
|
||||
this.cmapMax = cmapMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the invert
|
||||
*/
|
||||
public boolean isInvert() {
|
||||
return invert;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param invert
|
||||
* the invert to set
|
||||
*/
|
||||
public void setInvert(boolean invert) {
|
||||
this.invert = invert;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Marshaller extends
|
||||
XmlAdapter<ChannelSerializable[], HashMap<Channel, ChannelData>> {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* javax.xml.bind.annotation.adapters.XmlAdapter#unmarshal(java.lang
|
||||
* .Object)
|
||||
*/
|
||||
@Override
|
||||
public HashMap<Channel, ChannelData> unmarshal(ChannelSerializable[] v)
|
||||
throws Exception {
|
||||
HashMap<Channel, ChannelData> channelMap = new HashMap<Channel, ChannelData>();
|
||||
for (ChannelSerializable cs : v) {
|
||||
ColorMapParameters params = new ColorMapParameters();
|
||||
params.setDataMin(cs.dataMin);
|
||||
params.setDataMax(cs.dataMax);
|
||||
params.setColorMapMin(cs.cmapMin);
|
||||
params.setColorMapMax(cs.cmapMax);
|
||||
channelMap.put(cs.channel, new ChannelData(cs.name, params,
|
||||
cs.invert));
|
||||
}
|
||||
return channelMap;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* javax.xml.bind.annotation.adapters.XmlAdapter#marshal(java.lang.Object
|
||||
* )
|
||||
*/
|
||||
@Override
|
||||
public ChannelSerializable[] marshal(HashMap<Channel, ChannelData> v)
|
||||
throws Exception {
|
||||
ChannelSerializable[] serializable = new ChannelSerializable[v
|
||||
.size()];
|
||||
int i = 0;
|
||||
for (Entry<Channel, ChannelData> entry : v.entrySet()) {
|
||||
ChannelSerializable cs = new ChannelSerializable(
|
||||
entry.getKey(), entry.getValue());
|
||||
serializable[i++] = cs;
|
||||
}
|
||||
return serializable;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@XmlJavaTypeAdapter(value = Marshaller.class)
|
||||
private HashMap<Channel, ChannelData> channelMap = new HashMap<Channel, ChannelData>();
|
||||
|
||||
private String[] names;
|
||||
|
||||
/**
|
||||
* @return the names
|
||||
*/
|
||||
public String[] getNames() {
|
||||
return names;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param names
|
||||
* the names to set
|
||||
*/
|
||||
public void setNames(String[] names) {
|
||||
this.names = names;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the channelMap
|
||||
*/
|
||||
public Map<Channel, ChannelData> getChannelMap() {
|
||||
return channelMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param channelMap
|
||||
* the channelMap to set
|
||||
*/
|
||||
public void setChannelMap(HashMap<Channel, ChannelData> channelMap) {
|
||||
if (channelMap == null) {
|
||||
channelMap = new HashMap<Channel, ChannelData>();
|
||||
}
|
||||
this.channelMap = channelMap;
|
||||
capabilityChanged();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.core.rsc.capabilities.AbstractCapability#
|
||||
* capabilityChanged()
|
||||
*/
|
||||
@Override
|
||||
public void capabilityChanged() {
|
||||
super.capabilityChanged();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.core.rsc.capabilities.AbstractCapability#clone()
|
||||
*/
|
||||
@Override
|
||||
public AbstractCapability clone() {
|
||||
MultiChannelCapability cap = new MultiChannelCapability();
|
||||
cap.channelMap = new HashMap<Channel, ChannelData>(channelMap);
|
||||
return cap;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,195 @@
|
|||
/**
|
||||
* 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.viz.core.tile;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.geotools.coverage.grid.GridGeometry2D;
|
||||
import org.opengis.coverage.grid.GridEnvelope;
|
||||
import org.opengis.geometry.Envelope;
|
||||
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
||||
import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory;
|
||||
|
||||
/**
|
||||
* Object that represents a single Tile. Contains a level and GridGeometry as
|
||||
* well as a border which is used in {@link #intersects(Geometry)}
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 8, 2012 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class Tile {
|
||||
|
||||
public final int tileLevel;
|
||||
|
||||
public final GridGeometry2D tileGeometry;
|
||||
|
||||
public final List<PreparedGeometry> tileBorder;
|
||||
|
||||
/**
|
||||
* Create a Tile specifying a border for intersection checks
|
||||
*
|
||||
* @param tileLevel
|
||||
* @param tileGeometry
|
||||
* @param tileBorder
|
||||
*/
|
||||
public Tile(int tileLevel, GridGeometry2D tileGeometry, Geometry tileBorder) {
|
||||
this.tileLevel = tileLevel;
|
||||
this.tileGeometry = tileGeometry;
|
||||
if (tileBorder != null) {
|
||||
int num = tileBorder.getNumGeometries();
|
||||
this.tileBorder = new ArrayList<PreparedGeometry>(num);
|
||||
for (int n = 0; n < num; ++n) {
|
||||
this.tileBorder.add(PreparedGeometryFactory.prepare(tileBorder
|
||||
.getGeometryN(n)));
|
||||
}
|
||||
} else {
|
||||
this.tileBorder = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Tile with no border. intersects calls will always return true
|
||||
*
|
||||
* @param tileLevel
|
||||
* @param tileGeometry
|
||||
*/
|
||||
public Tile(int tileLevel, GridGeometry2D tileGeometry) {
|
||||
this(tileLevel, tileGeometry, null);
|
||||
}
|
||||
|
||||
public Rectangle getRectangle() {
|
||||
GridEnvelope env = tileGeometry.getGridRange();
|
||||
return new Rectangle(env.getLow(0), env.getLow(1), env.getSpan(0),
|
||||
env.getSpan(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the geometry intersects the Tile. Tiles without a
|
||||
* {@link #tileBorder} will always return true
|
||||
*
|
||||
* @param geometry
|
||||
* @return
|
||||
*/
|
||||
public boolean intersects(Geometry geometry) {
|
||||
if (tileBorder == null) {
|
||||
return true;
|
||||
}
|
||||
for (PreparedGeometry border : tileBorder) {
|
||||
if (border.intersects(geometry)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the x/y coordinate is contained by the Tile's CRS
|
||||
* Envelope
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*/
|
||||
public boolean crsContains(double x, double y) {
|
||||
Envelope env = tileGeometry.getEnvelope();
|
||||
return env.getMinimum(0) <= x && env.getMaximum(0) >= x
|
||||
&& env.getMinimum(1) <= y && env.getMaximum(1) >= y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the Coordinate is contained by the Tile's CRS Envelope
|
||||
*
|
||||
* @param c
|
||||
* @return
|
||||
*/
|
||||
public boolean crsContains(Coordinate c) {
|
||||
return crsContains(c.x, c.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the x/y coordinate is contained by the Tile's grid
|
||||
* envelope
|
||||
*
|
||||
* @param gridX
|
||||
* @param gridY
|
||||
* @return
|
||||
*/
|
||||
public boolean gridContains(int gridX, int gridY) {
|
||||
GridEnvelope ge = tileGeometry.getGridRange();
|
||||
return ge.getLow(0) <= gridX && ge.getHigh(0) >= gridX
|
||||
&& ge.getLow(1) <= gridY && ge.getHigh(1) >= gridY;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result
|
||||
+ ((tileGeometry == null) ? 0 : tileGeometry.hashCode());
|
||||
result = prime * result + tileLevel;
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Tile other = (Tile) obj;
|
||||
if (tileGeometry == null) {
|
||||
if (other.tileGeometry != null)
|
||||
return false;
|
||||
} else if (!tileGeometry.equals(other.tileGeometry))
|
||||
return false;
|
||||
if (tileLevel != other.tileLevel)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,418 @@
|
|||
/**
|
||||
* 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.viz.core.tile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.geotools.coverage.grid.GeneralGridEnvelope;
|
||||
import org.geotools.coverage.grid.GeneralGridGeometry;
|
||||
import org.geotools.coverage.grid.GridGeometry2D;
|
||||
import org.geotools.geometry.Envelope2D;
|
||||
import org.geotools.geometry.jts.JTS;
|
||||
import org.geotools.referencing.crs.DefaultGeographicCRS;
|
||||
import org.geotools.referencing.operation.DefaultMathTransformFactory;
|
||||
import org.opengis.coverage.grid.GridEnvelope;
|
||||
import org.opengis.geometry.Envelope;
|
||||
import org.opengis.referencing.datum.PixelInCell;
|
||||
import org.opengis.referencing.operation.MathTransform;
|
||||
import org.opengis.referencing.operation.TransformException;
|
||||
|
||||
import com.raytheon.uf.common.geospatial.CRSCache;
|
||||
import com.raytheon.uf.common.geospatial.util.WorldWrapCorrector;
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
|
||||
/**
|
||||
* This object represents a single tile level. It does this by containing a 2
|
||||
* dimensional array of {@link Tile} objects.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 8, 2012 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class TileLevel {
|
||||
|
||||
/** Tile level's GridGeometry */
|
||||
private GridGeometry2D levelGeometry;
|
||||
|
||||
/** GridGeometry tile level was created for */
|
||||
private GeneralGridGeometry targetGeometry;
|
||||
|
||||
// Cached MathTransforms
|
||||
private MathTransform crsToGrid;
|
||||
|
||||
private MathTransform gridToCRS;
|
||||
|
||||
private MathTransform tileCRSToTargetGrid;
|
||||
|
||||
/** Target grid to lat/lon for world wrap correcting */
|
||||
private MathTransform targetGridToLatLon;
|
||||
|
||||
/** World wrap corrector, corrects Tile borders */
|
||||
private WorldWrapCorrector corrector;
|
||||
|
||||
/** Level of this TileLevel */
|
||||
private int tileLevel;
|
||||
|
||||
/** size for tiles in this level */
|
||||
private int tileSize;
|
||||
|
||||
/** Pixel density of the tile level */
|
||||
private double pixelDensity;
|
||||
|
||||
/** Tile array */
|
||||
private Tile[][] tiles;
|
||||
|
||||
TileLevel(GridGeometry2D levelGeometry, GeneralGridGeometry targetGeometry,
|
||||
int tileLevel, int tileSize) {
|
||||
this.levelGeometry = levelGeometry;
|
||||
this.targetGeometry = targetGeometry;
|
||||
this.tileLevel = tileLevel;
|
||||
this.tileSize = tileSize;
|
||||
intialize(levelGeometry.getGridRange(), levelGeometry.getEnvelope());
|
||||
}
|
||||
|
||||
private void intialize(GridEnvelope range, Envelope envelope) {
|
||||
int width = range.getSpan(0);
|
||||
int height = range.getSpan(1);
|
||||
int fullTileDimX = width / tileSize;
|
||||
int tileRemainderX = width % tileSize;
|
||||
int fullTileDimY = height / tileSize;
|
||||
int tileRemainderY = height % tileSize;
|
||||
|
||||
int totalTilesX = fullTileDimX;
|
||||
if (tileRemainderX > 0) {
|
||||
totalTilesX++;
|
||||
}
|
||||
|
||||
int totalTilesY = fullTileDimY;
|
||||
if (tileRemainderY > 0) {
|
||||
totalTilesY++;
|
||||
}
|
||||
|
||||
tiles = new Tile[totalTilesY][totalTilesX];
|
||||
|
||||
try {
|
||||
gridToCRS = levelGeometry.getGridToCRS(PixelInCell.CELL_CORNER);
|
||||
crsToGrid = gridToCRS.inverse();
|
||||
|
||||
DefaultMathTransformFactory factory = new DefaultMathTransformFactory();
|
||||
tileCRSToTargetGrid = factory.createConcatenatedTransform(
|
||||
CRSCache.getInstance().findMathTransform(
|
||||
levelGeometry.getCoordinateReferenceSystem(),
|
||||
targetGeometry.getCoordinateReferenceSystem()),
|
||||
targetGeometry.getGridToCRS(PixelInCell.CELL_CORNER)
|
||||
.inverse());
|
||||
targetGridToLatLon = factory.createConcatenatedTransform(
|
||||
targetGeometry.getGridToCRS(PixelInCell.CELL_CORNER),
|
||||
CRSCache.getInstance().findMathTransform(
|
||||
targetGeometry.getCoordinateReferenceSystem(),
|
||||
DefaultGeographicCRS.WGS84));
|
||||
corrector = new WorldWrapCorrector(targetGeometry);
|
||||
|
||||
// Calculate pixel density
|
||||
// Grab the center x, 3/4 y of the map
|
||||
double mapXCenter = targetGeometry.getGridRange().getSpan(0) * 0.5;
|
||||
double mapYCenter = targetGeometry.getGridRange().getSpan(1) * 0.75;
|
||||
|
||||
double[] input = new double[] { mapXCenter, mapYCenter,
|
||||
mapXCenter + 1, mapYCenter + 1 };
|
||||
double[] output = new double[input.length];
|
||||
|
||||
tileCRSToTargetGrid.inverse().transform(input, 0, output, 0, 2);
|
||||
levelGeometry.getGridToCRS(PixelInCell.CELL_CORNER).inverse()
|
||||
.transform(output, 0, input, 0, 2);
|
||||
pixelDensity = 1.0 / Math.abs(new Coordinate(input[0], input[1],
|
||||
0.0).distance(new Coordinate(input[2], input[3], 0.0)));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(
|
||||
"Cannot tranform tile CRS into target CRS", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pixel density for the tile level. This is the approximate
|
||||
* number of target grid pixels a single tile grid pixel takes up
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public double getPixelDensity() {
|
||||
return pixelDensity;
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of tiles in the x direction (number of columns)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getNumXTiles() {
|
||||
return tiles[0].length;
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of tiles in the y direction (number of rows)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getNumYTiles() {
|
||||
return tiles.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Level of this TileLevel
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getLevel() {
|
||||
return tileLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Tile at the specified x/y index in the tile set
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*/
|
||||
public Tile getTile(int x, int y) {
|
||||
Tile tile = tiles[y][x];
|
||||
if (tile == null) {
|
||||
synchronized (tiles) {
|
||||
// Double check tile to see if another thread created it
|
||||
tile = tiles[y][x];
|
||||
if (tile == null) {
|
||||
tiles[y][x] = tile = createTile(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
return tile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Tile for the specified tile grid location
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*/
|
||||
public Tile getTile(double x, double y) {
|
||||
double xIdx = x / tileSize;
|
||||
double yIdx = y / tileSize;
|
||||
if (xIdx >= 0 && yIdx >= 0 && xIdx < getNumXTiles()
|
||||
&& yIdx < getNumYTiles()) {
|
||||
Tile tile = getTile((int) xIdx, (int) yIdx);
|
||||
if (tile.gridContains((int) x, (int) y)) {
|
||||
return tile;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms TileLevel crs x,y into tile level grid space x,y
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*/
|
||||
public double[] crsToGrid(double x, double y) throws TransformException {
|
||||
double[] out = new double[2];
|
||||
crsToGrid.transform(new double[] { x, y }, 0, out, 0, 1);
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Tile for the specified x/y {@link #tiles} index
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*/
|
||||
private Tile createTile(int x, int y) {
|
||||
GridEnvelope range = levelGeometry.getGridRange();
|
||||
// Get grid range ranges and calculate grid range for the tile
|
||||
int startX = range.getLow(0);
|
||||
int startY = range.getLow(1);
|
||||
int endX = range.getHigh(0) + 1;
|
||||
int endY = range.getHigh(1) + 1;
|
||||
|
||||
int tileY = startY + y * tileSize;
|
||||
int tileX = startX + x * tileSize;
|
||||
|
||||
int tileEndX = Math.min(endX, tileX + tileSize);
|
||||
int tileEndY = Math.min(endY, tileY + tileSize);
|
||||
|
||||
// Convert grid range into crs envelope range
|
||||
double[] in = new double[] { tileX, tileY, tileEndX, tileEndY };
|
||||
double[] out = new double[in.length];
|
||||
try {
|
||||
gridToCRS.transform(in, 0, out, 0, 2);
|
||||
} catch (TransformException e) {
|
||||
throw new RuntimeException("Error getting tile envelope from grid",
|
||||
e);
|
||||
}
|
||||
double envTileX = out[0];
|
||||
double envTileY = out[1];
|
||||
double envTileEndX = out[2];
|
||||
double envTileEndY = out[3];
|
||||
|
||||
// Create tile GridGeometry
|
||||
range = new GeneralGridEnvelope(new int[] { tileX, tileY }, new int[] {
|
||||
tileEndX, tileEndY }, false);
|
||||
GridGeometry2D tileGridGeom = new GridGeometry2D(range, new Envelope2D(
|
||||
levelGeometry.getCoordinateReferenceSystem(), out[0], envTileY,
|
||||
envTileEndX - envTileX, envTileEndY - envTileY));
|
||||
|
||||
// Calculate the border in target grid space for the Tile
|
||||
Geometry border = null;
|
||||
try {
|
||||
double[] UL = new double[] { envTileX, envTileY };
|
||||
double[] UR = new double[] { envTileEndX, envTileY };
|
||||
double[] LR = new double[] { envTileEndX, envTileEndY };
|
||||
double[] LL = new double[] { envTileX, envTileEndY };
|
||||
|
||||
// Create tile border based on pixel density tile level 0 should
|
||||
// always have threshold of 1.0
|
||||
border = createTileBorder(UL, UR, LR, LL,
|
||||
Math.max(range.getSpan(0) / 4, 1),
|
||||
Math.max(range.getSpan(1) / 4, 1),
|
||||
tileLevel > 0 ? Math.max(pixelDensity, 1.0) : 1.0);
|
||||
} catch (TransformException e) {
|
||||
// Invalid geometry, don't add a border
|
||||
}
|
||||
|
||||
// Create the Tile object
|
||||
return new Tile(tileLevel, tileGridGeom, border);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures all Tile objects are created for the level. This method can takes
|
||||
* lots of time depending on grid resolution of level and {@link #tileSize}.
|
||||
* Tiles are created dynamically as requested otherwise
|
||||
*/
|
||||
public void populateTiles() {
|
||||
int totalTilesY = getNumYTiles();
|
||||
int totalTilesX = getNumXTiles();
|
||||
for (int y = 0; y < totalTilesY; ++y) {
|
||||
for (int x = 0; x < totalTilesX; ++x) {
|
||||
if (tiles[y][x] == null) {
|
||||
tiles[y][x] = createTile(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Geometry createTileBorder(double[] UL, double[] UR, double[] LR,
|
||||
double[] LL, int maxHorDivisions, int maxVertDivisions,
|
||||
double threshold) throws TransformException {
|
||||
List<Coordinate> borderPoints = new ArrayList<Coordinate>(
|
||||
maxVertDivisions * 2 + maxHorDivisions * 2);
|
||||
double[] out = new double[2];
|
||||
|
||||
// UL to UR
|
||||
tileCRSToTargetGrid.transform(UL, 0, out, 0, 1);
|
||||
borderPoints.add(new Coordinate(out[0], out[1]));
|
||||
calculateBorder(borderPoints, UL, null, UR, null, maxHorDivisions,
|
||||
threshold);
|
||||
|
||||
// UR to LR
|
||||
tileCRSToTargetGrid.transform(UR, 0, out, 0, 1);
|
||||
borderPoints.add(new Coordinate(out[0], out[1]));
|
||||
calculateBorder(borderPoints, UR, null, LR, null, maxVertDivisions, 1.0);
|
||||
|
||||
// LR to LL
|
||||
tileCRSToTargetGrid.transform(LR, 0, out, 0, 1);
|
||||
borderPoints.add(new Coordinate(out[0], out[1]));
|
||||
calculateBorder(borderPoints, LR, null, LL, null, maxHorDivisions, 1.0);
|
||||
|
||||
// LL to UL
|
||||
tileCRSToTargetGrid.transform(LL, 0, out, 0, 1);
|
||||
borderPoints.add(new Coordinate(out[0], out[1]));
|
||||
calculateBorder(borderPoints, LL, null, UL, null, maxVertDivisions, 1.0);
|
||||
|
||||
// Add start point to complete linear ring
|
||||
tileCRSToTargetGrid.transform(UL, 0, out, 0, 1);
|
||||
borderPoints.add(new Coordinate(out[0], out[1]));
|
||||
|
||||
// Create Geometry and world wrap correct (need to be in lat/lon)
|
||||
return JTS.transform(corrector.correct(JTS.transform(TileSet.gf
|
||||
.createPolygon(TileSet.gf.createLinearRing(borderPoints
|
||||
.toArray(new Coordinate[borderPoints.size()])), null),
|
||||
targetGridToLatLon)), targetGridToLatLon.inverse());
|
||||
}
|
||||
|
||||
private int calculateBorder(List<Coordinate> borderList, double[] point1,
|
||||
double[] transformedPoint1, double[] point3,
|
||||
double[] transformedPoint3, double maxNumDivs, double threshold)
|
||||
throws TransformException {
|
||||
if (transformedPoint1 == null) {
|
||||
transformedPoint1 = new double[point1.length];
|
||||
tileCRSToTargetGrid.transform(point1, 0, transformedPoint1, 0, 1);
|
||||
}
|
||||
if (transformedPoint3 == null) {
|
||||
transformedPoint3 = new double[point3.length];
|
||||
tileCRSToTargetGrid.transform(point3, 0, transformedPoint3, 0, 1);
|
||||
}
|
||||
if (transformedPoint1 == null || transformedPoint3 == null) {
|
||||
// if the image has some points outside the valid range of the
|
||||
// screen then give up optimizing and assume the max number of
|
||||
// points.
|
||||
return (int) Math.ceil(maxNumDivs);
|
||||
}
|
||||
double[] point2 = { (point1[0] + point3[0]) / 2,
|
||||
(point1[1] + point3[1]) / 2 };
|
||||
double[] transformedPoint2 = new double[point2.length];
|
||||
tileCRSToTargetGrid.transform(point2, 0, transformedPoint2, 0, 1);
|
||||
double[] interp2 = { (transformedPoint1[0] + transformedPoint3[0]) / 2,
|
||||
(transformedPoint1[1] + transformedPoint3[1]) / 2 };
|
||||
double dX = transformedPoint2[0] - interp2[0];
|
||||
double dY = transformedPoint2[1] - interp2[1];
|
||||
double d = Math.hypot(dX, dY);
|
||||
if (d < threshold || maxNumDivs < 1) {
|
||||
return 1;
|
||||
} else {
|
||||
int nd1 = calculateBorder(borderList, point1, transformedPoint1,
|
||||
point2, transformedPoint2, maxNumDivs / 2, threshold);
|
||||
borderList.add(new Coordinate(transformedPoint2[0],
|
||||
transformedPoint2[1]));
|
||||
if (nd1 * 2 >= maxNumDivs) {
|
||||
nd1 = (int) Math.ceil(maxNumDivs);
|
||||
}
|
||||
int nd2 = calculateBorder(borderList, point2, transformedPoint2,
|
||||
point3, transformedPoint3, maxNumDivs / 2, threshold);
|
||||
if (nd2 * 2 >= maxNumDivs) {
|
||||
nd2 = (int) Math.ceil(maxNumDivs);
|
||||
}
|
||||
return (Math.max(nd1, nd2) * 2);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,462 @@
|
|||
/**
|
||||
* 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.viz.core.tile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.geotools.coverage.grid.GeneralGridGeometry;
|
||||
import org.geotools.coverage.grid.GridGeometry2D;
|
||||
import org.geotools.referencing.crs.DefaultGeographicCRS;
|
||||
import org.opengis.referencing.operation.MathTransform;
|
||||
import org.opengis.referencing.operation.TransformException;
|
||||
|
||||
import com.raytheon.uf.common.geospatial.CRSCache;
|
||||
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.viz.core.DrawableImage;
|
||||
import com.raytheon.uf.viz.core.IExtent;
|
||||
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
||||
import com.raytheon.uf.viz.core.IMesh;
|
||||
import com.raytheon.uf.viz.core.drawables.IColormappedImage;
|
||||
import com.raytheon.uf.viz.core.drawables.IImage;
|
||||
import com.raytheon.uf.viz.core.drawables.IImage.Status;
|
||||
import com.raytheon.uf.viz.core.drawables.IRenderable;
|
||||
import com.raytheon.uf.viz.core.drawables.PaintProperties;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.core.jobs.JobPool;
|
||||
import com.raytheon.uf.viz.core.rsc.capabilities.ImagingCapability;
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
|
||||
/**
|
||||
* Renderable tile set class that creates a {@link TileSet} and renders images
|
||||
* for tiles displayed using the {@link TileImageCreator} passed in at
|
||||
* construction
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 8, 2012 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class TileSetRenderable implements IRenderable {
|
||||
|
||||
public static interface TileImageCreator {
|
||||
|
||||
/**
|
||||
* Create a complete DrawableImage for the given tile on the
|
||||
* targetGeometry
|
||||
*/
|
||||
public DrawableImage createTileImage(IGraphicsTarget target, Tile tile,
|
||||
GeneralGridGeometry targetGeometry) throws VizException;
|
||||
|
||||
}
|
||||
|
||||
private class TileImageCreatorTask implements Runnable {
|
||||
|
||||
private IGraphicsTarget target;
|
||||
|
||||
private Tile tile;
|
||||
|
||||
private TileImageCreatorTask(IGraphicsTarget target, Tile tile) {
|
||||
this.target = target;
|
||||
this.tile = tile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
DrawableImage di = tileCreator.createTileImage(target, tile,
|
||||
tileSet.getTargetGeometry());
|
||||
if (di != null) {
|
||||
di.getImage().stage();
|
||||
}
|
||||
addTileImage(tile, di);
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
|
||||
e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(TileSetRenderable.class);
|
||||
|
||||
/** Screen pixel to image pixel threshold at which we change levels */
|
||||
protected static final double LEVEL_CHANGE_THRESHOLD = 2.0;
|
||||
|
||||
/** Job pool for tile creation */
|
||||
protected static final JobPool tileCreationPool = new JobPool(
|
||||
"Creating Image Tiles", 10, false);
|
||||
|
||||
/** Job map, should only have one job running per tile at a time */
|
||||
protected Map<Tile, Runnable> jobMap = new ConcurrentHashMap<Tile, Runnable>();
|
||||
|
||||
/** Image map for tiles */
|
||||
protected Map<Tile, DrawableImage> imageMap = new HashMap<Tile, DrawableImage>();
|
||||
|
||||
/** Full resolution tile set GridGeometry2D */
|
||||
protected final GridGeometry2D tileSetGeometry;
|
||||
|
||||
protected final TileImageCreator tileCreator;
|
||||
|
||||
/** Desired size for each tile */
|
||||
protected final int tileSize;
|
||||
|
||||
/** Number of tile levels to create */
|
||||
protected final int tileLevels;
|
||||
|
||||
/** {@link TileSet} object, manages tiles */
|
||||
protected TileSet tileSet;
|
||||
|
||||
/** Transform for tileset CRS to lat/lon */
|
||||
protected final MathTransform localProjToLL;
|
||||
|
||||
/** Transform for lat/lon to tileset CRS */
|
||||
protected final MathTransform llToLocalProj;
|
||||
|
||||
/** Stored imaging capability */
|
||||
protected final ImagingCapability imaging;
|
||||
|
||||
/** Last painted tile level, used for interrogating proper level */
|
||||
protected int lastPaintedLevel;
|
||||
|
||||
/** The ratio of target grid pixels / image pixel for each tile level */
|
||||
protected double[] pixelWidth;
|
||||
|
||||
/**
|
||||
* Constructs a tile set renderable, creators needs to call
|
||||
* {@link #project(GeneralGridGeometry)} before the renderable can be used
|
||||
*
|
||||
* @param resource
|
||||
* @param tileSetGeometry
|
||||
* @param tileCreator
|
||||
* @param tileLevels
|
||||
* @param tileSize
|
||||
*/
|
||||
public TileSetRenderable(ImagingCapability imaging,
|
||||
GridGeometry2D tileSetGeometry, TileImageCreator tileCreator,
|
||||
int tileLevels, int tileSize) {
|
||||
this.tileSetGeometry = tileSetGeometry;
|
||||
this.tileCreator = tileCreator;
|
||||
this.tileLevels = tileLevels;
|
||||
this.tileSize = tileSize;
|
||||
this.pixelWidth = new double[tileLevels];
|
||||
this.imaging = imaging;
|
||||
|
||||
try {
|
||||
// Set lat/lon math transforms for tile set
|
||||
llToLocalProj = CRSCache.getInstance().findMathTransform(
|
||||
DefaultGeographicCRS.WGS84,
|
||||
tileSetGeometry.getCoordinateReferenceSystem());
|
||||
localProjToLL = llToLocalProj.inverse();
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(
|
||||
"Could not get tranform from tile crs to lat/lon", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Projects the tile set for use with the target geometry
|
||||
*
|
||||
* @param targetGeometry
|
||||
*/
|
||||
public synchronized void project(GeneralGridGeometry targetGeometry) {
|
||||
// dispose the old TileSet
|
||||
if (tileSet != null) {
|
||||
tileSet.dispose();
|
||||
}
|
||||
// Create TileSet for new target geometry
|
||||
tileSet = TileSet.getTileSet(tileSetGeometry, targetGeometry,
|
||||
tileLevels, tileSize);
|
||||
|
||||
// Clear out meshes and create new ones cloning old ones
|
||||
for (DrawableImage di : imageMap.values()) {
|
||||
if (di != null) {
|
||||
IMesh currentMesh = di.getCoverage().getMesh();
|
||||
if (currentMesh != null) {
|
||||
try {
|
||||
di.getCoverage().setMesh(
|
||||
currentMesh.clone(targetGeometry));
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
}
|
||||
currentMesh.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the pixel densities for each tile level. This is approximately
|
||||
// how many target grid pixels per image pixel there are for the level
|
||||
for (int level = 0; level < tileLevels; ++level) {
|
||||
TileLevel tileLevel = tileSet.getTileLevel(level);
|
||||
pixelWidth[level] = tileLevel.getPixelDensity();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.viz.core.drawables.IRenderable#paint(com.raytheon.uf.
|
||||
* viz.core.IGraphicsTarget,
|
||||
* com.raytheon.uf.viz.core.drawables.PaintProperties)
|
||||
*/
|
||||
@Override
|
||||
public void paint(IGraphicsTarget target, PaintProperties paintProps)
|
||||
throws VizException {
|
||||
Collection<DrawableImage> images = getImagesToRender(target, paintProps);
|
||||
target.drawRasters(paintProps,
|
||||
images.toArray(new DrawableImage[images.size()]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes the tile set and any data associated with it
|
||||
*/
|
||||
public synchronized void dispose() {
|
||||
// Make sure any lingering jobs are canceled and joined on
|
||||
for (Runnable job : jobMap.values()) {
|
||||
tileCreationPool.cancel(job);
|
||||
}
|
||||
tileCreationPool.join();
|
||||
|
||||
// Dispose the tile set
|
||||
if (tileSet != null) {
|
||||
tileSet.dispose();
|
||||
tileSet = null;
|
||||
}
|
||||
|
||||
// Dispose of all the images for the tile set
|
||||
for (DrawableImage image : imageMap.values()) {
|
||||
if (image != null) {
|
||||
image.dispose();
|
||||
}
|
||||
}
|
||||
imageMap.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link DrawableImage} list to display for the given target and
|
||||
* paint properties
|
||||
*
|
||||
* @param target
|
||||
* @param paintProps
|
||||
* @return
|
||||
* @throws VizException
|
||||
*/
|
||||
public synchronized Collection<DrawableImage> getImagesToRender(
|
||||
IGraphicsTarget target, PaintProperties paintProps)
|
||||
throws VizException {
|
||||
double screenToWorldRatio = paintProps.getCanvasBounds().width
|
||||
/ paintProps.getView().getExtent().getWidth();
|
||||
|
||||
int usedTileLevel = tileLevels - 1;
|
||||
|
||||
/*
|
||||
* pixelRatios[usedTileLevel] * screenToWorldRatio gives us
|
||||
* canvasPixels/image pixel at the level, We should use the level if
|
||||
* there are less than LEVEL_CHANGE_THRESHOLD canvas pixels per image
|
||||
* pixel
|
||||
*/
|
||||
while ((pixelWidth[usedTileLevel] * screenToWorldRatio > LEVEL_CHANGE_THRESHOLD)
|
||||
&& usedTileLevel > 0) {
|
||||
usedTileLevel--;
|
||||
}
|
||||
lastPaintedLevel = usedTileLevel;
|
||||
|
||||
return getImagesWithinExtent(target, paintProps.getView().getExtent(),
|
||||
usedTileLevel, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param target
|
||||
* @param paintProps
|
||||
* @param level
|
||||
* @param depth
|
||||
* @return
|
||||
* @throws VizException
|
||||
*/
|
||||
protected List<DrawableImage> getImagesWithinExtent(IGraphicsTarget target,
|
||||
IExtent extent, int level, int depth) throws VizException {
|
||||
if (tileSet == null) {
|
||||
// Early exit condition, disposed or haven't projected yet
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// Flag to determine if we should draw lower tile levels. This will be
|
||||
// the case if we don't have all the images for all intersecting tiles
|
||||
// at this level
|
||||
boolean needDrawLower = false;
|
||||
// Get the intersecting tiles for the level
|
||||
Collection<Tile> intersecting = tileSet.getIntersectingTiles(level,
|
||||
extent);
|
||||
|
||||
// These Tiles still need images created for them
|
||||
List<Tile> tilesNeedingImage = new ArrayList<Tile>(intersecting.size());
|
||||
List<DrawableImage> drawableImages = new ArrayList<DrawableImage>(
|
||||
intersecting.size());
|
||||
|
||||
for (Tile tile : intersecting) {
|
||||
// Flag to indicate if a tile needs an image created for it
|
||||
boolean needsImage = false;
|
||||
DrawableImage di = imageMap.get(tile);
|
||||
if (di != null) {
|
||||
IImage image = di.getImage();
|
||||
if (image.getStatus() == Status.FAILED
|
||||
|| image.getStatus() == Status.INVALID) {
|
||||
// Image is invalid, re-request creation
|
||||
needsImage = true;
|
||||
} else {
|
||||
image.setBrightness(imaging.getBrightness());
|
||||
image.setContrast(imaging.getContrast());
|
||||
image.setInterpolated(imaging.isInterpolationState());
|
||||
|
||||
if (image.getStatus() != Status.LOADED) {
|
||||
needDrawLower = true;
|
||||
}
|
||||
drawableImages.add(di);
|
||||
}
|
||||
} else {
|
||||
needsImage = true;
|
||||
}
|
||||
|
||||
if (needsImage) {
|
||||
tilesNeedingImage.add(tile);
|
||||
needDrawLower = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (depth == 0) {
|
||||
// Only request images to be created if we are at the desired level
|
||||
// i.e. the recursion depth is 0
|
||||
if (tilesNeedingImage.isEmpty()) {
|
||||
// All intersecting tiles are loaded for this level, cancel any
|
||||
// jobs running for tiles we don't need anymore (may be case if
|
||||
// zooming or panning)
|
||||
for (Runnable job : jobMap.values()) {
|
||||
tileCreationPool.cancel(job);
|
||||
}
|
||||
jobMap.clear();
|
||||
} else {
|
||||
target.setNeedsRefresh(true);
|
||||
// Create tiles needing images
|
||||
createTileImages(target, tilesNeedingImage);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw lower resolution data first
|
||||
if (needDrawLower && (level + 1) < tileLevels) {
|
||||
// put lower levels first in the list so they are drawn first.
|
||||
List<DrawableImage> lowerImages = getImagesWithinExtent(target,
|
||||
extent, level + 1, depth + 1);
|
||||
lowerImages.addAll(drawableImages);
|
||||
drawableImages = lowerImages;
|
||||
}
|
||||
|
||||
return drawableImages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create tile images for the specified tiles
|
||||
*
|
||||
* @param target
|
||||
* @param tilesToCreate
|
||||
*/
|
||||
protected void createTileImages(IGraphicsTarget target,
|
||||
Collection<Tile> tilesToCreate) {
|
||||
for (Tile tile : tilesToCreate) {
|
||||
if (jobMap.get(tile) == null) {
|
||||
// No job already running for tile, create and schedule one
|
||||
TileImageCreatorTask job = new TileImageCreatorTask(target,
|
||||
tile);
|
||||
jobMap.put(tile, job);
|
||||
tileCreationPool.schedule(job);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a DrawableImage for the specified Tile. Disposes of any old image
|
||||
*
|
||||
* @param tile
|
||||
* @param image
|
||||
*/
|
||||
public void addTileImage(Tile tile, DrawableImage image) {
|
||||
DrawableImage oldImage = imageMap.put(tile, image);
|
||||
if (oldImage != null) {
|
||||
oldImage.dispose();
|
||||
}
|
||||
Runnable task = jobMap.remove(tile);
|
||||
if (task != null) {
|
||||
tileCreationPool.cancel(task);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw image value from tile image that contains the lat/lon
|
||||
* coordinate
|
||||
*
|
||||
* @param coordinate
|
||||
* in lat/lon space
|
||||
* @return
|
||||
* @throws VizException
|
||||
*/
|
||||
public double interrogate(Coordinate coordinate) throws VizException {
|
||||
try {
|
||||
double[] local = new double[2];
|
||||
llToLocalProj
|
||||
.transform(new double[] { coordinate.x, coordinate.y }, 0,
|
||||
local, 0, 1);
|
||||
double localX = local[0];
|
||||
double localY = local[1];
|
||||
|
||||
TileLevel level = tileSet.getTileLevel(lastPaintedLevel);
|
||||
double[] grid = level.crsToGrid(localX, localY);
|
||||
Tile tile = level.getTile(grid[0], grid[1]);
|
||||
DrawableImage di = imageMap.get(tile);
|
||||
if (di != null) {
|
||||
IImage image = di.getImage();
|
||||
if (image instanceof IColormappedImage) {
|
||||
return ((IColormappedImage) image).getValue((int) grid[0]
|
||||
% tileSize, (int) grid[1] % tileSize);
|
||||
}
|
||||
}
|
||||
} catch (TransformException e) {
|
||||
throw new VizException("Error interrogating ", e);
|
||||
}
|
||||
return Double.NaN;
|
||||
}
|
||||
}
|
|
@ -32,10 +32,12 @@ import com.raytheon.uf.viz.core.IDisplayPane;
|
|||
import com.raytheon.uf.viz.core.IDisplayPaneContainer;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.core.globals.VizGlobalsManager;
|
||||
import com.raytheon.uf.viz.core.maps.display.VizMapEditor;
|
||||
import com.raytheon.uf.viz.core.status.StatusConstants;
|
||||
import com.raytheon.uf.viz.d2d.ui.Activator;
|
||||
import com.raytheon.viz.ui.EditorUtil;
|
||||
import com.raytheon.viz.ui.HistoryList;
|
||||
import com.raytheon.viz.ui.editor.AbstractEditor;
|
||||
import com.raytheon.viz.ui.editor.IMultiPaneEditor;
|
||||
|
||||
/**
|
||||
|
@ -60,7 +62,8 @@ import com.raytheon.viz.ui.editor.IMultiPaneEditor;
|
|||
* @version 1
|
||||
*/
|
||||
public class ClearAction extends AbstractHandler {
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus.getHandler(ClearAction.class);
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(ClearAction.class);
|
||||
|
||||
@Override
|
||||
public Object execute(ExecutionEvent arg0) throws ExecutionException {
|
||||
|
@ -69,15 +72,14 @@ public class ClearAction extends AbstractHandler {
|
|||
new NewMapEditor().execute(null);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!(part instanceof IDisplayPaneContainer)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
HistoryList.getInstance().refreshLatestBundle();
|
||||
clear((IDisplayPaneContainer) part);
|
||||
HistoryList.getInstance().addBundle();
|
||||
if (part instanceof IDisplayPaneContainer) {
|
||||
HistoryList.getInstance().refreshLatestBundle();
|
||||
clear(part);
|
||||
HistoryList.getInstance().addBundle();
|
||||
} else {
|
||||
clear(part);
|
||||
}
|
||||
} catch (VizException e) {
|
||||
throw new ExecutionException("Error during clear", e);
|
||||
}
|
||||
|
@ -85,26 +87,19 @@ public class ClearAction extends AbstractHandler {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the map
|
||||
*
|
||||
* The map is cleared with either the provided default-procedure.xml or a
|
||||
* default world map, if no default-bundle.xml is available.
|
||||
*
|
||||
* @param target
|
||||
* the graphics target
|
||||
* @return the map descriptor prepared
|
||||
* @throws VizException
|
||||
*/
|
||||
public static void clear(IDisplayPaneContainer container)
|
||||
throws VizException {
|
||||
if (container instanceof IMultiPaneEditor) {
|
||||
((IMultiPaneEditor) container).clear();
|
||||
public static void clear(IEditorPart part) throws VizException {
|
||||
if (part instanceof VizMapEditor) {
|
||||
((VizMapEditor) part).clear();
|
||||
} else if (part instanceof AbstractEditor) {
|
||||
// AbstractEditor asks the user if they are sure if we pass in
|
||||
// save=true, if the user clicked clear than they must be sure so
|
||||
// pass in save=false.
|
||||
part.getSite().getPage().closeEditor(part, false);
|
||||
} else {
|
||||
for (IDisplayPane displayPane : container.getDisplayPanes()) {
|
||||
displayPane.clear();
|
||||
}
|
||||
// Give other editors a chance to save.
|
||||
part.getSite().getPage().closeEditor(part, true);
|
||||
}
|
||||
|
||||
if (EditorUtil.getActiveEditor() == null) {
|
||||
try {
|
||||
new NewMapEditor().execute(null);
|
||||
|
|
|
@ -385,11 +385,12 @@ public class MasterDerivScript extends PythonInterpreter {
|
|||
private void setDataRecordArg(String argName, IDataRecord argValue)
|
||||
throws JepException {
|
||||
boolean reshape = true;
|
||||
long[] sizes = argValue.getSizes();
|
||||
if (argValue instanceof FloatDataRecord) {
|
||||
FloatDataRecord record = (FloatDataRecord) argValue;
|
||||
if (record.getDimension() == 2) {
|
||||
jep.setNumeric(argName, record.getFloatData(),
|
||||
(int) record.getSizes()[0], (int) record.getSizes()[1]);
|
||||
if (sizes.length == 2) {
|
||||
jep.setNumeric(argName, record.getFloatData(), (int) sizes[0],
|
||||
(int) sizes[1]);
|
||||
reshape = false;
|
||||
} else {
|
||||
evaluateArgument(argName, record.getFloatData());
|
||||
|
@ -401,18 +402,18 @@ public class MasterDerivScript extends PythonInterpreter {
|
|||
jep.eval("del globals()['numpy']");
|
||||
} else if (argValue instanceof IntegerDataRecord) {
|
||||
IntegerDataRecord record = (IntegerDataRecord) argValue;
|
||||
if (record.getDimension() == 2) {
|
||||
jep.setNumeric(argName, record.getIntData(),
|
||||
(int) record.getSizes()[0], (int) record.getSizes()[1]);
|
||||
if (sizes.length == 2) {
|
||||
jep.setNumeric(argName, record.getIntData(), (int) sizes[0],
|
||||
(int) sizes[1]);
|
||||
reshape = false;
|
||||
} else {
|
||||
evaluateArgument(argName, record.getIntData());
|
||||
}
|
||||
} else if (argValue instanceof ByteDataRecord) {
|
||||
ByteDataRecord record = (ByteDataRecord) argValue;
|
||||
if (record.getDimension() == 2) {
|
||||
jep.setNumeric(argName, record.getByteData(),
|
||||
(int) record.getSizes()[0], (int) record.getSizes()[1]);
|
||||
if (sizes.length == 2) {
|
||||
jep.setNumeric(argName, record.getByteData(), (int) sizes[0],
|
||||
(int) sizes[1]);
|
||||
reshape = false;
|
||||
} else {
|
||||
evaluateArgument(argName, record.getByteData());
|
||||
|
|
|
@ -171,11 +171,11 @@ public abstract class AbstractInventory implements DerivParamUpdateListener {
|
|||
|
||||
protected Map<String, List<String>> sourceAliases = new HashMap<String, List<String>>();
|
||||
|
||||
private List<String> allSources;
|
||||
protected List<String> allSources;
|
||||
|
||||
private List<String> allParameters;
|
||||
protected List<String> allParameters;
|
||||
|
||||
private List<Level> allLevels;
|
||||
protected List<Level> allLevels;
|
||||
|
||||
/**
|
||||
* A call to this method assigns the passed grid tree to the original grid
|
||||
|
|
11
cave/com.raytheon.uf.viz.kml.export.feature/.project
Normal file
11
cave/com.raytheon.uf.viz.kml.export.feature/.project
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>com.raytheon.uf.viz.kml.export.feature</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1 @@
|
|||
bin.includes = feature.xml
|
32
cave/com.raytheon.uf.viz.kml.export.feature/feature.xml
Normal file
32
cave/com.raytheon.uf.viz.kml.export.feature/feature.xml
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<feature
|
||||
id="com.raytheon.uf.viz.kml.export.feature"
|
||||
label="Kml Export Feature"
|
||||
version="1.0.0.qualifier">
|
||||
|
||||
<description url="http://www.example.com/description">
|
||||
[Enter Feature Description here.]
|
||||
</description>
|
||||
|
||||
<copyright url="http://www.example.com/copyright">
|
||||
[Enter Copyright Description here.]
|
||||
</copyright>
|
||||
|
||||
<license url="http://www.example.com/license">
|
||||
[Enter License Description here.]
|
||||
</license>
|
||||
|
||||
<plugin
|
||||
id="de.micromata.opengis.kml"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"/>
|
||||
|
||||
<plugin
|
||||
id="com.raytheon.uf.viz.kml.export"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
</feature>
|
7
cave/com.raytheon.uf.viz.kml.export/.classpath
Normal file
7
cave/com.raytheon.uf.viz.kml.export/.classpath
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
28
cave/com.raytheon.uf.viz.kml.export/.project
Normal file
28
cave/com.raytheon.uf.viz.kml.export/.project
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>com.raytheon.uf.viz.kml.export</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,8 @@
|
|||
#Wed May 30 15:50:31 CDT 2012
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
27
cave/com.raytheon.uf.viz.kml.export/META-INF/MANIFEST.MF
Normal file
27
cave/com.raytheon.uf.viz.kml.export/META-INF/MANIFEST.MF
Normal file
|
@ -0,0 +1,27 @@
|
|||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: KML Export
|
||||
Bundle-SymbolicName: com.raytheon.uf.viz.kml.export;singleton:=true
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Activator: com.raytheon.uf.viz.kml.export.Activator
|
||||
Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization
|
||||
Bundle-Vendor: RAYTHEON
|
||||
Require-Bundle: org.eclipse.ui,
|
||||
org.eclipse.core.runtime,
|
||||
com.raytheon.uf.common.serialization;bundle-version="1.12.1174",
|
||||
org.geotools;bundle-version="2.6.4",
|
||||
com.raytheon.uf.viz.core;bundle-version="1.12.1174",
|
||||
com.raytheon.uf.viz.core.rsc;bundle-version="1.0.0",
|
||||
com.raytheon.uf.common.geospatial;bundle-version="1.12.1174",
|
||||
com.raytheon.uf.common.colormap;bundle-version="1.12.1174",
|
||||
com.raytheon.uf.common.time;bundle-version="1.12.1174",
|
||||
com.raytheon.viz.ui;bundle-version="1.12.1174",
|
||||
com.raytheon.uf.viz.core.maps;bundle-version="1.12.1174",
|
||||
de.micromata.opengis.kml;bundle-version="1.0.0",
|
||||
com.raytheon.viz.pointdata;bundle-version="1.12.1174",
|
||||
com.raytheon.viz.radar;bundle-version="1.12.1174",
|
||||
com.raytheon.uf.common.dataplugin.radar;bundle-version="1.0.0",
|
||||
javax.measure;bundle-version="1.0.0",
|
||||
javax.vecmath;bundle-version="1.3.1"
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||
Bundle-ActivationPolicy: lazy
|
5
cave/com.raytheon.uf.viz.kml.export/build.properties
Normal file
5
cave/com.raytheon.uf.viz.kml.export/build.properties
Normal file
|
@ -0,0 +1,5 @@
|
|||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.,\
|
||||
plugin.xml
|
62
cave/com.raytheon.uf.viz.kml.export/plugin.xml
Normal file
62
cave/com.raytheon.uf.viz.kml.export/plugin.xml
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?eclipse version="3.4"?>
|
||||
<plugin>
|
||||
<extension
|
||||
point="org.eclipse.ui.menus">
|
||||
<menuContribution
|
||||
locationURI="menu:export">
|
||||
<command
|
||||
commandId="com.raytheon.uf.viz.kml.export.exportKML"
|
||||
label="KML"
|
||||
style="push">
|
||||
</command>
|
||||
</menuContribution>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.ui.commands">
|
||||
<command
|
||||
id="com.raytheon.uf.viz.kml.export.exportKML"
|
||||
name="Export KML">
|
||||
</command>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.ui.handlers">
|
||||
<handler
|
||||
class="com.raytheon.uf.viz.kml.export.KmlExportHandler"
|
||||
commandId="com.raytheon.uf.viz.kml.export.exportKML">
|
||||
</handler>
|
||||
</extension>
|
||||
<extension
|
||||
point="com.raytheon.uf.viz.core.graphicsExtension">
|
||||
<graphicsExtension
|
||||
class="com.raytheon.uf.viz.kml.export.graphics.ext.point.KmlPointImageExtension">
|
||||
</graphicsExtension>
|
||||
<graphicsExtension
|
||||
class="com.raytheon.uf.viz.kml.export.graphics.ext.KmlSingleColorImageExtension">
|
||||
</graphicsExtension>
|
||||
<graphicsExtension
|
||||
class="com.raytheon.uf.viz.kml.export.graphics.ext.KmlColormappedImageExtension">
|
||||
</graphicsExtension>
|
||||
<graphicsExtension
|
||||
class="com.raytheon.uf.viz.kml.export.graphics.ext.KmlRasterImageExtension">
|
||||
</graphicsExtension>
|
||||
<graphicsExtension
|
||||
class="com.raytheon.uf.viz.kml.export.graphics.ext.KmlMapMeshExtension">
|
||||
</graphicsExtension>
|
||||
<graphicsExtension
|
||||
class="com.raytheon.uf.viz.kml.export.graphics.ext.radar.KmlRadialMeshExtension">
|
||||
</graphicsExtension>
|
||||
<graphicsExtension
|
||||
class="com.raytheon.uf.viz.kml.export.graphics.ext.KmlMosaicImageExtension">
|
||||
</graphicsExtension>
|
||||
<graphicsExtension
|
||||
class="com.raytheon.uf.viz.kml.export.graphics.ext.KmlMosaicMaxValImageExtension">
|
||||
</graphicsExtension>
|
||||
<graphicsExtension
|
||||
class="com.raytheon.uf.viz.kml.export.graphics.ext.KmlMosaicOrderedImageExtension">
|
||||
</graphicsExtension>
|
||||
<graphicsExtension
|
||||
class="com.raytheon.uf.viz.kml.export.graphics.ext.KmlCanvasRenderingExtension">
|
||||
</graphicsExtension>
|
||||
</extension>
|
||||
</plugin>
|
|
@ -0,0 +1,50 @@
|
|||
package com.raytheon.uf.viz.kml.export;
|
||||
|
||||
import org.eclipse.ui.plugin.AbstractUIPlugin;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
/**
|
||||
* The activator class controls the plug-in life cycle
|
||||
*/
|
||||
public class Activator extends AbstractUIPlugin {
|
||||
|
||||
// The plug-in ID
|
||||
public static final String PLUGIN_ID = "com.raytheon.uf.viz.kml.export"; //$NON-NLS-1$
|
||||
|
||||
// The shared instance
|
||||
private static Activator plugin;
|
||||
|
||||
/**
|
||||
* The constructor
|
||||
*/
|
||||
public Activator() {
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
|
||||
*/
|
||||
public void start(BundleContext context) throws Exception {
|
||||
super.start(context);
|
||||
plugin = this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
|
||||
*/
|
||||
public void stop(BundleContext context) throws Exception {
|
||||
plugin = null;
|
||||
super.stop(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the shared instance
|
||||
*
|
||||
* @return the shared instance
|
||||
*/
|
||||
public static Activator getDefault() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,606 @@
|
|||
/**
|
||||
* 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.viz.kml.export;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.events.SelectionAdapter;
|
||||
import org.eclipse.swt.events.SelectionEvent;
|
||||
import org.eclipse.swt.layout.FillLayout;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.layout.RowData;
|
||||
import org.eclipse.swt.layout.RowLayout;
|
||||
import org.eclipse.swt.widgets.Button;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.FileDialog;
|
||||
import org.eclipse.swt.widgets.Group;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.Layout;
|
||||
import org.eclipse.swt.widgets.MessageBox;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
import org.eclipse.swt.widgets.Tree;
|
||||
import org.eclipse.swt.widgets.TreeItem;
|
||||
|
||||
import com.raytheon.uf.viz.core.drawables.ResourcePair;
|
||||
import com.raytheon.uf.viz.kml.export.KmlExportOptions.KmlExportTimeMode;
|
||||
import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
|
||||
|
||||
/**
|
||||
* Allow user to select options for export and starts the KmlExportJob.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 5, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class KmlExportDialog extends CaveSWTDialog {
|
||||
|
||||
private final KmlExportOptions options;
|
||||
|
||||
private Text locationText;
|
||||
|
||||
private Tree productTree;
|
||||
|
||||
private Button exportHiddenButton;
|
||||
|
||||
private Button exportMapsButton;
|
||||
|
||||
private Button shadeEarthButton;
|
||||
|
||||
private Button setTimesButton;
|
||||
|
||||
private Button timeSpanButton;
|
||||
|
||||
private Button timeStampButton;
|
||||
|
||||
private Button fillPlotsButton;
|
||||
|
||||
private Button selectedFramesButton;
|
||||
|
||||
private Button currentFramesButton;
|
||||
|
||||
private Button allFramesButton;
|
||||
|
||||
private Text framesFromText;
|
||||
|
||||
private Text framesToText;
|
||||
|
||||
public KmlExportDialog(Shell shell, KmlExportOptions options) {
|
||||
super(shell, SWT.RESIZE | SWT.DIALOG_TRIM);
|
||||
this.setText("Export KML");
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initializeComponents(Shell shell) {
|
||||
|
||||
Composite leftComposite = new Composite(shell, SWT.NONE);
|
||||
leftComposite.setLayoutData(new GridData(SWT.NONE, SWT.FILL, false,
|
||||
true));
|
||||
RowLayout layout = new RowLayout(SWT.VERTICAL);
|
||||
layout.fill = true;
|
||||
leftComposite.setLayout(layout);
|
||||
|
||||
Group locationGroup = new Group(leftComposite, SWT.NONE);
|
||||
initializeLocationGroup(locationGroup);
|
||||
|
||||
Group framesGroup = new Group(leftComposite, SWT.NONE);
|
||||
initializeFramesGroup(framesGroup);
|
||||
|
||||
Group optionsGroup = new Group(leftComposite, SWT.NONE);
|
||||
initializeOptionsGroup(optionsGroup);
|
||||
|
||||
// Group timeOptionsGroup = new Group(leftComposite, SWT.NONE);
|
||||
// initializeTimeOptionsGroup(timeOptionsGroup);
|
||||
|
||||
Group productsGroup = new Group(shell, SWT.NONE);
|
||||
GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
|
||||
gridData.widthHint = 250;
|
||||
productsGroup.setLayoutData(gridData);
|
||||
initializeProductsGroup(productsGroup);
|
||||
|
||||
Composite buttonComposite = new Composite(shell, SWT.NONE);
|
||||
gridData = new GridData(SWT.FILL, SWT.NONE, true, false, 2, 1);
|
||||
gridData.horizontalAlignment = SWT.CENTER;
|
||||
buttonComposite.setLayoutData(gridData);
|
||||
initializeButtons(buttonComposite);
|
||||
|
||||
populateProductTree();
|
||||
if (productTree.getItemCount() == 0) {
|
||||
// for the intial load change this option so there is something to
|
||||
// export.
|
||||
exportMapsButton.setSelection(true);
|
||||
populateProductTree();
|
||||
}
|
||||
|
||||
shell.pack();
|
||||
shell.setMinimumSize(shell.getSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Layout constructShellLayout() {
|
||||
GridLayout mainLayout = new GridLayout(2, false);
|
||||
mainLayout.marginHeight = 3;
|
||||
mainLayout.marginWidth = 3;
|
||||
return mainLayout;
|
||||
}
|
||||
|
||||
protected void initializeLocationGroup(Group group) {
|
||||
group.setLayout(new GridLayout(2, false));
|
||||
group.setText("Export Location");
|
||||
locationText = new Text(group, SWT.BORDER);
|
||||
GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
|
||||
gridData.widthHint = 250;
|
||||
locationText.setLayoutData(gridData);
|
||||
locationText.setText(options.getKmzFileLocation().getAbsolutePath());
|
||||
Button button = new Button(group, SWT.PUSH);
|
||||
button.setText("Browse ...");
|
||||
button.addSelectionListener(new SelectionAdapter() {
|
||||
public void widgetSelected(SelectionEvent event) {
|
||||
selectDestinationFile();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void initializeFramesGroup(Group group) {
|
||||
group.setLayout(new GridLayout(5, false));
|
||||
group.setText("Export Location");
|
||||
|
||||
allFramesButton = new Button(group, SWT.RADIO);
|
||||
allFramesButton.setText("All Frames");
|
||||
GridData gridData = new GridData();
|
||||
gridData.horizontalSpan = 5;
|
||||
allFramesButton.setLayoutData(gridData);
|
||||
allFramesButton.setSelection(true);
|
||||
|
||||
currentFramesButton = new Button(group, SWT.RADIO);
|
||||
currentFramesButton.setText("Current Frame");
|
||||
gridData = new GridData();
|
||||
gridData.horizontalSpan = 5;
|
||||
currentFramesButton.setLayoutData(gridData);
|
||||
|
||||
selectedFramesButton = new Button(group, SWT.RADIO);
|
||||
selectedFramesButton.setText("Frames");
|
||||
|
||||
new Label(group, SWT.NONE).setText("from:");
|
||||
framesFromText = new Text(group, SWT.BORDER);
|
||||
gridData = new GridData();
|
||||
gridData.widthHint = 24;
|
||||
framesFromText.setLayoutData(gridData);
|
||||
framesFromText.setEnabled(false);
|
||||
framesFromText.setText("1");
|
||||
new Label(group, SWT.NONE).setText("to:");
|
||||
framesToText = new Text(group, SWT.BORDER);
|
||||
gridData = new GridData();
|
||||
gridData.widthHint = 24;
|
||||
framesToText.setLayoutData(gridData);
|
||||
framesToText.setEnabled(false);
|
||||
int numFrames = 1;
|
||||
for (KmlPane pane : options.getPanes()) {
|
||||
int frames = pane.getDisplay().getDescriptor().getFramesInfo()
|
||||
.getFrameCount();
|
||||
numFrames = Math.max(frames, numFrames);
|
||||
}
|
||||
framesToText.setText(Integer.toString(numFrames));
|
||||
selectedFramesButton.addSelectionListener(new SelectionAdapter() {
|
||||
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
framesToText.setEnabled(selectedFramesButton.getSelection());
|
||||
framesFromText.setEnabled(selectedFramesButton.getSelection());
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
protected void initializeOptionsGroup(Group group) {
|
||||
group.setText("Other Options");
|
||||
group.setLayout(new RowLayout(SWT.VERTICAL));
|
||||
exportHiddenButton = new Button(group, SWT.CHECK);
|
||||
exportHiddenButton.setText("Export Hidden");
|
||||
exportHiddenButton.setSelection(true);
|
||||
exportHiddenButton
|
||||
.setToolTipText("Include hidden products in the selection of products to export.");
|
||||
exportHiddenButton.addSelectionListener(new SelectionAdapter() {
|
||||
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
populateProductTree();
|
||||
}
|
||||
});
|
||||
exportMapsButton = new Button(group, SWT.CHECK);
|
||||
exportMapsButton.setText("Export Maps");
|
||||
exportMapsButton.setSelection(false);
|
||||
exportMapsButton
|
||||
.setToolTipText("Include maps in the selection of products to export.");
|
||||
exportMapsButton.addSelectionListener(new SelectionAdapter() {
|
||||
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
populateProductTree();
|
||||
}
|
||||
});
|
||||
shadeEarthButton = new Button(group, SWT.CHECK);
|
||||
shadeEarthButton.setText("Shade Earth");
|
||||
shadeEarthButton.setSelection(options.isShadeEarth());
|
||||
shadeEarthButton
|
||||
.setToolTipText("Hides the Google Earth surface imagery.");
|
||||
fillPlotsButton = new Button(group, SWT.CHECK);
|
||||
fillPlotsButton.setText("Show Background Tiles");
|
||||
fillPlotsButton.setSelection(options.isFillPlotBackground());
|
||||
fillPlotsButton
|
||||
.setToolTipText("Displays an opaque background tile behind point observations");
|
||||
}
|
||||
|
||||
protected void initializeTimeOptionsGroup(Group group) {
|
||||
group.setText("Time Options");
|
||||
group.setLayout(new RowLayout(SWT.VERTICAL));
|
||||
setTimesButton = new Button(group, SWT.CHECK);
|
||||
setTimesButton.setText("Set KML Time");
|
||||
setTimesButton
|
||||
.setSelection(options.getTimeMode() != KmlExportTimeMode.NONE);
|
||||
setTimesButton
|
||||
.setToolTipText("Causes Google Earth to display a time slider.");
|
||||
Composite timeComposite = new Composite(group, SWT.NONE);
|
||||
RowLayout layout = new RowLayout(SWT.VERTICAL);
|
||||
layout.marginLeft = 20;
|
||||
timeComposite.setLayout(layout);
|
||||
timeSpanButton = new Button(timeComposite, SWT.RADIO);
|
||||
timeSpanButton.setText("Time Span");
|
||||
timeSpanButton
|
||||
.setSelection(options.getTimeMode() != KmlExportTimeMode.TIME_STAMP);
|
||||
timeSpanButton.setEnabled(setTimesButton.getSelection());
|
||||
timeSpanButton
|
||||
.setToolTipText("Allow products to be visible over a time range.");
|
||||
timeStampButton = new Button(timeComposite, SWT.RADIO);
|
||||
timeStampButton.setText("Time Stamp");
|
||||
timeStampButton
|
||||
.setSelection(options.getTimeMode() == KmlExportTimeMode.TIME_STAMP);
|
||||
timeStampButton.setEnabled(setTimesButton.getSelection());
|
||||
timeStampButton
|
||||
.setToolTipText("Makes each product visible only at its exact valid time.");
|
||||
setTimesButton.addSelectionListener(new SelectionAdapter() {
|
||||
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
timeSpanButton.setEnabled(setTimesButton.getSelection());
|
||||
timeStampButton.setEnabled(setTimesButton.getSelection());
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
protected void initializeProductsGroup(Group group) {
|
||||
group.setText("Products");
|
||||
group.setLayout(new FillLayout());
|
||||
productTree = new Tree(group, SWT.CHECK);
|
||||
productTree.addSelectionListener(new SelectionAdapter() {
|
||||
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
if (e.detail == SWT.CHECK) {
|
||||
treeItemChecked((TreeItem) e.item);
|
||||
}
|
||||
super.widgetSelected(e);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
protected void initializeButtons(Composite comp) {
|
||||
comp.setLayout(new RowLayout(SWT.HORIZONTAL));
|
||||
Button okButton = new Button(comp, SWT.PUSH);
|
||||
okButton.setText("OK");
|
||||
okButton.setLayoutData(new RowData(100, SWT.DEFAULT));
|
||||
okButton.addSelectionListener(new SelectionAdapter() {
|
||||
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
okPressed();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Button cancelButton = new Button(comp, SWT.PUSH);
|
||||
cancelButton.setText("Cancel");
|
||||
cancelButton.setLayoutData(new RowData(100, SWT.DEFAULT));
|
||||
cancelButton.addSelectionListener(new SelectionAdapter() {
|
||||
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
close();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
protected void populateProductTree() {
|
||||
boolean exportMaps = exportMapsButton.getSelection();
|
||||
boolean exportHidden = exportHiddenButton.getSelection();
|
||||
if (options.isSinglePane()) {
|
||||
List<ResourcePair> rscList = options.getSinglPane().getResources(
|
||||
exportMaps, exportHidden);
|
||||
populateProductSubTree(rscList, null);
|
||||
} else {
|
||||
int index = 0;
|
||||
for (KmlPane pane : options.getPanes()) {
|
||||
List<ResourcePair> rscList = pane.getResources(exportMaps,
|
||||
exportHidden);
|
||||
TreeItem item = null;
|
||||
if (index < productTree.getItemCount()) {
|
||||
item = productTree.getItem(index);
|
||||
}
|
||||
if (!rscList.isEmpty()) {
|
||||
if (item == null || item.getData() != pane) {
|
||||
item = new TreeItem(productTree, SWT.NONE, index);
|
||||
item.setText("Pane " + (index + 1));
|
||||
item.setData(pane);
|
||||
populateProductSubTree(rscList, item);
|
||||
item.setExpanded(true);
|
||||
} else {
|
||||
populateProductSubTree(rscList, item);
|
||||
}
|
||||
index += 1;
|
||||
} else {
|
||||
if (item != null && item.getData() == pane) {
|
||||
item.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void populateProductSubTree(List<ResourcePair> rscList,
|
||||
final TreeItem parent) {
|
||||
TreeItem[] items = parent != null ? parent.getItems() : productTree
|
||||
.getItems();
|
||||
int itemIndex = 0;
|
||||
int rscIndex = 0;
|
||||
while (itemIndex < items.length || rscIndex < rscList.size()) {
|
||||
TreeItem item = null;
|
||||
if (itemIndex < items.length) {
|
||||
item = items[itemIndex];
|
||||
}
|
||||
ResourcePair pair = null;
|
||||
if (rscIndex < rscList.size()) {
|
||||
pair = rscList.get(rscIndex);
|
||||
}
|
||||
if (item != null && item.getData() == pair) {
|
||||
itemIndex += 1;
|
||||
rscIndex += 1;
|
||||
} else if (item != null && !rscList.contains(item.getData())) {
|
||||
item.dispose();
|
||||
itemIndex += 1;
|
||||
} else {
|
||||
if (parent != null) {
|
||||
item = new TreeItem(parent, SWT.NONE, rscIndex);
|
||||
} else {
|
||||
item = new TreeItem(productTree, SWT.NONE, rscIndex);
|
||||
}
|
||||
String name = pair.getResource().getName();
|
||||
if (name == null) {
|
||||
name = pair.getResource().getClass().getSimpleName();
|
||||
}
|
||||
item.setText(name);
|
||||
item.setData(pair);
|
||||
item.setChecked(true);
|
||||
treeItemChecked(item);
|
||||
rscIndex += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void treeItemChecked(TreeItem item) {
|
||||
for (TreeItem ti : item.getItems()) {
|
||||
ti.setChecked(item.getChecked());
|
||||
}
|
||||
TreeItem parent = item.getParentItem();
|
||||
while (parent != null) {
|
||||
parent.setChecked(true);
|
||||
for (TreeItem ti : parent.getItems()) {
|
||||
if (!ti.getChecked()) {
|
||||
parent.setChecked(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
parent = parent.getParentItem();
|
||||
}
|
||||
}
|
||||
|
||||
protected void selectDestinationFile() {
|
||||
FileDialog fileDialog = new FileDialog(this.shell, SWT.SAVE);
|
||||
File file = new File(locationText.getText());
|
||||
fileDialog.setFileName(file.getName());
|
||||
if (file.getParentFile() != null && file.getParentFile().isDirectory()) {
|
||||
fileDialog.setFilterPath(file.getParent());
|
||||
}
|
||||
fileDialog.setFilterExtensions(new String[] { ".kmz" });
|
||||
fileDialog.open();
|
||||
|
||||
String filterPath = fileDialog.getFilterPath();
|
||||
String selectedFile = fileDialog.getFileName();
|
||||
/*
|
||||
* Ensure that the user has entered a name for the file.
|
||||
*/
|
||||
if (selectedFile.equalsIgnoreCase("")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!filterPath.endsWith("/")) {
|
||||
filterPath += "/";
|
||||
}
|
||||
String destinationFile = filterPath + selectedFile;
|
||||
this.locationText.setText(destinationFile);
|
||||
this.locationText.setToolTipText(destinationFile);
|
||||
}
|
||||
|
||||
protected void okPressed() {
|
||||
if (allFramesButton.getSelection()) {
|
||||
options.setFirstFrameIndex(Integer.MIN_VALUE);
|
||||
options.setLastFrameIndex(Integer.MAX_VALUE);
|
||||
} else if (currentFramesButton.getSelection()) {
|
||||
for (KmlPane pane : options.getPanes()) {
|
||||
int frame = pane.getDisplay().getDescriptor().getFramesInfo()
|
||||
.getFrameIndex();
|
||||
frame = Math.max(0, frame);
|
||||
options.setFirstFrameIndex(frame);
|
||||
options.setLastFrameIndex(frame + 1);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
int from = Integer.parseInt(framesFromText.getText()) - 1;
|
||||
options.setFirstFrameIndex(from);
|
||||
} catch (NumberFormatException e) {
|
||||
MessageBox mb = new MessageBox(getShell(), SWT.ICON_ERROR
|
||||
| SWT.OK);
|
||||
mb.setText("Invalid Number");
|
||||
mb.setMessage(framesFromText.getText()
|
||||
+ " is not a valid number, please enter a valid number for the starting frame.");
|
||||
mb.open();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
int to = Integer.parseInt(framesToText.getText());
|
||||
options.setLastFrameIndex(to);
|
||||
} catch (NumberFormatException e) {
|
||||
MessageBox mb = new MessageBox(getShell(), SWT.ICON_ERROR
|
||||
| SWT.OK);
|
||||
mb.setText("Invalid Number");
|
||||
mb.setMessage(framesFromText.getText()
|
||||
+ " is not a valid number, please enter a valid number for the ending frame.");
|
||||
mb.open();
|
||||
return;
|
||||
}
|
||||
}
|
||||
options.setKmzFileLocation(new File(locationText.getText()));
|
||||
options.setShadeEarth(shadeEarthButton.getSelection());
|
||||
// if (!setTimesButton.getSelection()) {
|
||||
// options.setTimeMode(KmlExportTimeMode.NONE);
|
||||
// } else if (timeSpanButton.getSelection()) {
|
||||
// options.setTimeMode(KmlExportTimeMode.TIME_SPAN);
|
||||
// } else if (timeStampButton.getSelection()) {
|
||||
// options.setTimeMode(KmlExportTimeMode.TIME_STAMP);
|
||||
//
|
||||
// }
|
||||
options.setFillPlotBackground(fillPlotsButton.getSelection());
|
||||
if (options.isSinglePane()) {
|
||||
List<ResourcePair> resourcesToExport = new ArrayList<ResourcePair>();
|
||||
for (TreeItem ti : productTree.getItems()) {
|
||||
if (ti.getChecked()) {
|
||||
resourcesToExport.add((ResourcePair) ti.getData());
|
||||
}
|
||||
}
|
||||
options.getSinglPane().setResourcesToExport(resourcesToExport);
|
||||
} else {
|
||||
for (TreeItem paneitem : productTree.getItems()) {
|
||||
KmlPane pane = (KmlPane) paneitem.getData();
|
||||
List<ResourcePair> resourcesToExport = new ArrayList<ResourcePair>();
|
||||
for (TreeItem ti : paneitem.getItems()) {
|
||||
if (ti.getChecked()) {
|
||||
resourcesToExport.add((ResourcePair) ti.getData());
|
||||
}
|
||||
}
|
||||
pane.setResourcesToExport(resourcesToExport);
|
||||
}
|
||||
}
|
||||
if (!validate()) {
|
||||
// clear the current selection
|
||||
for (KmlPane pane : options.getPanes()) {
|
||||
pane.setResourcesToExport(null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
new KmlExportJob(options).schedule();
|
||||
close();
|
||||
}
|
||||
|
||||
protected boolean validate() {
|
||||
boolean products = false;
|
||||
for (KmlPane pane : options.getPanes()) {
|
||||
if (pane.getResourcesToExport() != null
|
||||
&& !pane.getResourcesToExport().isEmpty()) {
|
||||
products = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!products) {
|
||||
MessageBox mb = new MessageBox(getShell(), SWT.ICON_ERROR | SWT.OK);
|
||||
mb.setText("No Products");
|
||||
mb.setMessage("No products are selected.");
|
||||
mb.open();
|
||||
return false;
|
||||
}
|
||||
if (options.getFirstFrameIndex() > options.getLastFrameIndex()
|
||||
|| options.getLastFrameIndex() < 0) {
|
||||
MessageBox mb = new MessageBox(getShell(), SWT.ICON_ERROR | SWT.OK);
|
||||
mb.setText("Invalid Range");
|
||||
mb.setMessage("The frame range you entered is invalid, please enter a valid range");
|
||||
mb.open();
|
||||
return false;
|
||||
}
|
||||
File file = options.getKmzFileLocation();
|
||||
if (!file.getParentFile().exists()) {
|
||||
MessageBox mb = new MessageBox(getShell(), SWT.ICON_QUESTION
|
||||
| SWT.YES | SWT.NO);
|
||||
mb.setText("Create Directory");
|
||||
mb.setMessage("The directory " + file.getParent()
|
||||
+ " does not exist, would you like to create it.");
|
||||
int result = mb.open();
|
||||
if (result == SWT.YES) {
|
||||
if (!file.getParentFile().mkdirs()) {
|
||||
mb = new MessageBox(getShell(), SWT.ICON_ERROR | SWT.OK);
|
||||
mb.setText("Error Creating Directory");
|
||||
mb.setMessage("An unspecified error has occured creating the directory, please select a new file location.");
|
||||
mb.open();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (file.exists()) {
|
||||
MessageBox mb = new MessageBox(getShell(), SWT.ICON_WARNING
|
||||
| SWT.YES | SWT.NO);
|
||||
mb.setText("Overwrite file");
|
||||
mb.setMessage("The specified file already exist. Would you like to overwrite it?");
|
||||
int result = mb.open();
|
||||
if (result == SWT.NO) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/**
|
||||
* 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.viz.kml.export;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.core.commands.AbstractHandler;
|
||||
import org.eclipse.core.commands.ExecutionEvent;
|
||||
import org.eclipse.core.commands.ExecutionException;
|
||||
import org.eclipse.ui.handlers.HandlerUtil;
|
||||
|
||||
import com.raytheon.uf.viz.core.IDisplayPane;
|
||||
import com.raytheon.uf.viz.core.IDisplayPaneContainer;
|
||||
import com.raytheon.uf.viz.core.drawables.AbstractRenderableDisplay;
|
||||
import com.raytheon.uf.viz.core.maps.display.MapRenderableDisplay;
|
||||
import com.raytheon.uf.viz.kml.export.KmlExportOptions.KmlExportTimeMode;
|
||||
import com.raytheon.viz.ui.EditorUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* Handler for events from the KML Export menu item.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 1, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
public class KmlExportHandler extends AbstractHandler {
|
||||
|
||||
@Override
|
||||
public Object execute(ExecutionEvent event) throws ExecutionException {
|
||||
new KmlExportDialog(HandlerUtil.getActiveShell(event),
|
||||
getDefaultOptions()).open();
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static KmlExportOptions getDefaultOptions() {
|
||||
KmlExportOptions options = new KmlExportOptions();
|
||||
options.setFirstFrameIndex(Integer.MIN_VALUE);
|
||||
options.setLastFrameIndex(Integer.MAX_VALUE);
|
||||
options.setPreserveVisibility(true);
|
||||
options.setShadeEarth(false);
|
||||
options.setTimeMode(KmlExportTimeMode.TIME_SPAN);
|
||||
options.setKmzFileLocation(new File(System.getProperty("user.home"),
|
||||
"caveExport.kmz"));
|
||||
options.setPlotIconScale(3.5);
|
||||
options.setFillPlotBackground(false);
|
||||
options.setPaintSleepMillis(10);
|
||||
options.setMaxRefreshSeconds(60);
|
||||
IDisplayPaneContainer container = EditorUtil.getActiveVizContainer();
|
||||
List<KmlPane> panes = new ArrayList<KmlPane>();
|
||||
for (IDisplayPane pane : container.getDisplayPanes()) {
|
||||
AbstractRenderableDisplay display = (AbstractRenderableDisplay) pane
|
||||
.getRenderableDisplay();
|
||||
panes.add(new KmlPane(display, pane.getBounds()));
|
||||
}
|
||||
options.setPanes(panes);
|
||||
return options;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(Object evaluationContext) {
|
||||
IDisplayPaneContainer container = EditorUtil.getActiveVizContainer();
|
||||
if (container == null) {
|
||||
super.setBaseEnabled(false);
|
||||
return;
|
||||
}
|
||||
IDisplayPane pane = container.getActiveDisplayPane();
|
||||
if (pane == null) {
|
||||
super.setBaseEnabled(false);
|
||||
return;
|
||||
}
|
||||
super.setBaseEnabled(pane.getRenderableDisplay() instanceof MapRenderableDisplay);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,676 @@
|
|||
/**
|
||||
* 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.viz.kml.export;
|
||||
|
||||
import java.awt.Graphics;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.SubMonitor;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
import org.geotools.geometry.DirectPosition2D;
|
||||
import org.geotools.referencing.GeodeticCalculator;
|
||||
import org.opengis.referencing.FactoryException;
|
||||
import org.opengis.referencing.datum.PixelInCell;
|
||||
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.IColorMap;
|
||||
import com.raytheon.uf.common.geospatial.MapUtil;
|
||||
import com.raytheon.uf.common.geospatial.TransformFactory;
|
||||
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.IExtent;
|
||||
import com.raytheon.uf.viz.core.drawables.AbstractRenderableDisplay;
|
||||
import com.raytheon.uf.viz.core.drawables.ColorMapParameters;
|
||||
import com.raytheon.uf.viz.core.drawables.ColorMapParameters.LabelEntry;
|
||||
import com.raytheon.uf.viz.core.drawables.IDescriptor;
|
||||
import com.raytheon.uf.viz.core.drawables.IDescriptor.FramesInfo;
|
||||
import com.raytheon.uf.viz.core.drawables.PaintProperties;
|
||||
import com.raytheon.uf.viz.core.drawables.PaintStatus;
|
||||
import com.raytheon.uf.viz.core.drawables.ResourcePair;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.core.jobs.JobPool;
|
||||
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
|
||||
import com.raytheon.uf.viz.core.rsc.IResourceGroup;
|
||||
import com.raytheon.uf.viz.core.rsc.ResourceList;
|
||||
import com.raytheon.uf.viz.core.rsc.capabilities.BlendableCapability;
|
||||
import com.raytheon.uf.viz.core.rsc.capabilities.BlendedCapability;
|
||||
import com.raytheon.uf.viz.core.rsc.capabilities.ColorMapCapability;
|
||||
import com.raytheon.uf.viz.kml.export.graphics.KmlGraphicsFactoryAdapter;
|
||||
import com.raytheon.uf.viz.kml.export.graphics.KmlGraphicsTarget;
|
||||
import com.raytheon.uf.viz.kml.export.io.KmlOutputManager;
|
||||
import com.raytheon.uf.viz.kml.export.io.KmlRootOutputManager;
|
||||
|
||||
import de.micromata.opengis.kml.v_2_2_0.AbstractObject;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Document;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Feature;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Folder;
|
||||
import de.micromata.opengis.kml.v_2_2_0.LinearRing;
|
||||
import de.micromata.opengis.kml.v_2_2_0.LookAt;
|
||||
import de.micromata.opengis.kml.v_2_2_0.MultiGeometry;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Placemark;
|
||||
import de.micromata.opengis.kml.v_2_2_0.PolyStyle;
|
||||
import de.micromata.opengis.kml.v_2_2_0.ScreenOverlay;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Style;
|
||||
import de.micromata.opengis.kml.v_2_2_0.TimePrimitive;
|
||||
import de.micromata.opengis.kml.v_2_2_0.TimeSpan;
|
||||
import de.micromata.opengis.kml.v_2_2_0.TimeStamp;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Units;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Vec2;
|
||||
|
||||
/**
|
||||
* The main Job for exporting KML in a background thread
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 6, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class KmlExportJob extends Job {
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(KmlExportJob.class);
|
||||
|
||||
private static final SimpleDateFormat KML_TIME_FORMAT = new SimpleDateFormat(
|
||||
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
|
||||
|
||||
private final KmlExportOptions options;
|
||||
|
||||
private final JobPool backgroundPool = new JobPool("Exporting KML", 4,
|
||||
true, Job.INTERACTIVE);
|
||||
|
||||
public KmlExportJob(KmlExportOptions options) {
|
||||
super("Generating Kml");
|
||||
setUser(true);
|
||||
this.options = options;
|
||||
KML_TIME_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
SubMonitor smonitor = SubMonitor
|
||||
.convert(monitor, "Generating KML", 800);
|
||||
|
||||
try {
|
||||
copyPanes(smonitor.newChild(20, SubMonitor.SUPPRESS_NONE));
|
||||
|
||||
initPanes(smonitor.newChild(80, SubMonitor.SUPPRESS_NONE));
|
||||
|
||||
KmlRootOutputManager out = new KmlRootOutputManager(
|
||||
options.getKmzFileLocation());
|
||||
|
||||
exportPanes(smonitor.newChild(500, SubMonitor.SUPPRESS_NONE), out);
|
||||
joinBackground(smonitor.newChild(150, SubMonitor.SUPPRESS_NONE));
|
||||
// Do not dispose until all background processes are done
|
||||
for (KmlPane pane : options.getPanes()) {
|
||||
pane.getDisplay().dispose();
|
||||
}
|
||||
recursiveInvisibility(out.getContainer(), true);
|
||||
out.close();
|
||||
smonitor.worked(50);
|
||||
} catch (IOException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, "Error writing KML", e);
|
||||
}
|
||||
smonitor.done();
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy each pane and remove any panes that aren't being exported.
|
||||
*
|
||||
* @param monitor
|
||||
*/
|
||||
private void copyPanes(IProgressMonitor monitor) {
|
||||
// Keep this code as fast as possible, if the user runs kml export in
|
||||
// the background and modifies the main display it will affect kml if
|
||||
// copy is not done.
|
||||
List<KmlPane> panes = options.getPanes();
|
||||
monitor.beginTask("Copying Displays", panes.size());
|
||||
Iterator<KmlPane> paneIt = panes.iterator();
|
||||
while (paneIt.hasNext()) {
|
||||
KmlPane pane = paneIt.next();
|
||||
List<ResourcePair> exports = pane.getResourcesToExport();
|
||||
if (exports == null || exports.isEmpty()) {
|
||||
paneIt.remove();
|
||||
} else {
|
||||
try {
|
||||
AbstractRenderableDisplay display = pane.getDisplay();
|
||||
// copy the current time before clone
|
||||
FramesInfo fi = display.getDescriptor().getFramesInfo();
|
||||
if (fi.getFrameTimes() != null) {
|
||||
int index = fi.getFrameIndex();
|
||||
if (index > options.getFirstFrameIndex()
|
||||
&& index < options.getLastFrameIndex()) {
|
||||
pane.setDisplayedTime(fi.getFrameTimes()[fi
|
||||
.getFrameIndex()]);
|
||||
}
|
||||
}
|
||||
display = display.cloneDisplay();
|
||||
pane.setDisplay(display);
|
||||
KmlGraphicsFactoryAdapter graphicsAdapter = new KmlGraphicsFactoryAdapter(
|
||||
display.getView().getExtent(), pane.getBounds());
|
||||
display.setGraphicsAdapter(graphicsAdapter);
|
||||
KmlGraphicsTarget target = graphicsAdapter.constructTarget(
|
||||
null, 0.0f, 0.0f);
|
||||
target.setBackgroundColor(display.getBackgroundColor());
|
||||
display.setup(target);
|
||||
pane.setTarget(target);
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
paneIt.remove();
|
||||
}
|
||||
}
|
||||
monitor.worked(1);
|
||||
}
|
||||
monitor.done();
|
||||
}
|
||||
|
||||
private void initPanes(IProgressMonitor monitor) {
|
||||
List<KmlPane> panes = options.getPanes();
|
||||
monitor.beginTask("Initializing Displays", panes.size());
|
||||
Iterator<KmlPane> paneIt = panes.iterator();
|
||||
while (paneIt.hasNext()) {
|
||||
KmlPane pane = paneIt.next();
|
||||
try {
|
||||
AbstractRenderableDisplay display = pane.getDisplay();
|
||||
|
||||
IDescriptor descriptor = display.getDescriptor();
|
||||
descriptor.setRenderableDisplay(display);
|
||||
descriptor.getResourceList().instantiateResources(descriptor,
|
||||
true);
|
||||
for (ResourcePair rp : descriptor.getResourceList()) {
|
||||
rp.getResource().init(pane.getTarget());
|
||||
monitor.worked(1);
|
||||
}
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
|
||||
e);
|
||||
paneIt.remove();
|
||||
}
|
||||
monitor.worked(1);
|
||||
}
|
||||
monitor.done();
|
||||
}
|
||||
|
||||
private void exportPanes(IProgressMonitor monitor, KmlOutputManager out)
|
||||
throws IOException {
|
||||
List<KmlPane> panes = options.getPanes();
|
||||
SubMonitor smonitor = SubMonitor.convert(monitor, "Exporting Displays",
|
||||
panes.size() * 100);
|
||||
int paneNumber = 1;
|
||||
for (KmlPane pane : options.getPanes()) {
|
||||
KmlOutputManager displayOut = out;
|
||||
if (!options.isSinglePane()) {
|
||||
displayOut = out.createFolder("Pane " + (paneNumber++));
|
||||
}
|
||||
AbstractRenderableDisplay display = pane.getDisplay();
|
||||
setView(pane, displayOut);
|
||||
if (options.isShadeEarth()) {
|
||||
shadeEarth(displayOut, display.getBackgroundColor());
|
||||
}
|
||||
IDescriptor descriptor = display.getDescriptor();
|
||||
List<ResourcePair> exports = new ArrayList<ResourcePair>();
|
||||
for (ResourcePair rp : descriptor.getResourceList()) {
|
||||
if (pane.getResourcesToExport().contains(rp)) {
|
||||
exports.add(rp);
|
||||
} else {
|
||||
rp.getProperties().setVisible(false);
|
||||
}
|
||||
}
|
||||
exportResources(smonitor.newChild(100, SubMonitor.SUPPRESS_NONE),
|
||||
displayOut, exports, pane);
|
||||
if (smonitor.isCanceled()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
smonitor.done();
|
||||
}
|
||||
|
||||
private void exportResources(IProgressMonitor monitor,
|
||||
KmlOutputManager out, List<ResourcePair> exports, KmlPane pane)
|
||||
throws IOException {
|
||||
SubMonitor smonitor = SubMonitor.convert(monitor, "Exporting Products",
|
||||
exports.size() * 100);
|
||||
KmlGraphicsTarget target = pane.getTarget();
|
||||
AbstractRenderableDisplay display = pane.getDisplay();
|
||||
IDescriptor descriptor = display.getDescriptor();
|
||||
List<Boolean> visibility = new ArrayList<Boolean>();
|
||||
for (ResourcePair rp : exports) {
|
||||
visibility.add(rp.getProperties().isVisible());
|
||||
rp.getProperties().setVisible(false);
|
||||
}
|
||||
for (int c = 0; c < exports.size(); c++) {
|
||||
ResourcePair rp = exports.get(c);
|
||||
AbstractVizResource<?, ?> rsc = rp.getResource();
|
||||
rp.getProperties().setVisible(true);
|
||||
String name = rp.getResource().getName();
|
||||
if (name == null) {
|
||||
name = rp.getResource().getClass().getSimpleName();
|
||||
}
|
||||
KmlOutputManager resourceOut = out.createFolder(name.trim());
|
||||
SubMonitor rscmonitor = smonitor.newChild(100,
|
||||
SubMonitor.SUPPRESS_NONE);
|
||||
if (rsc.hasCapability(BlendableCapability.class)) {
|
||||
ResourceList list = rsc
|
||||
.getCapability(BlendableCapability.class)
|
||||
.getResourceList();
|
||||
exportResources(rscmonitor, resourceOut, list, pane);
|
||||
} else {
|
||||
int startIndex = options.getFirstFrameIndex();
|
||||
startIndex = Math.max(startIndex, 0);
|
||||
int lastIndex = options.getLastFrameIndex();
|
||||
lastIndex = Math.min(lastIndex, descriptor.getNumberOfFrames());
|
||||
rscmonitor.beginTask("Saving " + rsc.getName(), lastIndex
|
||||
- startIndex);
|
||||
addColorMap(resourceOut, display.getBackgroundColor(), rsc);
|
||||
DataTime[] times = descriptor.getFramesInfo().getTimeMap()
|
||||
.get(rsc);
|
||||
if ((times == null || times.length == 0)
|
||||
&& rsc instanceof IResourceGroup) {
|
||||
ResourceList list = ((IResourceGroup) rsc)
|
||||
.getResourceList();
|
||||
for (ResourcePair pair : list) {
|
||||
times = descriptor.getFramesInfo().getTimeMap()
|
||||
.get(pair.getResource());
|
||||
if (times != null && times.length > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
List<DataTime> pastFrames = new ArrayList<DataTime>();
|
||||
for (int i = startIndex; i < lastIndex; i += 1) {
|
||||
descriptor.setFramesInfo(new FramesInfo(i));
|
||||
KmlOutputManager timeOut = resourceOut;
|
||||
if (rsc.isTimeAgnostic()
|
||||
&& (times == null || times.length == 0)) {
|
||||
i = lastIndex - 1;
|
||||
} else {
|
||||
if (i < 0 || times == null || i >= times.length) {
|
||||
rscmonitor.worked(1);
|
||||
continue;
|
||||
}
|
||||
DataTime time = times[i];
|
||||
if (time == null || pastFrames.contains(time)) {
|
||||
rscmonitor.worked(1);
|
||||
continue;
|
||||
}
|
||||
timeOut = resourceOut.createFolder(time
|
||||
.getLegendString());
|
||||
timeOut.getContainer().setTimePrimitive(
|
||||
getTimePrimitive(times, i));
|
||||
pastFrames.add(time);
|
||||
}
|
||||
PaintProperties paintProps = new PaintProperties(1.0f,
|
||||
(float) display.getZoom(), display.getView(),
|
||||
pane.getBounds(), false, descriptor.getFramesInfo());
|
||||
paintResource(rscmonitor, timeOut, display, target, rsc,
|
||||
paintProps);
|
||||
rscmonitor.worked(1);
|
||||
if (rscmonitor.isCanceled()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
rp.getProperties().setVisible(false);
|
||||
if (options.isPreserveVisibility() && !visibility.get(c)) {
|
||||
resourceOut.getContainer().setVisibility(false);
|
||||
}
|
||||
rscmonitor.done();
|
||||
}
|
||||
}
|
||||
|
||||
private void setView(KmlPane pane, KmlOutputManager out) {
|
||||
IExtent extent = pane.getDisplay().getView().getExtent();
|
||||
try {
|
||||
DirectPosition2D center = new DirectPosition2D(
|
||||
extent.getCenter()[0], extent.getCenter()[1]);
|
||||
DirectPosition2D corner = new DirectPosition2D(extent.getMaxX(),
|
||||
extent.getMinX());
|
||||
MathTransform gridToLatLon = TransformFactory.gridToLatLon(pane
|
||||
.getDisplay().getDescriptor().getGridGeometry(),
|
||||
PixelInCell.CELL_CENTER);
|
||||
gridToLatLon.transform(center, center);
|
||||
gridToLatLon.transform(corner, corner);
|
||||
|
||||
GeodeticCalculator gc = new GeodeticCalculator();
|
||||
gc.setStartingGeographicPoint(MapUtil.correctLon(center.x),
|
||||
center.y);
|
||||
gc.setDestinationGeographicPoint(MapUtil.correctLon(corner.x),
|
||||
corner.y);
|
||||
LookAt lookAt = out.getContainer().createAndSetLookAt();
|
||||
lookAt.setLongitude(center.x);
|
||||
lookAt.setLatitude(center.y);
|
||||
lookAt.setRange(gc.getOrthodromicDistance());
|
||||
if (pane.getDisplayedTime() != null) {
|
||||
DataTime time = pane.getDisplayedTime();
|
||||
TimeStamp ts = new TimeStamp();
|
||||
ts.setWhen(KML_TIME_FORMAT.format(new Date(time.getMatchValid())));
|
||||
// At the time of this writing the current api doesn't allow
|
||||
// setting time primitive for AbstractView
|
||||
lookAt.setAbstractViewObjectExtension(Arrays
|
||||
.asList((AbstractObject) ts));
|
||||
}
|
||||
} catch (TransformException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e);
|
||||
} catch (FactoryException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list of times for a resource and the index of the current time,
|
||||
* generate a KML TimePrimitive for a resource. When the time mode is SPAN
|
||||
* the times in the array are used to calculate a span such that the spans
|
||||
* for every time create a continuos time line.
|
||||
*
|
||||
* @param times
|
||||
* @param index
|
||||
* @return
|
||||
*/
|
||||
private TimePrimitive getTimePrimitive(DataTime[] times, int index) {
|
||||
long validTime = times[index].getMatchValid();
|
||||
switch (options.getTimeMode()) {
|
||||
case TIME_STAMP: {
|
||||
TimeStamp ts = new TimeStamp();
|
||||
ts.setWhen(KML_TIME_FORMAT.format(new Date(validTime)));
|
||||
return ts;
|
||||
}
|
||||
case TIME_SPAN: {
|
||||
long prevValid = 0;
|
||||
long nextValid = 0;
|
||||
for (DataTime t : times) {
|
||||
if (t == null) {
|
||||
continue;
|
||||
}
|
||||
long valid = t.getMatchValid();
|
||||
if (valid < validTime) {
|
||||
if (prevValid == 0 || prevValid < valid) {
|
||||
prevValid = valid;
|
||||
}
|
||||
} else if (valid > validTime) {
|
||||
if (nextValid == 0 || nextValid > valid) {
|
||||
nextValid = valid;
|
||||
}
|
||||
}
|
||||
}
|
||||
long prevDist = 0;
|
||||
long nextDist = 0;
|
||||
if (prevValid != 0) {
|
||||
nextDist = prevDist = (validTime - prevValid) / 2;
|
||||
}
|
||||
if (nextValid != 0) {
|
||||
nextDist = (nextValid - validTime) / 2;
|
||||
if (prevDist == 0) {
|
||||
prevDist = nextDist;
|
||||
}
|
||||
}
|
||||
TimeSpan span = new TimeSpan();
|
||||
span.setBegin(KML_TIME_FORMAT
|
||||
.format(new Date(validTime - prevDist)));
|
||||
span.setEnd(KML_TIME_FORMAT.format(new Date(validTime + nextDist)));
|
||||
return span;
|
||||
}
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* KML reference documentation from google clearly states that a feature is
|
||||
* visible only if all of it's ancestors are also visible. Google
|
||||
* Earth(tested on version 6.2) ignores this and displays everything as
|
||||
* visible unless that item is specifically set to invisible even when
|
||||
* ancestors are invisible. This function makes google earth work properly
|
||||
* by finding invisible features and making all their children invisible.
|
||||
*
|
||||
* @param feature
|
||||
* @param parentVisibility
|
||||
*/
|
||||
private void recursiveInvisibility(Feature feature, boolean parentVisibility) {
|
||||
if (!parentVisibility) {
|
||||
feature.setVisibility(false);
|
||||
}
|
||||
List<Feature> features = null;
|
||||
if (feature instanceof Folder) {
|
||||
features = ((Folder) feature).getFeature();
|
||||
} else if (feature instanceof Document) {
|
||||
features = ((Document) feature).getFeature();
|
||||
}
|
||||
if (features == null) {
|
||||
return;
|
||||
}
|
||||
for (Feature f : features) {
|
||||
if (f == null) {
|
||||
continue;
|
||||
}
|
||||
recursiveInvisibility(f,
|
||||
!Boolean.FALSE.equals(feature.isVisibility()));
|
||||
}
|
||||
}
|
||||
|
||||
private void paintResource(IProgressMonitor monitor, KmlOutputManager out,
|
||||
AbstractRenderableDisplay display, KmlGraphicsTarget target,
|
||||
AbstractVizResource<?, ?> resource, PaintProperties paintProps) {
|
||||
target.setNeedsRefresh(true);
|
||||
long startTime = System.currentTimeMillis();
|
||||
while (target.isNeedsRefresh()
|
||||
|| resource.getPaintStatus() != PaintStatus.PAINTED) {
|
||||
if (target.isNeedsRefresh()) {
|
||||
target.beginFrame(paintProps.getView(), false);
|
||||
try {
|
||||
display.paint(target, paintProps);
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
return;
|
||||
}
|
||||
target.endFrame();
|
||||
}
|
||||
if (System.currentTimeMillis() - startTime > options
|
||||
.getMaxRefreshSeconds() * 1000) {
|
||||
statusHandler.handle(Priority.PROBLEM, resource.getName()
|
||||
+ " took more than " + options.getMaxRefreshSeconds()
|
||||
+ " seconds to paint, KML may be incomplete.");
|
||||
break;
|
||||
}
|
||||
try {
|
||||
Thread.sleep(options.getPaintSleepMillis());
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
if (monitor.isCanceled()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
List<KmlFeatureGenerator> generators = new ArrayList<KmlFeatureGenerator>(
|
||||
target.getGenerators());
|
||||
for (KmlFeatureGenerator generator : generators) {
|
||||
generator
|
||||
.setGridGeometry(display.getDescriptor().getGridGeometry());
|
||||
generator.setBackgroundColor(display.getBackgroundColor());
|
||||
generator.setOptions(options);
|
||||
}
|
||||
backgroundPool.schedule(new GenerateRunnable(generators, out));
|
||||
}
|
||||
|
||||
private void addColorMap(KmlOutputManager out, RGB backcolor,
|
||||
AbstractVizResource<?, ?> rsc) throws IOException {
|
||||
ColorMapParameters parameters = null;
|
||||
if (rsc.hasCapability(ColorMapCapability.class)) {
|
||||
ColorMapCapability cap = rsc
|
||||
.getCapability(ColorMapCapability.class);
|
||||
parameters = cap.getColorMapParameters();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
double xAnchor = 0;
|
||||
if (rsc.hasCapability(BlendedCapability.class)) {
|
||||
BlendedCapability cap = rsc.getCapability(BlendedCapability.class);
|
||||
xAnchor = Math.min(1, cap.getResourceIndex());
|
||||
}
|
||||
IColorMap colorMap = parameters.getColorMap();
|
||||
BufferedImage bi = new BufferedImage(colorMap.getSize() * 2, 25,
|
||||
BufferedImage.TYPE_INT_RGB);
|
||||
Graphics graphics = bi.getGraphics();
|
||||
graphics.setColor(new java.awt.Color(backcolor.red, backcolor.green,
|
||||
backcolor.blue));
|
||||
graphics.fillRect(0, 0, bi.getWidth(), 25);
|
||||
int x = 0;
|
||||
for (Color color : colorMap.getColors()) {
|
||||
graphics.setColor(new java.awt.Color(color.getRed(), color
|
||||
.getGreen(), color.getBlue(), color.getAlpha()));
|
||||
graphics.drawLine(x, 0, x, 25);
|
||||
x += 1;
|
||||
graphics.drawLine(x, 0, x, 25);
|
||||
x += 1;
|
||||
}
|
||||
for (LabelEntry label : parameters.getLabels()) {
|
||||
if (label.getText().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
Rectangle2D bounds = graphics.getFontMetrics().getStringBounds(
|
||||
label.getText(), graphics);
|
||||
int centerX = (int) (bi.getWidth() * label.getLocation());
|
||||
int leftX = (int) (centerX - bounds.getWidth() / 2);
|
||||
if (leftX < 0) {
|
||||
leftX = 0;
|
||||
} else if (leftX + bounds.getWidth() > bi.getWidth()) {
|
||||
leftX = (int) (bi.getWidth() - bounds.getWidth());
|
||||
}
|
||||
graphics.setColor(java.awt.Color.BLACK);
|
||||
graphics.fillRect(leftX - 1, 2, (int) bounds.getWidth() + 2,
|
||||
(int) bounds.getHeight() + 2);
|
||||
graphics.setColor(java.awt.Color.WHITE);
|
||||
graphics.drawString(label.getText(), leftX,
|
||||
(int) bounds.getHeight() + 1);
|
||||
}
|
||||
graphics.dispose();
|
||||
ScreenOverlay overlay = new ScreenOverlay();
|
||||
overlay.setName("ColorMap");
|
||||
Vec2 overlayxy = overlay.createAndSetOverlayXY();
|
||||
overlayxy.withX(xAnchor).withXunits(Units.FRACTION);
|
||||
overlayxy.withY(1).withYunits(Units.FRACTION);
|
||||
Vec2 screenxy = overlay.createAndSetScreenXY();
|
||||
screenxy.withX(xAnchor).withXunits(Units.FRACTION);
|
||||
screenxy.withY(1).withYunits(Units.FRACTION);
|
||||
overlay.createAndSetIcon().setHref(
|
||||
out.addImage(bi, "colormap" + xAnchor + ".png"));
|
||||
out.addFeature(overlay);
|
||||
}
|
||||
|
||||
private void shadeEarth(KmlOutputManager out, RGB color) {
|
||||
Placemark placemark = new Placemark();
|
||||
placemark.setName("Background Color");
|
||||
Style style = new Style();
|
||||
style.createAndSetIconStyle().setScale(0.0);
|
||||
PolyStyle polyStyle = style.createAndSetPolyStyle();
|
||||
polyStyle.setFill(true);
|
||||
polyStyle.setOutline(false);
|
||||
polyStyle.setColor(KmlFeatureGenerator.toColorStr(1.0, color));
|
||||
placemark.setStyleUrl(out.getStyleUrl(style));
|
||||
// Google earth seems to do a weird things with one big polygon when you
|
||||
// zoom way out, specifically there is lots of flickering and it misses
|
||||
// big pieces towards the back of the sphere, lots of smaller polygons
|
||||
// helps avoid the missing hunks but I still see a lot of flickering.
|
||||
MultiGeometry multi = placemark.createAndSetMultiGeometry();
|
||||
for (int i = -180; i < 180; i += 10) {
|
||||
for (int j = -90; j < 90; j += 10) {
|
||||
LinearRing ring = multi.createAndAddPolygon()
|
||||
.createAndSetOuterBoundaryIs().createAndSetLinearRing();
|
||||
ring.addToCoordinates(i, j);
|
||||
ring.addToCoordinates(i, j + 10);
|
||||
ring.addToCoordinates(i + 10, j + 10);
|
||||
ring.addToCoordinates(i + 10, j);
|
||||
ring.addToCoordinates(i, j);
|
||||
}
|
||||
|
||||
}
|
||||
out.addFeature(placemark);
|
||||
}
|
||||
|
||||
private void joinBackground(IProgressMonitor monitor) {
|
||||
// some tasks(like radar mosaic) can take a very long time to finish the
|
||||
// background task, so this waits for those to finish and makes an
|
||||
// attempt to let the user know how it is going.
|
||||
int remaining = backgroundPool.getWorkRemaining();
|
||||
monitor.beginTask("Finalizing KML", remaining);
|
||||
while (remaining > 0) {
|
||||
try {
|
||||
Thread.sleep(300);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
int r = backgroundPool.getWorkRemaining();
|
||||
monitor.worked(remaining - r);
|
||||
remaining = r;
|
||||
if (monitor.isCanceled()) {
|
||||
monitor.subTask("Canceling");
|
||||
backgroundPool.cancel();
|
||||
break;
|
||||
}
|
||||
}
|
||||
backgroundPool.join();
|
||||
}
|
||||
|
||||
private static class GenerateRunnable implements Runnable {
|
||||
|
||||
private final List<KmlFeatureGenerator> generators;
|
||||
|
||||
private final KmlOutputManager outputManager;
|
||||
|
||||
public GenerateRunnable(List<KmlFeatureGenerator> generators,
|
||||
KmlOutputManager outputManager) {
|
||||
this.generators = generators;
|
||||
this.outputManager = outputManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (KmlFeatureGenerator generator : generators) {
|
||||
generator.addFeature(outputManager);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
/**
|
||||
* 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.viz.kml.export;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Contains any options which can be configured for KML export.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 4, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class KmlExportOptions {
|
||||
|
||||
public enum KmlExportTimeMode {
|
||||
NONE, TIME_STAMP, TIME_SPAN;
|
||||
}
|
||||
|
||||
private File kmzFileLocation;
|
||||
|
||||
private int firstFrameIndex;
|
||||
|
||||
private int lastFrameIndex;
|
||||
|
||||
private boolean shadeEarth;
|
||||
|
||||
// Google Earth requires a fairly large plot scale to make plots look nice
|
||||
// but World Wind prefers a smaller scale.
|
||||
private double plotIconScale;
|
||||
|
||||
private boolean fillPlotBackground;
|
||||
|
||||
private boolean preserveVisibility;
|
||||
|
||||
private KmlExportTimeMode timeMode;
|
||||
|
||||
private List<KmlPane> panes;
|
||||
|
||||
private int paintSleepMillis;
|
||||
|
||||
private int maxRefreshSeconds;
|
||||
|
||||
public File getKmzFileLocation() {
|
||||
return kmzFileLocation;
|
||||
}
|
||||
|
||||
public void setKmzFileLocation(File kmzFileLocation) {
|
||||
this.kmzFileLocation = kmzFileLocation;
|
||||
}
|
||||
|
||||
public int getFirstFrameIndex() {
|
||||
return firstFrameIndex;
|
||||
}
|
||||
|
||||
public void setFirstFrameIndex(int firstFrameIndex) {
|
||||
this.firstFrameIndex = firstFrameIndex;
|
||||
}
|
||||
|
||||
public int getLastFrameIndex() {
|
||||
return lastFrameIndex;
|
||||
}
|
||||
|
||||
public void setLastFrameIndex(int lastFrameIndex) {
|
||||
this.lastFrameIndex = lastFrameIndex;
|
||||
}
|
||||
|
||||
public boolean isShadeEarth() {
|
||||
return shadeEarth;
|
||||
}
|
||||
|
||||
public void setShadeEarth(boolean shadeEarth) {
|
||||
this.shadeEarth = shadeEarth;
|
||||
}
|
||||
|
||||
public boolean isFillPlotBackground() {
|
||||
return fillPlotBackground;
|
||||
}
|
||||
|
||||
public void setFillPlotBackground(boolean fillPlotBackground) {
|
||||
this.fillPlotBackground = fillPlotBackground;
|
||||
}
|
||||
|
||||
public boolean isPreserveVisibility() {
|
||||
return preserveVisibility;
|
||||
}
|
||||
|
||||
public void setPreserveVisibility(boolean preserveVisibility) {
|
||||
this.preserveVisibility = preserveVisibility;
|
||||
}
|
||||
|
||||
public KmlExportTimeMode getTimeMode() {
|
||||
return timeMode;
|
||||
}
|
||||
|
||||
public void setTimeMode(KmlExportTimeMode timeMode) {
|
||||
this.timeMode = timeMode;
|
||||
}
|
||||
|
||||
public List<KmlPane> getPanes() {
|
||||
return panes;
|
||||
}
|
||||
|
||||
public void setPanes(List<KmlPane> panes) {
|
||||
this.panes = panes;
|
||||
}
|
||||
|
||||
public boolean isSinglePane() {
|
||||
return panes != null && panes.size() == 1;
|
||||
}
|
||||
|
||||
public KmlPane getSinglPane() {
|
||||
if (isSinglePane()) {
|
||||
return panes.get(0);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public int getPaintSleepMillis() {
|
||||
return paintSleepMillis;
|
||||
}
|
||||
|
||||
public void setPaintSleepMillis(int paintSleepMillis) {
|
||||
this.paintSleepMillis = paintSleepMillis;
|
||||
}
|
||||
|
||||
public int getMaxRefreshSeconds() {
|
||||
return maxRefreshSeconds;
|
||||
}
|
||||
|
||||
public void setMaxRefreshSeconds(int maxRefreshSeconds) {
|
||||
this.maxRefreshSeconds = maxRefreshSeconds;
|
||||
}
|
||||
|
||||
public double getPlotIconScale() {
|
||||
return plotIconScale;
|
||||
}
|
||||
|
||||
public void setPlotIconScale(double plotIconScale) {
|
||||
this.plotIconScale = plotIconScale;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/**
|
||||
* 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.viz.kml.export;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
import org.geotools.coverage.grid.GeneralGridGeometry;
|
||||
import org.geotools.coverage.grid.GridGeometry2D;
|
||||
import org.opengis.referencing.FactoryException;
|
||||
import org.opengis.referencing.datum.PixelInCell;
|
||||
import org.opengis.referencing.operation.MathTransform;
|
||||
import org.opengis.referencing.operation.TransformException;
|
||||
|
||||
import com.raytheon.uf.common.geospatial.TransformFactory;
|
||||
import com.raytheon.uf.viz.kml.export.io.KmlOutputManager;
|
||||
|
||||
import de.micromata.opengis.kml.v_2_2_0.Coordinate;
|
||||
|
||||
/**
|
||||
* Anything that can be drawn on the screen can also be used to create a KML
|
||||
* feature, this class provides some basic utility functions as well as an
|
||||
* interface for classes that generate KML.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 14, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public abstract class KmlFeatureGenerator {
|
||||
|
||||
protected GridGeometry2D gridGeometry;
|
||||
|
||||
protected MathTransform gridToLatLon;
|
||||
|
||||
protected RGB backgroundColor;
|
||||
|
||||
protected KmlExportOptions options;
|
||||
|
||||
public void setGridGeometry(GeneralGridGeometry gridGeometry) {
|
||||
this.gridGeometry = GridGeometry2D.wrap(gridGeometry);
|
||||
}
|
||||
|
||||
public void setBackgroundColor(RGB backgroundColor) {
|
||||
this.backgroundColor = backgroundColor;
|
||||
}
|
||||
|
||||
public void setOptions(KmlExportOptions options) {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public Coordinate transformToLatLon(double gridX, double gridY)
|
||||
throws TransformException, FactoryException {
|
||||
return transformToLatLon(new double[] { gridX, gridY });
|
||||
}
|
||||
|
||||
public Coordinate transformToLatLon(double[] gridPixel)
|
||||
throws TransformException, FactoryException {
|
||||
if (gridToLatLon == null) {
|
||||
gridToLatLon = TransformFactory.gridToLatLon(gridGeometry,
|
||||
PixelInCell.CELL_CENTER);
|
||||
}
|
||||
double[] out = new double[2];
|
||||
gridToLatLon.transform(gridPixel, 0, out, 0, 1);
|
||||
return new Coordinate(out[0], out[1]);
|
||||
}
|
||||
|
||||
public List<Coordinate> transformToLatLon(List<double[]> gridPixels)
|
||||
throws TransformException, FactoryException {
|
||||
List<Coordinate> result = new ArrayList<Coordinate>();
|
||||
for (double[] gridPixel : gridPixels) {
|
||||
result.add(transformToLatLon(gridPixel));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public abstract void addFeature(KmlOutputManager outputManager);
|
||||
|
||||
public static String toColorStr(double alpha, RGB rgb) {
|
||||
return String.format("%02x%02x%02x%02x", (int) (alpha * 255), rgb.blue,
|
||||
rgb.green, rgb.red);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
/**
|
||||
* 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.viz.kml.export;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.swt.graphics.Rectangle;
|
||||
|
||||
import com.raytheon.uf.common.time.DataTime;
|
||||
import com.raytheon.uf.viz.core.drawables.AbstractRenderableDisplay;
|
||||
import com.raytheon.uf.viz.core.drawables.ResourcePair;
|
||||
import com.raytheon.uf.viz.kml.export.graphics.KmlGraphicsTarget;
|
||||
|
||||
/**
|
||||
* VizDisplayPane but for KML!
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 5, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class KmlPane {
|
||||
|
||||
private List<ResourcePair> resourcesToExport;
|
||||
|
||||
private AbstractRenderableDisplay display;
|
||||
|
||||
private Rectangle bounds;
|
||||
|
||||
private KmlGraphicsTarget target;
|
||||
|
||||
private DataTime displayedTime;
|
||||
|
||||
public KmlPane(AbstractRenderableDisplay display, Rectangle bounds) {
|
||||
this.display = display;
|
||||
this.bounds = bounds;
|
||||
}
|
||||
|
||||
public List<ResourcePair> getResources(boolean includeMaps,
|
||||
boolean includeHidden) {
|
||||
List<ResourcePair> rscList = new ArrayList<ResourcePair>();
|
||||
for (ResourcePair rp : display.getDescriptor().getResourceList()) {
|
||||
if (!rp.getResourceData().equals(rp.getResourceData())) {
|
||||
// A special check for those special resources which will never
|
||||
// work with KML because they don't properly implement equals.
|
||||
// ... like GFE
|
||||
continue;
|
||||
} else if (rp.getProperties().isSystemResource()) {
|
||||
continue;
|
||||
} else if (!includeMaps && rp.getProperties().isMapLayer()) {
|
||||
continue;
|
||||
} else if (!includeHidden && !rp.getProperties().isVisible()) {
|
||||
continue;
|
||||
}
|
||||
rscList.add(rp);
|
||||
}
|
||||
return rscList;
|
||||
}
|
||||
|
||||
public void setDisplay(AbstractRenderableDisplay display) {
|
||||
this.display = display;
|
||||
}
|
||||
|
||||
public void setTarget(KmlGraphicsTarget target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public List<ResourcePair> getResourcesToExport() {
|
||||
return resourcesToExport;
|
||||
}
|
||||
|
||||
public void setResourcesToExport(List<ResourcePair> resourcesToExport) {
|
||||
this.resourcesToExport = resourcesToExport;
|
||||
}
|
||||
|
||||
public AbstractRenderableDisplay getDisplay() {
|
||||
return display;
|
||||
}
|
||||
|
||||
public Rectangle getBounds() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
public KmlGraphicsTarget getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
public DataTime getDisplayedTime() {
|
||||
return displayedTime;
|
||||
}
|
||||
|
||||
public void setDisplayedTime(DataTime displayedTime) {
|
||||
this.displayedTime = displayedTime;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,185 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.FontFormatException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.raytheon.uf.viz.core.drawables.IFont;
|
||||
|
||||
/**
|
||||
*
|
||||
* KML has really bad font support so only support the minimum operations
|
||||
* required to avoid errors.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 1, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
public class KmlFont implements IFont {
|
||||
|
||||
private Font font;
|
||||
|
||||
private float magnification;
|
||||
|
||||
private boolean scaleFont;
|
||||
|
||||
private boolean smoothing;
|
||||
|
||||
public KmlFont(Font font) {
|
||||
this.font = font;
|
||||
this.magnification = 1.0f;
|
||||
}
|
||||
|
||||
public KmlFont() {
|
||||
this(new Font(java.awt.Font.MONOSPACED, Font.BOLD, 14));
|
||||
}
|
||||
|
||||
public KmlFont(String fontName) {
|
||||
this(new Font(fontName, Font.PLAIN, 10));
|
||||
|
||||
}
|
||||
|
||||
public KmlFont(String fontName, float fontSize) {
|
||||
this(new Font(fontName, Font.PLAIN, (int) fontSize));
|
||||
}
|
||||
|
||||
public KmlFont(String fontName, float fontSize, Style[] styles) {
|
||||
this(new Font(fontName, toAwtStyle(styles), (int) fontSize));
|
||||
}
|
||||
|
||||
public KmlFont(File fontFile, float fontSize, Style[] styles)
|
||||
throws FontFormatException, IOException {
|
||||
this(Font.createFont(Font.TRUETYPE_FONT, fontFile).deriveFont(fontSize)
|
||||
.deriveFont(toAwtStyle(styles)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFontName() {
|
||||
return this.font.getFontName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFontSize() {
|
||||
return this.font.getSize2D();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Style[] getStyle() {
|
||||
return toVizStyles(font.getStyle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public IFont deriveWithSize(float size) {
|
||||
return new KmlFont(font.deriveFont(size));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMagnification(float magnification) {
|
||||
setMagnification(magnification, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMagnification(float magnification, boolean scaleFont) {
|
||||
if (scaleFont) {
|
||||
this.font = font.deriveFont(font.getSize2D() * magnification);
|
||||
} else {
|
||||
this.magnification = magnification;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMagnification() {
|
||||
return magnification;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSmoothing(boolean smooth) {
|
||||
this.smoothing = smooth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getSmoothing() {
|
||||
return smoothing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isScaleFont() {
|
||||
return scaleFont;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScaleFont(boolean scaleFont) {
|
||||
this.scaleFont = scaleFont;
|
||||
}
|
||||
|
||||
public Font getFont() {
|
||||
return font;
|
||||
}
|
||||
|
||||
public void setFont(Font font) {
|
||||
this.font = font;
|
||||
}
|
||||
|
||||
private static int toAwtStyle(Style[] styles) {
|
||||
int styleInt = Font.PLAIN;
|
||||
if (styles == null || styles.length == 0) {
|
||||
return styleInt;
|
||||
}
|
||||
for (Style style : styles) {
|
||||
if (style == Style.BOLD) {
|
||||
styleInt |= Font.BOLD;
|
||||
} else if (style == Style.ITALIC) {
|
||||
styleInt |= Font.ITALIC;
|
||||
}
|
||||
}
|
||||
return styleInt;
|
||||
}
|
||||
|
||||
private static Style[] toVizStyles(int style) {
|
||||
List<Style> styles = new ArrayList<Style>();
|
||||
if ((style & Font.BOLD) != 0) {
|
||||
styles.add(Style.BOLD);
|
||||
}
|
||||
if ((style & Font.ITALIC) != 0) {
|
||||
styles.add(Style.ITALIC);
|
||||
}
|
||||
return styles.toArray(new Style[0]);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics;
|
||||
|
||||
import org.eclipse.swt.graphics.Rectangle;
|
||||
import org.eclipse.swt.widgets.Canvas;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.opengis.coverage.grid.GridEnvelope;
|
||||
|
||||
import com.raytheon.uf.viz.core.AbstractGraphicsFactoryAdapter;
|
||||
import com.raytheon.uf.viz.core.IExtent;
|
||||
import com.raytheon.uf.viz.core.PixelExtent;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
|
||||
/**
|
||||
*
|
||||
* Not very interesting, just constructs KML things
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 1, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
public class KmlGraphicsFactoryAdapter extends AbstractGraphicsFactoryAdapter {
|
||||
|
||||
// The view needs to know the extent and canvas bounds from the source pane.
|
||||
private final IExtent extent;
|
||||
|
||||
private final Rectangle canvasBounds;
|
||||
|
||||
public KmlGraphicsFactoryAdapter(IExtent extent, Rectangle canvasBounds) {
|
||||
this.extent = extent;
|
||||
this.canvasBounds = canvasBounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KmlView constructView() {
|
||||
return new KmlView(extent, canvasBounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KmlGraphicsTarget constructTarget(Canvas canvas, float width,
|
||||
float height) throws VizException {
|
||||
return new KmlGraphicsTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IExtent constructExtent(Coordinate[] coords) throws VizException {
|
||||
return new PixelExtent(coords);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IExtent constructExtent(double aMinX, double aMaxX, double aMinY,
|
||||
double aMaxY) throws VizException {
|
||||
return new PixelExtent(aMinX, aMaxX, aMinY, aMaxY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IExtent constructExtent(Rectangle rect) throws VizException {
|
||||
return new PixelExtent(rect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IExtent constructExtent(GridEnvelope range) throws VizException {
|
||||
return new PixelExtent(range);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Canvas constrcutCanvas(Composite canvasComp) throws VizException {
|
||||
// Its possible we should just return null and not worry so much
|
||||
throw new UnsupportedOperationException(
|
||||
"KmlGraphicsFactoryAdapter does not support creating a canvas");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,333 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics;
|
||||
|
||||
import java.awt.FontFormatException;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jface.resource.FontRegistry;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.graphics.FontData;
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
import org.eclipse.ui.PlatformUI;
|
||||
import org.geotools.coverage.grid.GeneralGridGeometry;
|
||||
|
||||
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.viz.core.AbstractGraphicsTarget;
|
||||
import com.raytheon.uf.viz.core.DrawableCircle;
|
||||
import com.raytheon.uf.viz.core.DrawableColorMap;
|
||||
import com.raytheon.uf.viz.core.DrawableLine;
|
||||
import com.raytheon.uf.viz.core.DrawableString;
|
||||
import com.raytheon.uf.viz.core.IExtent;
|
||||
import com.raytheon.uf.viz.core.IView;
|
||||
import com.raytheon.uf.viz.core.data.IRenderedImageCallback;
|
||||
import com.raytheon.uf.viz.core.drawables.IFont;
|
||||
import com.raytheon.uf.viz.core.drawables.IFont.Style;
|
||||
import com.raytheon.uf.viz.core.drawables.IImage;
|
||||
import com.raytheon.uf.viz.core.drawables.IShadedShape;
|
||||
import com.raytheon.uf.viz.core.drawables.IWireframeShape;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.kml.export.KmlFeatureGenerator;
|
||||
import com.raytheon.uf.viz.kml.export.graphics.basicgen.KmlCirclesGenerator;
|
||||
import com.raytheon.uf.viz.kml.export.graphics.basicgen.KmlLinesGenerator;
|
||||
import com.raytheon.uf.viz.kml.export.graphics.basicgen.KmlPointsGenerator;
|
||||
import com.raytheon.uf.viz.kml.export.graphics.basicgen.KmlRectGenerator;
|
||||
import com.raytheon.uf.viz.kml.export.graphics.basicgen.KmlStringsGenerator;
|
||||
import com.raytheon.uf.viz.kml.export.graphics.ext.KmlRasterImage;
|
||||
|
||||
/**
|
||||
*
|
||||
* Takes graphics operations and produces a list of KmlFeatureGenerators that
|
||||
* can be used to make KML.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 1, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
public class KmlGraphicsTarget extends AbstractGraphicsTarget {
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(KmlGraphicsTarget.class);
|
||||
|
||||
private final KmlFont defaultFont = new KmlFont();
|
||||
|
||||
private List<KmlFeatureGenerator> generators = new ArrayList<KmlFeatureGenerator>(
|
||||
256);
|
||||
|
||||
protected IView view;
|
||||
|
||||
public KmlGraphicsTarget() {
|
||||
super();
|
||||
}
|
||||
|
||||
public void setView(IView view) {
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KmlFont initializeFont(String fontId) {
|
||||
FontRegistry registry = PlatformUI.getWorkbench().getThemeManager()
|
||||
.getCurrentTheme().getFontRegistry();
|
||||
if (registry.hasValueFor(fontId)) {
|
||||
FontData[] data = registry.getFontData(fontId);
|
||||
FontData fd = data[0];
|
||||
if (fd == null) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"No font data found for id: " + fontId);
|
||||
}
|
||||
float size = fd.height;
|
||||
String name = fd.getName();
|
||||
List<IFont.Style> styles = new ArrayList<IFont.Style>();
|
||||
|
||||
int style = fd.getStyle();
|
||||
if ((style & SWT.BOLD) != 0) {
|
||||
styles.add(IFont.Style.BOLD);
|
||||
}
|
||||
if ((style & SWT.ITALIC) != 0) {
|
||||
styles.add(IFont.Style.ITALIC);
|
||||
}
|
||||
|
||||
return new KmlFont(name, size,
|
||||
styles.toArray(new IFont.Style[styles.size()]));
|
||||
} else {
|
||||
return getDefaultFont();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public KmlFont initializeFont(String fontName, float size, Style[] styles) {
|
||||
return new KmlFont(fontName, size, styles);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KmlFont initializeFont(File fontFile, float size, Style[] styles) {
|
||||
try {
|
||||
return new KmlFont(fontFile, size, styles);
|
||||
} catch (FontFormatException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e);
|
||||
} catch (IOException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e);
|
||||
}
|
||||
return new KmlFont((String) null, size, styles);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawWireframeShape(IWireframeShape shape, RGB color,
|
||||
float lineWidth, LineStyle lineStyle, IFont font, float alpha)
|
||||
throws VizException {
|
||||
addGenerator(new KmlWireframeShape.Generator((KmlWireframeShape) shape,
|
||||
alpha, color, lineWidth));
|
||||
}
|
||||
|
||||
@Override
|
||||
public KmlWireframeShape createWireframeShape(boolean mutable,
|
||||
GeneralGridGeometry geom, float simplificationLevel) {
|
||||
return new KmlWireframeShape(geom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KmlWireframeShape createWireframeShape(boolean mutableFlag,
|
||||
GeneralGridGeometry geom) {
|
||||
return new KmlWireframeShape(geom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KmlWireframeShape createWireframeShape(boolean mutable,
|
||||
GeneralGridGeometry geom, float simplificationLevel,
|
||||
boolean spatialChopFlag, IExtent extent) {
|
||||
return new KmlWireframeShape(geom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KmlFont getDefaultFont() {
|
||||
return defaultFont;
|
||||
}
|
||||
|
||||
public RGB getBackgroundColor() {
|
||||
return backgroundColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle2D getStringsBounds(DrawableString parameters, String string) {
|
||||
KmlFont kmlFont = (KmlFont) parameters.font;
|
||||
if (kmlFont == null) {
|
||||
kmlFont = getDefaultFont();
|
||||
}
|
||||
FontRenderContext frc = new FontRenderContext(null, false, false);
|
||||
Rectangle2D rect = kmlFont.getFont().getStringBounds(string, frc);
|
||||
double width = rect.getWidth() * kmlFont.getMagnification();
|
||||
double height = rect.getHeight() * kmlFont.getMagnification();
|
||||
return new Rectangle2D.Double(0, 0, width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawStrings(Collection<DrawableString> parameters)
|
||||
throws VizException {
|
||||
addGenerator(new KmlStringsGenerator(parameters));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPoints(Collection<double[]> locations, RGB color,
|
||||
PointStyle pointStyle, float magnification) throws VizException {
|
||||
addGenerator(new KmlPointsGenerator(locations, color, pointStyle,
|
||||
magnification));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLine(DrawableLine... lines) throws VizException {
|
||||
addGenerator(new KmlLinesGenerator(lines));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawCircle(DrawableCircle... circles) throws VizException {
|
||||
addGenerator(new KmlCirclesGenerator(circles));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IImage initializeRaster(IRenderedImageCallback imageCallback) {
|
||||
return new KmlRasterImage(imageCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IShadedShape createShadedShape(boolean mutable,
|
||||
GeneralGridGeometry targetGeometry, boolean tesselate) {
|
||||
return new KmlShadedShape(targetGeometry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawShadedShapes(float alpha, float brightness,
|
||||
IShadedShape... shapes) throws VizException {
|
||||
for (IShadedShape shape : shapes) {
|
||||
addGenerator(new KmlShadedShape.Generator(alpha,
|
||||
(KmlShadedShape) shape));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRect(IExtent pe, RGB color, float lineWidth, double alpha)
|
||||
throws VizException {
|
||||
addGenerator(new KmlRectGenerator(pe, color, alpha, lineWidth, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawShadedRect(IExtent pe, RGB color, double alpha,
|
||||
byte[] pattern) throws VizException {
|
||||
addGenerator(new KmlRectGenerator(pe, color, alpha, 1.0f, true));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
// this function intentionally left blank
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginFrame(IView view, boolean isClearBackground) {
|
||||
setNeedsRefresh(false);
|
||||
generators.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endFrame() {
|
||||
// this function intentionally left blank
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resize() {
|
||||
// no need
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedImage screenshot() {
|
||||
// No one should be doing this.
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupClippingPlane(IExtent extent) {
|
||||
// for now always ignore cliiping panes
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearClippingPlane() {
|
||||
// for now always ignore cliiping panes
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawColorRamp(DrawableColorMap colorMap) throws VizException {
|
||||
// currently this is handled outside the target, it might move here some
|
||||
// day but screen overlay rendering through the target is a bit
|
||||
// difficult for labels and things.
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by graphics extensions to add generators to the current frame.
|
||||
*
|
||||
* @param generator
|
||||
*/
|
||||
public void addGenerator(KmlFeatureGenerator generator) {
|
||||
generators.add(generator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the generators used during the last frame paint.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<KmlFeatureGenerator> getGenerators() {
|
||||
return generators;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawWireframeShape(IWireframeShape shape, RGB color,
|
||||
float lineWidth, LineStyle lineStyle, float alpha)
|
||||
throws VizException {
|
||||
drawWireframeShape(shape, color, lineWidth, lineStyle,
|
||||
getDefaultFont(), alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IView getView() {
|
||||
return view;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,208 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
import org.geotools.coverage.grid.GeneralGridGeometry;
|
||||
import org.opengis.referencing.FactoryException;
|
||||
import org.opengis.referencing.datum.PixelInCell;
|
||||
import org.opengis.referencing.operation.MathTransform;
|
||||
import org.opengis.referencing.operation.TransformException;
|
||||
|
||||
import com.raytheon.uf.common.geospatial.TransformFactory;
|
||||
import com.raytheon.uf.viz.core.drawables.IShadedShape;
|
||||
import com.raytheon.uf.viz.kml.export.KmlFeatureGenerator;
|
||||
import com.raytheon.uf.viz.kml.export.io.KmlOutputManager;
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.LineString;
|
||||
|
||||
import de.micromata.opengis.kml.v_2_2_0.Folder;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Geometry;
|
||||
import de.micromata.opengis.kml.v_2_2_0.LinearRing;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Placemark;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Polygon;
|
||||
|
||||
/**
|
||||
* Implementation of shaded shape that can create a generator for making KML
|
||||
* filled polygons. KML has no concept of a fill pattern so it is completly
|
||||
* ignored and all polygons are filled with color.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 11, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class KmlShadedShape implements IShadedShape {
|
||||
|
||||
private Map<RGB, List<Polygon>> polygons = new HashMap<RGB, List<Polygon>>();
|
||||
|
||||
private final GeneralGridGeometry gridGeometry;
|
||||
|
||||
public KmlShadedShape(GeneralGridGeometry gridGeometry) {
|
||||
this.gridGeometry = gridGeometry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compile() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDrawable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
polygons.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
polygons.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPolygon(LineString[] lineString, RGB color) {
|
||||
Polygon p = new Polygon();
|
||||
LinearRing outer = p.createAndSetOuterBoundaryIs()
|
||||
.createAndSetLinearRing();
|
||||
for (Coordinate c : lineString[0].getCoordinates()) {
|
||||
outer.addToCoordinates(c.x, c.y);
|
||||
}
|
||||
for (int i = 1; i < lineString.length; i += 1) {
|
||||
LinearRing inner = p.createAndAddInnerBoundaryIs()
|
||||
.createAndSetLinearRing();
|
||||
for (Coordinate c : lineString[i].getCoordinates()) {
|
||||
inner.addToCoordinates(c.x, c.y);
|
||||
}
|
||||
}
|
||||
List<Polygon> polygons = this.polygons.get(color);
|
||||
if (polygons == null) {
|
||||
polygons = new ArrayList<Polygon>();
|
||||
this.polygons.put(color, polygons);
|
||||
}
|
||||
polygons.add(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPolygonPixelSpace(LineString[] contours, RGB color) {
|
||||
try {
|
||||
MathTransform transform = TransformFactory.gridToLatLon(
|
||||
gridGeometry, PixelInCell.CELL_CENTER);
|
||||
double[] loc = new double[2];
|
||||
LineString[] newContours = new LineString[contours.length];
|
||||
for (int i = 0; i < contours.length; i += 1) {
|
||||
List<Coordinate> newCoordinates = new ArrayList<Coordinate>();
|
||||
for (Coordinate c : contours[i].getCoordinates()) {
|
||||
loc = new double[] { c.x, c.y };
|
||||
transform.transform(loc, 0, loc, 0, 1);
|
||||
newCoordinates.add(new Coordinate(loc[0], loc[1]));
|
||||
}
|
||||
newContours[i] = contours[i].getFactory().createLineString(
|
||||
newCoordinates.toArray(new Coordinate[0]));
|
||||
}
|
||||
addPolygon(newContours, color);
|
||||
} catch (TransformException e) {
|
||||
throw new IllegalStateException(e);
|
||||
} catch (FactoryException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFillPattern(byte[] pattern) {
|
||||
|
||||
}
|
||||
|
||||
public static class Generator extends KmlFeatureGenerator {
|
||||
|
||||
private final double alpha;
|
||||
|
||||
private final Map<RGB, List<Polygon>> polygons;
|
||||
|
||||
public Generator(double alpha, KmlShadedShape shape) {
|
||||
this.alpha = alpha;
|
||||
this.polygons = new HashMap<RGB, List<Polygon>>(shape.polygons);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFeature(KmlOutputManager outputManager) {
|
||||
if (polygons.size() == 1) {
|
||||
Entry<RGB, List<Polygon>> entry = polygons.entrySet()
|
||||
.iterator().next();
|
||||
outputManager.addFeature(getPlacemark(outputManager,
|
||||
entry.getKey(), entry.getValue()));
|
||||
} else if (!polygons.isEmpty()) {
|
||||
Folder folder = new Folder();
|
||||
folder.setName("Shaded Shapes");
|
||||
for (Entry<RGB, List<Polygon>> entry : polygons.entrySet()) {
|
||||
folder.addToFeature(getPlacemark(outputManager,
|
||||
entry.getKey(), entry.getValue()));
|
||||
}
|
||||
outputManager.addFeature(folder);
|
||||
}
|
||||
}
|
||||
|
||||
private Placemark getPlacemark(KmlOutputManager out, RGB color,
|
||||
List<Polygon> polygons) {
|
||||
Placemark placemark = new Placemark();
|
||||
placemark.setName("Shaded Shape");
|
||||
|
||||
de.micromata.opengis.kml.v_2_2_0.Style kmlStyle = new de.micromata.opengis.kml.v_2_2_0.Style();
|
||||
|
||||
kmlStyle.createAndSetPolyStyle().withFill(true)
|
||||
.withColor(toColorStr(alpha, color));
|
||||
kmlStyle.createAndSetLineStyle()
|
||||
.withColor(toColorStr(alpha, color));
|
||||
placemark.setStyleUrl(out.getStyleUrl(kmlStyle));
|
||||
if (polygons.size() == 1) {
|
||||
placemark.setGeometry(polygons.get(0));
|
||||
} else {
|
||||
placemark.createAndSetMultiGeometry().setGeometry(
|
||||
new ArrayList<Geometry>(polygons));
|
||||
}
|
||||
return placemark;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics;
|
||||
|
||||
import org.eclipse.swt.graphics.Rectangle;
|
||||
|
||||
import com.raytheon.uf.viz.core.AbstractView;
|
||||
import com.raytheon.uf.viz.core.IExtent;
|
||||
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
||||
|
||||
/**
|
||||
*
|
||||
* Minimalistic implementation of a view for KML. Can not be shifted or
|
||||
* modified, so KML does not supprt Pan/Zoom.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 1, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
public class KmlView extends AbstractView {
|
||||
|
||||
private final Rectangle canvasBounds;
|
||||
|
||||
public KmlView(IExtent extent, Rectangle canvasBounds) {
|
||||
super(extent);
|
||||
this.canvasBounds = canvasBounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupView(IGraphicsTarget target) {
|
||||
if (target instanceof KmlGraphicsTarget) {
|
||||
((KmlGraphicsTarget) target).setView(this);
|
||||
return;
|
||||
}
|
||||
throw new IllegalArgumentException(
|
||||
"KmlView was expecting a KmlGraphicsTarget but recieved "
|
||||
+ target.getClass().getSimpleName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double recalcZoomLevel(int[] dimensions) {
|
||||
throw new UnsupportedOperationException("KmlView is read only!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void zoom(double zoomLevel) {
|
||||
throw new UnsupportedOperationException("KmlView is read only!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scaleAndBias(double factor, double screenX, double screenY,
|
||||
IGraphicsTarget target) {
|
||||
throw new UnsupportedOperationException("KmlView is read only!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExtent(IExtent pe) {
|
||||
throw new UnsupportedOperationException("KmlView is read only!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shiftExtent(double[] startScreen, double[] endScreen,
|
||||
IGraphicsTarget target) {
|
||||
throw new UnsupportedOperationException("KmlView is read only!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scaleToClientArea(Rectangle clientArea, int[] dimensions) {
|
||||
throw new UnsupportedOperationException("KmlView is read only!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public KmlView clone() {
|
||||
return new KmlView(extent.clone(), canvasBounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle getCanvasBounds(IGraphicsTarget target) {
|
||||
return canvasBounds;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,284 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
import org.geotools.coverage.grid.GeneralGridGeometry;
|
||||
import org.opengis.referencing.FactoryException;
|
||||
import org.opengis.referencing.datum.PixelInCell;
|
||||
import org.opengis.referencing.operation.MathTransform;
|
||||
import org.opengis.referencing.operation.TransformException;
|
||||
|
||||
import com.raytheon.uf.common.geospatial.TransformFactory;
|
||||
import com.raytheon.uf.viz.core.drawables.IWireframeShape;
|
||||
import com.raytheon.uf.viz.kml.export.KmlFeatureGenerator;
|
||||
import com.raytheon.uf.viz.kml.export.io.KmlOutputManager;
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
|
||||
import de.micromata.opengis.kml.v_2_2_0.Feature;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Folder;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Geometry;
|
||||
import de.micromata.opengis.kml.v_2_2_0.LabelStyle;
|
||||
import de.micromata.opengis.kml.v_2_2_0.LineString;
|
||||
import de.micromata.opengis.kml.v_2_2_0.LineStyle;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Placemark;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Point;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Style;
|
||||
|
||||
/**
|
||||
*
|
||||
* Converts a wireframe shape into KML LineStrings and Labels.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 1, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
public class KmlWireframeShape implements IWireframeShape {
|
||||
|
||||
private List<Geometry> segments = new ArrayList<Geometry>();
|
||||
|
||||
private Map<String, List<Geometry>> labels = new HashMap<String, List<Geometry>>();
|
||||
|
||||
private final GeneralGridGeometry gridGeometry;
|
||||
|
||||
public KmlWireframeShape(GeneralGridGeometry gridGeometry) {
|
||||
this.gridGeometry = gridGeometry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compile() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDrawable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
segments.clear();
|
||||
labels.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
segments.clear();
|
||||
labels.clear();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLineSegment(Coordinate[] latLong) {
|
||||
LineString line = new LineString();
|
||||
for (Coordinate c : latLong) {
|
||||
line.addToCoordinates(round(c.x), round(c.y));
|
||||
}
|
||||
segments.add(line);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLineSegment(double[][] screenCoordinates) {
|
||||
try {
|
||||
MathTransform transform = TransformFactory.gridToLatLon(
|
||||
gridGeometry, PixelInCell.CELL_CENTER);
|
||||
LineString line = new LineString();
|
||||
double[] out = new double[2];
|
||||
for (int i = 0; i < screenCoordinates.length; i += 1) {
|
||||
transform.transform(screenCoordinates[i], 0, out, 0, 1);
|
||||
line.addToCoordinates(round(out[0]), round(out[1]));
|
||||
}
|
||||
segments.add(line);
|
||||
} catch (TransformException e) {
|
||||
throw new IllegalStateException(e);
|
||||
} catch (FactoryException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* round a latitude or longitude, rounding can cut the size of the generated
|
||||
* kml and only moves the actual line by less than a meter.
|
||||
*
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
private double round(double value) {
|
||||
return ((long) (value * 100000)) / 100000.0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLabel(String label, double[] screenCoordinate) {
|
||||
try {
|
||||
MathTransform transform = TransformFactory.gridToLatLon(
|
||||
gridGeometry, PixelInCell.CELL_CENTER);
|
||||
double[] out = new double[2];
|
||||
transform.transform(screenCoordinate, 0, out, 0, 1);
|
||||
Point point = new Point();
|
||||
point.addToCoordinates(round(out[0]), round(out[1]));
|
||||
List<Geometry> points = labels.get(label);
|
||||
if (points == null) {
|
||||
points = new ArrayList<Geometry>();
|
||||
labels.put(label, points);
|
||||
}
|
||||
points.add(point);
|
||||
} catch (TransformException e) {
|
||||
throw new IllegalStateException(e);
|
||||
} catch (FactoryException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearLabels() {
|
||||
labels.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void allocate(int points) {
|
||||
}
|
||||
|
||||
public static class Generator extends KmlFeatureGenerator {
|
||||
|
||||
private final List<Geometry> segments;
|
||||
|
||||
private final Map<String, List<Geometry>> labels;
|
||||
|
||||
private final float alpha;
|
||||
|
||||
private final RGB color;
|
||||
|
||||
private final float lineWidth;
|
||||
|
||||
public Generator(KmlWireframeShape shape, float alpha, RGB color,
|
||||
float lineWidth) {
|
||||
this.segments = new ArrayList<Geometry>(shape.segments);
|
||||
this.labels = new HashMap<String, List<Geometry>>(shape.labels);
|
||||
this.alpha = alpha;
|
||||
this.color = color;
|
||||
this.lineWidth = lineWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFeature(KmlOutputManager outputManager) {
|
||||
if (segments.isEmpty() && labels.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
String styleUrl = outputManager.getStyleUrl(getStyle());
|
||||
Feature lineFeature = getLineFeature(styleUrl);
|
||||
Feature labelFeature = getLabelFeature(styleUrl);
|
||||
if (lineFeature == null) {
|
||||
outputManager.addFeature(labelFeature);
|
||||
} else if (labelFeature == null) {
|
||||
outputManager.addFeature(lineFeature);
|
||||
} else {
|
||||
Folder folder = new Folder();
|
||||
folder.setName("LinesAndLabels");
|
||||
folder.addToFeature(lineFeature);
|
||||
folder.addToFeature(labelFeature);
|
||||
outputManager.addFeature(folder);
|
||||
}
|
||||
}
|
||||
|
||||
private Style getStyle() {
|
||||
Style style = new de.micromata.opengis.kml.v_2_2_0.Style();
|
||||
LineStyle lineStyle = style.createAndSetLineStyle();
|
||||
LabelStyle labelStyle = style.createAndSetLabelStyle();
|
||||
style.createAndSetIconStyle().setScale(0);
|
||||
String colorStr = toColorStr(alpha, color);
|
||||
lineStyle.setColor(colorStr);
|
||||
lineStyle.setWidth(lineWidth);
|
||||
labelStyle.setColor(colorStr);
|
||||
labelStyle.setScale(1.0);
|
||||
return style;
|
||||
}
|
||||
|
||||
private Feature getLineFeature(String styleUrl) {
|
||||
if (segments.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Placemark placemark = new Placemark();
|
||||
placemark.setName("Lines");
|
||||
placemark.setStyleUrl(styleUrl);
|
||||
if (segments.size() == 1) {
|
||||
placemark.setGeometry(segments.get(0));
|
||||
} else {
|
||||
placemark.createAndSetMultiGeometry().setGeometry(
|
||||
new ArrayList<Geometry>(segments));
|
||||
}
|
||||
return placemark;
|
||||
}
|
||||
|
||||
private Feature getLabelFeature(String styleUrl) {
|
||||
if (labels.size() == 1) {
|
||||
for (Entry<String, List<Geometry>> entry : labels.entrySet()) {
|
||||
return createLabelPlacemark(entry.getKey(),
|
||||
entry.getValue(), styleUrl);
|
||||
}
|
||||
} else if (!labels.isEmpty()) {
|
||||
Folder folder = new Folder();
|
||||
folder.setName("Labels");
|
||||
for (Entry<String, List<Geometry>> entry : labels.entrySet()) {
|
||||
Placemark placemark = createLabelPlacemark(entry.getKey(),
|
||||
entry.getValue(), styleUrl);
|
||||
folder.addToFeature(placemark);
|
||||
}
|
||||
return folder;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Placemark createLabelPlacemark(String label,
|
||||
List<Geometry> points, String styleUrl) {
|
||||
Placemark placemark = new Placemark();
|
||||
placemark.setName(label);
|
||||
placemark.setStyleUrl(styleUrl);
|
||||
if (points.size() == 1) {
|
||||
placemark.setGeometry(points.get(0));
|
||||
} else {
|
||||
placemark.createAndSetMultiGeometry().setGeometry(points);
|
||||
}
|
||||
return placemark;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics.basicgen;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.opengis.referencing.FactoryException;
|
||||
import org.opengis.referencing.operation.TransformException;
|
||||
|
||||
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.viz.core.DrawableCircle;
|
||||
import com.raytheon.uf.viz.kml.export.KmlFeatureGenerator;
|
||||
import com.raytheon.uf.viz.kml.export.io.KmlOutputManager;
|
||||
|
||||
import de.micromata.opengis.kml.v_2_2_0.Placemark;
|
||||
|
||||
/**
|
||||
* Generates KML polygons for DrawableCircles.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 14, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class KmlCirclesGenerator extends KmlFeatureGenerator {
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(KmlLinesGenerator.class);
|
||||
|
||||
private final DrawableCircle[] circles;
|
||||
|
||||
public KmlCirclesGenerator(DrawableCircle[] circles) {
|
||||
this.circles = circles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFeature(KmlOutputManager outputManager) {
|
||||
if (circles.length > 1) {
|
||||
outputManager = outputManager.createFolder("Circles");
|
||||
}
|
||||
for (DrawableCircle circle : circles) {
|
||||
String colorStr = toColorStr(circle.basics.alpha,
|
||||
circle.basics.color);
|
||||
de.micromata.opengis.kml.v_2_2_0.Style kmlStyle = new de.micromata.opengis.kml.v_2_2_0.Style();
|
||||
kmlStyle.createAndSetLabelStyle().setScale(0);
|
||||
kmlStyle.createAndSetIconStyle().setScale(0);
|
||||
if (circle.filled) {
|
||||
kmlStyle.createAndSetPolyStyle().withFill(true)
|
||||
.withColor(colorStr);
|
||||
} else {
|
||||
kmlStyle.createAndSetLineStyle().withWidth(circle.lineWidth)
|
||||
.withColor(colorStr);
|
||||
}
|
||||
Placemark placemark = new Placemark();
|
||||
placemark.setName("Circle");
|
||||
placemark.setStyleUrl(outputManager.getStyleUrl(kmlStyle));
|
||||
List<double[]> pts = new ArrayList<double[]>();
|
||||
double step = 360.0 / (circle.numberOfPoints);
|
||||
double radius = circle.radius == null ? circle.screenRadius
|
||||
: circle.radius;
|
||||
try {
|
||||
for (double i = 0; i <= circle.numberOfPoints; i++) {
|
||||
double[] pt = new double[2];
|
||||
pt[0] = circle.basics.x + radius
|
||||
* Math.cos(Math.toRadians(i * step));
|
||||
pt[1] = circle.basics.y + radius
|
||||
* Math.sin(Math.toRadians(i * step));
|
||||
pts.add(pt);
|
||||
}
|
||||
if (circle.filled) {
|
||||
placemark.createAndSetPolygon()
|
||||
.createAndSetOuterBoundaryIs()
|
||||
.createAndSetLinearRing()
|
||||
.withCoordinates(transformToLatLon(pts));
|
||||
|
||||
} else {
|
||||
placemark.createAndSetLineString().withCoordinates(
|
||||
transformToLatLon(pts));
|
||||
}
|
||||
} catch (TransformException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
|
||||
e);
|
||||
} catch (FactoryException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
|
||||
e);
|
||||
}
|
||||
outputManager.addFeature(placemark);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics.basicgen;
|
||||
|
||||
import org.opengis.referencing.FactoryException;
|
||||
import org.opengis.referencing.operation.TransformException;
|
||||
|
||||
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.viz.core.DrawableLine;
|
||||
import com.raytheon.uf.viz.kml.export.KmlFeatureGenerator;
|
||||
import com.raytheon.uf.viz.kml.export.io.KmlOutputManager;
|
||||
|
||||
import de.micromata.opengis.kml.v_2_2_0.Placemark;
|
||||
|
||||
/**
|
||||
* Generates KML line strings for DrawableLine.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 14, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class KmlLinesGenerator extends KmlFeatureGenerator {
|
||||
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(KmlLinesGenerator.class);
|
||||
|
||||
private final DrawableLine[] lines;
|
||||
|
||||
public KmlLinesGenerator(DrawableLine[] lines) {
|
||||
super();
|
||||
this.lines = lines;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFeature(KmlOutputManager outputManager) {
|
||||
if (lines.length > 1) {
|
||||
outputManager = outputManager.createFolder("Lines");
|
||||
}
|
||||
for (DrawableLine line : lines) {
|
||||
de.micromata.opengis.kml.v_2_2_0.Style kmlStyle = new de.micromata.opengis.kml.v_2_2_0.Style();
|
||||
kmlStyle.createAndSetLabelStyle().setScale(0);
|
||||
kmlStyle.createAndSetIconStyle().setScale(0);
|
||||
kmlStyle.createAndSetLineStyle()
|
||||
.withWidth(line.width)
|
||||
.withColor(toColorStr(line.basics.alpha, line.basics.color));
|
||||
Placemark placemark = new Placemark();
|
||||
placemark.setName("Line");
|
||||
placemark.setStyleUrl(outputManager.getStyleUrl(kmlStyle));
|
||||
try {
|
||||
placemark.createAndSetLineString().withCoordinates(
|
||||
transformToLatLon(line.points));
|
||||
outputManager.addFeature(placemark);
|
||||
} catch (TransformException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
|
||||
e);
|
||||
} catch (FactoryException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
|
||||
e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics.basicgen;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
import org.opengis.referencing.FactoryException;
|
||||
import org.opengis.referencing.operation.TransformException;
|
||||
|
||||
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.viz.core.IGraphicsTarget.PointStyle;
|
||||
import com.raytheon.uf.viz.kml.export.KmlFeatureGenerator;
|
||||
import com.raytheon.uf.viz.kml.export.io.KmlOutputManager;
|
||||
|
||||
import de.micromata.opengis.kml.v_2_2_0.Coordinate;
|
||||
import de.micromata.opengis.kml.v_2_2_0.IconStyle;
|
||||
import de.micromata.opengis.kml.v_2_2_0.LabelStyle;
|
||||
import de.micromata.opengis.kml.v_2_2_0.MultiGeometry;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Placemark;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Point;
|
||||
|
||||
/**
|
||||
* Generates KML point icons.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 14, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class KmlPointsGenerator extends KmlFeatureGenerator {
|
||||
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(KmlStringsGenerator.class);
|
||||
|
||||
private final Collection<double[]> locations;
|
||||
|
||||
private final RGB color;
|
||||
|
||||
private final PointStyle pointStyle;
|
||||
|
||||
private final float magnification;
|
||||
|
||||
public KmlPointsGenerator(Collection<double[]> locations, RGB color,
|
||||
PointStyle pointStyle, float magnification) {
|
||||
super();
|
||||
this.locations = locations;
|
||||
this.color = color;
|
||||
this.pointStyle = pointStyle;
|
||||
this.magnification = magnification;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFeature(KmlOutputManager outputManager) {
|
||||
BufferedImage image = new BufferedImage(15, 15,
|
||||
BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics graphics = image.getGraphics();
|
||||
if (graphics instanceof Graphics2D) {
|
||||
((Graphics2D) graphics).setStroke(new BasicStroke(3.0f));
|
||||
}
|
||||
graphics.setColor(new java.awt.Color(0, 0, 0, 0));
|
||||
graphics.fillRect(0, 0, 24, 24);
|
||||
graphics.setColor(new java.awt.Color(color.red, color.green, color.blue));
|
||||
switch (pointStyle) {
|
||||
case NONE:
|
||||
graphics.dispose();
|
||||
return;
|
||||
case SQUARE:
|
||||
graphics.fillRect(1, 1, 13, 13);
|
||||
break;
|
||||
case CIRCLE:
|
||||
graphics.drawOval(1, 1, 13, 13);
|
||||
break;
|
||||
case CROSS:
|
||||
graphics.drawLine(7, 0, 7, 14);
|
||||
graphics.drawLine(0, 7, 14, 7);
|
||||
break;
|
||||
case DASH:
|
||||
graphics.drawLine(0, 7, 14, 7);
|
||||
break;
|
||||
case POINT:
|
||||
graphics.fillOval(5, 5, 5, 5);
|
||||
break;
|
||||
case BOX:
|
||||
graphics.drawRect(1, 1, 13, 13);
|
||||
break;
|
||||
case STAR:
|
||||
graphics.drawLine(7, 0, 7, 14);
|
||||
case X:
|
||||
graphics.drawLine(0, 0, 14, 14);
|
||||
graphics.drawLine(0, 14, 14, 0);
|
||||
break;
|
||||
case DISC:
|
||||
default:
|
||||
graphics.fillOval(1, 1, 13, 13);
|
||||
break;
|
||||
}
|
||||
|
||||
graphics.dispose();
|
||||
de.micromata.opengis.kml.v_2_2_0.Style kmlStyle = new de.micromata.opengis.kml.v_2_2_0.Style();
|
||||
LabelStyle kmlLabelStyle = kmlStyle.createAndSetLabelStyle();
|
||||
IconStyle kmlIconStyle = kmlStyle.createAndSetIconStyle();
|
||||
kmlIconStyle.createAndSetIcon().setHref(outputManager.addImage(image));
|
||||
kmlLabelStyle.setScale(0);
|
||||
kmlIconStyle.setScale(magnification * 0.5);
|
||||
Placemark placemark = new Placemark();
|
||||
placemark.setName(pointStyle.toString());
|
||||
placemark.setStyleUrl(outputManager.getStyleUrl(kmlStyle));
|
||||
try {
|
||||
if (locations.size() == 1) {
|
||||
Point p = placemark.createAndSetPoint();
|
||||
Coordinate loc = transformToLatLon(locations.iterator().next());
|
||||
p.addToCoordinates(loc.getLongitude(), loc.getLatitude());
|
||||
|
||||
} else {
|
||||
MultiGeometry multi = placemark.createAndSetMultiGeometry();
|
||||
for (double[] location : locations) {
|
||||
Point p = multi.createAndAddPoint();
|
||||
Coordinate loc = transformToLatLon(location);
|
||||
p.addToCoordinates(loc.getLongitude(), loc.getLatitude());
|
||||
}
|
||||
}
|
||||
outputManager.addFeature(placemark);
|
||||
} catch (TransformException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e);
|
||||
} catch (FactoryException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics.basicgen;
|
||||
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
import org.opengis.referencing.FactoryException;
|
||||
import org.opengis.referencing.operation.TransformException;
|
||||
|
||||
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.viz.core.IExtent;
|
||||
import com.raytheon.uf.viz.kml.export.KmlFeatureGenerator;
|
||||
import com.raytheon.uf.viz.kml.export.io.KmlOutputManager;
|
||||
|
||||
import de.micromata.opengis.kml.v_2_2_0.Coordinate;
|
||||
import de.micromata.opengis.kml.v_2_2_0.LinearRing;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Placemark;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Style;
|
||||
|
||||
/**
|
||||
* Generates kml Polygon for both filled and not filled rectangles.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 14, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class KmlRectGenerator extends KmlFeatureGenerator {
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(KmlRectGenerator.class);
|
||||
|
||||
private final IExtent pe;
|
||||
|
||||
private final RGB color;
|
||||
|
||||
private final double alpha;
|
||||
|
||||
private final float lineWidth;
|
||||
|
||||
private final boolean filled;
|
||||
|
||||
public KmlRectGenerator(IExtent pe, RGB color, double alpha,
|
||||
float lineWidth, boolean filled) {
|
||||
this.pe = pe;
|
||||
this.color = color;
|
||||
this.alpha = alpha;
|
||||
this.lineWidth = lineWidth;
|
||||
this.filled = filled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFeature(KmlOutputManager outputManager) {
|
||||
Placemark placemark = new Placemark();
|
||||
placemark.setName("Rectangle");
|
||||
Style style = new de.micromata.opengis.kml.v_2_2_0.Style();
|
||||
style.createAndSetLabelStyle().setScale(0);
|
||||
style.createAndSetIconStyle().setScale(0);
|
||||
style.createAndSetLineStyle().withWidth(lineWidth)
|
||||
.withColor(toColorStr(alpha, color));
|
||||
style.createAndSetPolyStyle().withFill(filled)
|
||||
.withColor(toColorStr(alpha, color));
|
||||
|
||||
try {
|
||||
LinearRing ring = placemark.createAndSetPolygon()
|
||||
.createAndSetOuterBoundaryIs().createAndSetLinearRing();
|
||||
Coordinate corner = transformToLatLon(pe.getMinX(), pe.getMinY());
|
||||
ring.addToCoordinates(corner.getLongitude(), corner.getLatitude());
|
||||
corner = transformToLatLon(pe.getMaxX(), pe.getMinY());
|
||||
ring.addToCoordinates(corner.getLongitude(), corner.getLatitude());
|
||||
corner = transformToLatLon(pe.getMaxX(), pe.getMaxY());
|
||||
ring.addToCoordinates(corner.getLongitude(), corner.getLatitude());
|
||||
corner = transformToLatLon(pe.getMinX(), pe.getMaxY());
|
||||
ring.addToCoordinates(corner.getLongitude(), corner.getLatitude());
|
||||
corner = transformToLatLon(pe.getMinX(), pe.getMinY());
|
||||
ring.addToCoordinates(corner.getLongitude(), corner.getLatitude());
|
||||
|
||||
placemark.setStyleUrl(outputManager.getStyleUrl(style));
|
||||
outputManager.addFeature(placemark);
|
||||
} catch (TransformException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e);
|
||||
} catch (FactoryException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,189 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics.basicgen;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
import org.opengis.referencing.FactoryException;
|
||||
import org.opengis.referencing.operation.TransformException;
|
||||
|
||||
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.viz.core.DrawableString;
|
||||
import com.raytheon.uf.viz.core.IGraphicsTarget.HorizontalAlignment;
|
||||
import com.raytheon.uf.viz.core.IGraphicsTarget.VerticalAlignment;
|
||||
import com.raytheon.uf.viz.kml.export.KmlFeatureGenerator;
|
||||
import com.raytheon.uf.viz.kml.export.io.KmlOutputManager;
|
||||
|
||||
import de.micromata.opengis.kml.v_2_2_0.Coordinate;
|
||||
import de.micromata.opengis.kml.v_2_2_0.IconStyle;
|
||||
import de.micromata.opengis.kml.v_2_2_0.LabelStyle;
|
||||
import de.micromata.opengis.kml.v_2_2_0.MultiGeometry;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Placemark;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Point;
|
||||
|
||||
/**
|
||||
* Generates KML Placemark Labels for DrawableStrings.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 14, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class KmlStringsGenerator extends KmlFeatureGenerator {
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(KmlStringsGenerator.class);
|
||||
|
||||
private final Collection<DrawableString> parameters;
|
||||
|
||||
public KmlStringsGenerator(Collection<DrawableString> parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFeature(KmlOutputManager outputManager) {
|
||||
Collection<DrawableString> parameters = mergeDuplicatePoints();
|
||||
if (parameters.size() > 1) {
|
||||
outputManager = outputManager.createFolder("Labels");
|
||||
}
|
||||
Map<String, Placemark> redundantPlacemarks = new HashMap<String, Placemark>();
|
||||
for (DrawableString dstring : parameters) {
|
||||
RGB color = dstring.getColors()[0];
|
||||
for (RGB dcolor : dstring.getColors()) {
|
||||
if (!dcolor.equals(color)) {
|
||||
statusHandler.handle(Priority.INFO,
|
||||
"Multicolor labels will be one color in kml");
|
||||
}
|
||||
break;
|
||||
}
|
||||
String colorStr = toColorStr(dstring.basics.alpha, color);
|
||||
StringBuilder text = new StringBuilder(dstring.getText()[0]);
|
||||
for (int i = 1; i < dstring.getText().length; i++) {
|
||||
text.append(" ");
|
||||
text.append(dstring.getText()[i]);
|
||||
}
|
||||
Placemark placemark = redundantPlacemarks.get(text.toString()
|
||||
+ colorStr + dstring.magnification);
|
||||
if (placemark == null) {
|
||||
// google earth handles multiple points in a single placemark
|
||||
// faster than multiple placemarks with a single point, so
|
||||
// combine wherever possible
|
||||
de.micromata.opengis.kml.v_2_2_0.Style kmlStyle = new de.micromata.opengis.kml.v_2_2_0.Style();
|
||||
LabelStyle kmlLabelStyle = kmlStyle.createAndSetLabelStyle();
|
||||
IconStyle kmlIconStyle = kmlStyle.createAndSetIconStyle();
|
||||
kmlLabelStyle.setColor(colorStr);
|
||||
double magnifiaction = dstring.magnification;
|
||||
if (dstring.font != null) {
|
||||
magnifiaction *= dstring.font.getMagnification();
|
||||
}
|
||||
kmlLabelStyle.setScale(magnifiaction);
|
||||
kmlIconStyle.setScale(0);
|
||||
placemark = new Placemark();
|
||||
placemark.setName(text.toString());
|
||||
placemark.setStyleUrl(outputManager.getStyleUrl(kmlStyle));
|
||||
outputManager.addFeature(placemark);
|
||||
redundantPlacemarks.put(text.toString() + colorStr
|
||||
+ dstring.magnification, placemark);
|
||||
}
|
||||
Point point = null;
|
||||
if (placemark.getGeometry() == null) {
|
||||
point = placemark.createAndSetPoint();
|
||||
} else if (placemark.getGeometry() instanceof Point) {
|
||||
point = (Point) placemark.getGeometry();
|
||||
MultiGeometry multi = placemark.createAndSetMultiGeometry();
|
||||
multi.addToGeometry(point);
|
||||
point = multi.createAndAddPoint();
|
||||
} else {
|
||||
MultiGeometry multi = (MultiGeometry) placemark.getGeometry();
|
||||
point = multi.createAndAddPoint();
|
||||
}
|
||||
try {
|
||||
Coordinate loc = transformToLatLon(dstring.basics.x,
|
||||
dstring.basics.y);
|
||||
point.addToCoordinates(loc.getLongitude(), loc.getLatitude());
|
||||
} catch (TransformException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
|
||||
e);
|
||||
} catch (FactoryException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Collection<DrawableString> mergeDuplicatePoints() {
|
||||
Map<Coordinate, DrawableString> pointMap = new HashMap<Coordinate, DrawableString>();
|
||||
for (DrawableString dstring : parameters) {
|
||||
Coordinate c = new Coordinate(dstring.basics.x, dstring.basics.y);
|
||||
if (pointMap.containsKey(c)) {
|
||||
DrawableString inMap = pointMap.get(c);
|
||||
DrawableString dstring2 = inMap;
|
||||
// try determine which of the two dtrings would be considered
|
||||
// "first"
|
||||
if (dstring2.verticallAlignment != dstring.verticallAlignment) {
|
||||
if (dstring2.verticallAlignment == VerticalAlignment.BOTTOM
|
||||
|| dstring.verticallAlignment == VerticalAlignment.TOP) {
|
||||
DrawableString tmp = dstring2;
|
||||
dstring2 = dstring;
|
||||
dstring = tmp;
|
||||
}
|
||||
} else if (dstring2.horizontalAlignment != dstring.horizontalAlignment) {
|
||||
if (dstring2.horizontalAlignment == HorizontalAlignment.RIGHT
|
||||
|| dstring.horizontalAlignment == HorizontalAlignment.LEFT) {
|
||||
DrawableString tmp = dstring2;
|
||||
dstring2 = dstring;
|
||||
dstring = tmp;
|
||||
}
|
||||
}
|
||||
String[] text1 = dstring.getText();
|
||||
String[] text2 = dstring2.getText();
|
||||
RGB[] colors1 = dstring.getColors();
|
||||
RGB[] colors2 = dstring2.getColors();
|
||||
String[] text = Arrays.copyOf(text1, text1.length
|
||||
+ text2.length);
|
||||
System.arraycopy(text2, 0, text, text1.length, text2.length);
|
||||
RGB[] colors = Arrays.copyOf(colors1, colors1.length
|
||||
+ colors2.length);
|
||||
System.arraycopy(colors2, 0, colors, colors1.length,
|
||||
colors2.length);
|
||||
inMap.setText(text, colors);
|
||||
} else {
|
||||
pointMap.put(c, dstring);
|
||||
}
|
||||
}
|
||||
return pointMap.values();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,412 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics.ext;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
import org.eclipse.swt.graphics.Rectangle;
|
||||
|
||||
import com.raytheon.uf.viz.core.DrawableColorMap;
|
||||
import com.raytheon.uf.viz.core.DrawableLine;
|
||||
import com.raytheon.uf.viz.core.DrawableString;
|
||||
import com.raytheon.uf.viz.core.IGraphicsTarget.HorizontalAlignment;
|
||||
import com.raytheon.uf.viz.core.IGraphicsTarget.TextStyle;
|
||||
import com.raytheon.uf.viz.core.IGraphicsTarget.VerticalAlignment;
|
||||
import com.raytheon.uf.viz.core.drawables.PaintProperties;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.GraphicsExtension;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.ICanvasRenderingExtension;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.kml.export.KmlFeatureGenerator;
|
||||
import com.raytheon.uf.viz.kml.export.graphics.KmlFont;
|
||||
import com.raytheon.uf.viz.kml.export.graphics.KmlGraphicsTarget;
|
||||
import com.raytheon.uf.viz.kml.export.io.KmlOutputManager;
|
||||
|
||||
import de.micromata.opengis.kml.v_2_2_0.ScreenOverlay;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Units;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Vec2;
|
||||
|
||||
/**
|
||||
* Converts canvas rendering into KML screen overlays.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 26, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class KmlCanvasRenderingExtension extends
|
||||
GraphicsExtension<KmlGraphicsTarget> implements
|
||||
ICanvasRenderingExtension {
|
||||
|
||||
@Override
|
||||
public void drawStrings(PaintProperties paintProps,
|
||||
DrawableString... parameters) throws VizException {
|
||||
getGenerator(paintProps).addStrings(parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLines(PaintProperties paintProps,
|
||||
DrawableLine... parameters) throws VizException {
|
||||
getGenerator(paintProps).addLines(parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawColorRamp(PaintProperties paintProps,
|
||||
DrawableColorMap colorMap) throws VizException {
|
||||
getGenerator(paintProps).addColorMaps(colorMap);
|
||||
}
|
||||
|
||||
protected Generator getGenerator(PaintProperties paintProps) {
|
||||
for (KmlFeatureGenerator generator : target.getGenerators()) {
|
||||
if (generator instanceof Generator) {
|
||||
return (Generator) generator;
|
||||
}
|
||||
}
|
||||
Generator generator = new Generator(paintProps.getCanvasBounds());
|
||||
target.addGenerator(generator);
|
||||
return generator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCompatibilityValue(KmlGraphicsTarget target) {
|
||||
return Compatibilty.TARGET_COMPATIBLE;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Renders all canvas drawables to one or more screen overlays. The number
|
||||
* of screen overlays is determined by overlapping the rendering area all
|
||||
* objects and drawing any overlapping objects to a single overlay. This
|
||||
* provides a good compromise between a single overlay which does not work
|
||||
* well on different sized clients and one screen overlay per object, which
|
||||
* causes problems when nearby objects do not line up(such as radar tables).
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 26, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
private static class Generator extends KmlFeatureGenerator {
|
||||
|
||||
private final Rectangle canvasBounds;
|
||||
|
||||
private final List<Object> objects = new ArrayList<Object>();
|
||||
|
||||
public Generator(Rectangle canvasBounds) {
|
||||
this.canvasBounds = canvasBounds;
|
||||
}
|
||||
|
||||
public void addStrings(DrawableString... strings) {
|
||||
this.objects.addAll(Arrays.asList(strings));
|
||||
}
|
||||
|
||||
public void addLines(DrawableLine... lines) {
|
||||
this.objects.addAll(Arrays.asList(lines));
|
||||
}
|
||||
|
||||
public void addColorMaps(DrawableColorMap... colorMaps) {
|
||||
this.objects.addAll(Arrays.asList(colorMaps));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFeature(KmlOutputManager outputManager) {
|
||||
Map<Object, Rectangle2D> boundsMap = new IdentityHashMap<Object, Rectangle2D>();
|
||||
List<Rectangle2D> combinedBounds = new ArrayList<Rectangle2D>();
|
||||
for (Object object : objects) {
|
||||
Rectangle2D bounds = getBounds(object);
|
||||
boundsMap.put(object, bounds);
|
||||
addBounds(combinedBounds, bounds);
|
||||
}
|
||||
for (Rectangle2D bounds : combinedBounds) {
|
||||
BufferedImage bi = new BufferedImage((int) Math.ceil(bounds
|
||||
.getWidth()), (int) Math.ceil(bounds.getHeight()),
|
||||
BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics graphics = bi.getGraphics();
|
||||
for (Object object : objects) {
|
||||
if (bounds.contains(boundsMap.get(object))) {
|
||||
draw(graphics, bounds, object);
|
||||
}
|
||||
}
|
||||
graphics.dispose();
|
||||
graphics.finalize();
|
||||
bi.flush();
|
||||
ScreenOverlay overlay = new ScreenOverlay();
|
||||
overlay.setName("ScreenOverlay");
|
||||
Vec2 overlayxy = overlay.createAndSetOverlayXY();
|
||||
overlayxy.withXunits(Units.FRACTION).withYunits(Units.FRACTION);
|
||||
Vec2 screenxy = overlay.createAndSetScreenXY();
|
||||
screenxy.withXunits(Units.FRACTION).withYunits(Units.FRACTION);
|
||||
|
||||
// This is fairly complex placement code but it produces rather
|
||||
// nice results on any size of display. Basically if something
|
||||
// is flush against either the left or right of the screen it
|
||||
// ends up anchored on that side, if some is smack in the center
|
||||
// than the anchor point is in the middle of both the overlay
|
||||
// and the display. Now if an object is offcenter to the left or
|
||||
// right than the anchor point moves in the correct direction in
|
||||
// proportion to how far off center it is, its hard to explain
|
||||
// without a picture but at the end of the day it produces a
|
||||
// nice result.
|
||||
double leftFrac = bounds.getMinX() / canvasBounds.width;
|
||||
double rightFrac = 1.0 - bounds.getMaxX() / canvasBounds.width;
|
||||
if (leftFrac < rightFrac) {
|
||||
overlayxy.setX(leftFrac / rightFrac / 2);
|
||||
} else {
|
||||
overlayxy.setX(1.0 - rightFrac / leftFrac / 2);
|
||||
}
|
||||
double x = (bounds.getX() + bounds.getWidth()
|
||||
* overlayxy.getX())
|
||||
/ canvasBounds.width;
|
||||
screenxy.setX(x);
|
||||
|
||||
double topFrac = bounds.getMinY() / canvasBounds.height;
|
||||
double botFrac = 1.0 - bounds.getMaxY() / canvasBounds.height;
|
||||
if (topFrac < botFrac) {
|
||||
overlayxy.setY(1.0 - topFrac / botFrac / 2);
|
||||
} else {
|
||||
overlayxy.setY(botFrac / topFrac / 2);
|
||||
}
|
||||
// all this 1.0 - stuff is because the math is mostly assuming 0
|
||||
// is up and 1.0 is down but kml expects the opposite.
|
||||
double y = 1.0
|
||||
- (bounds.getY() + bounds.getHeight()
|
||||
* (1.0 - overlayxy.getY()))
|
||||
/ canvasBounds.height;
|
||||
screenxy.setY(y);
|
||||
|
||||
overlay.createAndSetIcon().setHref(
|
||||
outputManager.addImage(bi, "ScreenOverlay.png"));
|
||||
outputManager.addFeature(overlay);
|
||||
}
|
||||
}
|
||||
|
||||
private void addBounds(List<Rectangle2D> allBounds, Rectangle2D bounds) {
|
||||
Iterator<Rectangle2D> it = allBounds.iterator();
|
||||
while (it.hasNext()) {
|
||||
Rectangle2D b = it.next();
|
||||
if (b.intersects(bounds)) {
|
||||
if (!b.contains(bounds)) {
|
||||
// need to recheck the larger rectangle of b for any new
|
||||
// intersections.
|
||||
it.remove();
|
||||
b.add(bounds);
|
||||
addBounds(allBounds, b);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
allBounds.add(bounds);
|
||||
}
|
||||
|
||||
protected void draw(Graphics graphics, Rectangle2D imageBounds,
|
||||
Object object) {
|
||||
if (object instanceof DrawableString) {
|
||||
drawStrings(graphics, imageBounds, (DrawableString) object);
|
||||
} else if (object instanceof DrawableLine) {
|
||||
drawLines(graphics, imageBounds, (DrawableLine) object);
|
||||
} else if (object instanceof DrawableColorMap) {
|
||||
drawColorMap(graphics, imageBounds, (DrawableColorMap) object);
|
||||
}
|
||||
}
|
||||
|
||||
protected void drawStrings(Graphics graphics, Rectangle2D imageBounds,
|
||||
DrawableString string) {
|
||||
KmlFont kmlFont = (KmlFont) string.font;
|
||||
if (kmlFont == null) {
|
||||
kmlFont = new KmlFont();
|
||||
}
|
||||
graphics.setFont(kmlFont.getFont());
|
||||
double x = (string.basics.x - imageBounds.getX());
|
||||
double y = (string.basics.y - imageBounds.getY());
|
||||
String[] text = string.getText();
|
||||
RGB[] colors = string.getColors();
|
||||
for (int i = 0; i < text.length; i += 1) {
|
||||
Rectangle2D bounds = graphics.getFontMetrics().getStringBounds(
|
||||
text[i], graphics);
|
||||
double realX = x;
|
||||
double realY = y;
|
||||
if (HorizontalAlignment.RIGHT == string.horizontalAlignment) {
|
||||
realX -= bounds.getWidth();
|
||||
} else if (HorizontalAlignment.CENTER == string.horizontalAlignment) {
|
||||
realX -= bounds.getWidth() / 2;
|
||||
}
|
||||
if (VerticalAlignment.TOP == string.verticallAlignment) {
|
||||
realY -= bounds.getY();
|
||||
} else if (VerticalAlignment.MIDDLE == string.verticallAlignment) {
|
||||
realY -= bounds.getY() / 2;
|
||||
}
|
||||
if (string.textStyle == TextStyle.BLANKED) {
|
||||
setColor(graphics, backgroundColor);
|
||||
graphics.fillRect((int) realX,
|
||||
(int) (realY + bounds.getY()),
|
||||
(int) bounds.getWidth(),
|
||||
(int) bounds.getHeight() + 1);
|
||||
}
|
||||
setColor(graphics, colors[i]);
|
||||
graphics.drawString(text[i], (int) realX, (int) realY);
|
||||
y += bounds.getHeight();
|
||||
}
|
||||
}
|
||||
|
||||
protected void drawLines(Graphics graphics, Rectangle2D imageBounds,
|
||||
DrawableLine line) {
|
||||
setColor(graphics, line.basics.color);
|
||||
double[] pt1 = line.points.get(0);
|
||||
pt1[0] -= imageBounds.getX();
|
||||
pt1[1] -= imageBounds.getY();
|
||||
for (int i = 1; i < line.points.size(); i++) {
|
||||
double[] pt2 = line.points.get(i);
|
||||
pt2[0] -= imageBounds.getX();
|
||||
pt2[1] -= imageBounds.getY();
|
||||
graphics.drawLine((int) pt1[0], (int) pt1[1], (int) pt2[0],
|
||||
(int) pt2[1]);
|
||||
pt1 = pt2;
|
||||
}
|
||||
}
|
||||
|
||||
protected void drawColorMap(Graphics graphics, Rectangle2D imageBounds,
|
||||
DrawableColorMap colorMap) {
|
||||
double xStart = colorMap.extent.getMinX() - imageBounds.getX();
|
||||
double yStart = colorMap.extent.getMinY() - imageBounds.getY();
|
||||
|
||||
setColor(graphics, backgroundColor);
|
||||
graphics.fillRect((int) xStart, (int) yStart,
|
||||
(int) colorMap.extent.getWidth(),
|
||||
(int) colorMap.extent.getHeight());
|
||||
double x1 = xStart;
|
||||
double xd = colorMap.extent.getWidth()
|
||||
/ colorMap.getColorMapParams().getColorMap().getSize();
|
||||
for (com.raytheon.uf.common.colormap.Color color : colorMap
|
||||
.getColorMapParams().getColorMap().getColors()) {
|
||||
graphics.setColor(new Color(color.getRed(), color.getGreen(),
|
||||
color.getBlue(), color.getAlpha()));
|
||||
graphics.fillRect((int) x1, (int) yStart, (int) Math.ceil(xd),
|
||||
(int) colorMap.extent.getHeight());
|
||||
x1 += xd;
|
||||
}
|
||||
}
|
||||
|
||||
protected void setColor(Graphics graphics, RGB color) {
|
||||
graphics.setColor(new Color(color.red, color.green, color.blue));
|
||||
}
|
||||
|
||||
protected Rectangle2D getBounds(Object object) {
|
||||
if (object instanceof DrawableString) {
|
||||
return getStringBounds((DrawableString) object);
|
||||
} else if (object instanceof DrawableLine) {
|
||||
return getLineBounds((DrawableLine) object);
|
||||
} else if (object instanceof DrawableColorMap) {
|
||||
return getColorMapBounds((DrawableColorMap) object);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Rectangle2D getLineBounds(DrawableLine line) {
|
||||
Rectangle2D bounds = null;
|
||||
for (double[] point : line.points) {
|
||||
if (bounds == null) {
|
||||
bounds = new Rectangle2D.Double(point[0], point[1], 0, 0);
|
||||
} else {
|
||||
bounds.add(point[0], point[1]);
|
||||
}
|
||||
}
|
||||
// add a buffer region to ensure we have room for wide lines on
|
||||
// the edge.
|
||||
bounds.add(bounds.getMinX() - line.width, bounds.getMinY()
|
||||
- line.width);
|
||||
bounds.add(bounds.getMaxX() + line.width, bounds.getMaxY()
|
||||
+ line.width);
|
||||
return bounds;
|
||||
}
|
||||
|
||||
protected Rectangle2D getStringBounds(DrawableString string) {
|
||||
KmlFont kmlFont = (KmlFont) string.font;
|
||||
if (kmlFont == null) {
|
||||
kmlFont = new KmlFont();
|
||||
}
|
||||
FontRenderContext frc = new FontRenderContext(null, false, false);
|
||||
Rectangle2D bounds = null;
|
||||
String[] text = string.getText();
|
||||
double x = string.basics.x;
|
||||
double y = string.basics.y;
|
||||
for (int i = 0; i < text.length; i += 1) {
|
||||
Rectangle2D b = kmlFont.getFont().getStringBounds(text[i], frc);
|
||||
b.setFrame(x, y, b.getWidth(), b.getHeight());
|
||||
y += b.getHeight();
|
||||
if (bounds == null) {
|
||||
bounds = b;
|
||||
} else {
|
||||
bounds.add(b);
|
||||
}
|
||||
}
|
||||
if (HorizontalAlignment.RIGHT == string.horizontalAlignment) {
|
||||
bounds.setFrame(bounds.getMinX() - bounds.getWidth(),
|
||||
bounds.getMinY(), bounds.getWidth(), bounds.getHeight());
|
||||
} else if (HorizontalAlignment.CENTER == string.horizontalAlignment) {
|
||||
bounds.setFrame(bounds.getMinX() - bounds.getWidth() / 2,
|
||||
bounds.getMinY(), bounds.getWidth(), bounds.getHeight());
|
||||
}
|
||||
if (VerticalAlignment.BOTTOM == string.verticallAlignment) {
|
||||
bounds.setFrame(bounds.getMinX(),
|
||||
bounds.getMinY() - bounds.getHeight(),
|
||||
bounds.getWidth(), bounds.getHeight());
|
||||
} else if (VerticalAlignment.MIDDLE == string.verticallAlignment) {
|
||||
bounds.setFrame(bounds.getMinX(),
|
||||
bounds.getMinY() - bounds.getHeight() / 2,
|
||||
bounds.getWidth(), bounds.getHeight());
|
||||
}
|
||||
return bounds;
|
||||
}
|
||||
|
||||
protected Rectangle2D getColorMapBounds(DrawableColorMap colorMap) {
|
||||
return new Rectangle2D.Double(colorMap.extent.getMinX(),
|
||||
colorMap.extent.getMinY(), colorMap.extent.getWidth(),
|
||||
colorMap.extent.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics.ext;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
import org.geotools.coverage.grid.GridGeometry2D;
|
||||
|
||||
import com.raytheon.uf.common.geospatial.interpolation.data.ByteBufferWrapper;
|
||||
import com.raytheon.uf.common.geospatial.interpolation.data.DataSource;
|
||||
import com.raytheon.uf.common.geospatial.interpolation.data.FloatBufferWrapper;
|
||||
import com.raytheon.uf.common.geospatial.interpolation.data.IntBufferWrapper;
|
||||
import com.raytheon.uf.common.geospatial.interpolation.data.ShortBufferWrapper;
|
||||
import com.raytheon.uf.common.geospatial.interpolation.data.UnsignedByteBufferWrapper;
|
||||
import com.raytheon.uf.common.geospatial.interpolation.data.UnsignedShortBufferWrapper;
|
||||
import com.raytheon.uf.viz.core.data.IColorMapDataRetrievalCallback;
|
||||
import com.raytheon.uf.viz.core.data.IColorMapDataRetrievalCallback.ColorMapData;
|
||||
import com.raytheon.uf.viz.core.drawables.ColorMapParameters;
|
||||
import com.raytheon.uf.viz.core.drawables.IColormappedImage;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.IImagingExtension;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
|
||||
/**
|
||||
*
|
||||
* Implements the interface and converts all data callbacks into raw float
|
||||
* arrays.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 1, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
public class KmlColormappedImage extends KmlImage implements IColormappedImage {
|
||||
|
||||
private final IColorMapDataRetrievalCallback dataCallback;
|
||||
|
||||
private ColorMapParameters colorMapParameters;
|
||||
|
||||
public KmlColormappedImage(IColorMapDataRetrievalCallback dataCallback,
|
||||
ColorMapParameters colorMapParameters) {
|
||||
this.dataCallback = dataCallback;
|
||||
this.colorMapParameters = colorMapParameters;
|
||||
}
|
||||
|
||||
public DataSource getData(GridGeometry2D geometry) throws VizException {
|
||||
ColorMapData data = dataCallback.getColorMapData();
|
||||
switch (data.getDataType()) {
|
||||
case FLOAT:
|
||||
return new FloatBufferWrapper(((FloatBuffer) data.getBuffer()),
|
||||
geometry);
|
||||
case BYTE: {
|
||||
return new UnsignedByteBufferWrapper(
|
||||
((ByteBuffer) data.getBuffer()), geometry);
|
||||
}
|
||||
case SIGNED_BYTE: {
|
||||
return new ByteBufferWrapper(((ByteBuffer) data.getBuffer()),
|
||||
geometry);
|
||||
}
|
||||
case INT: {
|
||||
return new IntBufferWrapper(((IntBuffer) data.getBuffer()),
|
||||
geometry);
|
||||
}
|
||||
case SHORT: {
|
||||
return new ShortBufferWrapper(((ShortBuffer) data.getBuffer()),
|
||||
geometry);
|
||||
}
|
||||
case UNSIGNED_SHORT: {
|
||||
return new UnsignedShortBufferWrapper(
|
||||
((ShortBuffer) data.getBuffer()), geometry);
|
||||
}
|
||||
}
|
||||
throw new UnsupportedOperationException(
|
||||
"Kml Export does not supprt image type: " + data.getDataType());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends IImagingExtension> getExtensionClass() {
|
||||
return KmlColormappedImageExtension.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorMapParameters getColorMapParameters() {
|
||||
return colorMapParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorMapParameters(ColorMapParameters params) {
|
||||
this.colorMapParameters = params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getValue(int x, int y) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,337 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics.ext;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.geotools.coverage.grid.GridEnvelope2D;
|
||||
import org.geotools.coverage.grid.GridGeometry2D;
|
||||
import org.geotools.coverage.grid.InvalidGridGeometryException;
|
||||
import org.geotools.geometry.Envelope2D;
|
||||
import org.opengis.coverage.grid.GridEnvelope;
|
||||
import org.opengis.geometry.Envelope;
|
||||
import org.opengis.referencing.FactoryException;
|
||||
import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
||||
import org.opengis.referencing.operation.TransformException;
|
||||
|
||||
import com.raytheon.uf.common.geospatial.MapUtil;
|
||||
import com.raytheon.uf.common.geospatial.interpolation.data.DataSource;
|
||||
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.viz.core.DrawableImage;
|
||||
import com.raytheon.uf.viz.core.data.IColorMapDataRetrievalCallback;
|
||||
import com.raytheon.uf.viz.core.drawables.ColorMapParameters;
|
||||
import com.raytheon.uf.viz.core.drawables.IColormappedImage;
|
||||
import com.raytheon.uf.viz.core.drawables.PaintProperties;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.GraphicsExtension;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.colormap.IColormappedImageExtension;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.kml.export.graphics.KmlGraphicsTarget;
|
||||
import com.raytheon.uf.viz.kml.export.io.KmlOutputManager;
|
||||
|
||||
/**
|
||||
*
|
||||
* Responsible for creating KML Ground Overlays from colormapped images.
|
||||
* Converts all raw data to floats, reproject to LatLon using an Interpolation
|
||||
* and use the Colormapper to generate a RenderedImage.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 1, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
public class KmlColormappedImageExtension extends
|
||||
GraphicsExtension<KmlGraphicsTarget> implements
|
||||
IColormappedImageExtension {
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(KmlColormappedImageExtension.class);
|
||||
|
||||
@Override
|
||||
public boolean drawRasters(PaintProperties paintProps,
|
||||
DrawableImage... images) throws VizException {
|
||||
target.addGenerator(new Generator(paintProps.getAlpha(), images));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IColormappedImage initializeRaster(
|
||||
IColorMapDataRetrievalCallback dataCallback,
|
||||
ColorMapParameters colorMapParameters) {
|
||||
return new KmlColormappedImage(dataCallback, colorMapParameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCompatibilityValue(KmlGraphicsTarget target) {
|
||||
return Compatibilty.TARGET_COMPATIBLE;
|
||||
}
|
||||
|
||||
private static class Generator extends KmlGroundOverlayGenerator {
|
||||
|
||||
private final DrawableImage[] images;
|
||||
|
||||
public Generator(float alpha, DrawableImage[] images) {
|
||||
super(alpha);
|
||||
this.images = images;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFeature(KmlOutputManager outputManager) {
|
||||
drawRasters(outputManager, Arrays.asList(images));
|
||||
}
|
||||
|
||||
private void drawRasters(KmlOutputManager out,
|
||||
List<DrawableImage> images) {
|
||||
Map<GridGeometry2D, DataSource> matches = new HashMap<GridGeometry2D, DataSource>();
|
||||
List<DrawableImage> others = new ArrayList<DrawableImage>();
|
||||
ColorMapParameters params = null;
|
||||
boolean interpolated = false;
|
||||
// find candidates for merging tiles, matches must have the same
|
||||
// color map parameters and interpolations state.
|
||||
for (DrawableImage image : images) {
|
||||
KmlColormappedImage kmlImage = (KmlColormappedImage) image
|
||||
.getImage();
|
||||
KmlMesh mesh = (KmlMesh) image.getCoverage().getMesh();
|
||||
try {
|
||||
if (params == null) {
|
||||
params = kmlImage.getColorMapParameters();
|
||||
interpolated = kmlImage.isInterpolated();
|
||||
matches.put(mesh.getImageGeometry(),
|
||||
kmlImage.getData(mesh.getImageGeometry()));
|
||||
} else if (!params.equals(kmlImage.getColorMapParameters())) {
|
||||
others.add(image);
|
||||
} else if (interpolated != kmlImage.isInterpolated()) {
|
||||
others.add(image);
|
||||
} else {
|
||||
matches.put(mesh.getImageGeometry(),
|
||||
kmlImage.getData(mesh.getImageGeometry()));
|
||||
}
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
if (!others.isEmpty()) {
|
||||
drawRasters(out, others);
|
||||
}
|
||||
try {
|
||||
drawRastersInternal(out, matches, params, interpolated);
|
||||
} catch (FactoryException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
|
||||
e);
|
||||
} catch (TransformException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* images must all have the same colormap parameters and interpolation
|
||||
*
|
||||
* @param paintProps
|
||||
* @param images
|
||||
* @return
|
||||
* @throws TransformException
|
||||
* @throws FactoryException
|
||||
* @throws VizException
|
||||
*/
|
||||
private void drawRastersInternal(KmlOutputManager out,
|
||||
Map<GridGeometry2D, DataSource> map,
|
||||
ColorMapParameters parameters, boolean interpolated)
|
||||
throws FactoryException, TransformException {
|
||||
// attempt to merge
|
||||
map = mergeTiles(map);
|
||||
// and then draw any that were merged.
|
||||
for (Entry<GridGeometry2D, DataSource> entry : map.entrySet()) {
|
||||
reprojectAndMakeOverlay(out, entry.getKey(), entry.getValue(),
|
||||
parameters, interpolated);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* make the kml overlay object.
|
||||
*
|
||||
* @param paintProps
|
||||
* @param geometry
|
||||
* @param images
|
||||
* @throws TransformException
|
||||
* @throws FactoryException
|
||||
* @throws VizException
|
||||
*/
|
||||
private void reprojectAndMakeOverlay(KmlOutputManager out,
|
||||
GridGeometry2D geometry, DataSource data,
|
||||
ColorMapParameters parameters, boolean interpolated)
|
||||
throws FactoryException, TransformException {
|
||||
Envelope env = new Envelope2D(MapUtil.LATLON_PROJECTION, -180, -90,
|
||||
360, 180);
|
||||
GridGeometry2D projectedGeometry;
|
||||
projectedGeometry = GridGeometry2D.wrap(MapUtil.reprojectGeometry(
|
||||
geometry, env));
|
||||
float[] fdata = reproject(geometry, projectedGeometry, data,
|
||||
interpolated);
|
||||
makeOverlay(out, projectedGeometry, fdata, parameters);
|
||||
}
|
||||
|
||||
private Map<GridGeometry2D, DataSource> mergeTiles(
|
||||
Map<GridGeometry2D, DataSource> map) {
|
||||
Map<GridGeometry2D, DataSource> newmap = new HashMap<GridGeometry2D, DataSource>();
|
||||
while (!map.isEmpty()) {
|
||||
// each iteration removes a single entry and also any entries
|
||||
// that are representable in the same grid space.
|
||||
Iterator<Entry<GridGeometry2D, DataSource>> it = map.entrySet()
|
||||
.iterator();
|
||||
Entry<GridGeometry2D, DataSource> entry = it.next();
|
||||
it.remove();
|
||||
GridGeometry2D geom = entry.getKey();
|
||||
CoordinateReferenceSystem crs = geom
|
||||
.getCoordinateReferenceSystem();
|
||||
Envelope2D env = geom.getEnvelope2D();
|
||||
// bigenv will be an envelope big enopugh to hold all compatible
|
||||
// grids.
|
||||
Envelope2D bigenv = null;
|
||||
Map<Envelope2D, DataSource> envmap = new HashMap<Envelope2D, DataSource>();
|
||||
envmap.put(env, entry.getValue());
|
||||
float dx = (float) (env.width / geom.getGridRange2D().width);
|
||||
float dy = (float) (env.height / geom.getGridRange2D().height);
|
||||
// loop through remaining entries to find any matches, a match
|
||||
// will have the same crs, grid spacing and the distance between
|
||||
// the envelopes will be a multiple of the grid spacing.
|
||||
while (it.hasNext()) {
|
||||
entry = it.next();
|
||||
GridGeometry2D geom2 = entry.getKey();
|
||||
CoordinateReferenceSystem crs2 = geom2
|
||||
.getCoordinateReferenceSystem();
|
||||
Envelope2D env2 = geom2.getEnvelope2D();
|
||||
float dx2 = (float) (env2.width / geom2.getGridRange2D().width);
|
||||
float dy2 = (float) (env2.height / geom2.getGridRange2D().height);
|
||||
// numeric comparisons are done using floats because float
|
||||
// precision is considered "close enough" and double
|
||||
// precision results in very small inconsitencies.
|
||||
if (!crs.equals(crs2) || dx != dx2 || dy != dy2) {
|
||||
continue;
|
||||
}
|
||||
// Make sure that the two grids line up, the distance
|
||||
// between the envelopes should be an even multiple of dx
|
||||
// and dy otherwise the grids are slightly offset from
|
||||
// eachother and incompatible.
|
||||
float xoffset = (float) ((env.x - env2.x) / dx);
|
||||
float yoffset = (float) ((env.y - env2.y) / dy);
|
||||
if (xoffset != (int) xoffset || yoffset != (int) yoffset) {
|
||||
continue;
|
||||
}
|
||||
// at this point the two grids are compatible so we add them
|
||||
// to the bigenv.
|
||||
if (bigenv == null) {
|
||||
bigenv = new Envelope2D(env);
|
||||
}
|
||||
it.remove();
|
||||
envmap.put(env2, entry.getValue());
|
||||
bigenv.add(env2);
|
||||
}
|
||||
if (bigenv != null) {
|
||||
// determine GridEnvelope mapping needed to put all the
|
||||
// matching grids into the same space.
|
||||
try {
|
||||
GridEnvelope2D range = geom.worldToGrid(bigenv);
|
||||
range.x = 0;
|
||||
range.y = 0;
|
||||
GridGeometry2D newGeom = new GridGeometry2D(
|
||||
(GridEnvelope) range, bigenv);
|
||||
Map<GridEnvelope2D, DataSource> rangemap = new HashMap<GridEnvelope2D, DataSource>();
|
||||
for (Entry<Envelope2D, DataSource> envent : envmap
|
||||
.entrySet()) {
|
||||
rangemap.put(newGeom.worldToGrid(envent.getKey()),
|
||||
envent.getValue());
|
||||
}
|
||||
newmap.put(newGeom, new MergedDataSource(rangemap));
|
||||
} catch (InvalidGridGeometryException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
} catch (TransformException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
}
|
||||
} else {
|
||||
// if there are no compatible grids than this grid must be
|
||||
// handled all alone.
|
||||
newmap.put(geom, envmap.get(env));
|
||||
}
|
||||
}
|
||||
return newmap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Wraps multiple data sources that each cover a tile into a single data
|
||||
* source so it can all be reprojected in a single pass.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 25, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
private static class MergedDataSource implements DataSource {
|
||||
|
||||
private final Map<GridEnvelope2D, DataSource> sources;
|
||||
|
||||
public MergedDataSource(Map<GridEnvelope2D, DataSource> sources) {
|
||||
this.sources = sources;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDataValue(int x, int y) {
|
||||
for (Entry<GridEnvelope2D, DataSource> entry : sources.entrySet()) {
|
||||
GridEnvelope2D env = entry.getKey();
|
||||
if (env.contains(x, y)) {
|
||||
x -= env.x;
|
||||
y -= env.y;
|
||||
return entry.getValue().getDataValue(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
return Double.NaN;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics.ext;
|
||||
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.collections.keyvalue.MultiKey;
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
import org.geotools.coverage.grid.GridEnvelope2D;
|
||||
import org.geotools.coverage.grid.GridGeometry2D;
|
||||
import org.geotools.geometry.Envelope2D;
|
||||
import org.opengis.referencing.FactoryException;
|
||||
import org.opengis.referencing.operation.TransformException;
|
||||
|
||||
import com.raytheon.uf.common.geospatial.interpolation.BilinearInterpolation;
|
||||
import com.raytheon.uf.common.geospatial.interpolation.GridReprojection;
|
||||
import com.raytheon.uf.common.geospatial.interpolation.Interpolation;
|
||||
import com.raytheon.uf.common.geospatial.interpolation.NearestNeighborInterpolation;
|
||||
import com.raytheon.uf.common.geospatial.interpolation.data.DataSource;
|
||||
import com.raytheon.uf.common.geospatial.interpolation.data.FloatArrayWrapper;
|
||||
import com.raytheon.uf.viz.core.data.IColorMapDataRetrievalCallback.ColorMapData;
|
||||
import com.raytheon.uf.viz.core.data.prep.Colormapper;
|
||||
import com.raytheon.uf.viz.core.drawables.ColorMapParameters;
|
||||
import com.raytheon.uf.viz.kml.export.KmlFeatureGenerator;
|
||||
import com.raytheon.uf.viz.kml.export.io.KmlOutputManager;
|
||||
|
||||
import de.micromata.opengis.kml.v_2_2_0.GroundOverlay;
|
||||
import de.micromata.opengis.kml.v_2_2_0.LatLonBox;
|
||||
|
||||
/**
|
||||
* Base class for any feature generator that is creating a ground overlay,
|
||||
* provides the reproject logic as well as logic for actually making the
|
||||
* overlay.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 14, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public abstract class KmlGroundOverlayGenerator extends KmlFeatureGenerator {
|
||||
|
||||
private static Map<MultiKey, Reference<GridReprojection>> reprojCache = new HashMap<MultiKey, Reference<GridReprojection>>();
|
||||
|
||||
protected final double alpha;
|
||||
|
||||
public KmlGroundOverlayGenerator(double alpha) {
|
||||
this.alpha = alpha;
|
||||
}
|
||||
|
||||
protected void makeOverlay(KmlOutputManager out, GridGeometry2D geometry,
|
||||
float[] fdata, ColorMapParameters parameters) {
|
||||
GridEnvelope2D range = geometry.getGridRange2D();
|
||||
int[] dimensions = { range.width, range.height };
|
||||
ColorMapData data = new ColorMapData(FloatBuffer.wrap(fdata),
|
||||
dimensions);
|
||||
RenderedImage image = Colormapper.colorMap(data, parameters);
|
||||
makeOverlay(out, image, geometry.getEnvelope2D());
|
||||
}
|
||||
|
||||
protected void makeOverlay(KmlOutputManager out, RenderedImage image,
|
||||
Envelope2D envelope) {
|
||||
GroundOverlay overlay = new GroundOverlay();
|
||||
overlay.setColor(toColorStr(alpha, new RGB(255, 255, 255)));
|
||||
overlay.setName("Image");
|
||||
overlay.createAndSetIcon().setHref(out.addImage(image));
|
||||
LatLonBox box = overlay.createAndSetLatLonBox();
|
||||
box.setNorth(envelope.getMaxY());
|
||||
box.setEast(envelope.getMaxX());
|
||||
box.setSouth(envelope.getMinY());
|
||||
box.setWest(envelope.getMinX());
|
||||
out.addFeature(overlay);
|
||||
}
|
||||
|
||||
protected float[] reproject(GridGeometry2D src, GridGeometry2D dest,
|
||||
DataSource data, Boolean interpolated) throws FactoryException,
|
||||
TransformException {
|
||||
GridReprojection reproj = getReprojection(src, dest);
|
||||
Interpolation interp = null;
|
||||
if (interpolated) {
|
||||
interp = new BilinearInterpolation();
|
||||
} else {
|
||||
interp = new NearestNeighborInterpolation();
|
||||
}
|
||||
FloatArrayWrapper dst = new FloatArrayWrapper(dest);
|
||||
return reproj.reprojectedGrid(interp, data, dst).getArray();
|
||||
}
|
||||
|
||||
protected GridReprojection getReprojection(GridGeometry2D src,
|
||||
GridGeometry2D dest) throws FactoryException, TransformException {
|
||||
MultiKey key = new MultiKey(src, dest);
|
||||
GridReprojection reproj = null;
|
||||
boolean needsCompute = false;
|
||||
synchronized (reprojCache) {
|
||||
Reference<GridReprojection> reprojRef = reprojCache.get(key);
|
||||
if (reprojRef != null) {
|
||||
reproj = reprojRef.get();
|
||||
}
|
||||
if (reproj == null) {
|
||||
reproj = new GridReprojection(src, dest);
|
||||
needsCompute = true;
|
||||
reprojCache.put(key,
|
||||
new SoftReference<GridReprojection>(reproj));
|
||||
}
|
||||
}
|
||||
synchronized (reproj) {
|
||||
if (needsCompute) {
|
||||
reproj.computeTransformTable();
|
||||
}
|
||||
}
|
||||
return reproj;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics.ext;
|
||||
|
||||
import com.raytheon.uf.viz.core.drawables.IImage;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
|
||||
/**
|
||||
* Base image class for KML that does almost nothing and ignores any of the
|
||||
* methods that aren't important to KML.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 1, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public abstract class KmlImage implements IImage {
|
||||
|
||||
private boolean interpolated;
|
||||
|
||||
@Override
|
||||
public void stage() throws VizException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Status getStatus() {
|
||||
return Status.LOADED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInterpolated(boolean isInterpolated) {
|
||||
this.interpolated = isInterpolated;
|
||||
}
|
||||
|
||||
public boolean isInterpolated() {
|
||||
return interpolated;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.core.drawables.IImage#dispose()
|
||||
*/
|
||||
@Override
|
||||
public void dispose() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBrightness(float brightness) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContrast(float contrast) {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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.uf.viz.kml.export.graphics.ext;
|
||||
|
||||
import org.geotools.coverage.grid.GeneralGridGeometry;
|
||||
import org.geotools.coverage.grid.GridEnvelope2D;
|
||||
import org.geotools.coverage.grid.GridGeometry2D;
|
||||
import org.geotools.geometry.Envelope2D;
|
||||
import org.opengis.coverage.grid.GridEnvelope;
|
||||
|
||||
import com.raytheon.uf.viz.core.IMesh;
|
||||
import com.raytheon.uf.viz.core.drawables.IDescriptor;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.GraphicsExtension;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.core.map.IMapMeshExtension;
|
||||
import com.raytheon.uf.viz.kml.export.graphics.KmlGraphicsTarget;
|
||||
|
||||
/**
|
||||
*
|
||||
* Creates meshes.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 1, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
public class KmlMapMeshExtension extends GraphicsExtension<KmlGraphicsTarget>
|
||||
implements IMapMeshExtension {
|
||||
|
||||
@Override
|
||||
public IMesh constructMesh(GridGeometry2D imageGeometry,
|
||||
GeneralGridGeometry targetGeometry) throws VizException {
|
||||
GridEnvelope2D range = imageGeometry.getGridRange2D();
|
||||
Envelope2D envelope = imageGeometry.getEnvelope2D();
|
||||
range.x = 0;
|
||||
range.y = 0;
|
||||
imageGeometry = new GridGeometry2D((GridEnvelope) range, envelope);
|
||||
return new KmlMesh(imageGeometry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMesh constructMesh(GridGeometry2D imageGeometry,
|
||||
IDescriptor targetDescriptor) throws VizException {
|
||||
return constructMesh(imageGeometry, targetDescriptor.getGridGeometry());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCompatibilityValue(KmlGraphicsTarget target) {
|
||||
return Compatibilty.TARGET_COMPATIBLE;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics.ext;
|
||||
|
||||
import org.geotools.coverage.grid.GeneralGridGeometry;
|
||||
import org.geotools.coverage.grid.GridGeometry2D;
|
||||
import org.geotools.geometry.jts.ReferencedEnvelope;
|
||||
import org.opengis.geometry.Envelope;
|
||||
import org.opengis.referencing.FactoryException;
|
||||
import org.opengis.referencing.operation.TransformException;
|
||||
|
||||
import com.raytheon.uf.common.geospatial.MapUtil;
|
||||
import com.raytheon.uf.viz.core.IExtent;
|
||||
import com.raytheon.uf.viz.core.IMesh;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
|
||||
/**
|
||||
*
|
||||
* Basically just a container for a grid geometry.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 1, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
public class KmlMesh implements IMesh {
|
||||
|
||||
private final GridGeometry2D imageGeometry;
|
||||
|
||||
private Envelope latLonEnvelope;
|
||||
|
||||
public KmlMesh(GridGeometry2D imageGeometry) {
|
||||
this.imageGeometry = imageGeometry;
|
||||
}
|
||||
|
||||
public GridGeometry2D getImageGeometry() {
|
||||
return imageGeometry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean intersects(IExtent extent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KmlMesh reproject(GeneralGridGeometry targetGeometry)
|
||||
throws VizException {
|
||||
return clone(targetGeometry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KmlMesh clone(GeneralGridGeometry targetGeometry)
|
||||
throws VizException {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Envelope getLatLonEnvelope() throws TransformException {
|
||||
if (latLonEnvelope == null) {
|
||||
ReferencedEnvelope env = new ReferencedEnvelope(
|
||||
imageGeometry.getEnvelope());
|
||||
try {
|
||||
latLonEnvelope = env.transform(MapUtil.LATLON_PROJECTION, true,
|
||||
500);
|
||||
} catch (FactoryException e) {
|
||||
throw new TransformException(e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
return latLonEnvelope;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics.ext;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import com.raytheon.uf.viz.core.DrawableImage;
|
||||
import com.raytheon.uf.viz.core.IExtent;
|
||||
import com.raytheon.uf.viz.core.drawables.ColorMapParameters;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.IMosaicImageExtension;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.IMosaicImageExtension.IMosaicImage;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
|
||||
/**
|
||||
*
|
||||
* Keeps track of the images that are to be mosaiced so that the extension can
|
||||
* handle rendering them.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 20, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
class KmlMosaicImage implements IMosaicImage {
|
||||
|
||||
private ColorMapParameters colorMapParameters;
|
||||
|
||||
private int[] bounds;
|
||||
|
||||
private IExtent imageExtent;
|
||||
|
||||
private DrawableImage[] imagesToMosaic;
|
||||
|
||||
private Comparator<Double> mosaicComparator;
|
||||
|
||||
public KmlMosaicImage(int[] imageBounds, IExtent imageExtent,
|
||||
ColorMapParameters params, Comparator<Double> mosaicComparator) {
|
||||
this.colorMapParameters = params;
|
||||
this.bounds = imageBounds;
|
||||
this.imageExtent = imageExtent;
|
||||
this.mosaicComparator = mosaicComparator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorMapParameters getColorMapParameters() {
|
||||
return colorMapParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorMapParameters(ColorMapParameters params) {
|
||||
this.colorMapParameters = params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getValue(int x, int y) {
|
||||
// TODO do I need this?
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stage() throws VizException {
|
||||
// TODO do I need this?
|
||||
}
|
||||
|
||||
@Override
|
||||
public Status getStatus() {
|
||||
// TODO do I need this?
|
||||
return Status.LOADED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInterpolated(boolean isInterpolated) {
|
||||
// TODO do I need this?
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
// TODO do I need this?
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth() {
|
||||
return bounds[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return bounds[1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBrightness(float brightness) {
|
||||
// TODO do I need this?
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContrast(float contrast) {
|
||||
// TODO do I need this?
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends IMosaicImageExtension> getExtensionClass() {
|
||||
return IMosaicImageExtension.class;
|
||||
}
|
||||
|
||||
public Comparator<Double> getMosaicComparator() {
|
||||
return mosaicComparator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImagesToMosaic(DrawableImage... images) {
|
||||
this.imagesToMosaic = images;
|
||||
}
|
||||
|
||||
public DrawableImage[] getImagesToMosaic() {
|
||||
return this.imagesToMosaic;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImageExtent(IExtent imageExtent) {
|
||||
this.imageExtent = imageExtent;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,255 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics.ext;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.geotools.coverage.grid.GridEnvelope2D;
|
||||
import org.geotools.coverage.grid.GridGeometry2D;
|
||||
import org.geotools.geometry.Envelope2D;
|
||||
import org.geotools.geometry.jts.ReferencedEnvelope;
|
||||
import org.opengis.coverage.grid.GridEnvelope;
|
||||
import org.opengis.referencing.FactoryException;
|
||||
import org.opengis.referencing.operation.TransformException;
|
||||
|
||||
import com.raytheon.uf.common.geospatial.interpolation.Interpolation;
|
||||
import com.raytheon.uf.common.geospatial.interpolation.NearestNeighborInterpolation;
|
||||
import com.raytheon.uf.common.geospatial.interpolation.data.AbstractDataWrapper;
|
||||
import com.raytheon.uf.common.geospatial.interpolation.data.ByteBufferWrapper;
|
||||
import com.raytheon.uf.common.geospatial.interpolation.data.DataDestination;
|
||||
import com.raytheon.uf.common.geospatial.interpolation.data.DataSource;
|
||||
import com.raytheon.uf.common.geospatial.interpolation.data.FloatArrayWrapper;
|
||||
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.viz.core.DrawableImage;
|
||||
import com.raytheon.uf.viz.core.IExtent;
|
||||
import com.raytheon.uf.viz.core.drawables.ColorMapParameters;
|
||||
import com.raytheon.uf.viz.core.drawables.PaintProperties;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.GraphicsExtension;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.IMosaicImageExtension;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.kml.export.graphics.KmlGraphicsTarget;
|
||||
import com.raytheon.uf.viz.kml.export.io.KmlOutputManager;
|
||||
|
||||
/**
|
||||
* Generates a KMLGroundOverlay for mosaic by reprojecting all the images to a
|
||||
* common Lat/Lon space and performing a MaxVal algorithm.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 8, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class KmlMosaicImageExtension extends
|
||||
GraphicsExtension<KmlGraphicsTarget> implements IMosaicImageExtension {
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(KmlMosaicImageExtension.class);
|
||||
|
||||
@Override
|
||||
public boolean drawRasters(PaintProperties paintProps,
|
||||
DrawableImage... images) throws VizException {
|
||||
for (DrawableImage image : images) {
|
||||
target.addGenerator(new Generator(paintProps.getAlpha(),
|
||||
(KmlMosaicImage) image.getImage()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMosaicImage initializeRaster(int[] imageBounds,
|
||||
IExtent imageExtent, ColorMapParameters params) throws VizException {
|
||||
return new KmlMosaicImage(imageBounds, imageExtent, params,
|
||||
getMosaicComparator());
|
||||
}
|
||||
|
||||
/**
|
||||
* The mosaic comparator is used to implement different mosaicing
|
||||
* algorithms. The first Double will be the current value, and the second
|
||||
* double will be the dataValue, the dataValue will only be used if it is
|
||||
* greater than the existing value.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected Comparator<Double> getMosaicComparator() {
|
||||
return new Comparator<Double>() {
|
||||
@Override
|
||||
public int compare(Double o1, Double o2) {
|
||||
// always use data value.
|
||||
return -1;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCompatibilityValue(KmlGraphicsTarget target) {
|
||||
return Compatibilty.TARGET_COMPATIBLE;
|
||||
}
|
||||
|
||||
private static class Generator extends KmlGroundOverlayGenerator {
|
||||
|
||||
private final Comparator<Double> mosaicComparator;
|
||||
|
||||
private final ColorMapParameters parameters;
|
||||
|
||||
private final DrawableImage[] images;
|
||||
|
||||
public Generator(float alpha, KmlMosaicImage image) {
|
||||
super(alpha);
|
||||
this.images = image.getImagesToMosaic();
|
||||
this.parameters = image.getColorMapParameters();
|
||||
this.mosaicComparator = image.getMosaicComparator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFeature(KmlOutputManager outputManager) {
|
||||
if (images.length == 0) {
|
||||
return;
|
||||
}
|
||||
long startTime = System.currentTimeMillis();
|
||||
// make a big envelope in lat lon space that is large enough to hold
|
||||
// all radar sites.
|
||||
ReferencedEnvelope bigenv = null;
|
||||
for (DrawableImage image : images) {
|
||||
KmlMesh mesh = (KmlMesh) image.getCoverage().getMesh();
|
||||
try {
|
||||
ReferencedEnvelope env = new ReferencedEnvelope(
|
||||
mesh.getLatLonEnvelope());
|
||||
if (bigenv == null) {
|
||||
bigenv = env;
|
||||
} else {
|
||||
bigenv.expandToInclude(env);
|
||||
}
|
||||
} catch (TransformException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
// create a range that preserves aspect ratio with the larger
|
||||
// dimension as 1024 pixels, 1024 is a randomly chosen number.
|
||||
GridEnvelope2D range = new GridEnvelope2D(0, 0, 1024, 1024);
|
||||
if (bigenv.getWidth() > bigenv.getHeight()) {
|
||||
range.height = (int) (range.width * bigenv.getHeight() / bigenv
|
||||
.getWidth());
|
||||
} else {
|
||||
range.width = (int) (range.height * bigenv.getWidth() / bigenv
|
||||
.getHeight());
|
||||
}
|
||||
GridGeometry2D geom = new GridGeometry2D(range, bigenv);
|
||||
// fullDest is the end location of reprojected data values
|
||||
FloatArrayWrapper fullDest = new FloatArrayWrapper(geom);
|
||||
Arrays.fill(fullDest.getArray(), Float.NaN);
|
||||
Interpolation interp = new NearestNeighborInterpolation();
|
||||
for (DrawableImage image : images) {
|
||||
KmlMesh mesh = (KmlMesh) image.getCoverage().getMesh();
|
||||
KmlColormappedImage kmlImage = (KmlColormappedImage) image
|
||||
.getImage();
|
||||
try {
|
||||
// Reproject a subgrid rather than the full grid because it
|
||||
// is faster. The MosaicDataDestination maps the subgrid to
|
||||
// the larger grid.
|
||||
GridEnvelope2D gridenv = geom.worldToGrid(new Envelope2D(
|
||||
mesh.getLatLonEnvelope()));
|
||||
DataDestination dest = new MosaicDataDestination(
|
||||
mosaicComparator, fullDest, gridenv.clone());
|
||||
Envelope2D env = geom.gridToWorld(gridenv);
|
||||
gridenv.x = 0;
|
||||
gridenv.y = 0;
|
||||
GridGeometry2D newGeom = new GridGeometry2D(
|
||||
(GridEnvelope) gridenv, env);
|
||||
GridGeometry2D oldGeom = mesh.getImageGeometry();
|
||||
DataSource source = kmlImage.getData(oldGeom);
|
||||
getReprojection(oldGeom, newGeom).reprojectedGrid(interp,
|
||||
source, dest);
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
} catch (TransformException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
} catch (FactoryException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
makeOverlay(outputManager, geom, fullDest.getArray(), parameters);
|
||||
System.out.println(System.currentTimeMillis() - startTime);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Provides a mapping into a subgrid of a larger destination and performs
|
||||
* maxVal mosaic algorithm when multiple radars map t a single grid cell.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 25, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
private static class MosaicDataDestination implements DataDestination {
|
||||
|
||||
private final Comparator<Double> mosaicComparator;
|
||||
|
||||
private final AbstractDataWrapper fullDest;
|
||||
|
||||
private final GridEnvelope2D envelope;
|
||||
|
||||
public MosaicDataDestination(Comparator<Double> mosaicComparator,
|
||||
AbstractDataWrapper fullDest, GridEnvelope2D envelope) {
|
||||
this.mosaicComparator = mosaicComparator;
|
||||
this.fullDest = fullDest;
|
||||
this.envelope = envelope;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDataValue(double dataValue, int x, int y) {
|
||||
x = x + envelope.x;
|
||||
y = y + envelope.y;
|
||||
// shift the data and apply maxVal algorithm
|
||||
double oldValue = fullDest.getDataValue(x, y);
|
||||
if (mosaicComparator.compare(oldValue, dataValue) < 0) {
|
||||
fullDest.setDataValue(dataValue, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -17,46 +17,46 @@
|
|||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.viz.ghg;
|
||||
package com.raytheon.uf.viz.kml.export.graphics.ext;
|
||||
|
||||
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 java.util.Comparator;
|
||||
|
||||
import com.raytheon.viz.gfe.core.DataManager;
|
||||
import com.raytheon.viz.ghg.makehazard.MakeHazardDialog;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.IMosaicMaxValImageExtension;
|
||||
|
||||
/**
|
||||
* TODO Add Description MakeHazardsAction.java Jun 5, 2008
|
||||
* Extends mosaic extesnion to perform maxVal mosaicing.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 5, 2008 Eric Babin Initial Creation
|
||||
* Jul 10, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author ebabin
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class MakeHazardsAction extends AbstractHandler {
|
||||
public class KmlMosaicMaxValImageExtension extends KmlMosaicImageExtension
|
||||
implements IMosaicMaxValImageExtension {
|
||||
|
||||
@Override
|
||||
public Object execute(ExecutionEvent arg0) throws ExecutionException {
|
||||
DataManager dm = DataManager.getCurrentInstance();
|
||||
if (dm == null) {
|
||||
return null;
|
||||
}
|
||||
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
|
||||
.getShell();
|
||||
MakeHazardDialog monitorDlg = new MakeHazardDialog(shell, dm);
|
||||
monitorDlg.open();
|
||||
protected Comparator<Double> getMosaicComparator() {
|
||||
return new Comparator<Double>() {
|
||||
@Override
|
||||
public int compare(Double o1, Double o2) {
|
||||
if (Double.isNaN(o2)) {
|
||||
return 1;
|
||||
} else if (Double.isNaN(o1)) {
|
||||
return -1;
|
||||
} else {
|
||||
return Double.compare(o1, o2);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics.ext;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import com.raytheon.uf.viz.core.drawables.ext.IMosaicOrderedImageExtension;
|
||||
|
||||
/**
|
||||
* Extends mosaic extesnion to perform ordered mosaicing.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jul 10, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class KmlMosaicOrderedImageExtension extends KmlMosaicImageExtension
|
||||
implements IMosaicOrderedImageExtension {
|
||||
|
||||
@Override
|
||||
protected Comparator<Double> getMosaicComparator() {
|
||||
return new Comparator<Double>() {
|
||||
@Override
|
||||
public int compare(Double o1, Double o2) {
|
||||
if (o2 != 0 && !Double.isNaN(o2)) {
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics.ext;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.RenderedImage;
|
||||
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
|
||||
import com.raytheon.uf.viz.core.data.IRenderedImageCallback;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.IImagingExtension;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
|
||||
/**
|
||||
* Basically a wrapper around a RenderedImageCallback but also has logic for
|
||||
* filling in transparent parts of plots.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 11, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class KmlRasterImage extends KmlImage {
|
||||
|
||||
protected final IRenderedImageCallback callback;
|
||||
|
||||
/**
|
||||
* @param imageCallback
|
||||
*/
|
||||
public KmlRasterImage(IRenderedImageCallback imageCallback) {
|
||||
this.callback = imageCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends IImagingExtension> getExtensionClass() {
|
||||
return KmlRasterImageExtension.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the image for a ground overlay
|
||||
*
|
||||
* @return
|
||||
* @throws VizException
|
||||
*/
|
||||
public RenderedImage getImage() throws VizException {
|
||||
return callback.getImage();
|
||||
}
|
||||
|
||||
/**
|
||||
* get the image for a plot
|
||||
*
|
||||
* @param target
|
||||
* @return
|
||||
* @throws VizException
|
||||
*/
|
||||
public RenderedImage getImage(RGB backcolor) throws VizException {
|
||||
RenderedImage ri = getImage();
|
||||
|
||||
BufferedImage bi = cloneRenderedImage(ri);
|
||||
applyFill(bi, backcolor);
|
||||
return bi;
|
||||
}
|
||||
|
||||
protected BufferedImage cloneRenderedImage(RenderedImage ri)
|
||||
throws VizException {
|
||||
BufferedImage bi = new BufferedImage(ri.getWidth(), ri.getHeight(),
|
||||
BufferedImage.TYPE_INT_ARGB);
|
||||
if (ri instanceof Image) {
|
||||
bi.getGraphics().drawImage((Image) ri, 0, 0, null);
|
||||
} else {
|
||||
throw new VizException("Cannot handle image of type "
|
||||
+ ri.getClass().getSimpleName());
|
||||
}
|
||||
return bi;
|
||||
}
|
||||
|
||||
protected void applyFill(BufferedImage bi, RGB backcolor) {
|
||||
int backint = (0xFF << 24) | (backcolor.red << 16)
|
||||
| (backcolor.green << 8) | backcolor.blue;
|
||||
for (int i = 0; i < bi.getWidth(); i++) {
|
||||
for (int j = 0; j < bi.getHeight(); j++) {
|
||||
int argb = bi.getRGB(i, j);
|
||||
int alphaint = ((argb >> 24) & 0xFF);
|
||||
if (alphaint == 0) {
|
||||
argb = backint;
|
||||
} else if (alphaint != 255) {
|
||||
// blend the colors.
|
||||
double alpha = alphaint / 255.0;
|
||||
int red = (argb >> 16) & 0xFF;
|
||||
int green = (argb >> 8) & 0xFF;
|
||||
int blue = (argb >> 0) & 0xFF;
|
||||
red = (int) (red * alpha + backcolor.red * (1.0 - alpha));
|
||||
green = (int) (green * alpha + backcolor.green
|
||||
* (1.0 - alpha));
|
||||
blue = (int) (blue * alpha + backcolor.blue * (1.0 - alpha));
|
||||
argb = (0xFF << 24) | (red << 16) | (green << 8) | blue;
|
||||
}
|
||||
bi.setRGB(i, j, argb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics.ext;
|
||||
|
||||
import org.geotools.coverage.grid.GridCoverage2D;
|
||||
import org.geotools.coverage.grid.GridCoverageFactory;
|
||||
import org.geotools.coverage.processing.Operations;
|
||||
import org.geotools.geometry.DirectPosition2D;
|
||||
import org.geotools.geometry.Envelope2D;
|
||||
import org.geotools.geometry.jts.ReferencedEnvelope;
|
||||
import org.opengis.referencing.operation.MathTransform;
|
||||
import org.opengis.referencing.operation.TransformException;
|
||||
|
||||
import com.raytheon.uf.common.geospatial.MapUtil;
|
||||
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.viz.core.DrawableImage;
|
||||
import com.raytheon.uf.viz.core.PixelCoverage;
|
||||
import com.raytheon.uf.viz.core.drawables.PaintProperties;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.GraphicsExtension;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.IImagingExtension;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.kml.export.graphics.KmlGraphicsTarget;
|
||||
import com.raytheon.uf.viz.kml.export.io.KmlOutputManager;
|
||||
|
||||
/**
|
||||
* Extension for creating KML Ground Overlay from raster images.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 11, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class KmlRasterImageExtension extends
|
||||
GraphicsExtension<KmlGraphicsTarget> implements IImagingExtension {
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(KmlRasterImageExtension.class);
|
||||
|
||||
@Override
|
||||
public boolean drawRasters(PaintProperties paintProps,
|
||||
DrawableImage... images) throws VizException {
|
||||
target.addGenerator(new Generator(paintProps.getAlpha(), images));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCompatibilityValue(KmlGraphicsTarget target) {
|
||||
return Compatibilty.TARGET_COMPATIBLE;
|
||||
}
|
||||
|
||||
private static class Generator extends KmlGroundOverlayGenerator {
|
||||
|
||||
private final DrawableImage[] images;
|
||||
|
||||
public Generator(float alpha, DrawableImage[] images) {
|
||||
super(alpha);
|
||||
this.images = images;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFeature(KmlOutputManager outputManager) {
|
||||
GridCoverageFactory coverageFactory = new GridCoverageFactory();
|
||||
for (DrawableImage image : images) {
|
||||
KmlRasterImage kmlImage = (KmlRasterImage) image.getImage();
|
||||
PixelCoverage coverage = image.getCoverage();
|
||||
MathTransform transform = gridGeometry.getGridToCRS();
|
||||
DirectPosition2D min = new DirectPosition2D(coverage.getMinX(),
|
||||
coverage.getMinY());
|
||||
DirectPosition2D max = new DirectPosition2D(coverage.getMaxX(),
|
||||
coverage.getMaxY());
|
||||
try {
|
||||
transform.transform(min, min);
|
||||
transform.transform(max, max);
|
||||
ReferencedEnvelope env = new ReferencedEnvelope(
|
||||
new Envelope2D(min, max),
|
||||
gridGeometry.getCoordinateReferenceSystem());
|
||||
GridCoverage2D source = coverageFactory.create("Test",
|
||||
kmlImage.getImage(), env);
|
||||
GridCoverage2D result = (GridCoverage2D) new Operations(
|
||||
null).resample(source, MapUtil.LATLON_PROJECTION);
|
||||
makeOverlay(outputManager, result.getRenderedImage(),
|
||||
result.getEnvelope2D());
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
|
||||
} catch (TransformException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics.ext;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.RenderedImage;
|
||||
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
|
||||
import com.raytheon.uf.viz.core.data.IRenderedImageCallback;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.IImagingExtension;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.ISingleColorImageExtension.ISingleColorImage;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
|
||||
/**
|
||||
*
|
||||
* Adds logic to change colors to KmlRasterIamge.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 1, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
public class KmlSingleColorImage extends KmlRasterImage implements
|
||||
ISingleColorImage {
|
||||
|
||||
private RGB color;
|
||||
|
||||
public KmlSingleColorImage(IRenderedImageCallback callback, RGB color) {
|
||||
super(callback);
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends IImagingExtension> getExtensionClass() {
|
||||
return KmlSingleColorImageExtension.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColor(RGB color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderedImage getImage() throws VizException {
|
||||
RenderedImage ri = callback.getImage();
|
||||
BufferedImage bi = cloneRenderedImage(ri);
|
||||
makeSingleColor(bi);
|
||||
return bi;
|
||||
}
|
||||
|
||||
protected void makeSingleColor(BufferedImage bi) {
|
||||
int colorint = (0xFF << 24) | (color.red << 16) | (color.green << 8)
|
||||
| color.blue;
|
||||
for (int i = 0; i < bi.getWidth(); i++) {
|
||||
for (int j = 0; j < bi.getHeight(); j++) {
|
||||
int argb = bi.getRGB(i, j);
|
||||
// preserve alpha but color becomes color.
|
||||
argb = (0xFF000000 & argb) | (0x00FFFFFF & colorint);
|
||||
bi.setRGB(i, j, argb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics.ext;
|
||||
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
|
||||
import com.raytheon.uf.viz.core.data.IRenderedImageCallback;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.ISingleColorImageExtension;
|
||||
|
||||
/**
|
||||
* Extesnion for creating single color images.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 14, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class KmlSingleColorImageExtension extends KmlRasterImageExtension
|
||||
implements ISingleColorImageExtension {
|
||||
|
||||
@Override
|
||||
public ISingleColorImage constructImage(IRenderedImageCallback callback,
|
||||
RGB color) {
|
||||
return new KmlSingleColorImage(callback, color);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics.ext.point;
|
||||
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.opengis.referencing.FactoryException;
|
||||
import org.opengis.referencing.operation.TransformException;
|
||||
|
||||
import com.raytheon.uf.common.geospatial.MapUtil;
|
||||
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.viz.core.drawables.PaintProperties;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.GraphicsExtension;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.kml.export.KmlFeatureGenerator;
|
||||
import com.raytheon.uf.viz.kml.export.graphics.KmlGraphicsTarget;
|
||||
import com.raytheon.uf.viz.kml.export.graphics.ext.KmlRasterImage;
|
||||
import com.raytheon.uf.viz.kml.export.graphics.ext.KmlRasterImageExtension;
|
||||
import com.raytheon.uf.viz.kml.export.io.KmlOutputManager;
|
||||
import com.raytheon.viz.pointdata.drawables.IPointImageExtension;
|
||||
|
||||
import de.micromata.opengis.kml.v_2_2_0.Coordinate;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Icon;
|
||||
import de.micromata.opengis.kml.v_2_2_0.IconStyle;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Placemark;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Point;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Style;
|
||||
|
||||
/**
|
||||
*
|
||||
* Renders images at points as placemark icons in KML
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 1, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
public class KmlPointImageExtension extends GraphicsExtension<KmlGraphicsTarget>
|
||||
implements IPointImageExtension {
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(KmlRasterImageExtension.class);
|
||||
|
||||
@Override
|
||||
public void drawPointImages(PaintProperties paintProps,
|
||||
PointImage... images) throws VizException {
|
||||
drawPointImages(paintProps, Arrays.asList(images));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPointImages(PaintProperties paintProps,
|
||||
Collection<PointImage> images) throws VizException {
|
||||
target.addGenerator(new Generator(images));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCompatibilityValue(KmlGraphicsTarget target) {
|
||||
return Compatibilty.TARGET_COMPATIBLE;
|
||||
}
|
||||
|
||||
private static class Generator extends KmlFeatureGenerator {
|
||||
|
||||
private final Collection<PointImage> images;
|
||||
|
||||
public Generator(Collection<PointImage> images) {
|
||||
this.images = images;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFeature(KmlOutputManager outputManager) {
|
||||
if (images.size() > 1) {
|
||||
outputManager = outputManager.createFolder("Points");
|
||||
}
|
||||
for (PointImage image : images) {
|
||||
try {
|
||||
Placemark placemark = new Placemark();
|
||||
placemark.setName(image.getSiteId());
|
||||
Coordinate loc = transformToLatLon(image.getX(),
|
||||
image.getY());
|
||||
Point point = placemark.createAndSetPoint();
|
||||
point.addToCoordinates(loc.getLongitude(),
|
||||
loc.getLatitude());
|
||||
Style style = new Style();
|
||||
style.createAndSetLabelStyle().setScale(0);
|
||||
|
||||
IconStyle iconStyle = style.createAndSetIconStyle();
|
||||
iconStyle.setScale(options.getPlotIconScale());
|
||||
double heading = 180 + MapUtil.rotation(
|
||||
new com.vividsolutions.jts.geom.Coordinate(loc
|
||||
.getLongitude(), loc.getLatitude()),
|
||||
gridGeometry);
|
||||
iconStyle.setHeading(heading);
|
||||
Icon icon = iconStyle.createAndSetIcon();
|
||||
|
||||
RenderedImage rImage = null;
|
||||
if (options.isFillPlotBackground()) {
|
||||
rImage = ((KmlRasterImage) image.getImage())
|
||||
.getImage(backgroundColor);
|
||||
} else {
|
||||
rImage = ((KmlRasterImage) image.getImage()).getImage();
|
||||
}
|
||||
String siteId = image.getSiteId();
|
||||
if (siteId == null) {
|
||||
icon.setHref(outputManager.addImage(rImage));
|
||||
} else {
|
||||
siteId = siteId.replaceAll("\\?", "QuestionMark");
|
||||
icon.setHref(outputManager.addImage(rImage,
|
||||
"pointIcons/" + siteId + ".png"));
|
||||
}
|
||||
placemark.setStyleUrl(outputManager.getStyleUrl(style));
|
||||
outputManager.addFeature(placemark);
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
} catch (TransformException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
} catch (FactoryException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
* 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.viz.kml.export.graphics.ext.radar;
|
||||
|
||||
import org.geotools.coverage.grid.GeneralGridGeometry;
|
||||
import org.geotools.coverage.grid.GridGeometry2D;
|
||||
import org.opengis.referencing.FactoryException;
|
||||
|
||||
import com.raytheon.uf.common.dataplugin.radar.RadarRecord;
|
||||
import com.raytheon.uf.common.dataplugin.radar.projection.RadarProjectionFactory;
|
||||
import com.raytheon.uf.viz.core.IMesh;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.GraphicsExtension;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.kml.export.graphics.KmlGraphicsTarget;
|
||||
import com.raytheon.uf.viz.kml.export.graphics.ext.KmlMesh;
|
||||
import com.raytheon.viz.radar.rsc.image.IRadialMeshExtension;
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
|
||||
/**
|
||||
* Creates a KMLMesh by constructing a RadialBinCRS based CrigGeometry object.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 6, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class KmlRadialMeshExtension extends
|
||||
GraphicsExtension<KmlGraphicsTarget> implements IRadialMeshExtension {
|
||||
|
||||
@Override
|
||||
public int getCompatibilityValue(KmlGraphicsTarget target) {
|
||||
return Compatibilty.TARGET_COMPATIBLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMesh constructMesh(RadarRecord record,
|
||||
GeneralGridGeometry targetGeometry) throws VizException {
|
||||
GridGeometry2D imageGeometry;
|
||||
try {
|
||||
imageGeometry = RadarProjectionFactory
|
||||
.constructGridGeometry(new Coordinate(
|
||||
record.getLongitude(), record.getLatitude()),
|
||||
record.getAngleData(), record.getGateResolution(),
|
||||
record.getTrueElevationAngle(),
|
||||
record.getNumBins(), true);
|
||||
} catch (FactoryException e) {
|
||||
throw new VizException(e);
|
||||
}
|
||||
return new KmlMesh(imageGeometry);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
/**
|
||||
* 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.viz.kml.export.io;
|
||||
|
||||
import java.awt.image.RenderedImage;
|
||||
|
||||
import de.micromata.opengis.kml.v_2_2_0.Container;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Feature;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Folder;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Style;
|
||||
|
||||
/**
|
||||
* The Folder output does not actually contain a KMZ stream but allows the
|
||||
* parent to handle all file io.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 1, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class KmlFolderOutputManager implements KmlOutputManager {
|
||||
|
||||
protected final KmlOutputManager parent;
|
||||
|
||||
protected final Folder folder;
|
||||
|
||||
private int imageCounter = 1;
|
||||
|
||||
public KmlFolderOutputManager(KmlOutputManager parent, Folder folder) {
|
||||
this.parent = parent;
|
||||
this.folder = folder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KmlOutputManager createFolder(String name) {
|
||||
return new KmlFolderOutputManager(this, folder.createAndAddFolder()
|
||||
.withName(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String addImage(RenderedImage image) {
|
||||
return addImage(image, "image" + (imageCounter++) + ".png");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String addImage(RenderedImage image, String name) {
|
||||
return parent.addImage(image, folder.getName() + "/" + name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolvePath(String name) {
|
||||
return parent.resolvePath(folder.getName() + "/" + name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStyleUrl(Style style) {
|
||||
return parent.getStyleUrl(style);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFeature(Feature feature) {
|
||||
folder.addToFeature(feature);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Container getContainer() {
|
||||
return folder;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* 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.viz.kml.export.io;
|
||||
|
||||
import java.awt.image.RenderedImage;
|
||||
|
||||
import de.micromata.opengis.kml.v_2_2_0.Container;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Feature;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Style;
|
||||
|
||||
/**
|
||||
* Wrapper around a KMZ file as well as a container java object, each folder an
|
||||
* outputManager creates will be a folder in the KML view as well as a folder in
|
||||
* the kmz file for any image resources that are stored.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 1, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public interface KmlOutputManager {
|
||||
|
||||
public KmlOutputManager createFolder(String name);
|
||||
|
||||
public String addImage(RenderedImage image);
|
||||
|
||||
public String addImage(RenderedImage image, String name);
|
||||
|
||||
public String resolvePath(String name);
|
||||
|
||||
public String getStyleUrl(Style style);
|
||||
|
||||
public void addFeature(Feature feature);
|
||||
|
||||
public Container getContainer();
|
||||
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
/**
|
||||
* 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.viz.kml.export.io;
|
||||
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.xml.bind.JAXB;
|
||||
|
||||
import de.micromata.opengis.kml.v_2_2_0.Container;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Document;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Feature;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Kml;
|
||||
import de.micromata.opengis.kml.v_2_2_0.Style;
|
||||
|
||||
/**
|
||||
* The root output manager holds a the base output stream as well as the root
|
||||
* KML Document.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 1, 2012 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class KmlRootOutputManager implements KmlOutputManager {
|
||||
|
||||
private Set<String> names = new HashSet<String>();
|
||||
|
||||
private final Kml kml;
|
||||
|
||||
private final Document document;
|
||||
|
||||
private IOException exception;
|
||||
|
||||
private int imageCounter = 1;
|
||||
|
||||
private int styleCounter = 1;
|
||||
|
||||
private Map<Style, String> styleMap = new HashMap<Style, String>();
|
||||
|
||||
private final ZipOutputStream zos;
|
||||
|
||||
public KmlRootOutputManager(File kmzFile) throws FileNotFoundException {
|
||||
this.zos = new ZipOutputStream(new FileOutputStream(kmzFile));
|
||||
this.kml = new Kml();
|
||||
this.document = this.kml.createAndSetDocument();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KmlOutputManager createFolder(String name) {
|
||||
return new KmlFolderOutputManager(this, document.createAndAddFolder()
|
||||
.withName(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String addImage(RenderedImage image) {
|
||||
return addImage(image, "image" + (imageCounter++) + ".png");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String addImage(RenderedImage image, String name) {
|
||||
if (names.contains(name)) {
|
||||
String newName = name;
|
||||
for (int i = 1; names.contains(newName); i++) {
|
||||
newName = name.replace(".png", "-" + i + ".png");
|
||||
}
|
||||
name = newName;
|
||||
}
|
||||
names.add(name);
|
||||
synchronized (zos) {
|
||||
try {
|
||||
zos.putNextEntry(new ZipEntry(name));
|
||||
ImageIO.write(image, "png", zos);
|
||||
zos.closeEntry();
|
||||
} catch (IOException e) {
|
||||
exception = e;
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolvePath(String name) {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized String getStyleUrl(Style style) {
|
||||
Style key = style.clone().withId(null);
|
||||
String id = styleMap.get(key);
|
||||
if (id == null) {
|
||||
id = style.getId();
|
||||
if (id == null) {
|
||||
id = "style" + this.styleCounter++;
|
||||
}
|
||||
styleMap.put(key, id);
|
||||
style.setId(id);
|
||||
document.addToStyleSelector(style);
|
||||
}
|
||||
return "#" + id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFeature(Feature feature) {
|
||||
document.addToFeature(feature);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Container getContainer() {
|
||||
return document;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the kmz stream and serializes the kml document.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
if (exception != null) {
|
||||
throw exception;
|
||||
}
|
||||
zos.putNextEntry(new ZipEntry("doc.kml"));
|
||||
JAXB.marshal(kml, zos);
|
||||
zos.closeEntry();
|
||||
zos.close();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
#include <colorUtil>
|
||||
#include <indexing>
|
||||
|
||||
// Multiplier used to store bit mask safely between 0-1
|
||||
const float maskMultiplier = 8.0;
|
||||
|
||||
uniform sampler2D rawTex;
|
||||
uniform float naturalMin;
|
||||
uniform float naturalMax;
|
||||
uniform float cmapMin;
|
||||
uniform float cmapMax;
|
||||
uniform int isFloat;
|
||||
|
||||
uniform int band;
|
||||
|
||||
uniform sampler2D trueColorTexture;
|
||||
uniform int height;
|
||||
uniform int width;
|
||||
|
||||
uniform float noDataValue;
|
||||
uniform float alphaStep;
|
||||
uniform int expectedMask;
|
||||
|
||||
int toBitMask(float alpha) {
|
||||
return int((alpha * maskMultiplier) + 0.5);
|
||||
}
|
||||
|
||||
float getIndex(sampler2D rawTex, float cmapMin, float cmapMax, float naturalMin, float naturalMax, int isFloat) {
|
||||
vec4 textureValue = texture2D(rawTex, gl_TexCoord[0].st);
|
||||
float naturalVal = textureValue.r;
|
||||
if ( isFloat == 0 ) {
|
||||
naturalVal = ((naturalVal * (naturalMax - naturalMin)) + naturalMin);
|
||||
}
|
||||
|
||||
float index = -1.0;
|
||||
if (naturalVal != noDataValue && naturalVal == naturalVal) {
|
||||
index = findIndex(naturalVal, cmapMin, cmapMax);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
if ( band == -1 ) {
|
||||
vec4 imageVal = texture2D(rawTex,gl_TexCoord[0].st);
|
||||
float r = imageVal.r;
|
||||
float g = imageVal.g;
|
||||
float b = imageVal.b;
|
||||
float a = imageVal.a;
|
||||
|
||||
// Round because of 8-bit floating point precision
|
||||
int bitMask = toBitMask(a);
|
||||
if (expectedMask > 0 && bitMask == expectedMask ) {
|
||||
a = 1.0;
|
||||
} else {
|
||||
a = 0.0;
|
||||
}
|
||||
|
||||
gl_FragColor = vec4(r,g,b,a);
|
||||
} else {
|
||||
vec2 xy = gl_FragCoord.xy;
|
||||
vec4 imageVal = texture2D(rawTex,gl_TexCoord[0].st);
|
||||
vec4 curVal = texture2D(trueColorTexture, vec2((xy.x / float(width)), (xy.y / float(height))));
|
||||
|
||||
float r = curVal.r;
|
||||
float g = curVal.g;
|
||||
float b = curVal.b;
|
||||
float a = curVal.a;
|
||||
|
||||
float index = getIndex(rawTex, cmapMin, cmapMax, naturalMin, naturalMax, isFloat);
|
||||
if ( index != -1.0 ) {
|
||||
int currentMask = toBitMask(a);
|
||||
int bitValue = (1 << band);
|
||||
if ( band == 0 && index > r ) {
|
||||
r = index;
|
||||
} else if ( band == 1 && index > g ) {
|
||||
g = index;
|
||||
} else if ( band == 2 && index > b ) {
|
||||
b = index;
|
||||
}
|
||||
|
||||
if ( (currentMask & bitValue) == 0 ) {
|
||||
// alpha does not contain this bit yet!
|
||||
a = (currentMask | bitValue) / maskMultiplier;
|
||||
}
|
||||
}
|
||||
|
||||
gl_FragColor = vec4(r,g,b,a);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,257 @@
|
|||
/**
|
||||
* 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.viz.truecolor.gl.extension;
|
||||
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.media.opengl.GL;
|
||||
|
||||
import com.raytheon.uf.viz.core.DrawableImage;
|
||||
import com.raytheon.uf.viz.core.IExtent;
|
||||
import com.raytheon.uf.viz.core.PixelCoverage;
|
||||
import com.raytheon.uf.viz.core.drawables.ColorMapParameters;
|
||||
import com.raytheon.uf.viz.core.drawables.IImage;
|
||||
import com.raytheon.uf.viz.core.drawables.ImagingSupport;
|
||||
import com.raytheon.uf.viz.core.drawables.PaintProperties;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension;
|
||||
import com.raytheon.uf.viz.truecolor.gl.image.GLTrueColorImage;
|
||||
import com.raytheon.viz.core.gl.ext.GLOffscreenRenderingExtension;
|
||||
import com.raytheon.viz.core.gl.glsl.AbstractGLSLImagingExtension;
|
||||
import com.raytheon.viz.core.gl.glsl.GLShaderProgram;
|
||||
import com.raytheon.viz.core.gl.images.AbstractGLImage;
|
||||
import com.raytheon.viz.core.gl.images.GLColormappedImage;
|
||||
|
||||
/**
|
||||
* GL implementation of the {@link ITrueColorImagingExtension}
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 6, 2012 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class GLTrueColorImagingExtension extends AbstractGLSLImagingExtension
|
||||
implements ITrueColorImagingExtension {
|
||||
|
||||
private AbstractGLImage writeToImage;
|
||||
|
||||
private Channel renderingChannel;
|
||||
|
||||
/** The current rendering bit mask, specifies what bands we rendered */
|
||||
private int currentMask = 0;
|
||||
|
||||
private Map<ColorMapParameters, Object> parameters = new IdentityHashMap<ColorMapParameters, Object>();
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension#
|
||||
* initializeRaster(int[], com.raytheon.uf.viz.core.IExtent)
|
||||
*/
|
||||
@Override
|
||||
public ITrueColorImage initializeRaster(int[] imageBounds,
|
||||
IExtent imageExtent) throws VizException {
|
||||
return new GLTrueColorImage(GLTrueColorImagingExtension.class,
|
||||
imageBounds, imageExtent);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.viz.core.gl.ext.AbstractGLImagingExtension#getShaderProgramName
|
||||
* ()
|
||||
*/
|
||||
@Override
|
||||
public String getShaderProgramName() {
|
||||
return "truecolor";
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.viz.core.gl.ext.AbstractGLImagingExtension#preImageRender
|
||||
* (com.raytheon.uf.viz.core.drawables.PaintProperties,
|
||||
* com.raytheon.viz.core.gl.images.AbstractGLImage,
|
||||
* com.raytheon.uf.viz.core.PixelCoverage)
|
||||
*/
|
||||
@Override
|
||||
public Object preImageRender(PaintProperties paintProps,
|
||||
AbstractGLImage image, PixelCoverage imageCoverage)
|
||||
throws VizException {
|
||||
if (image instanceof GLTrueColorImage) {
|
||||
GLTrueColorImage trueColorImage = (GLTrueColorImage) image;
|
||||
if (trueColorImage.isRepaint()) {
|
||||
// Reset current bit mask
|
||||
currentMask = 0;
|
||||
parameters.clear();
|
||||
writeToImage = trueColorImage;
|
||||
GLOffscreenRenderingExtension extension = target
|
||||
.getExtension(GLOffscreenRenderingExtension.class);
|
||||
try {
|
||||
extension.renderOffscreen(trueColorImage,
|
||||
trueColorImage.getImageExtent());
|
||||
boolean allPainted = true;
|
||||
for (Channel channel : Channel.values()) {
|
||||
renderingChannel = channel;
|
||||
DrawableImage[] imagesToDraw = trueColorImage
|
||||
.getImages(channel);
|
||||
if (imagesToDraw != null && imagesToDraw.length > 0) {
|
||||
// Mark the channel bit in the current bit mask
|
||||
currentMask |= (1 << channel.ordinal());
|
||||
|
||||
// Make sure images are staged before we mosaic them
|
||||
ImagingSupport.prepareImages(target, imagesToDraw);
|
||||
|
||||
// Each image needs to draw separately due to gl
|
||||
// issues when zoomed in very far, rendered parts
|
||||
// near the corners don't show all the pixels for
|
||||
// each image. Pushing and popping GL_TEXTURE_BIT
|
||||
// before/after each render fixes this issue
|
||||
for (DrawableImage di : imagesToDraw) {
|
||||
allPainted &= drawRasters(paintProps, di);
|
||||
}
|
||||
// Need to set repaint based on if drawing
|
||||
// completed.
|
||||
trueColorImage.setRepaint(allPainted == false);
|
||||
}
|
||||
}
|
||||
} catch (VizException e) {
|
||||
extension.renderOnscreen();
|
||||
throw e;
|
||||
}
|
||||
renderingChannel = null;
|
||||
writeToImage = null;
|
||||
trueColorImage.setImageParameters(parameters.keySet());
|
||||
trueColorImage.bind(target.getGl());
|
||||
return imageCoverage;
|
||||
} else {
|
||||
target.drawRasters(paintProps,
|
||||
new DrawableImage(trueColorImage.getWrappedImage(),
|
||||
imageCoverage));
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
GL gl = target.getGl();
|
||||
// bind on GL_TEXTURE1 as 0 is channel image
|
||||
writeToImage.bind(gl, GL.GL_TEXTURE1);
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.viz.core.gl.ext.AbstractGLImagingExtension#postImageRender
|
||||
* (com.raytheon.uf.viz.core.drawables.PaintProperties,
|
||||
* com.raytheon.viz.core.gl.images.AbstractGLImage, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public void postImageRender(PaintProperties paintProps,
|
||||
AbstractGLImage image, Object data) throws VizException {
|
||||
if (image instanceof GLTrueColorImage) {
|
||||
target.getExtension(GLOffscreenRenderingExtension.class)
|
||||
.renderOnscreen();
|
||||
target.drawRasters(paintProps, new DrawableImage(
|
||||
((GLTrueColorImage) image).getWrappedImage(),
|
||||
(PixelCoverage) data));
|
||||
} else if (writeToImage != null) {
|
||||
GL gl = target.getGl();
|
||||
// Unbind the writeToImage from GL_TEXTURE1
|
||||
gl.glActiveTexture(GL.GL_TEXTURE1);
|
||||
gl.glBindTexture(writeToImage.getTextureStorageType(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.viz.core.gl.ext.AbstractGLImagingExtension#loadShaderData
|
||||
* (com.raytheon.viz.core.gl.glsl.GLShaderProgram,
|
||||
* com.raytheon.uf.viz.core.drawables.IImage,
|
||||
* com.raytheon.uf.viz.core.drawables.PaintProperties)
|
||||
*/
|
||||
@Override
|
||||
public void loadShaderData(GLShaderProgram program, IImage image,
|
||||
PaintProperties paintProps) throws VizException {
|
||||
if (image instanceof GLTrueColorImage) {
|
||||
program.setUniform("band", -1);
|
||||
program.setUniform("rawTex", 0);
|
||||
program.setUniform("expectedMask", currentMask);
|
||||
} else {
|
||||
if (image instanceof GLColormappedImage == false) {
|
||||
throw new VizException(
|
||||
"Can only render colormapped images in true color");
|
||||
}
|
||||
|
||||
GLColormappedImage cmapImage = (GLColormappedImage) image;
|
||||
ColorMapParameters colorMapParameters = cmapImage
|
||||
.getColorMapParameters();
|
||||
parameters.put(colorMapParameters, null);
|
||||
int textureType = cmapImage.getTextureType();
|
||||
|
||||
// Set the band image data
|
||||
program.setUniform("rawTex", 0);
|
||||
program.setUniform("naturalMin", colorMapParameters.getDataMin());
|
||||
program.setUniform("naturalMax", colorMapParameters.getDataMax());
|
||||
program.setUniform("cmapMin", colorMapParameters.getColorMapMin());
|
||||
program.setUniform("cmapMax", colorMapParameters.getColorMapMax());
|
||||
program.setUniform("isFloat", textureType == GL.GL_FLOAT
|
||||
|| textureType == GL.GL_HALF_FLOAT_ARB ? 1 : 0);
|
||||
program.setUniform("noDataValue",
|
||||
colorMapParameters.getNoDataValue());
|
||||
|
||||
// Set the composite image data
|
||||
program.setUniform("trueColorTexture", 1);
|
||||
program.setUniform("width", writeToImage.getWidth());
|
||||
program.setUniform("height", writeToImage.getHeight());
|
||||
|
||||
// Set the band we are rendering to
|
||||
program.setUniform("band", renderingChannel.ordinal());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.viz.core.gl.ext.AbstractGLImagingExtension#enableBlending
|
||||
* (javax.media.opengl.GL)
|
||||
*/
|
||||
@Override
|
||||
protected void enableBlending(GL gl) {
|
||||
// Do not enable blending for this extension as it messes with alpha
|
||||
// values between passes
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,249 @@
|
|||
/**
|
||||
* 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.viz.truecolor.gl.image;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.raytheon.uf.viz.core.DrawableImage;
|
||||
import com.raytheon.uf.viz.core.IExtent;
|
||||
import com.raytheon.uf.viz.core.data.IRenderedImageCallback;
|
||||
import com.raytheon.uf.viz.core.drawables.ColorMapParameters;
|
||||
import com.raytheon.uf.viz.core.drawables.IColorMapParametersListener;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.IImagingExtension;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension.Channel;
|
||||
import com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension.ITrueColorImage;
|
||||
import com.raytheon.viz.core.gl.images.GLDelegateImage;
|
||||
import com.raytheon.viz.core.gl.images.GLImage;
|
||||
|
||||
/**
|
||||
* GL implementation of {@link ITrueColorImage}. Manages drawable images for
|
||||
* {@link Channel} objects. Listens for changes on the ColorMapParameters for
|
||||
* the underlying images so it knows when repaint
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 6, 2012 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class GLTrueColorImage extends GLDelegateImage<GLImage> implements
|
||||
ITrueColorImage, IColorMapParametersListener {
|
||||
|
||||
private static class RGBCallback implements IRenderedImageCallback {
|
||||
private int[] bounds;
|
||||
|
||||
private RGBCallback(int[] bounds) {
|
||||
this.bounds = bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderedImage getImage() throws VizException {
|
||||
return new BufferedImage(bounds[0], bounds[1],
|
||||
BufferedImage.TYPE_INT_ARGB);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean repaint = true;
|
||||
|
||||
private int[] bounds;
|
||||
|
||||
private IExtent imageExtent;
|
||||
|
||||
private Map<Channel, DrawableImage[]> channelMap = new HashMap<Channel, DrawableImage[]>();
|
||||
|
||||
/* Identity set used to track color map parameters currently listening on */
|
||||
private Map<ColorMapParameters, Object> listening = new IdentityHashMap<ColorMapParameters, Object>();
|
||||
|
||||
/**
|
||||
* @param extensionClass
|
||||
*/
|
||||
public GLTrueColorImage(Class<? extends IImagingExtension> extensionClass,
|
||||
int[] bounds, IExtent imageExtent) {
|
||||
super(new GLImage(new RGBCallback(bounds), IImagingExtension.class),
|
||||
extensionClass);
|
||||
this.bounds = bounds;
|
||||
this.imageExtent = imageExtent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the imageExtent
|
||||
*/
|
||||
public IExtent getImageExtent() {
|
||||
return imageExtent;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension.
|
||||
* ITrueColorImage
|
||||
* #setImages(com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension
|
||||
* .Channel, com.raytheon.uf.viz.core.DrawableImage[])
|
||||
*/
|
||||
@Override
|
||||
public void setImages(Channel channel, DrawableImage... images) {
|
||||
DrawableImage[] prev = channelMap.put(channel, images);
|
||||
if (prev != images) {
|
||||
// Try to find equal array
|
||||
if (prev != null && images != null && prev.length == images.length) {
|
||||
for (int i = 0; i < images.length; ++i) {
|
||||
if (images[i].getImage() != prev[i].getImage()) {
|
||||
repaint = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
repaint = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension.
|
||||
* ITrueColorImage
|
||||
* #getImages(com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension
|
||||
* .Channel)
|
||||
*/
|
||||
@Override
|
||||
public DrawableImage[] getImages(Channel channel) {
|
||||
return channelMap.get(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the repaint
|
||||
*/
|
||||
public boolean isRepaint() {
|
||||
return repaint;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param repaint
|
||||
* the repaint to set
|
||||
*/
|
||||
public void setRepaint(boolean repaint) {
|
||||
this.repaint = repaint;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension.
|
||||
* ITrueColorImage#setSize(int[])
|
||||
*/
|
||||
@Override
|
||||
public void setSize(int[] bounds) {
|
||||
if (Arrays.equals(bounds, this.bounds) == false) {
|
||||
this.bounds = bounds;
|
||||
image.dispose();
|
||||
image = new GLImage(new RGBCallback(bounds),
|
||||
IImagingExtension.class);
|
||||
repaint = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension.
|
||||
* ITrueColorImage#setImageExtent(com.raytheon.uf.viz.core.IExtent)
|
||||
*/
|
||||
@Override
|
||||
public void setImageExtent(IExtent extent) {
|
||||
if (extent.equals(this.imageExtent) == false) {
|
||||
this.imageExtent = extent;
|
||||
repaint = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.core.drawables.IColorMapParametersListener#
|
||||
* colorMapChanged()
|
||||
*/
|
||||
@Override
|
||||
public void colorMapChanged() {
|
||||
// Repaint image on colormap change events
|
||||
repaint = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ColorMapParameters it's images are using. We add ourselves as
|
||||
* listeners so we can repaint on changes
|
||||
*
|
||||
* @param parameters
|
||||
*/
|
||||
public void setImageParameters(Collection<ColorMapParameters> parameters) {
|
||||
boolean same = false;
|
||||
if (parameters.size() == listening.size()) {
|
||||
same = true;
|
||||
for (ColorMapParameters params : parameters) {
|
||||
same &= listening.containsKey(params);
|
||||
if (!same) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!same) {
|
||||
// Current image parameters list different from passed in, set up
|
||||
// listeners on new set and remove from current set
|
||||
for (ColorMapParameters params : listening.keySet()) {
|
||||
params.removeListener(this);
|
||||
}
|
||||
listening.clear();
|
||||
for (ColorMapParameters params : parameters) {
|
||||
params.addListener(this);
|
||||
listening.put(params, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.viz.core.gl.images.GLDelegateImage#dispose()
|
||||
*/
|
||||
@Override
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
for (ColorMapParameters params : listening.keySet()) {
|
||||
params.removeListener(this);
|
||||
}
|
||||
listening.clear();
|
||||
}
|
||||
|
||||
}
|
18
cave/com.raytheon.uf.viz.truecolor/META-INF/MANIFEST.MF
Normal file
18
cave/com.raytheon.uf.viz.truecolor/META-INF/MANIFEST.MF
Normal file
|
@ -0,0 +1,18 @@
|
|||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Truecolor
|
||||
Bundle-SymbolicName: com.raytheon.uf.viz.truecolor;singleton:=true
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Activator: com.raytheon.uf.viz.truecolor.Activator
|
||||
Bundle-Vendor: RAYTHEON
|
||||
Eclipse-RegisterBuddy: com.raytheon.uf.viz.core, com.raytheon.viz.ui
|
||||
Require-Bundle: org.eclipse.ui,
|
||||
org.eclipse.core.runtime,
|
||||
com.raytheon.uf.viz.core;bundle-version="1.12.1174",
|
||||
com.raytheon.viz.ui;bundle-version="1.12.1174",
|
||||
com.raytheon.uf.common.time;bundle-version="1.12.1174",
|
||||
com.raytheon.uf.common.geospatial;bundle-version="1.12.1174",
|
||||
javax.measure;bundle-version="1.0.0"
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Export-Package: com.raytheon.uf.viz.truecolor.extension
|
|
@ -0,0 +1,3 @@
|
|||
com.raytheon.uf.viz.truecolor.rsc.TrueColorResourceGroupData
|
||||
com.raytheon.uf.viz.truecolor.rsc.ChannelInfo
|
||||
com.raytheon.uf.viz.truecolor.rsc.ChannelResource
|
39
cave/com.raytheon.uf.viz.truecolor/plugin.xml
Normal file
39
cave/com.raytheon.uf.viz.truecolor/plugin.xml
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<?eclipse version="3.2"?>
|
||||
<plugin>
|
||||
<extension
|
||||
point="com.raytheon.uf.viz.core.resource">
|
||||
<resource
|
||||
class="com.raytheon.uf.viz.truecolor.rsc.TrueColorResourceGroup"
|
||||
name="True Color Imagery"
|
||||
renderingOrderId="IMAGE_COUNTRY"
|
||||
resourceType="PLAN_VIEW"/>
|
||||
</extension>
|
||||
<extension
|
||||
point="com.raytheon.viz.ui.contextualMenu">
|
||||
<contextualMenu
|
||||
actionClass="com.raytheon.uf.viz.truecolor.ui.TrueColorDialogAction"
|
||||
capabilityClass="com.raytheon.uf.viz.truecolor.rsc.TrueColorResourceGroup"
|
||||
name="TrueColorImaging"
|
||||
sortID="25"/>
|
||||
</extension>
|
||||
</plugin>
|
|
@ -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.uf.viz.truecolor.extension;
|
||||
|
||||
import com.raytheon.uf.viz.core.DrawableImage;
|
||||
import com.raytheon.uf.viz.core.IExtent;
|
||||
import com.raytheon.uf.viz.core.drawables.IColormappedImage;
|
||||
import com.raytheon.uf.viz.core.drawables.IImage;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.IImagingExtension;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
|
||||
/**
|
||||
* Imaging extension for "true color" images. Where a set of
|
||||
* {@link IColormappedImage} images are assigned to each band of an RGB channel
|
||||
* image
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 6, 2012 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public interface ITrueColorImagingExtension extends IImagingExtension {
|
||||
|
||||
public static enum Channel {
|
||||
RED, GREEN, BLUE;
|
||||
}
|
||||
|
||||
public static interface ITrueColorImage extends IImage {
|
||||
|
||||
public void setImages(Channel channel, DrawableImage... images);
|
||||
|
||||
public DrawableImage[] getImages(Channel channel);
|
||||
|
||||
public void setSize(int[] bounds);
|
||||
|
||||
public void setImageExtent(IExtent extent);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a true color image with the given imageBounds and imageExtent
|
||||
*
|
||||
* @param imageBounds
|
||||
* @param imageExtent
|
||||
* @param params
|
||||
* @return
|
||||
* @throws VizException
|
||||
*/
|
||||
public ITrueColorImage initializeRaster(int[] imageBounds,
|
||||
IExtent imageExtent) throws VizException;
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
/**
|
||||
* 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.viz.truecolor.rsc;
|
||||
|
||||
import java.text.ParsePosition;
|
||||
|
||||
import javax.measure.unit.Unit;
|
||||
import javax.measure.unit.UnitFormat;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
|
||||
import com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension.Channel;
|
||||
|
||||
/**
|
||||
* Channel information (range/unit) for a true color channel
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 20, 2012 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.NONE)
|
||||
public class ChannelInfo {
|
||||
|
||||
@XmlAttribute
|
||||
private Channel channel;
|
||||
|
||||
@XmlElement
|
||||
private double rangeMin = 0.0;
|
||||
|
||||
@XmlElement
|
||||
private double rangeMax = 1.0;
|
||||
|
||||
private Unit<?> unit = Unit.ONE;
|
||||
|
||||
/**
|
||||
* @return the channel
|
||||
*/
|
||||
public Channel getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param channel
|
||||
* the channel to set
|
||||
*/
|
||||
public void setChannel(Channel channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the rangeMin
|
||||
*/
|
||||
public double getRangeMin() {
|
||||
return rangeMin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rangeMin
|
||||
* the rangeMin to set
|
||||
*/
|
||||
public void setRangeMin(double rangeMin) {
|
||||
this.rangeMin = rangeMin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the rangeMax
|
||||
*/
|
||||
public double getRangeMax() {
|
||||
return rangeMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rangeMax
|
||||
* the rangeMax to set
|
||||
*/
|
||||
public void setRangeMax(double rangeMax) {
|
||||
this.rangeMax = rangeMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the unit
|
||||
*/
|
||||
public Unit<?> getUnit() {
|
||||
return unit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param unit
|
||||
* the unit to set
|
||||
*/
|
||||
public void setUnit(Unit<?> unit) {
|
||||
this.unit = unit;
|
||||
}
|
||||
|
||||
@XmlElement(name = "unit")
|
||||
public void setUnitString(String unit) {
|
||||
if (unit != null) {
|
||||
this.unit = UnitFormat.getUCUMInstance().parseObject(unit,
|
||||
new ParsePosition(0));
|
||||
} else {
|
||||
this.unit = null;
|
||||
}
|
||||
if (this.unit == null) {
|
||||
this.unit = Unit.ONE;
|
||||
}
|
||||
}
|
||||
|
||||
public String getUnitString() {
|
||||
// Let anything with Unit.ONE serialize back out as null since it was
|
||||
// probably never set and will default to Unit.ONE
|
||||
return unit != Unit.ONE ? UnitFormat.getUCUMInstance().format(unit)
|
||||
: null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((channel == null) ? 0 : channel.hashCode());
|
||||
long temp;
|
||||
temp = Double.doubleToLongBits(rangeMax);
|
||||
result = prime * result + (int) (temp ^ (temp >>> 32));
|
||||
temp = Double.doubleToLongBits(rangeMin);
|
||||
result = prime * result + (int) (temp ^ (temp >>> 32));
|
||||
result = prime * result + ((unit == null) ? 0 : unit.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
ChannelInfo other = (ChannelInfo) obj;
|
||||
if (channel != other.channel)
|
||||
return false;
|
||||
if (Double.doubleToLongBits(rangeMax) != Double
|
||||
.doubleToLongBits(other.rangeMax))
|
||||
return false;
|
||||
if (Double.doubleToLongBits(rangeMin) != Double
|
||||
.doubleToLongBits(other.rangeMin))
|
||||
return false;
|
||||
if (unit == null) {
|
||||
if (other.unit != null)
|
||||
return false;
|
||||
} else if (!unit.equals(other.unit))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
/**
|
||||
* 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.viz.truecolor.rsc;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
|
||||
import com.raytheon.uf.viz.core.rsc.AbstractResourceData;
|
||||
import com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension.Channel;
|
||||
|
||||
/**
|
||||
* Object that represents a resource bound to a {@link Channel}
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 16, 2012 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.NONE)
|
||||
public class ChannelResource {
|
||||
|
||||
@XmlElement
|
||||
protected AbstractResourceData resourceData;
|
||||
|
||||
@XmlElement
|
||||
protected Channel channel;
|
||||
|
||||
@XmlAttribute
|
||||
protected String channelName;
|
||||
|
||||
/**
|
||||
* @return the resourceData
|
||||
*/
|
||||
public AbstractResourceData getResourceData() {
|
||||
return resourceData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resourceData
|
||||
* the resourceData to set
|
||||
*/
|
||||
public void setResourceData(AbstractResourceData resourceData) {
|
||||
this.resourceData = resourceData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the channel
|
||||
*/
|
||||
public Channel getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param channel
|
||||
* the channel to set
|
||||
*/
|
||||
public void setChannel(Channel channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the channelName
|
||||
*/
|
||||
public String getChannelName() {
|
||||
return channelName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param channelName
|
||||
* the channelName to set
|
||||
*/
|
||||
public void setChannelName(String channelName) {
|
||||
this.channelName = channelName;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result
|
||||
+ ((channelName == null) ? 0 : channelName.hashCode());
|
||||
result = prime * result
|
||||
+ ((resourceData == null) ? 0 : resourceData.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
ChannelResource other = (ChannelResource) obj;
|
||||
if (channelName == null) {
|
||||
if (other.channelName != null)
|
||||
return false;
|
||||
} else if (!channelName.equals(other.channelName))
|
||||
return false;
|
||||
if (resourceData == null) {
|
||||
if (other.resourceData != null)
|
||||
return false;
|
||||
} else if (!resourceData.equals(other.resourceData))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,441 @@
|
|||
/**
|
||||
* 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.viz.truecolor.rsc;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.swt.graphics.Rectangle;
|
||||
import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
||||
|
||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||
import com.raytheon.uf.common.time.DataTime;
|
||||
import com.raytheon.uf.viz.core.DrawableImage;
|
||||
import com.raytheon.uf.viz.core.IExtent;
|
||||
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
||||
import com.raytheon.uf.viz.core.PixelCoverage;
|
||||
import com.raytheon.uf.viz.core.drawables.ColorMapParameters;
|
||||
import com.raytheon.uf.viz.core.drawables.IDescriptor;
|
||||
import com.raytheon.uf.viz.core.drawables.IDescriptor.FramesInfo;
|
||||
import com.raytheon.uf.viz.core.drawables.PaintProperties;
|
||||
import com.raytheon.uf.viz.core.drawables.ResourcePair;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.IImagingExtension.ImageProvider;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
|
||||
import com.raytheon.uf.viz.core.rsc.IResourceDataChanged;
|
||||
import com.raytheon.uf.viz.core.rsc.IResourceGroup;
|
||||
import com.raytheon.uf.viz.core.rsc.LoadProperties;
|
||||
import com.raytheon.uf.viz.core.rsc.ResourceList;
|
||||
import com.raytheon.uf.viz.core.rsc.capabilities.ColorMapCapability;
|
||||
import com.raytheon.uf.viz.core.rsc.capabilities.GroupNamingCapability;
|
||||
import com.raytheon.uf.viz.core.rsc.capabilities.ImagingCapability;
|
||||
import com.raytheon.uf.viz.truecolor.Activator;
|
||||
import com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension;
|
||||
import com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension.Channel;
|
||||
import com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension.ITrueColorImage;
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
|
||||
/**
|
||||
* Resource group that operates on 3 resources, one assigned to each band of an
|
||||
* RGB image. This resource checks for the {@link ImageProvider} on the
|
||||
* {@link ImagingCapability}
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 6, 2012 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class TrueColorResourceGroup extends
|
||||
AbstractVizResource<TrueColorResourceGroupData, IDescriptor> implements
|
||||
IResourceGroup, IResourceDataChanged {
|
||||
|
||||
public static class DisplayedChannelResource {
|
||||
|
||||
private String displayName;
|
||||
|
||||
public AbstractVizResource<?, ?> resource;
|
||||
|
||||
public ChannelResource channel;
|
||||
|
||||
private DisplayedChannelResource(ChannelResource cr,
|
||||
AbstractVizResource<?, ?> resource) {
|
||||
this.channel = cr;
|
||||
this.resource = resource;
|
||||
this.displayName = cr.getChannelName();
|
||||
if (displayName == null) {
|
||||
displayName = resource.getName();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the display name of the channel
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the resource is bound to the specified {@link Channel}
|
||||
*
|
||||
* @param channel
|
||||
* @return
|
||||
*/
|
||||
public boolean isChannel(Channel channel) {
|
||||
return this.channel.getChannel() == channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public Channel getChannel() {
|
||||
return channel.getChannel();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final String DEFAULT_NAME = "RGB Composite";
|
||||
|
||||
private Map<Channel, DisplayedChannelResource> displayedResources;
|
||||
|
||||
private ITrueColorImage image;
|
||||
|
||||
private boolean timeAgnostic = true;
|
||||
|
||||
private String baseName;
|
||||
|
||||
/**
|
||||
* Mapping to keep colormap parameters in sync with ChannelInfo in
|
||||
* resourceData
|
||||
*/
|
||||
private Map<ColorMapParameters, ChannelInfo> channelInfoMap = new IdentityHashMap<ColorMapParameters, ChannelInfo>();
|
||||
|
||||
/**
|
||||
* @param resourceData
|
||||
* @param loadProperties
|
||||
*/
|
||||
public TrueColorResourceGroup(TrueColorResourceGroupData resourceData,
|
||||
LoadProperties loadProperties) {
|
||||
super(resourceData, loadProperties);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.core.rsc.IResourceGroup#getResourceList()
|
||||
*/
|
||||
@Override
|
||||
public ResourceList getResourceList() {
|
||||
return resourceData.getResourceList();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.core.rsc.AbstractVizResource#disposeInternal()
|
||||
*/
|
||||
@Override
|
||||
protected void disposeInternal() {
|
||||
resourceData.removeChangeListener(this);
|
||||
for (ResourcePair rp : getResourceList()) {
|
||||
rp.getResource().dispose();
|
||||
}
|
||||
image.dispose();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.viz.core.rsc.AbstractVizResource#paintInternal(com.raytheon
|
||||
* .uf.viz.core.IGraphicsTarget,
|
||||
* com.raytheon.uf.viz.core.drawables.PaintProperties)
|
||||
*/
|
||||
@Override
|
||||
protected void paintInternal(IGraphicsTarget target,
|
||||
PaintProperties paintProps) throws VizException {
|
||||
Rectangle rect = paintProps.getCanvasBounds();
|
||||
IExtent extent = paintProps.getView().getExtent();
|
||||
image.setSize(new int[] { rect.width, rect.height });
|
||||
image.setImageExtent(extent);
|
||||
|
||||
FramesInfo fi = paintProps.getFramesInfo();
|
||||
for (Channel c : Channel.values()) {
|
||||
DrawableImage[] images = null;
|
||||
DisplayedChannelResource dcr = displayedResources.get(c);
|
||||
if (dcr != null) {
|
||||
DataTime dcrTime = fi.getTimeForResource(dcr.resource);
|
||||
if (dcrTime != null) {
|
||||
paintProps.setDataTime(fi.getTimeForResource(dcr.resource));
|
||||
Collection<DrawableImage> dcrImages = dcr.resource
|
||||
.getCapability(ImagingCapability.class)
|
||||
.getProvider().getImages(target, paintProps);
|
||||
if (dcrImages != null) {
|
||||
images = dcrImages.toArray(new DrawableImage[dcrImages
|
||||
.size()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
image.setImages(c, images);
|
||||
}
|
||||
|
||||
Coordinate ul = new Coordinate(extent.getMinX(), extent.getMaxY());
|
||||
Coordinate ur = new Coordinate(extent.getMaxX(), extent.getMaxY());
|
||||
Coordinate lr = new Coordinate(extent.getMaxX(), extent.getMinY());
|
||||
Coordinate ll = new Coordinate(extent.getMinX(), extent.getMinY());
|
||||
|
||||
target.drawRaster(image, new PixelCoverage(ul, ur, lr, ll), paintProps);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.core.rsc.AbstractVizResource#isTimeAgnostic()
|
||||
*/
|
||||
@Override
|
||||
public boolean isTimeAgnostic() {
|
||||
return timeAgnostic;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.viz.core.rsc.AbstractVizResource#initInternal(com.raytheon
|
||||
* .uf.viz.core.IGraphicsTarget)
|
||||
*/
|
||||
@Override
|
||||
protected void initInternal(IGraphicsTarget target) throws VizException {
|
||||
// We will name the composite
|
||||
getCapability(GroupNamingCapability.class);
|
||||
|
||||
displayedResources = new HashMap<Channel, DisplayedChannelResource>();
|
||||
ResourceList resources = getResourceList();
|
||||
for (ChannelResource cr : resourceData.getChannelResources()) {
|
||||
for (ResourcePair rp : resources) {
|
||||
if (cr.getResourceData() == rp.getResourceData()) {
|
||||
DisplayedChannelResource displayedResource = new DisplayedChannelResource(
|
||||
cr, rp.getResource());
|
||||
AbstractVizResource<?, ?> resource = rp.getResource();
|
||||
resource.init(target);
|
||||
|
||||
// Check resource for required capabilities
|
||||
String error = null;
|
||||
if (resource.hasCapability(ImagingCapability.class)) {
|
||||
ImagingCapability imaging = resource
|
||||
.getCapability(ImagingCapability.class);
|
||||
if (imaging.getProvider() != null) {
|
||||
if (resource
|
||||
.hasCapability(ColorMapCapability.class) == false) {
|
||||
error = "does not have ColorMapCapability";
|
||||
} else if (resource.getCapability(
|
||||
ColorMapCapability.class)
|
||||
.getColorMapParameters() == null) {
|
||||
error = "does not have ColorMapParameters set";
|
||||
}
|
||||
} else {
|
||||
error = "does not have image provider set on the ImagingCapability";
|
||||
}
|
||||
} else {
|
||||
error = "does not have the ImagingCapability";
|
||||
}
|
||||
if (cr.getChannel() == null) {
|
||||
error = "is not tied to any channel";
|
||||
} else if (displayedResources.containsKey(cr.getChannel())) {
|
||||
error = "is tied to a channel already in use";
|
||||
}
|
||||
|
||||
if (error == null) {
|
||||
// No errors so far, check for ChannelInfo override
|
||||
ColorMapParameters params = resource.getCapability(
|
||||
ColorMapCapability.class)
|
||||
.getColorMapParameters();
|
||||
ChannelInfo ci = resourceData
|
||||
.getChannelInfo(displayedResource.getChannel());
|
||||
if (ci == null
|
||||
|| ci.getUnit().isCompatible(
|
||||
params.getDataUnit())) {
|
||||
if (ci == null) {
|
||||
ci = new ChannelInfo();
|
||||
ci.setChannel(displayedResource.getChannel());
|
||||
resourceData.setChannelInfo(ci);
|
||||
} else {
|
||||
params.setDisplayUnit(ci.getUnit());
|
||||
params.setColorMapMin((float) params
|
||||
.getDisplayToDataConverter().convert(
|
||||
ci.getRangeMin()));
|
||||
params.setColorMapMax((float) params
|
||||
.getDisplayToDataConverter().convert(
|
||||
ci.getRangeMax()));
|
||||
}
|
||||
channelInfoMap.put(params, ci);
|
||||
resourceChanged(
|
||||
ChangeType.CAPABILITY,
|
||||
resource.getCapability(ColorMapCapability.class));
|
||||
} else {
|
||||
error = "is not compatible with custom ChannelInfo for Channel="
|
||||
+ displayedResource.getChannel();
|
||||
}
|
||||
}
|
||||
|
||||
if (error != null) {
|
||||
Activator.statusHandler.handle(Priority.PROBLEM,
|
||||
displayedResource.getDisplayName()
|
||||
+ " resource in true color composite "
|
||||
+ error);
|
||||
resources.remove(rp);
|
||||
} else {
|
||||
resource.getResourceData().addChangeListener(this);
|
||||
displayedResources.put(displayedResource.getChannel(),
|
||||
displayedResource);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (displayedResources.size() == 0) {
|
||||
throw new VizException(
|
||||
"No resources to draw in true color composite");
|
||||
}
|
||||
|
||||
ITrueColorImagingExtension ext = target
|
||||
.getExtension(ITrueColorImagingExtension.class);
|
||||
image = ext.initializeRaster(new int[] { 0, 0 }, null);
|
||||
resourceData.addChangeListener(this);
|
||||
// Set initial ImagingCapability parameters
|
||||
resourceChanged(ChangeType.CAPABILITY,
|
||||
getCapability(ImagingCapability.class));
|
||||
|
||||
// Every resource has to be time agnostic for us to be as well
|
||||
timeAgnostic = true;
|
||||
for (DisplayedChannelResource dr : displayedResources.values()) {
|
||||
timeAgnostic &= dr.resource.isTimeAgnostic();
|
||||
}
|
||||
|
||||
String groupName = resourceData.getGroupName();
|
||||
if (groupName == null) {
|
||||
groupName = "True Color Composite";
|
||||
}
|
||||
String channels = " (";
|
||||
for (Channel c : Channel.values()) {
|
||||
if (displayedResources.containsKey(c)) {
|
||||
channels += c.name().substring(0, 1);
|
||||
}
|
||||
}
|
||||
channels += "): ";
|
||||
baseName = groupName + channels;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.core.rsc.AbstractVizResource#getName()
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
String name = baseName;
|
||||
boolean first = true;
|
||||
for (Channel c : Channel.values()) {
|
||||
DisplayedChannelResource dcr = displayedResources.get(c);
|
||||
if (dcr != null) {
|
||||
if (!first) {
|
||||
name += "/";
|
||||
}
|
||||
first = false;
|
||||
|
||||
boolean has = true;
|
||||
if (image != null && image.getImages(c) == null) {
|
||||
has = false;
|
||||
}
|
||||
if (has) {
|
||||
name += dcr.getDisplayName();
|
||||
} else {
|
||||
String channelName = c.name();
|
||||
name += "No " + channelName.substring(0, 1)
|
||||
+ channelName.substring(1).toLowerCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.viz.core.rsc.AbstractVizResource#project(org.opengis.
|
||||
* referencing.crs.CoordinateReferenceSystem)
|
||||
*/
|
||||
@Override
|
||||
public void project(CoordinateReferenceSystem crs) throws VizException {
|
||||
for (ResourcePair rp : getResourceList()) {
|
||||
rp.getResource().project(crs);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.viz.core.rsc.IResourceDataChanged#resourceChanged(com
|
||||
* .raytheon.uf.viz.core.rsc.IResourceDataChanged.ChangeType,
|
||||
* java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public void resourceChanged(ChangeType type, Object object) {
|
||||
if (type == ChangeType.CAPABILITY) {
|
||||
if (object instanceof ImagingCapability) {
|
||||
ImagingCapability imaging = (ImagingCapability) object;
|
||||
image.setBrightness(imaging.getBrightness());
|
||||
image.setContrast(imaging.getContrast());
|
||||
image.setInterpolated(imaging.isInterpolationState());
|
||||
} else if (object instanceof ColorMapCapability) {
|
||||
ColorMapParameters params = ((ColorMapCapability) object)
|
||||
.getColorMapParameters();
|
||||
ChannelInfo ci = channelInfoMap.get(params);
|
||||
if (ci != null) {
|
||||
ci.setRangeMin(params.getDataToDisplayConverter().convert(
|
||||
params.getColorMapMin()));
|
||||
ci.setRangeMax(params.getDataToDisplayConverter().convert(
|
||||
params.getColorMapMax()));
|
||||
ci.setUnit(params.getDisplayUnit());
|
||||
}
|
||||
}
|
||||
}
|
||||
issueRefresh();
|
||||
}
|
||||
|
||||
public Collection<DisplayedChannelResource> getChannelResources() {
|
||||
return displayedResources.values();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,249 @@
|
|||
/**
|
||||
* 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.viz.truecolor.rsc;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
|
||||
import com.raytheon.uf.viz.core.drawables.IDescriptor;
|
||||
import com.raytheon.uf.viz.core.drawables.ResourcePair;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.core.rsc.AbstractResourceData;
|
||||
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
|
||||
import com.raytheon.uf.viz.core.rsc.IResourceGroup;
|
||||
import com.raytheon.uf.viz.core.rsc.LoadProperties;
|
||||
import com.raytheon.uf.viz.core.rsc.ResourceList;
|
||||
import com.raytheon.uf.viz.core.rsc.ResourceProperties;
|
||||
import com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension.Channel;
|
||||
|
||||
/**
|
||||
* {@link TrueColorResourceGroup} resource data. Contains a red/blue/green
|
||||
* channel resource and a name.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 6, 2012 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.NONE)
|
||||
public class TrueColorResourceGroupData extends AbstractResourceData implements
|
||||
IResourceGroup {
|
||||
|
||||
private ResourceList resourceList;
|
||||
|
||||
@XmlElement
|
||||
private String groupName;
|
||||
|
||||
@XmlElement(name = "channelResource")
|
||||
private List<ChannelResource> channelResources;
|
||||
|
||||
private Map<Channel, ChannelInfo> channelInfo = new HashMap<Channel, ChannelInfo>();
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.core.rsc.IResourceGroup#getResourceList()
|
||||
*/
|
||||
@Override
|
||||
public ResourceList getResourceList() {
|
||||
if (resourceList == null) {
|
||||
resourceList = new ResourceList() {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
protected boolean canAdd(ResourcePair e) {
|
||||
// Don't allow a ResourcePair that == another in the list
|
||||
Iterator<ResourcePair> iter = iterator();
|
||||
while (iter.hasNext()) {
|
||||
if (iter.next() == e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
for (ChannelResource resource : channelResources) {
|
||||
addResource(resource.getResourceData());
|
||||
}
|
||||
}
|
||||
return resourceList;
|
||||
}
|
||||
|
||||
private void addResource(AbstractResourceData resourceData) {
|
||||
ResourcePair rp = new ResourcePair();
|
||||
rp.setResourceData(resourceData);
|
||||
rp.setLoadProperties(new LoadProperties());
|
||||
rp.setProperties(new ResourceProperties());
|
||||
resourceList.add(rp);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.viz.core.rsc.AbstractResourceData#construct(com.raytheon
|
||||
* .uf.viz.core.rsc.LoadProperties,
|
||||
* com.raytheon.uf.viz.core.drawables.IDescriptor)
|
||||
*/
|
||||
@Override
|
||||
public AbstractVizResource<?, ?> construct(LoadProperties loadProperties,
|
||||
IDescriptor descriptor) throws VizException {
|
||||
return new TrueColorResourceGroup(this, loadProperties);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.viz.core.rsc.AbstractResourceData#update(java.lang.Object
|
||||
* )
|
||||
*/
|
||||
@Override
|
||||
public void update(Object updateData) {
|
||||
// Nothing to update, updates will be handled by sub resources
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the groupName
|
||||
*/
|
||||
public String getGroupName() {
|
||||
return groupName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param groupName
|
||||
* the groupName to set
|
||||
*/
|
||||
public void setGroupName(String groupName) {
|
||||
this.groupName = groupName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the channelResources
|
||||
*/
|
||||
public List<ChannelResource> getChannelResources() {
|
||||
return channelResources;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param channelResources
|
||||
* the channelResources to set
|
||||
*/
|
||||
public void setChannelResources(List<ChannelResource> channelResources) {
|
||||
this.channelResources = channelResources;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the channelInfo
|
||||
*/
|
||||
public ChannelInfo getChannelInfo(Channel channel) {
|
||||
return channelInfo.get(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param channelInfo
|
||||
* the channelInfo to set
|
||||
*/
|
||||
public void setChannelInfo(ChannelInfo channelInfo) {
|
||||
this.channelInfo.put(channelInfo.getChannel(), channelInfo);
|
||||
}
|
||||
|
||||
public ChannelInfo[] getChannelInfoArray() {
|
||||
return this.channelInfo.values().toArray(
|
||||
new ChannelInfo[channelInfo.size()]);
|
||||
}
|
||||
|
||||
@XmlElement(name = "channelInfo")
|
||||
public void setChannelInfoArray(ChannelInfo[] channelInfo) {
|
||||
if (channelInfo == null) {
|
||||
channelInfo = new ChannelInfo[0];
|
||||
}
|
||||
this.channelInfo.clear();
|
||||
for (ChannelInfo ci : channelInfo) {
|
||||
setChannelInfo(ci);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result
|
||||
+ ((channelInfo == null) ? 0 : channelInfo.hashCode());
|
||||
result = prime
|
||||
* result
|
||||
+ ((channelResources == null) ? 0 : channelResources.hashCode());
|
||||
result = prime * result
|
||||
+ ((groupName == null) ? 0 : groupName.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
TrueColorResourceGroupData other = (TrueColorResourceGroupData) obj;
|
||||
if (channelInfo == null) {
|
||||
if (other.channelInfo != null)
|
||||
return false;
|
||||
} else if (!channelInfo.equals(other.channelInfo))
|
||||
return false;
|
||||
if (channelResources == null) {
|
||||
if (other.channelResources != null)
|
||||
return false;
|
||||
} else if (!channelResources.equals(other.channelResources))
|
||||
return false;
|
||||
if (groupName == null) {
|
||||
if (other.groupName != null)
|
||||
return false;
|
||||
} else if (!groupName.equals(other.groupName))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -17,11 +17,11 @@
|
|||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.viz.ui.dialogs;
|
||||
package com.raytheon.uf.viz.truecolor.ui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jface.dialogs.IDialogConstants;
|
||||
import org.eclipse.swt.SWT;
|
||||
|
@ -30,20 +30,24 @@ import org.eclipse.swt.events.SelectionEvent;
|
|||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Button;
|
||||
import org.eclipse.swt.widgets.Combo;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Group;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
|
||||
import com.raytheon.uf.viz.core.drawables.ColorMapParameters;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.colormap.IMultiChannelImageExtension.Channel;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.colormap.IMultiChannelImageExtension.ChannelData;
|
||||
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
|
||||
import com.raytheon.uf.viz.core.rsc.capabilities.MultiChannelCapability;
|
||||
import com.raytheon.uf.viz.core.rsc.IDisposeListener;
|
||||
import com.raytheon.uf.viz.core.rsc.capabilities.ColorMapCapability;
|
||||
import com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension.Channel;
|
||||
import com.raytheon.uf.viz.truecolor.rsc.TrueColorResourceGroup;
|
||||
import com.raytheon.uf.viz.truecolor.rsc.TrueColorResourceGroup.DisplayedChannelResource;
|
||||
import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
|
||||
import com.raytheon.viz.ui.dialogs.ColorMapSliderComp;
|
||||
|
||||
/**
|
||||
* Dialog for manipulating multi channel capability
|
||||
* Dialog for modifying true color attributes on a dialog
|
||||
*
|
||||
* TODO: Update sliders when combo changes
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
|
@ -51,7 +55,7 @@ import com.raytheon.uf.viz.core.rsc.capabilities.MultiChannelCapability;
|
|||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jan 3, 2012 mschenke Initial creation
|
||||
* Aug 16, 2012 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -59,29 +63,26 @@ import com.raytheon.uf.viz.core.rsc.capabilities.MultiChannelCapability;
|
|||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class MultiChannelDialog extends CaveSWTDialog {
|
||||
public class TrueColorDialog extends CaveSWTDialog implements IDisposeListener {
|
||||
|
||||
private static final String DISABLED = "Disabled";
|
||||
|
||||
private AbstractVizResource<?, ?> resource;
|
||||
|
||||
private MultiChannelCapability capability;
|
||||
|
||||
private String[] items;
|
||||
protected TrueColorResourceGroup resource;
|
||||
|
||||
private List<ColorMapSliderComp> sliderComps;
|
||||
|
||||
public MultiChannelDialog(Shell parent, AbstractVizResource<?, ?> resource,
|
||||
MultiChannelCapability capability) {
|
||||
super(parent);
|
||||
this.capability = capability;
|
||||
/**
|
||||
* Creates the TrueColorDialog as a window of the parent Shell
|
||||
*
|
||||
* @param parent
|
||||
* @param resource
|
||||
*/
|
||||
public TrueColorDialog(Shell parent, TrueColorResourceGroup resource) {
|
||||
super(parent, SWT.DIALOG_TRIM);
|
||||
this.resource = resource;
|
||||
String[] names = capability.getNames();
|
||||
this.items = new String[names.length + 1];
|
||||
System.arraycopy(names, 0, items, 1, names.length);
|
||||
items[0] = DISABLED;
|
||||
this.sliderComps = new ArrayList<ColorMapSliderComp>();
|
||||
setText("Channel Options");
|
||||
setText("Composite Options");
|
||||
resource.registerListener(this);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -93,9 +94,15 @@ public class MultiChannelDialog extends CaveSWTDialog {
|
|||
*/
|
||||
@Override
|
||||
protected void initializeComponents(Shell shell) {
|
||||
Map<Channel, ChannelData> channelMap = capability.getChannelMap();
|
||||
Collection<DisplayedChannelResource> resources = resource
|
||||
.getChannelResources();
|
||||
for (Channel c : Channel.values()) {
|
||||
addGroup(shell, c, channelMap.get(c));
|
||||
for (DisplayedChannelResource rsc : resources) {
|
||||
if (rsc.isChannel(c)) {
|
||||
addGroup(shell, c, rsc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Composite buttonComp = new Composite(shell, SWT.NONE);
|
||||
|
@ -129,73 +136,39 @@ public class MultiChannelDialog extends CaveSWTDialog {
|
|||
b.setLayoutData(gd);
|
||||
}
|
||||
|
||||
private void addGroup(Composite parent, Channel channel,
|
||||
final ChannelData data) {
|
||||
/**
|
||||
* @param shell
|
||||
* @param c
|
||||
* @param displayedChannelResource
|
||||
*/
|
||||
private void addGroup(Composite parent, final Channel channel,
|
||||
DisplayedChannelResource displayedResource) {
|
||||
ColorMapParameters params = null;
|
||||
if (data != null) {
|
||||
params = data.parameters;
|
||||
if (displayedResource != null) {
|
||||
params = displayedResource.resource.getCapability(
|
||||
ColorMapCapability.class).getColorMapParameters();
|
||||
} else {
|
||||
params = new ColorMapParameters();
|
||||
}
|
||||
|
||||
String groupName = channel.name();
|
||||
if (displayedResource != null) {
|
||||
groupName += " (" + displayedResource.getDisplayName() + ")";
|
||||
}
|
||||
|
||||
Group group = new Group(parent, SWT.SHADOW_ETCHED_IN);
|
||||
group.setLayout(new GridLayout(4, false));
|
||||
group.setText(channel + ":");
|
||||
group.setLayout(new GridLayout(1, false));
|
||||
group.setText(groupName + ":");
|
||||
group.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true));
|
||||
|
||||
final ColorMapSliderComp cmapSlider = new ColorMapSliderComp(group,
|
||||
params);
|
||||
cmapSlider.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
|
||||
((GridData) cmapSlider.getLayoutData()).widthHint = 450;
|
||||
sliderComps.add(cmapSlider);
|
||||
|
||||
final Button invertBtn = new Button(group, SWT.CHECK);
|
||||
invertBtn.addSelectionListener(new SelectionAdapter() {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse
|
||||
* .swt.events.SelectionEvent)
|
||||
*/
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
data.invert = invertBtn.getSelection();
|
||||
resource.issueRefresh();
|
||||
}
|
||||
});
|
||||
|
||||
if (data != null) {
|
||||
invertBtn.setSelection(data.invert);
|
||||
}
|
||||
|
||||
Label label = new Label(group, SWT.NONE);
|
||||
label.setText("Invert");
|
||||
|
||||
final Combo options = new Combo(group, SWT.DROP_DOWN | SWT.READ_ONLY);
|
||||
options.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
|
||||
options.setItems(items);
|
||||
if (data == null) {
|
||||
options.setText(DISABLED);
|
||||
if (displayedResource == null) {
|
||||
enable(group, false);
|
||||
} else {
|
||||
if (data.name == null) {
|
||||
options.setText(DISABLED);
|
||||
enable(cmapSlider, false);
|
||||
} else {
|
||||
options.setText(data.name);
|
||||
}
|
||||
options.addSelectionListener(new SelectionAdapter() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
if (DISABLED.equals(options.getText())) {
|
||||
enable(cmapSlider, false);
|
||||
data.name = null;
|
||||
} else {
|
||||
enable(cmapSlider, true);
|
||||
data.name = options.getText();
|
||||
}
|
||||
capability.capabilityChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,4 +182,28 @@ public class MultiChannelDialog extends CaveSWTDialog {
|
|||
private void okPressed() {
|
||||
close();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.viz.core.rsc.IDisposeListener#disposed(com.raytheon.uf
|
||||
* .viz.core.rsc.AbstractVizResource)
|
||||
*/
|
||||
@Override
|
||||
public void disposed(AbstractVizResource<?, ?> rsc) {
|
||||
close();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#disposed()
|
||||
*/
|
||||
@Override
|
||||
protected void disposed() {
|
||||
super.disposed();
|
||||
resource.unregisterListener(this);
|
||||
}
|
||||
|
||||
}
|
|
@ -17,7 +17,10 @@
|
|||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.viz.ui.cmenu;
|
||||
package com.raytheon.uf.viz.truecolor.ui;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.widgets.Event;
|
||||
|
@ -25,14 +28,11 @@ import org.eclipse.swt.widgets.Listener;
|
|||
import org.eclipse.swt.widgets.Shell;
|
||||
import org.eclipse.ui.PlatformUI;
|
||||
|
||||
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
|
||||
import com.raytheon.uf.viz.core.rsc.IDisposeListener;
|
||||
import com.raytheon.uf.viz.core.rsc.capabilities.MultiChannelCapability;
|
||||
import com.raytheon.viz.ui.dialogs.MultiChannelDialog;
|
||||
import com.raytheon.uf.viz.truecolor.rsc.TrueColorResourceGroup;
|
||||
import com.raytheon.viz.ui.cmenu.AbstractRightClickAction;
|
||||
|
||||
/**
|
||||
* Right click action that opens a dialog for modifying resources with
|
||||
* MultiChannelCapability
|
||||
* Action that opens the {@link TrueColorDialog}
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
|
@ -40,7 +40,7 @@ import com.raytheon.viz.ui.dialogs.MultiChannelDialog;
|
|||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jan 3, 2012 mschenke Initial creation
|
||||
* Aug 16, 2012 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -48,7 +48,9 @@ import com.raytheon.viz.ui.dialogs.MultiChannelDialog;
|
|||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class MultiChannelImagingAction extends AbstractRightClickAction {
|
||||
public class TrueColorDialogAction extends AbstractRightClickAction {
|
||||
|
||||
private static Map<TrueColorResourceGroup, TrueColorDialog> dialogMap = new HashMap<TrueColorResourceGroup, TrueColorDialog>();
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
|
@ -57,7 +59,7 @@ public class MultiChannelImagingAction extends AbstractRightClickAction {
|
|||
*/
|
||||
@Override
|
||||
public String getText() {
|
||||
return "Channel Options...";
|
||||
return "Composite Options...";
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -67,26 +69,22 @@ public class MultiChannelImagingAction extends AbstractRightClickAction {
|
|||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
|
||||
.getShell();
|
||||
final AbstractVizResource<?, ?> rsc = getSelectedRsc();
|
||||
MultiChannelCapability cap = rsc
|
||||
.getCapability(MultiChannelCapability.class);
|
||||
final MultiChannelDialog dialog = new MultiChannelDialog(shell, rsc,
|
||||
cap);
|
||||
final IDisposeListener listener = new IDisposeListener() {
|
||||
@Override
|
||||
public void disposed(AbstractVizResource<?, ?> rsc) {
|
||||
dialog.close();
|
||||
}
|
||||
};
|
||||
rsc.registerListener(listener);
|
||||
dialog.addListener(SWT.Dispose, new Listener() {
|
||||
@Override
|
||||
public void handleEvent(Event event) {
|
||||
rsc.unregisterListener(listener);
|
||||
}
|
||||
});
|
||||
TrueColorResourceGroup resource = (TrueColorResourceGroup) getSelectedRsc();
|
||||
TrueColorDialog dialog = dialogMap.get(resource);
|
||||
if (dialog == null) {
|
||||
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
|
||||
.getShell();
|
||||
dialog = new TrueColorDialog(shell, resource);
|
||||
final TrueColorDialog toRemove = dialog;
|
||||
dialogMap.put(resource, dialog);
|
||||
dialog.addListener(SWT.Close, new Listener() {
|
||||
@Override
|
||||
public void handleEvent(Event event) {
|
||||
dialogMap.remove(toRemove.resource);
|
||||
}
|
||||
});
|
||||
}
|
||||
dialog.open();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
#include <colorUtil>
|
||||
#include <indexing>
|
||||
|
||||
uniform float alpha;
|
||||
uniform float brightness;
|
||||
uniform float contrast;
|
||||
|
||||
uniform sampler2D rawTexR;
|
||||
uniform float naturalMinR;
|
||||
uniform float naturalMaxR;
|
||||
uniform float cmapMinR;
|
||||
uniform float cmapMaxR;
|
||||
uniform int isFloatR;
|
||||
uniform int invertR;
|
||||
uniform int applyR;
|
||||
|
||||
uniform sampler2D rawTexG;
|
||||
uniform float naturalMinG;
|
||||
uniform float naturalMaxG;
|
||||
uniform float cmapMinG;
|
||||
uniform float cmapMaxG;
|
||||
uniform int isFloatG;
|
||||
uniform int invertG;
|
||||
uniform int applyG;
|
||||
|
||||
uniform sampler2D rawTexB;
|
||||
uniform float naturalMinB;
|
||||
uniform float naturalMaxB;
|
||||
uniform float cmapMinB;
|
||||
uniform float cmapMaxB;
|
||||
uniform int isFloatB;
|
||||
uniform int invertB;
|
||||
uniform int applyB;
|
||||
|
||||
|
||||
float getIndex(sampler2D rawTex, float cmapMin, float cmapMax, float naturalMin, float naturalMax, int isFloat) {
|
||||
vec4 textureValue = texture2D(rawTex, gl_TexCoord[0].st);
|
||||
float naturalVal = textureValue.r;
|
||||
if ( isFloat == 0 ) {
|
||||
naturalVal = ((naturalVal * (naturalMax - naturalMin)) + naturalMin);
|
||||
}
|
||||
return findIndex(naturalVal, cmapMin, cmapMax);
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
float r = 0.0;
|
||||
float g = 0.0;
|
||||
float b = 0.0;
|
||||
|
||||
if ( applyR != 0 ) {
|
||||
r = getIndex(rawTexR, cmapMinR, cmapMaxR, naturalMinR, naturalMaxR, isFloatR);
|
||||
if ( invertR != 0 ) {
|
||||
r = 1.0 - r;
|
||||
}
|
||||
}
|
||||
if ( applyG != 0 ) {
|
||||
g = getIndex(rawTexG, cmapMinG, cmapMaxG, naturalMinG, naturalMaxG, isFloatG);
|
||||
if ( invertG != 0 ) {
|
||||
g = 1.0 - g;
|
||||
}
|
||||
}
|
||||
if ( applyB != 0 ) {
|
||||
b = getIndex(rawTexB, cmapMinB, cmapMaxB, naturalMinB, naturalMaxB, isFloatB);
|
||||
if ( invertB != 0 ) {
|
||||
b = 1.0 - b;
|
||||
}
|
||||
}
|
||||
|
||||
gl_FragColor = applyContrastAlphaBrightness(vec4(r,g,b,alpha), alpha, brightness, contrast);
|
||||
}
|
|
@ -53,9 +53,6 @@
|
|||
<graphicsExtension
|
||||
class="com.raytheon.viz.core.gl.internal.ext.GLDefaultImagingExtension">
|
||||
</graphicsExtension>
|
||||
<graphicsExtension
|
||||
class="com.raytheon.viz.core.gl.internal.ext.GLMultiChannelImageExtension">
|
||||
</graphicsExtension>
|
||||
<graphicsExtension
|
||||
class="com.raytheon.viz.core.gl.internal.ext.mosaic.GLMosaicImageExtension">
|
||||
</graphicsExtension>
|
||||
|
|
|
@ -90,8 +90,7 @@ public abstract class AbstractGLImagingExtension extends
|
|||
try {
|
||||
gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL);
|
||||
rval = drawRastersInternal(paintProps, images);
|
||||
gl.glPolygonMode(GL.GL_BACK, GL.GL_LINE);
|
||||
gl.glDisable(GL.GL_BLEND);
|
||||
disableBlending(gl);
|
||||
} finally {
|
||||
target.popGLState();
|
||||
}
|
||||
|
@ -159,14 +158,7 @@ public abstract class AbstractGLImagingExtension extends
|
|||
program.startShader();
|
||||
}
|
||||
|
||||
gl.glTexEnvi(GL.GL_TEXTURE_ENV,
|
||||
GL.GL_TEXTURE_ENV_MODE, GL.GL_ADD);
|
||||
gl.glEnable(GL.GL_BLEND);
|
||||
gl.glTexEnvi(GL.GL_TEXTURE_ENV,
|
||||
GL.GL_TEXTURE_ENV_MODE, GL.GL_BLEND);
|
||||
gl.glBlendFunc(GL.GL_SRC_ALPHA,
|
||||
GL.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
enableBlending(gl);
|
||||
gl.glColor4f(0.0f, 0.0f, 0.0f,
|
||||
paintProps.getAlpha());
|
||||
}
|
||||
|
@ -311,6 +303,27 @@ public abstract class AbstractGLImagingExtension extends
|
|||
return PaintStatus.ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to enable blending for images
|
||||
*
|
||||
* @param gl
|
||||
*/
|
||||
protected void enableBlending(GL gl) {
|
||||
gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_ADD);
|
||||
gl.glEnable(GL.GL_BLEND);
|
||||
gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_BLEND);
|
||||
gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to disable blending for images
|
||||
*
|
||||
* @param gl
|
||||
*/
|
||||
protected void disableBlending(GL gl) {
|
||||
gl.glDisable(GL.GL_BLEND);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup anything that is required pre image rendering. Object returned is a
|
||||
* state object and will be passed in to postImageRender. If the image
|
||||
|
|
|
@ -209,7 +209,10 @@ public class GLShaderProgram {
|
|||
* @param value
|
||||
*/
|
||||
private void setUniformInternal(String uniformName, Object value) {
|
||||
if (value instanceof Float) {
|
||||
if (value instanceof Double) {
|
||||
gl.glUniform1f(getUniformLocation(uniformName),
|
||||
((Double) value).floatValue());
|
||||
} else if (value instanceof Float) {
|
||||
gl.glUniform1f(getUniformLocation(uniformName), (Float) value);
|
||||
} else if (value instanceof Integer) {
|
||||
gl.glUniform1i(getUniformLocation(uniformName), (Integer) value);
|
||||
|
|
|
@ -74,6 +74,8 @@ public class GLProgramManager {
|
|||
|
||||
private final Map<String, File> programFiles = new HashMap<String, File>();
|
||||
|
||||
private final Map<String, Long> programFileModTimes = new HashMap<String, Long>();
|
||||
|
||||
private final IPathManager pm;
|
||||
|
||||
private GLProgramManager() {
|
||||
|
@ -86,6 +88,7 @@ public class GLProgramManager {
|
|||
File fileObj = file.getFile();
|
||||
String name = fileObj.getName();
|
||||
programFiles.put(name, fileObj);
|
||||
programFileModTimes.put(name, fileObj.lastModified());
|
||||
programsCode.put(name, readProgramContents(fileObj));
|
||||
}
|
||||
}
|
||||
|
@ -107,9 +110,15 @@ public class GLProgramManager {
|
|||
* @throws VizException
|
||||
*/
|
||||
public String getProgramCode(String aProgramName) throws VizException {
|
||||
String fileName = aProgramName + GLSL_EXTENSION;
|
||||
hasBeenModified(aProgramName);
|
||||
return programsCode.get(fileName);
|
||||
if (aProgramName.endsWith(GLSL_EXTENSION) == false) {
|
||||
aProgramName += GLSL_EXTENSION;
|
||||
}
|
||||
if (hasBeenModified(aProgramName)) {
|
||||
File programFile = programFiles.get(aProgramName);
|
||||
programsCode.put(aProgramName, readProgramContents(programFile));
|
||||
programFileModTimes.put(aProgramName, programFile.lastModified());
|
||||
}
|
||||
return programsCode.get(aProgramName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -119,9 +128,16 @@ public class GLProgramManager {
|
|||
* @return
|
||||
*/
|
||||
public boolean hasBeenModified(String programName) {
|
||||
// TODO: Check file modification time and reload contents. Should also
|
||||
// check modification times of files depends on and reload if any
|
||||
// changes
|
||||
if (programName.endsWith(GLSL_EXTENSION) == false) {
|
||||
programName += GLSL_EXTENSION;
|
||||
}
|
||||
File programFile = programFiles.get(programName);
|
||||
if (programFile != null) {
|
||||
long lastMod = programFileModTimes.get(programName);
|
||||
if (lastMod != programFile.lastModified()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,113 +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.viz.core.gl.images;
|
||||
|
||||
import com.raytheon.uf.viz.core.drawables.ColorMapParameters;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.colormap.IMultiChannelImageExtension.ChannelData;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.colormap.IMultiChannelImageExtension.IImageChannel;
|
||||
import com.raytheon.viz.core.gl.internal.ext.GLMultiChannelImageExtension;
|
||||
|
||||
/**
|
||||
* GL implementation of {@link IImageChannel}
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 9, 2012 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class GLImageChannel extends GLDelegateImage<GLColormappedImage>
|
||||
implements IImageChannel {
|
||||
|
||||
private ChannelData channelData;
|
||||
|
||||
/**
|
||||
* @param target
|
||||
* @param image
|
||||
* @param extensionClass
|
||||
*/
|
||||
public GLImageChannel(GLColormappedImage image, ChannelData channelData) {
|
||||
super(image, GLMultiChannelImageExtension.class);
|
||||
this.channelData = channelData;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.viz.core.drawables.IColormappedImage#getColorMapParameters
|
||||
* ()
|
||||
*/
|
||||
@Override
|
||||
public ColorMapParameters getColorMapParameters() {
|
||||
return image.getColorMapParameters();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.viz.core.drawables.IColormappedImage#setColorMapParameters
|
||||
* (com.raytheon.uf.viz.core.drawables.ColorMapParameters)
|
||||
*/
|
||||
@Override
|
||||
public void setColorMapParameters(ColorMapParameters params) {
|
||||
image.setColorMapParameters(params);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.core.drawables.IColormappedImage#getValue(int,
|
||||
* int)
|
||||
*/
|
||||
@Override
|
||||
public double getValue(int x, int y) {
|
||||
return image.getValue(x, y);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.viz.core.drawables.ext.colormap.IMultiChannelImageExtension
|
||||
* .IChannelImage#setInvert(boolean)
|
||||
*/
|
||||
@Override
|
||||
public void setInverted(boolean inverted) {
|
||||
channelData.invert = inverted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the invert
|
||||
*/
|
||||
public boolean isInverted() {
|
||||
return channelData.invert;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,262 +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.viz.core.gl.images;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.media.opengl.GL;
|
||||
|
||||
import com.raytheon.uf.viz.core.drawables.IColormappedImage;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.colormap.IMultiChannelImageExtension.Channel;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.colormap.IMultiChannelImageExtension.IImageChannel;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.colormap.IMultiChannelImageExtension.IMultiChannelImage;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.viz.core.gl.IGLTarget;
|
||||
import com.raytheon.viz.core.gl.internal.ext.GLMultiChannelImageExtension;
|
||||
import com.sun.opengl.util.texture.TextureCoords;
|
||||
|
||||
/**
|
||||
* GL implementation of a multi channel image
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Dec 19, 2011 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class GLMultiChannelImage extends AbstractGLImage implements
|
||||
IMultiChannelImage {
|
||||
|
||||
private Map<Channel, IImageChannel> channelMap;
|
||||
|
||||
/**
|
||||
* @param target
|
||||
* @param extensionClass
|
||||
*/
|
||||
public GLMultiChannelImage(IGLTarget target,
|
||||
Map<Channel, IImageChannel> channelMap) {
|
||||
super(GLMultiChannelImageExtension.class);
|
||||
this.channelMap = channelMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first IColormappedImage in the map
|
||||
*
|
||||
* @return first image in the map or null if none
|
||||
*/
|
||||
private IColormappedImage getFirstImage() {
|
||||
if (channelMap != null) {
|
||||
for (IColormappedImage image : channelMap.values()) {
|
||||
if (image != null) {
|
||||
return image;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.viz.core.gl.images.AbstractGLImage#setInterpolated(boolean)
|
||||
*/
|
||||
@Override
|
||||
public void setInterpolated(boolean isInterpolated) {
|
||||
super.setInterpolated(isInterpolated);
|
||||
for (IColormappedImage image : channelMap.values()) {
|
||||
((AbstractGLImage) image).setInterpolated(isInterpolated);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.core.drawables.IImage#getWidth()
|
||||
*/
|
||||
@Override
|
||||
public int getWidth() {
|
||||
IColormappedImage image = getFirstImage();
|
||||
if (image != null) {
|
||||
return image.getWidth();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.core.drawables.IImage#getHeight()
|
||||
*/
|
||||
@Override
|
||||
public int getHeight() {
|
||||
IColormappedImage image = getFirstImage();
|
||||
if (image != null) {
|
||||
return image.getHeight();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.viz.core.drawables.ext.colormap.IMultiChannelImageExtension
|
||||
* .IMultiChannelImage#getImageMapping()
|
||||
*/
|
||||
@Override
|
||||
public Map<Channel, IImageChannel> getImageMapping() {
|
||||
return channelMap;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.viz.core.drawables.ext.colormap.IMultiChannelImageExtension
|
||||
* .IMultiChannelImage#setImageMapping(java.util.Map)
|
||||
*/
|
||||
@Override
|
||||
public void setImageMapping(Map<Channel, IImageChannel> mapping) {
|
||||
this.channelMap = mapping;
|
||||
// Set ourselves as unloaded since we are updating the mapping
|
||||
setStatus(Status.UNLOADED);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.viz.core.gl.images.AbstractGLImage#getTextureCoords()
|
||||
*/
|
||||
@Override
|
||||
public TextureCoords getTextureCoords() {
|
||||
return new TextureCoords(0, 1, 1, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.viz.core.gl.images.AbstractGLImage#getTextureid()
|
||||
*/
|
||||
@Override
|
||||
public int getTextureid() {
|
||||
// We do not have a single textureid specifically
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.viz.core.gl.images.AbstractGLImage#getTextureStorageType()
|
||||
*/
|
||||
@Override
|
||||
public int getTextureStorageType() {
|
||||
AbstractGLImage image = (AbstractGLImage) getFirstImage();
|
||||
return image.getTextureStorageType();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.viz.core.gl.images.AbstractGLImage#stage()
|
||||
*/
|
||||
@Override
|
||||
public boolean stageTexture() throws VizException {
|
||||
boolean rval = false;
|
||||
if (channelMap.size() > 0) {
|
||||
rval = true;
|
||||
for (IColormappedImage image : channelMap.values()) {
|
||||
AbstractGLImage glImage = (AbstractGLImage) image;
|
||||
glImage.stage();
|
||||
if (glImage.getStatus() == Status.FAILED) {
|
||||
rval = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadTexture(GL gl) throws VizException {
|
||||
if (channelMap.size() > 0) {
|
||||
Status status = Status.LOADED;
|
||||
for (IColormappedImage image : channelMap.values()) {
|
||||
AbstractGLImage glImage = (AbstractGLImage) image;
|
||||
glImage.loadTexture(gl);
|
||||
if (glImage.getStatus() == Status.FAILED) {
|
||||
status = Status.FAILED;
|
||||
}
|
||||
}
|
||||
setStatus(status);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.viz.core.gl.images.AbstractGLImage#dispose()
|
||||
*/
|
||||
@Override
|
||||
public void dispose() {
|
||||
for (IColormappedImage image : channelMap.values()) {
|
||||
((AbstractGLImage) image).dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.viz.core.gl.images.AbstractGLImage#bind()
|
||||
*/
|
||||
@Override
|
||||
public boolean bind(GL gl) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.viz.core.gl.images.AbstractGLImage#bind(int)
|
||||
*/
|
||||
@Override
|
||||
public boolean bind(GL gl, int texture) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.viz.core.gl.images.AbstractGLImage#usaAsFrameBuffer()
|
||||
*/
|
||||
@Override
|
||||
public void usaAsFrameBuffer() throws VizException {
|
||||
throw new VizException(
|
||||
"Using a GLMultiChannelImage as a frame buffer is not supported");
|
||||
}
|
||||
}
|
|
@ -1,184 +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.viz.core.gl.internal.ext;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.media.opengl.GL;
|
||||
|
||||
import com.raytheon.uf.viz.core.data.IColorMapDataRetrievalCallback;
|
||||
import com.raytheon.uf.viz.core.drawables.ColorMapParameters;
|
||||
import com.raytheon.uf.viz.core.drawables.IColormappedImage;
|
||||
import com.raytheon.uf.viz.core.drawables.IImage;
|
||||
import com.raytheon.uf.viz.core.drawables.PaintProperties;
|
||||
import com.raytheon.uf.viz.core.drawables.ext.colormap.IMultiChannelImageExtension;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.viz.core.gl.glsl.AbstractGLSLImagingExtension;
|
||||
import com.raytheon.viz.core.gl.glsl.GLShaderProgram;
|
||||
import com.raytheon.viz.core.gl.images.GLImageChannel;
|
||||
import com.raytheon.viz.core.gl.images.GLMultiChannelImage;
|
||||
|
||||
/**
|
||||
* GL implementation of {@link IMultiChannelImageExtension}
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Dec 19, 2011 mschenke Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class GLMultiChannelImageExtension extends AbstractGLSLImagingExtension
|
||||
implements IMultiChannelImageExtension {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.viz.core.drawables.ext.colormap.IMultiChannelImageExtension
|
||||
* #constructImage(java.util.Map)
|
||||
*/
|
||||
@Override
|
||||
public IMultiChannelImage constructImage(
|
||||
Map<Channel, IImageChannel> imageMapping) throws VizException {
|
||||
return new GLMultiChannelImage(target, imageMapping);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.viz.core.drawables.ext.colormap.IMultiChannelImageExtension
|
||||
* #
|
||||
* constructImage(com.raytheon.uf.viz.core.data.IColorMapDataRetrievalCallback
|
||||
* , com.raytheon.uf.viz.core.drawables.ColorMapParameters)
|
||||
*/
|
||||
@Override
|
||||
public IImageChannel constructImage(
|
||||
IColorMapDataRetrievalCallback callback, ChannelData channelData)
|
||||
throws VizException {
|
||||
return new GLImageChannel(target.getExtension(
|
||||
GLColormappedImageExtension.class).initializeRaster(callback,
|
||||
channelData.parameters), channelData);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.viz.core.gl.ext.AbstractGLImagingExtension#getShaderProgramName
|
||||
* ()
|
||||
*/
|
||||
@Override
|
||||
public String getShaderProgramName() {
|
||||
return "multichannel";
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.viz.core.gl.ext.AbstractGLImagingExtension#loadShaderData
|
||||
* (com.raytheon.viz.core.gl.glsl.GLShaderProgram,
|
||||
* com.raytheon.uf.viz.core.drawables.IImage,
|
||||
* com.raytheon.uf.viz.core.drawables.PaintProperties)
|
||||
*/
|
||||
@Override
|
||||
public void loadShaderData(GLShaderProgram program, IImage image,
|
||||
PaintProperties paintProps) throws VizException {
|
||||
GLMultiChannelImage glImage = null;
|
||||
if (image instanceof GLMultiChannelImage == false) {
|
||||
throw new VizException(
|
||||
"Cannot apply glsl multichannel shader to non gl multichannel image");
|
||||
}
|
||||
glImage = (GLMultiChannelImage) image;
|
||||
Map<Channel, IImageChannel> channelMap = glImage.getImageMapping();
|
||||
|
||||
program.setUniform("brightness", glImage.getBrightness());
|
||||
program.setUniform("contrast", glImage.getContrast());
|
||||
program.setUniform("alpha", paintProps.getAlpha());
|
||||
|
||||
for (Channel c : Channel.values()) {
|
||||
String suffix = "";
|
||||
int texture = -1;
|
||||
int texNum = -1;
|
||||
switch (c) {
|
||||
case RED:
|
||||
suffix = "R";
|
||||
texture = GL.GL_TEXTURE0;
|
||||
texNum = 0;
|
||||
break;
|
||||
case GREEN:
|
||||
suffix = "G";
|
||||
texture = GL.GL_TEXTURE1;
|
||||
texNum = 1;
|
||||
break;
|
||||
case BLUE:
|
||||
suffix = "B";
|
||||
texture = GL.GL_TEXTURE2;
|
||||
texNum = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
boolean applied = false;
|
||||
IColormappedImage ci = channelMap.get(c);
|
||||
if (ci != null) {
|
||||
if (ci instanceof GLImageChannel == false) {
|
||||
throw new VizException(
|
||||
"Cannot apply glsl multichannel shader to non gl colormapped image");
|
||||
}
|
||||
GLImageChannel glCMImage = (GLImageChannel) ci;
|
||||
if (glCMImage.bind(target.getGl(), texture)) {
|
||||
int textureType = glCMImage.getWrappedImage()
|
||||
.getTextureType();
|
||||
|
||||
ColorMapParameters colorMapParameters = ci
|
||||
.getColorMapParameters();
|
||||
|
||||
program.setUniform("rawTex" + suffix, texNum);
|
||||
program.setUniform("naturalMin" + suffix,
|
||||
colorMapParameters.getDataMin());
|
||||
program.setUniform("naturalMax" + suffix,
|
||||
colorMapParameters.getDataMax());
|
||||
program.setUniform("cmapMin" + suffix,
|
||||
colorMapParameters.getColorMapMin());
|
||||
program.setUniform("cmapMax" + suffix,
|
||||
colorMapParameters.getColorMapMax());
|
||||
program.setUniform("isFloat" + suffix,
|
||||
textureType == GL.GL_FLOAT
|
||||
|| textureType == GL.GL_HALF_FLOAT_ARB ? 1
|
||||
: 0);
|
||||
program.setUniform("invert" + suffix,
|
||||
glCMImage.isInverted());
|
||||
applied = true;
|
||||
}
|
||||
}
|
||||
program.setUniform("apply" + suffix, applied ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -27,12 +27,17 @@
|
|||
</extension>
|
||||
<extension point="org.eclipse.core.expressions.definitions">
|
||||
<definition id="com.raytheon.viz.gfe.inGFEActionSet">
|
||||
<with variable="activeContexts">
|
||||
<iterate operator="or">
|
||||
<equals value="com.raytheon.viz.gfe.GFEActionSet">
|
||||
</equals>
|
||||
</iterate>
|
||||
</with>
|
||||
<and>
|
||||
<with variable="activeContexts">
|
||||
<iterate operator="or">
|
||||
<equals value="com.raytheon.viz.gfe.GFEActionSet">
|
||||
</equals>
|
||||
</iterate>
|
||||
</with>
|
||||
<with variable="activeEditor">
|
||||
<instanceof value="com.raytheon.uf.viz.core.IDisplayPaneContainer"/>
|
||||
</with>
|
||||
</and>
|
||||
</definition>
|
||||
</extension>
|
||||
<extension point="org.eclipse.ui.commands">
|
||||
|
|
|
@ -407,9 +407,11 @@ public class ReferenceSetManager implements IReferenceSetManager,
|
|||
areas.add(areaName);
|
||||
}
|
||||
}
|
||||
Collections.sort(areas);
|
||||
return areas;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveGroup(String groupName, List<String> areaNames) {
|
||||
statusHandler.handle(Priority.VERBOSE, "Save Edit Area Group: "
|
||||
+ groupName + " areas:" + areaNames);
|
||||
|
@ -469,6 +471,7 @@ public class ReferenceSetManager implements IReferenceSetManager,
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteGroup(String groupName) {
|
||||
IPathManager pm = PathManagerFactory.getPathManager();
|
||||
|
||||
|
@ -545,7 +548,7 @@ public class ReferenceSetManager implements IReferenceSetManager,
|
|||
refDataCache.remove(add.getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor for ReferenceSet taking a pointer to the Data Manager
|
||||
*
|
||||
|
@ -655,6 +658,7 @@ public class ReferenceSetManager implements IReferenceSetManager,
|
|||
* @see
|
||||
* com.raytheon.viz.gfe.core.internal.IReferenceSetManager#getActiveRefSet()
|
||||
*/
|
||||
@Override
|
||||
public ReferenceData getActiveRefSet() {
|
||||
return new ReferenceData(activeRefSet);
|
||||
}
|
||||
|
@ -666,6 +670,7 @@ public class ReferenceSetManager implements IReferenceSetManager,
|
|||
* com.raytheon.viz.gfe.core.internal.IReferenceSetManager#setActiveRefSet
|
||||
* (com.raytheon.edex.plugin.gfe.reference.ReferenceData)
|
||||
*/
|
||||
@Override
|
||||
public void setActiveRefSet(final ReferenceData refData) {
|
||||
refData.getGrid(); // force it to a grid
|
||||
|
||||
|
@ -706,6 +711,7 @@ public class ReferenceSetManager implements IReferenceSetManager,
|
|||
* com.raytheon.viz.gfe.core.internal.IReferenceSetManager#getAvailableSets
|
||||
* ()
|
||||
*/
|
||||
@Override
|
||||
public List<ReferenceID> getAvailableSets() {
|
||||
return Collections.unmodifiableList(availableSets);
|
||||
}
|
||||
|
@ -716,6 +722,7 @@ public class ReferenceSetManager implements IReferenceSetManager,
|
|||
* @see
|
||||
* com.raytheon.viz.gfe.core.internal.IReferenceSetManager#emptyRefSet()
|
||||
*/
|
||||
@Override
|
||||
public ReferenceData emptyRefSet() {
|
||||
return EMPTY;
|
||||
}
|
||||
|
@ -725,6 +732,7 @@ public class ReferenceSetManager implements IReferenceSetManager,
|
|||
*
|
||||
* @see com.raytheon.viz.gfe.core.internal.IReferenceSetManager#fullRefSet()
|
||||
*/
|
||||
@Override
|
||||
public ReferenceData fullRefSet() {
|
||||
return FULL;
|
||||
}
|
||||
|
@ -736,6 +744,7 @@ public class ReferenceSetManager implements IReferenceSetManager,
|
|||
* com.raytheon.viz.gfe.core.internal.IReferenceSetManager#loadRefSet(com
|
||||
* .raytheon.edex.plugin.gfe.reference.ReferenceID)
|
||||
*/
|
||||
@Override
|
||||
public ReferenceData loadRefSet(final ReferenceID refSetID) {
|
||||
// UFStatus.handle(Priority.VERBOSE, Activator.PLUGIN_ID,
|
||||
// StatusConstants.CATEGORY_GFE, null, "LoadRefSet: " + refSetID);
|
||||
|
@ -789,6 +798,7 @@ public class ReferenceSetManager implements IReferenceSetManager,
|
|||
* the referenceIDs
|
||||
* @return a List of ReferenceData
|
||||
*/
|
||||
@Override
|
||||
public List<ReferenceData> getReferenceData(List<ReferenceID> need) {
|
||||
List<ReferenceData> refData = new ArrayList<ReferenceData>();
|
||||
for (int i = 0; i < need.size(); i++) {
|
||||
|
@ -804,6 +814,7 @@ public class ReferenceSetManager implements IReferenceSetManager,
|
|||
* com.raytheon.viz.gfe.core.internal.IReferenceSetManager#saveActiveRefSet
|
||||
* (com.raytheon.edex.plugin.gfe.reference.ReferenceID)
|
||||
*/
|
||||
@Override
|
||||
public boolean saveActiveRefSet(final ReferenceID refID) {
|
||||
statusHandler.handle(Priority.VERBOSE, "saveActiveRefSet req=" + refID);
|
||||
|
||||
|
@ -832,6 +843,7 @@ public class ReferenceSetManager implements IReferenceSetManager,
|
|||
* com.raytheon.viz.gfe.core.internal.IReferenceSetManager#saveRefSet(com
|
||||
* .raytheon.edex.plugin.gfe.reference.ReferenceData)
|
||||
*/
|
||||
@Override
|
||||
public boolean saveRefSet(final ReferenceData orefData) {
|
||||
statusHandler.handle(Priority.VERBOSE,
|
||||
"SaveRefSet id=" + orefData.getId());
|
||||
|
@ -867,9 +879,9 @@ public class ReferenceSetManager implements IReferenceSetManager,
|
|||
"Unable to save reference set", e));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// cache it temporarily
|
||||
refDataCache.put(refData.getId().getName(), refData);
|
||||
refDataCache.put(refData.getId().getName(), refData);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -881,6 +893,7 @@ public class ReferenceSetManager implements IReferenceSetManager,
|
|||
* com.raytheon.viz.gfe.core.internal.IReferenceSetManager#deleteRefSet(
|
||||
* com.raytheon.edex.plugin.gfe.reference.ReferenceID)
|
||||
*/
|
||||
@Override
|
||||
public boolean deleteRefSet(final ReferenceID refID,
|
||||
boolean withVerification) {
|
||||
IPathManager pm = PathManagerFactory.getPathManager();
|
||||
|
@ -911,6 +924,7 @@ public class ReferenceSetManager implements IReferenceSetManager,
|
|||
*
|
||||
* @see com.raytheon.viz.gfe.core.internal.IReferenceSetManager#undoRefSet()
|
||||
*/
|
||||
@Override
|
||||
public void undoRefSet() {
|
||||
ReferenceData newRefSet = prevRefSet;
|
||||
setActiveRefSet(newRefSet);
|
||||
|
@ -1020,6 +1034,7 @@ public class ReferenceSetManager implements IReferenceSetManager,
|
|||
* com.raytheon.viz.gfe.core.internal.IReferenceSetManager#taperGrid(com
|
||||
* .raytheon.edex.plugin.gfe.reference.ReferenceData, int)
|
||||
*/
|
||||
@Override
|
||||
public Grid2DFloat taperGrid(final ReferenceData refData, int taperFactor) {
|
||||
// Get some info and make a grid of zeros
|
||||
|
||||
|
@ -1106,6 +1121,7 @@ public class ReferenceSetManager implements IReferenceSetManager,
|
|||
* com.raytheon.viz.gfe.core.internal.IReferenceSetManager#directionTaperGrid
|
||||
* (com.raytheon.edex.plugin.gfe.reference.ReferenceData, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Grid2DFloat directionTaperGrid(final ReferenceData refData,
|
||||
final String direction) {
|
||||
|
||||
|
@ -1230,6 +1246,7 @@ public class ReferenceSetManager implements IReferenceSetManager,
|
|||
* com.raytheon.viz.gfe.core.internal.IReferenceSetManager#mySiteGridpoints
|
||||
* ()
|
||||
*/
|
||||
@Override
|
||||
public Grid2DBit mySiteGridpoints() {
|
||||
return siteGridpoints(Arrays.asList(dataManager.getSiteID()), true);
|
||||
}
|
||||
|
@ -1263,6 +1280,7 @@ public class ReferenceSetManager implements IReferenceSetManager,
|
|||
*
|
||||
* @see com.raytheon.viz.gfe.core.internal.IReferenceSetManager#getMode()
|
||||
*/
|
||||
@Override
|
||||
public RefSetMode getMode() {
|
||||
return mode;
|
||||
}
|
||||
|
@ -1274,6 +1292,7 @@ public class ReferenceSetManager implements IReferenceSetManager,
|
|||
* com.raytheon.viz.gfe.core.internal.IReferenceSetManager#setMode(com.raytheon
|
||||
* .viz.gfe.core.internal.ReferenceSetManager.RefSetMode)
|
||||
*/
|
||||
@Override
|
||||
public void setMode(RefSetMode mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
@ -1514,6 +1533,7 @@ public class ReferenceSetManager implements IReferenceSetManager,
|
|||
* @param slot
|
||||
* @return the quickset area
|
||||
*/
|
||||
@Override
|
||||
public ReferenceData getQuickSet(int slot) {
|
||||
// Return the ReferenceData contents of the given quickSet button
|
||||
ReferenceData result = emptyRefSet();
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -62,8 +62,8 @@ public class ProcedureFactory {
|
|||
GfePyIncludeUtil.getCommonPythonIncludePath(),
|
||||
GfePyIncludeUtil.getVtecIncludePath(),
|
||||
GfePyIncludeUtil.getCommonGfeIncludePath(),
|
||||
GfePyIncludeUtil.getUtilitiesIncludePath(),
|
||||
GfePyIncludeUtil.getProceduresIncludePath());
|
||||
GfePyIncludeUtil.getProceduresIncludePath(),
|
||||
GfePyIncludeUtil.getUtilitiesIncludePath());
|
||||
|
||||
ProcedureController procCont = null;
|
||||
if (ui) {
|
||||
|
|
|
@ -19,10 +19,6 @@
|
|||
**/
|
||||
package com.raytheon.viz.gfe.procedures.menu;
|
||||
|
||||
import org.eclipse.ui.PlatformUI;
|
||||
import org.eclipse.ui.menus.CommandContributionItem;
|
||||
import org.eclipse.ui.menus.CommandContributionItemParameter;
|
||||
|
||||
/**
|
||||
* Specific contribution item for contributing procedures to the Hazards menu
|
||||
*
|
||||
|
@ -62,18 +58,4 @@ public class HazardsItems extends AbstractProcedureMenuItems {
|
|||
return "Hazards";
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @seecom.raytheon.viz.gfe.procedures.menu.AbstractProcedureMenuItems#
|
||||
* getAdditionalItems()
|
||||
*/
|
||||
@Override
|
||||
protected CommandContributionItemParameter[] getAdditionalItems() {
|
||||
return new CommandContributionItemParameter[] { new CommandContributionItemParameter(
|
||||
PlatformUI.getWorkbench(), getId(),
|
||||
"com.raytheon.viz.ghg.openmakehazards", null, null, null, null,
|
||||
"MakeHazard", null, null, CommandContributionItem.STYLE_PUSH,
|
||||
null, true) };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,8 +63,8 @@ public class SmartToolFactory {
|
|||
GfePyIncludeUtil.getCommonPythonIncludePath(),
|
||||
GfePyIncludeUtil.getVtecIncludePath(),
|
||||
GfePyIncludeUtil.getCommonGfeIncludePath(),
|
||||
GfePyIncludeUtil.getUtilitiesIncludePath(),
|
||||
GfePyIncludeUtil.getSmartToolsIncludePath());
|
||||
GfePyIncludeUtil.getSmartToolsIncludePath(),
|
||||
GfePyIncludeUtil.getUtilitiesIncludePath());
|
||||
|
||||
SmartToolController smartCont = null;
|
||||
if (ui) {
|
||||
|
|
|
@ -26,10 +26,6 @@
|
|||
id="com.raytheon.viz.ghg.openGhgMonitor"
|
||||
name="GHGHazardsMonnitor">
|
||||
</command>
|
||||
<command
|
||||
id="com.raytheon.viz.ghg.openmakehazards"
|
||||
name="MakeHazards">
|
||||
</command>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.ui.handlers">
|
||||
|
@ -37,9 +33,5 @@
|
|||
class="com.raytheon.viz.ghg.GhgMonitorAction"
|
||||
commandId="com.raytheon.viz.ghg.openGhgMonitor">
|
||||
</handler>
|
||||
<handler
|
||||
class="com.raytheon.viz.ghg.MakeHazardsAction"
|
||||
commandId="com.raytheon.viz.ghg.openmakehazards">
|
||||
</handler>
|
||||
</extension>
|
||||
</plugin>
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
scriptName=ghg/userPython/MakeHazard.py
|
||||
tcmScriptName=ghg/userPython/TCMETNDecoder.py
|
||||
hazardDict=gfe/userPython/procedures/MakeHazardConfig.py
|
||||
includePath=gfe/userPython/utilities/SmartScript.py:python/gfe/AbsTime.py:python/BaseTool.py:python/JUtil.py:gfe/userPython/textUtilities/regular:vtec/VTECTable.py
|
|
@ -1,5 +1,4 @@
|
|||
com.raytheon.viz.satellite.rsc.SatResourceData
|
||||
com.raytheon.viz.satellite.rsc.SatBlendedResourceData
|
||||
com.raytheon.viz.satellite.rsc.SatBestResResourceData
|
||||
com.raytheon.viz.satellite.rsc.SatTrueColorResourceData
|
||||
com.raytheon.viz.satellite.SatelliteProductBrowserDataDefinition
|
|
@ -31,11 +31,6 @@
|
|||
class="com.raytheon.viz.satellite.rsc.SatBlendedResource"
|
||||
name="satBlendedResource"
|
||||
renderingOrderId="IMAGE_COUNTRY"/>
|
||||
<resource
|
||||
class="com.raytheon.viz.satellite.rsc.SatTrueColorResource"
|
||||
name="Satellite True Color"
|
||||
renderingOrderId="IMAGE_COUNTRY"
|
||||
resourceType="PLAN_VIEW"/>
|
||||
</extension>
|
||||
<extension
|
||||
point="com.raytheon.uf.viz.core.scriptTemplate">
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue