diff --git a/deltaScripts/14.2.1/undoDropLSRdataURI.sh b/deltaScripts/14.2.1/undoDropLSRdataURI.sh new file mode 100644 index 0000000000..df564c24f6 --- /dev/null +++ b/deltaScripts/14.2.1/undoDropLSRdataURI.sh @@ -0,0 +1,29 @@ +#!/bin/bash +# DR #2581 - This update script will add the dataURI column to the lsr table +# The column needs to be there for 14.2.1. +# Only run this if you have already run dropLSRdataURI.sh, otherwise +# don't run this script or that one. + + +PSQL="/awips2/psql/bin/psql" + +# adds the datauri constraint and column +function addDataUriLSR { + echo "INFO: Adding DataURI column to lsr" + ${PSQL} -U awips -d metadata -c "ALTER TABLE lsr DROP CONSTRAINT IF EXISTS lsr_latitude_longitude_stationId_reftime_forecasttime_eventtype;" + ${PSQL} -U awips -d metadata -c "ALTER TABLE lsr ADD COLUMN datauri varchar(255);" + ${PSQL} -U awips -d metadata -c "ALTER TABLE lsr ADD CONSTRAINT lsr_datauri_key UNIQUE (datauri);" + if [ $? -ne 0 ]; then + echo "ERROR: Failed to repair dataURI for lsr" + echo "FATAL: The update has failed." + exit 1 + fi +} + + + +echo "INFO: Adding LSR dataURI column back in." + +addDataUriLSR + +echo "INFO: LSR dataURI column added successfully" diff --git a/edexOsgi/build.edex/opt/db/ddl/ncep/importNcepShapeFile.sh b/edexOsgi/build.edex/opt/db/ddl/ncep/importNcepShapeFile.sh old mode 100644 new mode 100755 index 3e08cbb81e..b8e1a9fc4b --- a/edexOsgi/build.edex/opt/db/ddl/ncep/importNcepShapeFile.sh +++ b/edexOsgi/build.edex/opt/db/ddl/ncep/importNcepShapeFile.sh @@ -35,29 +35,31 @@ fi if [ -z $7 ] ; then PGBINDIR='' + PSQLBINDIR='' else PGBINDIR=${7}/bin/ + PSQLBINDIR=/awips2/psql/bin/ fi echo " Importing `basename ${SHAPEFILE}` into ${SCHEMA}.${TABLE} ..." if [ -n "$LOGFILE" ] ; then - ${PGBINDIR}psql -d ncep -U ${PGUSER} -q -p ${PGPORT} -c " + ${PSQLBINDIR}psql -d ncep -U ${PGUSER} -q -p ${PGPORT} -c " DELETE FROM public.geometry_columns WHERE f_table_schema = '${SCHEMA}' AND f_table_name = '${TABLE}'; DROP TABLE IF EXISTS ${SCHEMA}.${TABLE} " >> $LOGFILE 2>&1 - ${PGBINDIR}shp2pgsql -s 4326 -I ${SHAPEFILE} ${SCHEMA}.${TABLE} 2>> $LOGFILE | ${PGBINDIR}psql -d ncep -U ${PGUSER} -q -p ${PGPORT} -f - >> $LOGFILE 2>&1 - ${PGBINDIR}psql -d ncep -U ${PGUSER} -q -p ${PGPORT} -c " + ${PGBINDIR}shp2pgsql -s 4326 -g the_geom -I ${SHAPEFILE} ${SCHEMA}.${TABLE} 2>> $LOGFILE | ${PSQLBINDIR}psql -d ncep -U ${PGUSER} -q -p ${PGPORT} -f - >> $LOGFILE 2>&1 + ${PSQLBINDIR}psql -d ncep -U ${PGUSER} -q -p ${PGPORT} -c " SELECT AddGeometryColumn('${SCHEMA}','${TABLE}','the_geom_0','4326',(SELECT type FROM public.geometry_columns WHERE f_table_schema='${SCHEMA}' and f_table_name='${TABLE}' and f_geometry_column='the_geom'),2); UPDATE ${SCHEMA}.${TABLE} SET the_geom_0=ST_Segmentize(the_geom,0.1); CREATE INDEX ${TABLE}_the_geom_0_gist ON ${SCHEMA}.${TABLE} USING gist(the_geom_0); " >> $LOGFILE 2>&1 else - ${PGBINDIR}psql -d ncep -U ${PGUSER} -q -p ${PGPORT} -c " + ${PSQLBINDIR}psql -d ncep -U ${PGUSER} -q -p ${PGPORT} -c " DELETE FROM public.geometry_columns WHERE f_table_schema = '${SCHEMA}' AND f_table_name = '${TABLE}'; DROP TABLE IF EXISTS ${SCHEMA}.${TABLE} " - ${PGBINDIR}shp2pgsql -s 4326 -I ${SHAPEFILE} ${SCHEMA}.${TABLE} | ${PGBINDIR}psql -d ncep -U ${PGUSER} -q -p ${PGPORT} -f - - ${PGBINDIR}psql -d ncep -U ${PGUSER} -q -p ${PGPORT} -c " + ${PGBINDIR}shp2pgsql -s 4326 -g the_geom -I ${SHAPEFILE} ${SCHEMA}.${TABLE} | ${PSQLBINDIR}psql -d ncep -U ${PGUSER} -q -p ${PGPORT} -f - + ${PSQLBINDIR}psql -d ncep -U ${PGUSER} -q -p ${PGPORT} -c " SELECT AddGeometryColumn('${SCHEMA}','${TABLE}','the_geom_0','4326',(SELECT type FROM public.geometry_columns WHERE f_table_schema='${SCHEMA}' and f_table_name='${TABLE}' and f_geometry_column='the_geom'),2); UPDATE ${SCHEMA}.${TABLE} SET the_geom_0=ST_Segmentize(the_geom,0.1); CREATE INDEX ${TABLE}_the_geom_0_gist ON ${SCHEMA}.${TABLE} USING gist(the_geom_0); @@ -73,12 +75,12 @@ if [ -n "$SIMPLEVS" ] ; then SUFFIX= for x in $LEV ; do SUFFIX=${SUFFIX}_${x} ; done if [ -n "$LOGFILE" ] ; then - ${PGBINDIR}psql -d ncep -U ${PGUSER} -q -p ${PGPORT} -c " + ${PSQLBINDIR}psql -d ncep -U ${PGUSER} -q -p ${PGPORT} -c " SELECT AddGeometryColumn('${SCHEMA}','${TABLE}','the_geom${SUFFIX}','4326',(SELECT type FROM public.geometry_columns WHERE f_table_schema='${SCHEMA}' and f_table_name='${TABLE}' and f_geometry_column='the_geom'),2); UPDATE ${SCHEMA}.${TABLE} SET the_geom${SUFFIX}=ST_Segmentize(ST_Multi(ST_SimplifyPreserveTopology(the_geom,${LEV})),0.1); CREATE INDEX ${TABLE}_the_geom${SUFFIX}_gist ON ${SCHEMA}.${TABLE} USING gist(the_geom${SUFFIX});" >> $LOGFILE 2>&1 else - ${PGBINDIR}psql -d ncep -U ${PGUSER} -q -p ${PGPORT} -c " + ${PSQLBINDIR}psql -d ncep -U ${PGUSER} -q -p ${PGPORT} -c " SELECT AddGeometryColumn('${SCHEMA}','${TABLE}','the_geom${SUFFIX}','4326',(SELECT type FROM public.geometry_columns WHERE f_table_schema='${SCHEMA}' and f_table_name='${TABLE}' and f_geometry_column='the_geom'),2); UPDATE ${SCHEMA}.${TABLE} SET the_geom${SUFFIX}=ST_Segmentize(ST_Multi(ST_SimplifyPreserveTopology(the_geom,${LEV})),0.1); CREATE INDEX ${TABLE}_the_geom${SUFFIX}_gist ON ${SCHEMA}.${TABLE} USING gist(the_geom${SUFFIX});" diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/res/spring/gfe-spring.xml b/edexOsgi/com.raytheon.edex.plugin.gfe/res/spring/gfe-spring.xml index e4b5bd8270..811ab38a54 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/res/spring/gfe-spring.xml +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/res/spring/gfe-spring.xml @@ -38,7 +38,7 @@ - + @@ -50,7 +50,7 @@ - + @@ -63,7 +63,14 @@ - + + + + java.lang.Throwable + + + diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/config/gfe/serverConfig.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/config/gfe/serverConfig.py index 3acc05646e..fc669bf35e 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/config/gfe/serverConfig.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/config/gfe/serverConfig.py @@ -628,12 +628,17 @@ NDFD_Oceanic_10K = ('NDFD_Oceanic_10km', MERCATOR, (-230.094, -30.4192), (10.71, 80.01), (0.0, 0.0), 0.0, 0.0, (1, 1), (2517, 1793), 0.0, -109.962, 0.0) +# Add a new domain for NHC purposes +GridForNHA = ('GridForNHA', LAMBERT_CONFORMAL, + (-97.647915, 7.783091), (-38.900400, 52.092726), + (-95.0, 25.0), 25.0, 25.0, (1, 1), (894,1176), 0.0, 0.0, 0.0) + # list of all projections allProjections = [Grid201, Grid202, Grid203, Grid204, Grid205, Grid206, Grid207, Grid208, Grid209, Grid210, Grid211, Grid212, Grid213, Grid214, Grid214AK, Grid215, Grid216, Grid217, Grid218, Grid219, Grid221, Grid222, Grid225, Grid226, Grid227, Grid228, Grid229, Grid230, Grid231, Grid232, - Grid233, Grid234, Grid235, HRAP, NDFD_Oceanic_10K] + Grid233, Grid234, Grid235, HRAP, NDFD_Oceanic_10K, GridForNHA] #--------------------------------------------------------------------------- # @@ -838,6 +843,7 @@ SITES = { #National Centers 'HAK' : ( [825,553], ( 1.0, 1.0), (103.0, 69.0), 'EST5EDT', Grid214AK, "nc"), 'HUS' : ([1073,689], (19.0, 8.0), ( 67.0, 43.0), 'EST5EDT', Grid211, "nc"), + 'NHA' : ([894,1176], (0.0,0.0), (894.0, 1176.0), 'EST5EDT', GridForNHA, "nc"), } @@ -1146,7 +1152,7 @@ elif SID in CONUS_EAST_SITES: ('HiResW-NMM-East', 'HIRESWnmm'), ('SPCGuide', 'SPC'), ('ECMWF-HiRes','ECMWFHiRes'), - ('ENPWAVE253', 'ENPwave'), + ('ENPWAVE253', 'ENPwave'), ] else: #######DCS3501 WEST_CONUS @@ -1197,7 +1203,7 @@ else: #######DCS3501 WEST_CONUS ('HiResW-NMM-West', 'HIRESWnmm'), ('SPCGuide', 'SPC'), ('ECMWF-HiRes','ECMWFHiRes'), - ('ENPWAVE253', 'ENPwave'), + ('ENPWAVE253', 'ENPwave'), ] if SID in GreatLake_SITES: @@ -1433,7 +1439,7 @@ else: # "WCwave4" : ["WCwave4"], # "WNAwave10" : ["WNAwave10"], # "WNAwave4" : ["WNAwave4"], -# "ENPwave": ["ENPwave"], +# "ENPwave": ["ENPwave"], } #initialization skip certain model runs @@ -1875,7 +1881,7 @@ DATABASES = [(Official, OFFICIALDBS + localParms), (RTMA, RTMAPARMS + localRTMAParms), (NamDNG5, NamDNG5PARMS + localNamDNG5Parms), (TPCProb, TPCProbPARMS + localTPCProbParms), - (ENPwave, ENPwave_parms + localENPwaveParms), + (ENPwave, ENPwave_parms + localENPwaveParms), (Test, OFFICIALDBS + localParms)] + localDBs # Intersite coordination database parameter groupings, based on @@ -1984,4 +1990,4 @@ def doIt(): IFPConfigServer.requestedISCparms = requestedISCparms IFPConfigServer.transmitScript = transmitScript -doIt() +doIt() \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/common_static/base/grid/grib1ParameterConvTable.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/common_static/base/grid/grib1ParameterConvTable.xml index a8f112f66c..fabbf7ff67 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/common_static/base/grid/grib1ParameterConvTable.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/common_static/base/grid/grib1ParameterConvTable.xml @@ -1,4 +1,4 @@ - +
98
128 @@ -6891,6 +6893,26 @@ 255
+ + +
98
+ 128 + 15 + 0 + 0 + 4 +
+ + +
98
+ 128 + 16 + 0 + 0 + 5 +
+ +
98
128 @@ -8740,5 +8762,252 @@ 10 0 13 +
+ + + + + +
74
+ 3 + 1 + 0 + 3 + 0
+ + +
74
+ 3 + 2 + 0 + 3 + 1 +
+ + +
74
+ 3 + 5 + 0 + 3 + 3 +
+ + +
74
+ 3 + 7 + 0 + 3 + 5 +
+ + +
74
+ 3 + 11 + 0 + 0 + 0 +
+ + +
74
+ 3 + 15 + 0 + 0 + 4 +
+ + +
74
+ 3 + 16 + 0 + 0 + 5 +
+ + +
74
+ 3 + 20 + 0 + 19 + 0 +
+ + +
74
+ 3 + 33 + 0 + 2 + 2 +
+ + +
74
+ 3 + 34 + 0 + 2 + 3 +
+ + +
74
+ 3 + 40 + 0 + 2 + 9 +
+ + +
74
+ 3 + 51 + 0 + 1 + 0 +
+ + +
74
+ 3 + 52 + 0 + 1 + 1 +
+ + +
74
+ 3 + 59 + 0 + 1 + 7 +
+ + +
74
+ 3 + 61 + 0 + 1 + 8 +
+ + +
74
+ 3 + 72 + 0 + 6 + 2 +
+ + +
74
+ 3 + 73 + 0 + 6 + 3 +
+ + +
74
+ 3 + 74 + 0 + 6 + 4 +
+ + +
74
+ 3 + 75 + 0 + 6 + 5 +
+ + +
74
+ 3 + 111 + 0 + 4 + 0 +
+ + +
74
+ 3 + 128 + 0 + 3 + 1 +
+ + +
74
+ 3 + 138 + 255 + 255 + 255 +
+ + +
74
+ 3 + 143 + 0 + 1 + 195 +
+ + +
74
+ 3 + 144 + 2 + 0 + 192 +
+ + +
74
+ 3 + 146 + 0 + 6 + 15 +
+ + +
74
+ 3 + 147 + 0 + 3 + 16 +
+ + +
74
+ 3 + 149 + 0 + 2 + 14 +
+ diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-Grid1.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-Grid1.xml new file mode 100755 index 0000000000..bcdcf61c4c --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-Grid1.xml @@ -0,0 +1,35 @@ + + + + 108162001 + UKMet HiRes tile - Northern Hemisphere + Longitude range 341.25E - 70.416E + 0.279 + 341.25 + LowerLeft + 108 + 162 + 0.833 + 0.556 + degree + 89.722 + 70.416 + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-Grid2.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-Grid2.xml new file mode 100755 index 0000000000..d035f4a23e --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-Grid2.xml @@ -0,0 +1,35 @@ + + + + 108162002 + UKMet HiRes tile - Northern Hemisphere + Longitude range 71.25E - 160.416E + 0.279 + 71.25 + LowerLeft + 108 + 162 + 0.833 + 0.556 + degree + 89.722 + 160.416 + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-Grid3.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-Grid3.xml new file mode 100755 index 0000000000..e503693fe3 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-Grid3.xml @@ -0,0 +1,35 @@ + + + + 108162003 + UKMet HiRes tile - Northern Hemisphere + Longitude range 161.25E - 250.416E + 0.279 + 161.25 + LowerLeft + 108 + 162 + 0.833 + 0.556 + degree + 89.722 + 250.416 + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-Grid4.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-Grid4.xml new file mode 100755 index 0000000000..2f47a455fc --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-Grid4.xml @@ -0,0 +1,35 @@ + + + + 108162004 + UKMet HiRes tile - Northern Hemisphere + Longitude range 251.25E - 340.416E + 0.279 + 251.25 + LowerLeft + 108 + 162 + 0.833 + 0.556 + degree + 89.722 + 340.416 + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-Grid5.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-Grid5.xml new file mode 100755 index 0000000000..8776dfab67 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-Grid5.xml @@ -0,0 +1,35 @@ + + + + 108162005 + UKMet HiRes tile - Southern Hemisphere + Longitude range 341.25E - 70.416E + -89.721 + 341.25 + LowerLeft + 108 + 162 + 0.833 + 0.556 + degree + -0.278 + 70.416 + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-Grid6.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-Grid6.xml new file mode 100755 index 0000000000..515121aca3 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-Grid6.xml @@ -0,0 +1,35 @@ + + + + 108162006 + UKMet HiRes tile - Southern Hemisphere + Longitude range 71.25E - 160.416E + -89.721 + 71.25 + LowerLeft + 108 + 162 + 0.833 + 0.556 + degree + -0.278 + 160.416 + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-Grid7.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-Grid7.xml new file mode 100755 index 0000000000..01461ae493 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-Grid7.xml @@ -0,0 +1,35 @@ + + + + 108162007 + UKMet HiRes tile - Southern Hemisphere + Longitude range 161.25E - 250.416E + -89.721 + 161.25 + LowerLeft + 108 + 162 + 0.833 + 0.556 + degree + -0.278 + 250.416 + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-Grid8.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-Grid8.xml new file mode 100755 index 0000000000..2fd6dadf21 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-Grid8.xml @@ -0,0 +1,35 @@ + + + + 108162008 + UKMet HiRes tile - Southern Hemisphere + Longitude range 251.25E - 340.416E + -89.721 + 251.25 + LowerLeft + 108 + 162 + 0.833 + 0.556 + degree + -0.278 + 340.416 + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-NHemisphere.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-NHemisphere.xml new file mode 100755 index 0000000000..b407b250d1 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-NHemisphere.xml @@ -0,0 +1,35 @@ + + + + 864162001 + UKMet HiRes combined - Northern Hemisphere + Longitude range 71.25E - 70.416E + 0.279 + 71.25 + LowerLeft + 864 + 162 + 0.833 + 0.556 + degree + 89.722 + 70.416 + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-SHemisphere.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-SHemisphere.xml new file mode 100755 index 0000000000..f72631f876 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/UkmetHR-SHemisphere.xml @@ -0,0 +1,35 @@ + + + + 864162002 + UKMet HiRes combined - Southern Hemisphere + Longitude range 71.25E - 70.416E + -89.721 + 71.25 + LowerLeft + 864 + 162 + 0.833 + 0.556 + degree + -0.278 + 70.416 + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid115001.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid115001.xml new file mode 100644 index 0000000000..d0bf065392 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid115001.xml @@ -0,0 +1,32 @@ + + + + 115001 + SWPC IRGF C + 38.0 + 250.0 + LowerLeft + 11 + 5 + 1 + 1 + degree + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid18060001.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid18060001.xml new file mode 100644 index 0000000000..b668173ad2 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid18060001.xml @@ -0,0 +1,32 @@ + + + + 18060001 + SWPC Enlil C + 59.0 + 1.0 + UpperLeft + 180 + 60 + 2 + 2 + degree + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid18090001.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid18090001.xml new file mode 100644 index 0000000000..2319b8d70e --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid18090001.xml @@ -0,0 +1,32 @@ + + + + 18090001 + SWPC XRAY C + 89.0 + 178.0 + UpperLeft + 180 + 90 + 2 + 2 + degree + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid2090001.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid2090001.xml new file mode 100644 index 0000000000..8c38353646 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid2090001.xml @@ -0,0 +1,32 @@ + + + + 2090001 + SWPC Conductivity C + -90.0 + 180.0 + LowerLeft + 20 + 90 + 18 + 2 + degree + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid2091001.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid2091001.xml new file mode 100644 index 0000000000..06c2ae9bba --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid2091001.xml @@ -0,0 +1,32 @@ + + + + 2091001 + SWPC Ion Temperature C + -90.0 + 0.0 + LowerLeft + 20 + 91 + 18 + 2 + degree + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid360180001.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid360180001.xml new file mode 100644 index 0000000000..ed9134a568 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid360180001.xml @@ -0,0 +1,32 @@ + + + + 360180001 + SWPC SXI C + 90.0 + 0.0 + UpperLeft + 360 + 180 + 1 + 1 + degree + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid3636001.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid3636001.xml new file mode 100644 index 0000000000..8da1845930 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid3636001.xml @@ -0,0 +1,32 @@ + + + + 3636001 + SWPC SOLAR FLUX C + 87.5 + 185.0 + UpperLeft + 36 + 36 + 10 + 5 + degree + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid9050001.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid9050001.xml new file mode 100644 index 0000000000..46b3305503 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid9050001.xml @@ -0,0 +1,32 @@ + + + + 9050001 + SWPC Ovation C + 40.0 + 0.0 + LowerLeft + 90 + 50 + 4 + 1 + degree + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid9090001.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid9090001.xml new file mode 100644 index 0000000000..316e7cf0a9 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/grids/grid9090001.xml @@ -0,0 +1,32 @@ + + + + 9090001 + SWPC DRAP20 C + 89.0 + 182.0 + UpperLeft + 90 + 90 + 4 + 2 + degree + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/models/gribModels_ECMWF-98.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/models/gribModels_ECMWF-98.xml index d2bfc35298..6b54fab4d5 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/models/gribModels_ECMWF-98.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/models/gribModels_ECMWF-98.xml @@ -11,6 +11,20 @@ + + ecens +
98
+ 0 + 360181001 + + 141 + 142 + 143 + 144 + 145 + +
+ ecmwfP25
98
diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/models/gribModels_NCEP-7.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/models/gribModels_NCEP-7.xml index 7e83234f0c..cec4d8e4e3 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/models/gribModels_NCEP-7.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/models/gribModels_NCEP-7.xml @@ -2879,6 +2879,7 @@ HPCGuide
7
5 + 197 183 @@ -3131,6 +3132,16 @@
+ + AK-RTMA-HR +
7
+ 4 + 1023 + + 109 + +
+ GFSLAMPTstorm
7
@@ -3184,4 +3195,90 @@ + + + + Conductivity +
7
+ 16 + 2090001 + + 255 + +
+ + SXI +
7
+ 16 + 360180001 + + 255 + +
+ + DRAP20 +
7
+ 16 + 9090001 + + 255 + +
+ + ENLIL +
7
+ 16 + 18060001 + + 255 + +
+ + EPFlux +
7
+ 16 + 3636001 + + 255 + +
+ + SolarFlux +
7
+ 16 + 18090001 + + 255 + +
+ + IonTemperature +
7
+ 16 + 2091001 + + 255 + +
+ + IRGF +
7
+ 16 + 115001 + + 255 + +
+ + Ovation +
7
+ 16 + 9050001 + + 255 + +
+ + +
diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/models/gribModels_UKMET-74.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/models/gribModels_UKMET-74.xml index c334d4fb3f..af5704c089 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/models/gribModels_UKMET-74.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/models/gribModels_UKMET-74.xml @@ -5,7 +5,10 @@ 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. --> + See_the_AWIPS_II_Master_Rights_File_("Master_Rights_File.pdf")_for further_licensing_information. +History: +F.Achorn/OPC 10/15/13 Added Ukmet HR tiles 1-8 +--> @@ -182,6 +185,100 @@ - + + + UkmetHR-1 +
74
+ 0 + 108162001 + + 15 + 44 + 45 + +
+ + UkmetHR-2 +
74
+ 0 + 108162002 + + 15 + 44 + 45 + +
+ + + UkmetHR-3 +
74
+ 0 + 108162003 + + 15 + 44 + 45 + +
+ + + UkmetHR-4 +
74
+ 0 + 108162004 + + 15 + 44 + 45 + +
+ + + UkmetHR-5 +
74
+ 0 + 108162005 + + 15 + 44 + 45 + +
+ + + UkmetHR-6 +
74
+ 0 + 108162006 + + 15 + 44 + 45 + +
+ + + UkmetHR-7 +
74
+ 0 + 108162007 + + 15 + 44 + 45 + +
+ + + UkmetHR-8 +
74
+ 0 + 108162008 + + 15 + 44 + 45 + +
diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/0.0.table b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/0.0.table new file mode 100644 index 0000000000..5a61b54c3a --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/0.0.table @@ -0,0 +1,5 @@ +#Code Table 0.0: Discipline of processed data in the GRIB message, number of GRIB Master table +3:3:Satellite remote sensing products +4:4:Space Weather Products +# 192-254 Reserved for local use +255:255:Missing diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/3.2.table b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/3.2.table new file mode 100644 index 0000000000..3b2a4a9ca3 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/3.2.table @@ -0,0 +1,5 @@ +# CODE TABLE 3.2, Shape of the reference system +10:10:Earth model assumed WGS84 with corrected geomagnetic coordinates (latitude and longitude) defined by Gustafsson et al., 1992 +11:11:Sun assumed spherical with radius = 695,990,000 m (Allen, C.W., 1976 Astrophysical Quantities (3rd Ed.; London: Athlone) and Stonyhurst latitude and longitude system with origin at the intersection of the solar central meridian (as seen from Earth) and the solar equator (Thompson, W, Coordinate systems for solar image data, A&A 449, 791–803 (2006)) +# 192- 254 Reserved for local use +255:255:Missing diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.1.table b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.1.table new file mode 100644 index 0000000000..f571386795 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.1.table @@ -0,0 +1,15 @@ +# CODE TABLE 4.1, Parameter category by product discipline +0:0:Temperature +1:1:Momentum +2:2:Charged particle mass and number +3:3:Electric and magnetic fields +4:4:Energetic particles +5:5:Waves +6:6:Solar electromagnetic emissions +7:7:Terrestrial electromagnetic emissions +8:8:Imagery +9:9:Ion-neutral coupling +#10-191 Reserved +#192-254 Reserved for Local Use +255:255:Missing + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.0.table b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.0.table new file mode 100644 index 0000000000..eb9b080aa0 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.0.table @@ -0,0 +1,10 @@ +# Product Discipline 4: Space Weather Products, Parameter Category 0: Temperature +0:0:Temperature:K:TMPSWP +1:1:Electron Temperature:K:ELECTMP +2:2:Proton Temperature:K:PROTTMP +3:3:Ion Temperature:K:IONTMP +4:4:Parallel Temperature:K:PRATMP +5:5:Perpendicular Temperature:K:PRPTMP +# 6-191 Reserved +# 192-254 Reserved for local use +255:255:Missing \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.1.table b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.1.table new file mode 100644 index 0000000000..bbb309452f --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.1.table @@ -0,0 +1,8 @@ +# Product Discipline 4: Space Weather Products, Parameter Category 1: Momentum +0:0:Velocity Magnitude (Speed):m*s^1:SPEED +1:1:1st Vector Component of Velocity (Coordinate system dependent):m*s^1:VEL1 +2:2:2nd Vector Component of Velocity (Coordinate system dependent):m*s^1:VEL2 +3:3:3rd Vector Component of Velocity (Coordinate system dependent):m*s^1:VEL3 +# 4-191 Reserved +# 192-254 Reserved for local use +255:255:Missing \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.2.table b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.2.table new file mode 100644 index 0000000000..02af676f2a --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.2.table @@ -0,0 +1,17 @@ +# Product Discipline 4: Space Weather Products, Parameter Category 2: Charged Particle Mass and Number +0:0:Particle Number Density:m^3:PLSMDEN +1:1:Electron Density:m^3:ELCDEN +2:2:Proton Density:m^3:PROTDEN +3:3:Ion Density:m^3:IONDEN +4:4:Vertical Electron Content:m^2:VTEC +5:5:HF Absorption Frequency:Hz:ABSFRQ +6:6:HF Absorption:dB:ABSRB +7:7:Spread F:m:SPRDF +8:8:h'F:m:HPRIMF +9:9:Critical Frequency:Hz:CRTFRQ +10:10:Scintillation:Numeric:SCINT +# 11-191 Reserved +# 192-254 Reserved for local use +255:255:Missing + + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.3.table b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.3.table new file mode 100644 index 0000000000..af18377221 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.3.table @@ -0,0 +1,12 @@ +# Product Discipline 4: Space Weather Products, Parameter Category 3: Electric and Magnetic Fields +0:0:Magnetic Field Magnitude:T:BTOT +1:1:1st Vector Component of Magnetic Field:T:BVEC1 +2:2:2nd Vector Component of Magnetic Field:T:BVEC2 +3:3:3rd Vector Component of Magnetic Field:T:BVEC3 +4:4:Electric Field Magnitude:V*m^1:ETOT +5:5:1st Vector Component of Electric Field:V*m^1:EVEC1 +6:6:2nd Vector Component of Electric Field:V*m^1:EVEC2 +7:7:3rd Vector Component of Electric Field:V*m^1:EVEC3 +# 8-191 Reserved +# 192-254 Reserved for local use +255:255:Missing \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.4.table b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.4.table new file mode 100644 index 0000000000..c9a64da52d --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.4.table @@ -0,0 +1,11 @@ +# Product Discipline 4: Space Weather Products, Parameter Category 4: Energetic Particles +0:0:Proton Flux (Differential):(m^2*s*sr*eV)^1:DIFPFLUX +1:1:Proton Flux (Integral):(m^2*s*sr)^1:INTPFLUX +2:2:Electron Flux (Differential):(m^2*s*sr*eV)^1:DIFEFLUX +3:3:Electron Flux (Integral):(m^2*s*sr)^1:INTEFLUX +4:4:Heavy Ion Flux (Differential):((m^2*s*sr*eV)/nuc)^1:DIFIFLUX +5:5:Heavy Ion Flux (iIntegral):(m^2*s*sr)^1:INTIFLUX +6:6:Cosmic Ray Neutron Flux:h^1:NTRNFLUX +# 7-191 Reserved +# 192-254 Reserved for local use +255:255:Missing \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.5.table b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.5.table new file mode 100644 index 0000000000..7a8a4dab99 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.5.table @@ -0,0 +1,4 @@ +# Product Discipline 4: Space Weather Products, Parameter Category 5: Waves +# 0-191 Reserved +# 192-254 Reserved for local use +255:255:Missing diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.6.table b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.6.table new file mode 100644 index 0000000000..d4620a017f --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.6.table @@ -0,0 +1,13 @@ +# Product Discipline 4: Space Weather Products, Parameter Category 6: Solar Electromagnetic Emissions +0:0:Integrated Solar Irradiance:W*m^2:TSI +1:1:Solar X-ray Flux (XRS Long):W*m^2:XLONG +2:2:Solar X-ray Flux (XRS Short):W*m^2:XSHRT +3:3:Solar EUV Irradiance:W*m^2:EUVIRR +4:4:Solar Spectral Irradiance:W*m^2*n*m^1:SPECIRR +5:5:F10.7:W*m^2*H*z^1:F107 +6:6:Solar Radio Emissions:W*m^2*Hz^1:SOLRF +# 7-191 Reserved +# 192-254 Reserved for local use +255:255:Missing + + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.7.table b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.7.table new file mode 100644 index 0000000000..639976511c --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.7.table @@ -0,0 +1,10 @@ +# Product Discipline 4: Space Weather Products, Parameter Category 7: Terrestrial electromagnetic emissions +0:0:Limb Intensity:J*m^2*s^1:LMBINT +1:1:Disk Intensity:j*m^2*s^1:DSKINT +2:2:Disk Intensity Day:J*m^2*s^1:DSKDAY +3:3:Disk Intensity Night:J*m^2*s^1:DSKNGT +# 4-191 Reserved +# 192-254 Reserved for local use +255:255:Missing + + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.8.table b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.8.table new file mode 100644 index 0000000000..d913d9e458 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.8.table @@ -0,0 +1,14 @@ +# Product Discipline 4: Space Weather Products, Parameter Category 8: Imagery +0:0:X-Ray Radiance:W*s*r^1*m^2:XRAYRAD +1:1:EUV Radiance:W*s*r^1*m^2:EUVRAD +2:2:H-Alpha Radiance:W*s*r^1*m^2:HARAD +3:3:White Light Radiance:W*s*r^1*m^2:WHTRAD +4:4:CaII-K Radiance:W*s*r^1*m^2:CAIIRAD +5:5:White Light Coronagraph Radiance:W*s*r^1*m^2:WHTCOR +6:6:Heliospheric Radiance:W*s*r^1*m^2:HELCOR +7:7:Thematic Mask:Numeric:MASK +# 8-191 Reserved +# 192-254 Reserved for local use +255:255:Missing + + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.9.table b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.9.table new file mode 100644 index 0000000000..4e0e86035c --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.2.4.9.table @@ -0,0 +1,7 @@ +# Product Discipline 4: Space Weather Products, Parameter Category 9: Ion-Neutral Coupling +0:0:Pedersen Conductivity:S*m^1:SIGPED +1:1:Hall Conductivity:S*m^1:SIGHAL +2:2:Parallel Conductivity:S*m^1:SIGPAR +# 3-191 Reserved +# 192-254 Reserved for local use +255:255:Missing \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.5.table b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.5.table new file mode 100644 index 0000000000..941066c6f5 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/7/16/4.5.table @@ -0,0 +1,48 @@ +# Code:table:4.5: Fixed surface types and units +170:170:Ionospheric D-region level::IDRL +171:171:Ionospheric E-region level::IERL +172:172:Ionospheric F1-region level::IF1RL +173:173:Ionospheric F2-region level::IF2RL +174:174:Specified radius from the center of the Sun:m:SRCS +175:175:Solar photosphere::SP +#192-254 Reserved for local use +200:200:Entire Atmosphere::EATM:EA +201:201:Entire Ocean::EOCN +204:204:Highest Tropospheric Freezing Level::HTFL +206:206:Grid Scale Cloud Bottom Level::GCBL +207:207:Grid Scale Cloud Top Level::GCTL +209:209:Boundary Layer Cloud Bottom Level::BCBL +210:210:Boundary Layer Cloud Top Level::BCTL +211:211:Boundary Layer Cloud Layer::BCY +212:212:Low Cloud Bottom Level::LCBL +213:213:Low Cloud Top Level::LCTL +214:214:Low Cloud Layer::LCY +215:215:Cloud Ceiling::CLG +220:220:Planetary Boundary Layer:: BLD +221:221:Layer Between Two Hybrid Levels::LBTHL +222:222:Middle Cloud Bottom Level::MCBL +223:223:Middle Cloud Top Level::MCTL +224:224:Middle Cloud Layer::MCY +232:232:High Cloud Bottom Level::HCBL +233:233:High Cloud Top Level::HCTL +234:234:High Cloud Layer::HCL +235:235:Ocean Isotherm Level:1/10 ℃:OITL +236:236:Layer Between Two Depths Below Ocean Surface::OLYR +237:237:Bottom of Ocean Mixed Layer (m):m:OBML +238:238:Bottom of Ocean Isothermal Layer:m:OBIL +239:239:Layer Ocean Surface and 26C Ocean Isothermal Level::LOS +240:240:Ocean Mixed Layer::OML +241:241:Ordered Sequence of Data::OSD +242:242:Convective Cloud Bottom Level::CCBL +243:243:Convective Cloud Top Level::CCTL +244:244:Convective Cloud::CCY +245:245:Lowest Level of the Wet Bulb Zero::WBZ +246:246:Maximum Equivalent Potential Temperature level::MTHE:MEPT +247:247:Equilibrium Level::EHLT:EL +248:248:Shallow Convective Cloud Bottom Level::SCBL +249:249:Shallow Convective Cloud Top Level::SCTL +251:251:Deep Convective Cloud Bottom Level::DCBL +252:252:Deep Convective Cloud Top Level::DCTL +253:253:Lowest Bottom Level of Supercooled Liquid Water Layer::LSCLW +254:254:Highest Top Level of Supercooled Liquid Water Layer::HSCLW +255:255:Missing diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/74/0/4.2.2.0.table b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/74/0/4.2.2.0.table new file mode 100644 index 0000000000..65f6dfdb15 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/tables/74/0/4.2.2.0.table @@ -0,0 +1,5 @@ +# Product Discipline 2: Land surface products, Parameter Category 0: Vegetation/Biomass +#192-254 Reserved for local use +192:192:Volumetric soil moisture content:Proportion:SOILW +255:255:Missing + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/thinnedModels/UkmetHR-NH.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/thinnedModels/UkmetHR-NH.xml new file mode 100644 index 0000000000..5325335d6b --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/thinnedModels/UkmetHR-NH.xml @@ -0,0 +1,26 @@ + + + + + UkmetHR-NorthernHemisphere + 864162001 + UkmetHR-2:UkmetHR-3:UkmetHR-4:UkmetHR-1 + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/thinnedModels/UkmetHR-SH.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/thinnedModels/UkmetHR-SH.xml new file mode 100644 index 0000000000..6503a56ffa --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/thinnedModels/UkmetHR-SH.xml @@ -0,0 +1,26 @@ + + + + + UkmetHR-SouthernHemisphere + 864162002 + UkmetHR-6:UkmetHR-7:UkmetHR-8:UkmetHR-5 + diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.level/utility/common_static/base/level/alias/gempak.xml b/edexOsgi/com.raytheon.uf.common.dataplugin.level/utility/common_static/base/level/alias/gempak.xml index 50cca22d39..8059f7a35d 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.level/utility/common_static/base/level/alias/gempak.xml +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.level/utility/common_static/base/level/alias/gempak.xml @@ -137,4 +137,8 @@ GCBL SCBL SCTL + SPXX + IDRL + SRCS + NTAT \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.lsr/src/com/raytheon/uf/common/dataplugin/lsr/LSREventType.java b/edexOsgi/com.raytheon.uf.common.dataplugin.lsr/src/com/raytheon/uf/common/dataplugin/lsr/LSREventType.java index bb38201db2..885f7c2be0 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.lsr/src/com/raytheon/uf/common/dataplugin/lsr/LSREventType.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.lsr/src/com/raytheon/uf/common/dataplugin/lsr/LSREventType.java @@ -37,6 +37,7 @@ import java.util.Map; * Jan 03, 2014 2581 njensen Added coastal flood * Jan 13, 2014 2581 njensen Added debris flow * Jan 17, 2014 2581 njensen Added blowing snow + * Jan 30, 2014 2581 njensen Added rain * * * @@ -89,7 +90,8 @@ public enum LSREventType { FREEZINGDRIZZLE("FREEZING DRIZZLE", 40, LSRUnits.NOUNITS), COASTALFLOOD("COASTAL FLOOD", 41, LSRUnits.NOUNITS), DEBRISFLOW("DEBRIS FLOW", 42, LSRUnits.NOUNITS), - BLOWINGSNOW("BLOWING SNOW", 43, LSRUnits.NOUNITS); + BLOWINGSNOW("BLOWING SNOW", 43, LSRUnits.NOUNITS), + RAIN("RAIN", 44, LSRUnits.NOUNITS); // TODO contemplate storing the event type as a string in the database instead of an enum/integer diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.lsr/src/com/raytheon/uf/common/dataplugin/lsr/LocalStormReport.java b/edexOsgi/com.raytheon.uf.common.dataplugin.lsr/src/com/raytheon/uf/common/dataplugin/lsr/LocalStormReport.java index a952eafe65..39d08765ef 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.lsr/src/com/raytheon/uf/common/dataplugin/lsr/LocalStormReport.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.lsr/src/com/raytheon/uf/common/dataplugin/lsr/LocalStormReport.java @@ -30,6 +30,8 @@ import javax.measure.quantity.Velocity; import javax.measure.unit.NonSI; import javax.measure.unit.SI; import javax.measure.unit.Unit; +import javax.persistence.Access; +import javax.persistence.AccessType; import javax.persistence.Column; import javax.persistence.Embedded; import javax.persistence.Entity; @@ -70,6 +72,7 @@ import com.vividsolutions.jts.geom.Geometry; * Oct 14, 2013 2361 njensen Removed XML annotations and IDecoderGettable * Dec 10, 2013 2581 njensen Removed dataURI column * Jan 15, 2014 2581 njensen Changed constraint to use officeId instead of stationId + * Jan 30, 2014 2581 njensen Added dataURI column back in * * * @@ -79,8 +82,8 @@ import com.vividsolutions.jts.geom.Geometry; @Entity @SequenceGenerator(initialValue = 1, name = PluginDataObject.ID_GEN, sequenceName = "lsrseq") @Table(name = "lsr", uniqueConstraints = { @UniqueConstraint(columnNames = { - "latitude", "longitude", "officeId", "refTime", "forecastTime", - "eventType" }) }) +// "latitude", "longitude", "officeId", "refTime", "forecastTime", "eventType" +"dataURI" }) }) /* * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. @@ -509,4 +512,11 @@ public class LocalStormReport extends PersistablePluginDataObject implements public String getPluginName() { return "lsr"; } + + @Override + @Column + @Access(AccessType.PROPERTY) + public String getDataURI() { + return super.getDataURI(); + } } diff --git a/edexOsgi/com.raytheon.uf.common.parameter/utility/common_static/base/parameter/alias/gempak.xml b/edexOsgi/com.raytheon.uf.common.parameter/utility/common_static/base/parameter/alias/gempak.xml index e8dcce7bf6..b00caba142 100644 --- a/edexOsgi/com.raytheon.uf.common.parameter/utility/common_static/base/parameter/alias/gempak.xml +++ b/edexOsgi/com.raytheon.uf.common.parameter/utility/common_static/base/parameter/alias/gempak.xml @@ -91,7 +91,7 @@ WXTP18 WXTP24 WXTP48 - CINH + CINS CLWMR ACPCP C01M @@ -294,15 +294,15 @@ TMPK24 TMPK48 TMPKA - CLD - CLD01 - CLD03 - CLD06 - CLD09 - CLD12 - CLD18 - CLD24 - CLD48 + TCLD + TCLD01 + TCLD03 + TCLD06 + TCLD09 + TCLD12 + TCLD18 + TCLD24 + TCLD48 TSTM TOZO APCP diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/ingestAT.py b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/ingestAT.py index ca592c81c0..2fdfe2db5e 100644 --- a/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/ingestAT.py +++ b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/ingestAT.py @@ -63,7 +63,7 @@ def execute_ingest_at(incomingRecords, activeTable, atName, ztime, makeBackups, results = None try: results = MergeVTEC.merge(activeTable, atName, incomingRecords, ztime, makeBackups, - logging.getLogger('MergeVTEC')) + logger) except: logger.exception("MergeVTEC fail:") return results diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/res/spring/modelsounding-common.xml b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/res/spring/modelsounding-common.xml index 5e294f68ab..21ab96a78f 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/res/spring/modelsounding-common.xml +++ b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/res/spring/modelsounding-common.xml @@ -8,7 +8,7 @@ - + diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.mcidas/src/gov/noaa/nws/ncep/common/dataplugin/mcidas/McidasMapCoverage.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.mcidas/src/gov/noaa/nws/ncep/common/dataplugin/mcidas/McidasMapCoverage.java index a1ca872051..ca528b7dbd 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.mcidas/src/gov/noaa/nws/ncep/common/dataplugin/mcidas/McidasMapCoverage.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.mcidas/src/gov/noaa/nws/ncep/common/dataplugin/mcidas/McidasMapCoverage.java @@ -14,8 +14,8 @@ * 12/2009 144 T. Lee Migrated to TO11D6 * 01/2010 201 M. Li Split into dataplugin project * 05/2010 144 L. Lin Migration to TO11DR11. + * 11/2013 1066 G. Hull call constructCRSfromWKT * Nov 14, 2013 2393 bclement added getGridGeometry() - * * */ @@ -24,8 +24,6 @@ package gov.noaa.nws.ncep.common.dataplugin.mcidas; import gov.noaa.nws.ncep.common.tools.IDecoderConstantsN; import java.awt.geom.Rectangle2D; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import javax.persistence.Column; import javax.persistence.Entity; @@ -69,16 +67,18 @@ import com.vividsolutions.jts.geom.Polygon; @Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL) @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize -public class McidasMapCoverage extends PersistableDataObject implements ISpatialObject { +public class McidasMapCoverage extends PersistableDataObject implements + ISpatialObject { private static final long serialVersionUID = 1; + @Id private int pid; /** - * The projection of the map coverage 1 = Mercator, 3 = Lambert Conformal or TANC - * 5 = Polar Stereographic - * 7585 = native satellite navigation e.g. GVAR, ... + * The projection of the map coverage 1 = Mercator, 3 = Lambert Conformal or + * TANC 5 = Polar Stereographic 7585 = native satellite navigation e.g. + * GVAR, ... */ @Column @XmlAttribute @@ -96,7 +96,7 @@ public class McidasMapCoverage extends PersistableDataObject implements ISpatial @XmlAttribute @DynamicSerializeElement private Integer ny; - + /** The pixel resolution of the image */ @Column @XmlAttribute @@ -116,10 +116,11 @@ public class McidasMapCoverage extends PersistableDataObject implements ISpatial private Float clon; /** - * The standard latitude 1. For the Lambert Conformal projection this is the latitude - * of the proection cone intersects the earth. For the Polar Stereographic this is the - * latitude at which projection plan intersects the earth. For Mercator this is the - * latitude at which the Mercator projection cylinder intersects the earth. + * The standard latitude 1. For the Lambert Conformal projection this is the + * latitude of the proection cone intersects the earth. For the Polar + * Stereographic this is the latitude at which projection plan intersects + * the earth. For Mercator this is the latitude at which the Mercator + * projection cylinder intersects the earth. */ @Column @XmlAttribute @@ -127,14 +128,14 @@ public class McidasMapCoverage extends PersistableDataObject implements ISpatial private Float stdlat1; /** - * The standard latitude 2 is the second latitude of a secant cone which intersects the - * earth for the Lambert Conformal projection. + * The standard latitude 2 is the second latitude of a secant cone which + * intersects the earth for the Lambert Conformal projection. */ @Column @XmlAttribute @DynamicSerializeElement private Float stdlat2; - + /** The latitude of the lower-left corner */ @Column @XmlAttribute @@ -158,31 +159,31 @@ public class McidasMapCoverage extends PersistableDataObject implements ISpatial @XmlAttribute @DynamicSerializeElement private Float urlon; - + /** image element coordinate of area line 0, element 0 */ @Column @XmlAttribute @DynamicSerializeElement private int upperLeftElement; - + /** image line coordinate of area line 0, element 0 */ @Column @XmlAttribute @DynamicSerializeElement private int upperLeftLine; - + /** element resolution */ @Column @XmlAttribute @DynamicSerializeElement private int elementRes; - + /** line resolution */ @Column @XmlAttribute @DynamicSerializeElement private int lineRes; - + @Column(length = 5120) @XmlAttribute @DynamicSerializeElement @@ -245,9 +246,10 @@ public class McidasMapCoverage extends PersistableDataObject implements ISpatial * @param geometry * The geometry */ - public McidasMapCoverage(Integer projection, Integer nx, Integer ny, Float dx, - Float dy, Float clon, Float stdlat1, Float stdlat2, Float lllat, Float lllon, - Float urlat,Float urlon, CoordinateReferenceSystem crs, Geometry geometry) { + public McidasMapCoverage(Integer projection, Integer nx, Integer ny, + Float dx, Float dy, Float clon, Float stdlat1, Float stdlat2, + Float lllat, Float lllon, Float urlat, Float urlon, + CoordinateReferenceSystem crs, Geometry geometry) { this.projection = projection; this.nx = nx; this.ny = ny; @@ -274,19 +276,27 @@ public class McidasMapCoverage extends PersistableDataObject implements ISpatial * Constructs a new SatMapCoverage Object for native satellite navigation * * @param mapProjection - * @param nx The number of horizontal scan lines - * @param ny The number vertical scan lines - * @param reflon Reference Longitude - * @param upperLeftElement image element coordinate of area line 0, element 0 - * @param upperLeftLine image line coordinate of area line 0, element 0 - * @param xres Element resolution - * @param yres Line resolution - * @param crs The coordinate reference system + * @param nx + * The number of horizontal scan lines + * @param ny + * The number vertical scan lines + * @param reflon + * Reference Longitude + * @param upperLeftElement + * image element coordinate of area line 0, element 0 + * @param upperLeftLine + * image line coordinate of area line 0, element 0 + * @param xres + * Element resolution + * @param yres + * Line resolution + * @param crs + * The coordinate reference system * @param geometry */ public McidasMapCoverage(Integer projection, Integer nx, Integer ny, - Float reflon, int upperLeftElement, int upperLeftLine, int xres, - int yres, ProjectedCRS crs, Geometry geometry) { + Float reflon, int upperLeftElement, int upperLeftLine, int xres, + int yres, ProjectedCRS crs, Geometry geometry) { this.projection = projection; this.nx = nx; this.ny = ny; @@ -307,10 +317,10 @@ public class McidasMapCoverage extends PersistableDataObject implements ISpatial this.crsWKT = crsObject.toWKT(); this.location = (Polygon) geometry; pid = this.hashCode(); - } + } @Override - public int hashCode() { + public int hashCode() { HashCodeBuilder hashBuilder = new HashCodeBuilder(); hashBuilder.append(projection); hashBuilder.append(nx); @@ -342,39 +352,9 @@ public class McidasMapCoverage extends PersistableDataObject implements ISpatial if (crsObject == null) { try { crsObject = CRS.parseWKT(crsWKT); - // ReferencingFactoryFinder.getCRSFactory(null).createFromWKT(crsWKT); } catch (Exception e) { - /* - * parseWKT() doesn't recognize PROJCS PARAMETERS whose value is a "String" (it - * assumes all PARAMETER values are doubles.) - * If this crsWKT is a MCIDAS NAV, use McidasSpatialFactory instead. - */ - //e.printStackTrace(); - Pattern p = Pattern.compile("PROJCS\\[\"MCIDAS\\sAREA\\s(.*)\""); - Matcher m = p.matcher(crsWKT); - m.find(); - - if ( m.groupCount() == 1 ) { - String type = m.group(1); - //System.out.println("FOUND PROJCS:"+m.group(0)+":"+type); - p = Pattern.compile("\\[\"NAV_BLOCK_BASE64\",\\s\"(.*)\"\\]"); - m = p.matcher(crsWKT); - boolean found = m.find(); - - //System.out.println(m.group()); - //System.out.println(m.groupCount()+m.group(1)); - if ( found ) { - String navBlock = m.group(1); - crsObject = McidasSpatialFactory.getInstance().constructCRS(type, navBlock); - } - else { - crsObject = null; - } - } - else { - crsObject = null; - } - + crsObject = McidasSpatialFactory.getInstance() + .constructCRSfromWKT(crsWKT); } } return crsObject; @@ -466,7 +446,7 @@ public class McidasMapCoverage extends PersistableDataObject implements ISpatial public void setStdlat1(Float stdlat1) { this.stdlat1 = stdlat1; } - + public Float getStdlat2() { return stdlat2; } @@ -541,73 +521,78 @@ public class McidasMapCoverage extends PersistableDataObject implements ISpatial this.ny = ny; } - /** - * @return the upperLeftElement - */ - public int getUpperLeftElement() { - return upperLeftElement; - } + * @return the upperLeftElement + */ + public int getUpperLeftElement() { + return upperLeftElement; + } - /** - * @param upperLeftElement the upperLeftElement to set - */ - public void setUpperLeftElement(int upperLeftElement) { - this.upperLeftElement = upperLeftElement; - } + /** + * @param upperLeftElement + * the upperLeftElement to set + */ + public void setUpperLeftElement(int upperLeftElement) { + this.upperLeftElement = upperLeftElement; + } - /** - * @return the upperLeftLine - */ - public int getUpperLeftLine() { - return upperLeftLine; - } + /** + * @return the upperLeftLine + */ + public int getUpperLeftLine() { + return upperLeftLine; + } - /** - * @param upperLeftLine the upperLeftLine to set - */ - public void setUpperLeftLine(int upperLeftLine) { - this.upperLeftLine = upperLeftLine; - } + /** + * @param upperLeftLine + * the upperLeftLine to set + */ + public void setUpperLeftLine(int upperLeftLine) { + this.upperLeftLine = upperLeftLine; + } - /** - * @return the elementRes - */ - public int getElementRes() { - return elementRes; - } + /** + * @return the elementRes + */ + public int getElementRes() { + return elementRes; + } - /** - * @param elementRes the elementRes to set - */ - public void setElementRes(int elementRes) { - this.elementRes = elementRes; - } + /** + * @param elementRes + * the elementRes to set + */ + public void setElementRes(int elementRes) { + this.elementRes = elementRes; + } - /** - * @return the lineRes - */ - public int getLineRes() { - return lineRes; - } + /** + * @return the lineRes + */ + public int getLineRes() { + return lineRes; + } - /** - * @param lineRes the lineRes to set - */ - public void setLineRes(int lineRes) { - this.lineRes = lineRes; - } + /** + * @param lineRes + * the lineRes to set + */ + public void setLineRes(int lineRes) { + this.lineRes = lineRes; + } - public String getCrsWKT() { + public String getCrsWKT() { return crsWKT; } public void setCrsWKT(String crsWKT) { - //TODO new 2.6 version of geotools adds \r\n to long String parameters in WKT format - // this temp hack removes the extraneous characters, but we may want to investigate - // using a specific formatter to keep this consistent and in our control + // TODO new 2.6 version of geotools adds \r\n to long String parameters + // in WKT format + // this temp hack removes the extraneous characters, but we may want to + // investigate + // using a specific formatter to keep this consistent and in our control this.crsWKT = crsWKT.replaceAll("\r\n", ""); - //this.crsWKT = crsWKT; + // this.crsWKT = crsWKT; } public Polygon getLocation() { diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.mcidas/src/gov/noaa/nws/ncep/common/dataplugin/mcidas/McidasSpatialFactory.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.mcidas/src/gov/noaa/nws/ncep/common/dataplugin/mcidas/McidasSpatialFactory.java index dd1e676cce..91da6527a8 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.mcidas/src/gov/noaa/nws/ncep/common/dataplugin/mcidas/McidasSpatialFactory.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.mcidas/src/gov/noaa/nws/ncep/common/dataplugin/mcidas/McidasSpatialFactory.java @@ -9,6 +9,7 @@ * ------------ ---------- ----------- -------------------------- * 10/2009 144 T. Lee Created * 12/2009 144 T. Lee Migrated to TO11D6 + * 11/2013 1066 G. Hull constructCRSfromWKT (from McidasMapCoverage) * * * @@ -18,6 +19,9 @@ package gov.noaa.nws.ncep.common.dataplugin.mcidas; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import gov.noaa.nws.ncep.common.dataplugin.mcidas.dao.McidasMapCoverageDao; import org.apache.commons.codec.binary.Base64; @@ -28,6 +32,7 @@ import org.geotools.referencing.operation.DefaultMathTransformFactory; import org.opengis.parameter.ParameterValueGroup; import org.opengis.referencing.FactoryException; import org.opengis.referencing.NoSuchIdentifierException; +import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.crs.ProjectedCRS; import org.opengis.referencing.operation.MathTransform; @@ -408,6 +413,30 @@ public class McidasSpatialFactory { return new String(coded); } + public ProjectedCRS constructCRSfromWKT( String crsWKT) { + Pattern p = Pattern.compile("PROJCS\\[\"MCIDAS\\sAREA\\s(.*)\""); + Matcher m = p.matcher(crsWKT); + m.find(); + ProjectedCRS crsObject=null; + + if ( m.groupCount() == 1 ) { + String type = m.group(1); + //System.out.println("FOUND PROJCS:"+m.group(0)+":"+type); + p = Pattern.compile("\\[\"NAV_BLOCK_BASE64\",\\s\"(.*)\"\\]"); + m = p.matcher(crsWKT); + boolean found = m.find(); + + //System.out.println(m.group()); + //System.out.println(m.groupCount()+m.group(1)); + if ( found ) { + String navBlock = m.group(1); + crsObject = McidasSpatialFactory.getInstance().constructCRS(type, navBlock); + } + } + + return crsObject; + } + public ProjectedCRS constructCRS(String type, String encoded) { ParameterValueGroup pvg = null; diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.ncscat/src/gov/noaa/nws/ncep/common/dataplugin/ncscat/NcscatRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.ncscat/src/gov/noaa/nws/ncep/common/dataplugin/ncscat/NcscatRecord.java index 031199a14b..348cb46bdb 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.ncscat/src/gov/noaa/nws/ncep/common/dataplugin/ncscat/NcscatRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.ncscat/src/gov/noaa/nws/ncep/common/dataplugin/ncscat/NcscatRecord.java @@ -167,6 +167,6 @@ public class NcscatRecord extends PersistablePluginDataObject { @Override public String getPluginName() { - return "ncsat"; + return "ncscat"; } } diff --git a/ncep/gov.noaa.nws.ncep.edex.common/src/gov/noaa/nws/ncep/edex/common/metparameters/parameterconversion/PRLibrary.java b/ncep/gov.noaa.nws.ncep.edex.common/src/gov/noaa/nws/ncep/edex/common/metparameters/parameterconversion/PRLibrary.java index 40646838a1..34e3392658 100644 --- a/ncep/gov.noaa.nws.ncep.edex.common/src/gov/noaa/nws/ncep/edex/common/metparameters/parameterconversion/PRLibrary.java +++ b/ncep/gov.noaa.nws.ncep.edex.common/src/gov/noaa/nws/ncep/edex/common/metparameters/parameterconversion/PRLibrary.java @@ -8,13 +8,9 @@ */ package gov.noaa.nws.ncep.edex.common.metparameters.parameterconversion; -import java.util.Arrays; - import gov.noaa.nws.ncep.edex.common.metparameters.Amount; -import gov.noaa.nws.ncep.edex.common.metparameters.parameterconversion.GempakConstants; -import gov.noaa.nws.ncep.edex.common.metparameters.parameterconversion.NcUnits; -//import com.raytheon.uf.viz.core.exception.VizException; +import java.util.Arrays; import javax.measure.quantity.Temperature; import javax.measure.quantity.VolumetricDensity; @@ -22,2555 +18,2885 @@ import javax.measure.unit.NonSI; import javax.measure.unit.SI; import javax.measure.unit.Unit; -public final class PRLibrary -{ +import org.opengis.coverage.grid.InvalidRangeException; +//import com.raytheon.uf.viz.core.exception.VizException; - /** - * No-arguments constructor - */ - public PRLibrary(){ - - } - /** - * Computes altimeter from the station pressure and elevation - * @param pres - pressure at the station - * @param selv - elevation of the station - * @return the computed altimeter in Inches - * @throws NullPointerException - * - */ - public static final Amount prAltp( Amount pres, Amount selv) throws InvalidValueException, NullPointerException{ - //System.out.println("From prAltp:"); - //System.out.println(" pres = " + pres.doubleValue()); - //System.out.println(" selv = " + selv.doubleValue()); - - if ( !checkNullOrInvalidValue( pres ) || !checkNullOrInvalidValue( selv ) ) - return new Amount ( NonSI.INCH_OF_MERCURY); - - selv = checkAndConvertInputAmountToExpectedUnits(selv, SI.METER ); - pres = checkAndConvertInputAmountToExpectedUnits(pres, NcUnits.MILLIBAR); - double seaLevelTempInKelvin = GempakConstants.TMCK + 15; - double hgtk = selv.getUnit().getConverterTo( SI.KILOMETER ).convert( selv.doubleValue() ) ; - double exponent = - ( GempakConstants.GRAVTY / ( GempakConstants.GAMUSD * GempakConstants.RDGAS ) * 1000 ); -// double base = pres * ( 1.0f - ( hgtk * GempakConstants.GAMUSD / seaLevelTempInKelvin ) ); -// float altm = (float) Math.pow( base, Math.exp( exponent ) ); -// return prAlti( pres * altm ); - double base = ( 1.0 - ( hgtk * GempakConstants.GAMUSD / seaLevelTempInKelvin ) ); - double altm = Math.pow( base, exponent ); - double altp = pres.doubleValue() * altm; - return ( new Amount ( altp, NonSI.INCH_OF_MERCURY ) ); - } - - +public final class PRLibrary { - - /*** - * Computes the Ceiling converted to Mean Sea Level in hundreds of feet - * @param ceil - Ceiling in hundreds of feet - * @param selv - Station elevation in meters - * @return The ceiling converted to Mean Sea Level in hundreds of feet - * @throws NullPointerException - * - */ - public static final Amount prCmsl( Amount ceil, Amount selv) throws InvalidValueException, NullPointerException{ - //System.out.println("From prCmsl:"); - //System.out.println(" ceil = " + ceil.doubleValue()); - //System.out.println(" selv = " + selv.doubleValue()); - /*Sanity check*/ -// checkNullOrInvalidValue( ceil ); -// checkNullOrInvalidValue( selv ); - if ( !checkNullOrInvalidValue( ceil ) || !checkNullOrInvalidValue( selv ) ) - return new Amount ( NcUnits.HUNDREDS_OF_FEET); - - selv = checkAndConvertInputAmountToExpectedUnits(selv, NcUnits.HUNDREDS_OF_FEET); - ceil = checkAndConvertInputAmountToExpectedUnits(ceil, NcUnits.HUNDREDS_OF_FEET); - return ( new Amount ( selv.doubleValue() + ceil.doubleValue() , NcUnits.HUNDREDS_OF_FEET ) ); - } - - /** - * Computes the wind direction in degrees from the input u and v components of velocity, - * both of which must be in the same units (either meters/second or knots) - * @param uX - U component of velocity - * @param vX- V component of velocity - * @return The wind direction in degrees - * @throws NullPointerException - * - */ - public static final Amount prDrct ( Amount uX, Amount vX) throws InvalidValueException, NullPointerException{ - //System.out.println("From prDrct:"); - //System.out.println(" uX = " + uX.doubleValue()); - //System.out.println(" vX = " + vX.doubleValue()); - -// checkNullOrInvalidValue(uX); -// checkNullOrInvalidValue(vX); - if ( !checkNullOrInvalidValue( uX ) || !checkNullOrInvalidValue( vX ) ) - return new Amount ( NonSI.DEGREE_ANGLE); - - double vXVal = Double.NaN; - double uXVal = Double.NaN; - if ( uX.getUnit() != vX.getUnit() && uX.getUnit().isCompatible(vX.getUnit() )) { - vXVal = vX.getUnit().getConverterTo(uX.getUnit() ).convert(vX.doubleValue() ); - vX = new Amount ( vXVal, uX.getUnit() ); - } - uXVal = uX.doubleValue(); - double prDrct = 0.0; + /** + * No-arguments constructor + */ + public PRLibrary() { - if ( ( uXVal != 0 ) || ( vXVal != 0 ) ){ - prDrct = Math.atan2(-uXVal, -vXVal) * GempakConstants.RTD; - if ( prDrct <= 0 ) - prDrct += 360; - } - return ( new Amount ( prDrct , NonSI.DEGREE_ANGLE )); + } - } - - /** - * Computes the density of dry air given the pressure (in mb) - * and temperature (in Celsius) - * @param pres - Pressure in millibars - * @param tmpc - Temperature in Celsius - * @return Density of dry air in kg/(m**3) - * @throws InvalidRangeException - * @throws NullPointerException - * - */ - public static final Amount prDden ( Amount pres, Amount tmpc ) throws InvalidValueException, NullPointerException{ - //System.out.println("From prDden:"); - //System.out.println(" pres = " + pres.doubleValue()); - //System.out.println(" tmpc = " + tmpc.doubleValue()); - - double prdden = GempakConstants.RMISSD; - /*Check for bad data*/ -// checkNullOrInvalidValue(pres); -// checkNullOrInvalidValue(tmpc); + /** + * Computes altimeter from the station pressure and elevation + * + * @param pres + * - pressure at the station + * @param selv + * - elevation of the station + * @return the computed altimeter in Inches + * @throws NullPointerException + * + */ + public static final Amount prAltp(Amount pres, Amount selv) + throws InvalidValueException, NullPointerException { + // System.out.println("From prAltp:"); + // System.out.println(" pres = " + pres.doubleValue()); + // System.out.println(" selv = " + selv.doubleValue()); - if ( !checkNullOrInvalidValue( pres ) || !checkNullOrInvalidValue( tmpc ) ) - return new Amount ( VolumetricDensity.UNIT ); - - pres = checkAndConvertInputAmountToExpectedUnits( pres, NcUnits.MILLIBAR ); - tmpc = checkAndConvertInputAmountToExpectedUnits( tmpc, SI.CELSIUS ); - - double tmpcVal = tmpc.doubleValue(); - if ( tmpcVal < -GempakConstants.TMCK ){ - System.out.println("From prDden: temperature must be greater than or equal to -273.15 "); - return new Amount ( VolumetricDensity.UNIT ); -// throw new InvalidRangeException("From prDden: temperature must be greater than or equal to -273.15 "); - } - /* Convert temperature and compute*/ - double tmpk = tmpc.getUnit().getConverterTo( SI.KELVIN ).convert( tmpcVal ); - prdden = 100 * pres.doubleValue() / ( GempakConstants.RDGAS * tmpk ); + if (!checkNullOrInvalidValue(pres) || !checkNullOrInvalidValue(selv)) + return new Amount(NonSI.INCH_OF_MERCURY); - return new Amount ( prdden, VolumetricDensity.UNIT ); - } - - /*** - * Computes the dewpoint depression, from tmpx and dwpx, both of which - * must be in the same units (one of Kelvin, Celsius or Farenheit) - * @param tmpx - Air temperature - * @param dwpx - Dewpoint temperature - * @return the dewpoint depresssion (in the same units are tmpx and dwpx) - * if both tmpx and dwpx are valid values - */ - - public static final Amount prDdep ( Amount tmpx, Amount dwpx) throws InvalidValueException, NullPointerException{ - //System.out.println("From prDdep:"); - //System.out.println(" tmpx = " + tmpx.doubleValue()); - //System.out.println(" dwpx = " + dwpx.doubleValue()); -// checkNullOrInvalidValue(tmpx); -// checkNullOrInvalidValue(dwpx); - if ( !checkNullOrInvalidValue( tmpx ) || !checkNullOrInvalidValue( dwpx ) ) - return new Amount ( tmpx.getUnit() ); - - - Amount prDdep = null; - - dwpx = checkAndConvertInputAmountToExpectedUnits( dwpx, tmpx.getUnit() ); - double dewpointDepression = tmpx.doubleValue() - dwpx.doubleValue(); - prDdep = new Amount ( dewpointDepression , tmpx.getUnit()); - return prDdep; - } - - /** - * Computes DMAX, the maximum temperature obtained by - * comparing the 6-hour maximum at 00Z, - * the 6-hour maximum at 06Z and - * the local midnight maximum (reported at 00 LST) - * if either of the 6-hour values is missing, the maximum is set to missing. - * The inputs are in Celsius, the output in degrees Farenheit - * @param t00x - 6-hour maximum temperature at 00Z, Celsius - * @param t06x - 6-hour maximum temperature at 06Z, Celsius - * @param tdxc - Local midnight max temperature at 00 LST, Celsius - * @return The maximum of the 3 temperature values (in Farenheit) - * @throws NullPointerException - * - */ - public static final Amount prDmax ( Amount t00x, Amount t06x, Amount tdxc) throws InvalidValueException, NullPointerException{ - //System.out.println("From prDmax:"); - //System.out.println(" t00x = " + t00x.doubleValue()); - //System.out.println(" t06x = " + t06x.doubleValue()); - //System.out.println(" tdxc= " + tdxc.doubleValue()); - -// checkNullOrInvalidValue(t00x); -// checkNullOrInvalidValue(t06x); - - if ( !checkNullOrInvalidValue( t00x ) || !checkNullOrInvalidValue( t06x ) ) - return new Amount ( NonSI.FAHRENHEIT ); - - t00x = checkAndConvertInputAmountToExpectedUnits( t00x, SI.CELSIUS ); - t06x = checkAndConvertInputAmountToExpectedUnits( t06x, SI.CELSIUS ); + selv = checkAndConvertInputAmountToExpectedUnits(selv, SI.METER); + pres = checkAndConvertInputAmountToExpectedUnits(pres, NcUnits.MILLIBAR); + double seaLevelTempInKelvin = GempakConstants.TMCK + 15; + double hgtk = selv.getUnit().getConverterTo(SI.KILOMETER) + .convert(selv.doubleValue()); + double exponent = -(GempakConstants.GRAVTY + / (GempakConstants.GAMUSD * GempakConstants.RDGAS) * 1000); + // double base = pres * ( 1.0f - ( hgtk * GempakConstants.GAMUSD / + // seaLevelTempInKelvin ) ); + // float altm = (float) Math.pow( base, Math.exp( exponent ) ); + // return prAlti( pres * altm ); + double base = (1.0 - (hgtk * GempakConstants.GAMUSD / seaLevelTempInKelvin)); + double altm = Math.pow(base, exponent); + double altp = pres.doubleValue() * altm; + return (new Amount(altp, NonSI.INCH_OF_MERCURY)); + } - if ( tdxc != null && tdxc.doubleValue() > -9999 ) { - tdxc = checkAndConvertInputAmountToExpectedUnits( tdxc, SI.CELSIUS ); - double[] tempArray = { t00x.doubleValue(), t06x.doubleValue(), tdxc.doubleValue() }; - - Arrays.sort(tempArray); - double newTemp = SI.CELSIUS.getConverterTo(NonSI.FAHRENHEIT).convert(tempArray[2]); - return ( new Amount ( newTemp , NonSI.FAHRENHEIT ) ); - } - else{ - double t00xVal = t00x.doubleValue(); - double t06xVal = t06x.doubleValue(); - Amount dmax = ( t00xVal > t06xVal - ? checkAndConvertInputAmountToExpectedUnits(t00x, NonSI.FAHRENHEIT) - : checkAndConvertInputAmountToExpectedUnits(t06x, NonSI.FAHRENHEIT ) ); - return dmax; - } + /*** + * Computes the Ceiling converted to Mean Sea Level in hundreds of feet + * + * @param ceil + * - Ceiling in hundreds of feet + * @param selv + * - Station elevation in meters + * @return The ceiling converted to Mean Sea Level in hundreds of feet + * @throws NullPointerException + * + */ + public static final Amount prCmsl(Amount ceil, Amount selv) + throws InvalidValueException, NullPointerException { + // System.out.println("From prCmsl:"); + // System.out.println(" ceil = " + ceil.doubleValue()); + // System.out.println(" selv = " + selv.doubleValue()); + /* Sanity check */ + // checkNullOrInvalidValue( ceil ); + // checkNullOrInvalidValue( selv ); + if (!checkNullOrInvalidValue(ceil) || !checkNullOrInvalidValue(selv)) + return new Amount(NcUnits.HUNDREDS_OF_FEET); + + selv = checkAndConvertInputAmountToExpectedUnits(selv, + NcUnits.HUNDREDS_OF_FEET); + ceil = checkAndConvertInputAmountToExpectedUnits(ceil, + NcUnits.HUNDREDS_OF_FEET); + return (new Amount(selv.doubleValue() + ceil.doubleValue(), + NcUnits.HUNDREDS_OF_FEET)); + } + + /** + * Computes the wind direction in degrees from the input u and v components + * of velocity, both of which must be in the same units (either + * meters/second or knots) + * + * @param uX + * - U component of velocity + * @param vX + * - V component of velocity + * @return The wind direction in degrees + * @throws NullPointerException + * + */ + public static final Amount prDrct(Amount uX, Amount vX) + throws InvalidValueException, NullPointerException { + // System.out.println("From prDrct:"); + // System.out.println(" uX = " + uX.doubleValue()); + // System.out.println(" vX = " + vX.doubleValue()); + + // checkNullOrInvalidValue(uX); + // checkNullOrInvalidValue(vX); + if (!checkNullOrInvalidValue(uX) || !checkNullOrInvalidValue(vX)) + return new Amount(NonSI.DEGREE_ANGLE); + + double vXVal = Double.NaN; + double uXVal = Double.NaN; + if (uX.getUnit() != vX.getUnit() + && uX.getUnit().isCompatible(vX.getUnit())) { + vXVal = vX.getUnit().getConverterTo(uX.getUnit()) + .convert(vX.doubleValue()); + vX = new Amount(vXVal, uX.getUnit()); + } + uXVal = uX.doubleValue(); + double prDrct = 0.0; + + if ((uXVal != 0) || (vXVal != 0)) { + prDrct = Math.atan2(-uXVal, -vXVal) * GempakConstants.RTD; + if (prDrct <= 0) + prDrct += 360; + } + return (new Amount(prDrct, NonSI.DEGREE_ANGLE)); + + } + + /** + * Computes the density of dry air given the pressure (in mb) and + * temperature (in Celsius) + * + * @param pres + * - Pressure in millibars + * @param tmpc + * - Temperature in Celsius + * @return Density of dry air in kg/(m**3) + * @throws InvalidRangeException + * @throws NullPointerException + * + */ + public static final Amount prDden(Amount pres, Amount tmpc) + throws InvalidValueException, NullPointerException { + // System.out.println("From prDden:"); + // System.out.println(" pres = " + pres.doubleValue()); + // System.out.println(" tmpc = " + tmpc.doubleValue()); + + double prdden = GempakConstants.RMISSD; + /* Check for bad data */ + // checkNullOrInvalidValue(pres); + // checkNullOrInvalidValue(tmpc); + + if (!checkNullOrInvalidValue(pres) || !checkNullOrInvalidValue(tmpc)) + return new Amount(VolumetricDensity.UNIT); + + pres = checkAndConvertInputAmountToExpectedUnits(pres, NcUnits.MILLIBAR); + tmpc = checkAndConvertInputAmountToExpectedUnits(tmpc, SI.CELSIUS); + + double tmpcVal = tmpc.doubleValue(); + if (tmpcVal < -GempakConstants.TMCK) { + System.out + .println("From prDden: temperature must be greater than or equal to -273.15 "); + return new Amount(VolumetricDensity.UNIT); + // throw new + // InvalidRangeException("From prDden: temperature must be greater than or equal to -273.15 "); + } + /* Convert temperature and compute */ + double tmpk = tmpc.getUnit().getConverterTo(SI.KELVIN).convert(tmpcVal); + prdden = 100 * pres.doubleValue() / (GempakConstants.RDGAS * tmpk); + + return new Amount(prdden, VolumetricDensity.UNIT); + } + + /*** + * Computes the dewpoint depression, from tmpx and dwpx, both of which must + * be in the same units (one of Kelvin, Celsius or Farenheit) + * + * @param tmpx + * - Air temperature + * @param dwpx + * - Dewpoint temperature + * @return the dewpoint depresssion (in the same units are tmpx and dwpx) if + * both tmpx and dwpx are valid values + */ + + public static final Amount prDdep(Amount tmpx, Amount dwpx) + throws InvalidValueException, NullPointerException { + // System.out.println("From prDdep:"); + // System.out.println(" tmpx = " + tmpx.doubleValue()); + // System.out.println(" dwpx = " + dwpx.doubleValue()); + // checkNullOrInvalidValue(tmpx); + // checkNullOrInvalidValue(dwpx); + if (!checkNullOrInvalidValue(tmpx) || !checkNullOrInvalidValue(dwpx)) + return new Amount(tmpx.getUnit()); + + Amount prDdep = null; + + dwpx = checkAndConvertInputAmountToExpectedUnits(dwpx, tmpx.getUnit()); + double dewpointDepression = tmpx.doubleValue() - dwpx.doubleValue(); + prDdep = new Amount(dewpointDepression, tmpx.getUnit()); + return prDdep; + } + + /** + * Computes DMAX, the maximum temperature obtained by comparing the 6-hour + * maximum at 00Z, the 6-hour maximum at 06Z and the local midnight maximum + * (reported at 00 LST) if either of the 6-hour values is missing, the + * maximum is set to missing. The inputs are in Celsius, the output in + * degrees Farenheit + * + * @param t00x + * - 6-hour maximum temperature at 00Z, Celsius + * @param t06x + * - 6-hour maximum temperature at 06Z, Celsius + * @param tdxc + * - Local midnight max temperature at 00 LST, Celsius + * @return The maximum of the 3 temperature values (in Farenheit) + * @throws NullPointerException + * + */ + public static final Amount prDmax(Amount t00x, Amount t06x, Amount tdxc) + throws InvalidValueException, NullPointerException { + // System.out.println("From prDmax:"); + // System.out.println(" t00x = " + t00x.doubleValue()); + // System.out.println(" t06x = " + t06x.doubleValue()); + // System.out.println(" tdxc= " + tdxc.doubleValue()); + + // checkNullOrInvalidValue(t00x); + // checkNullOrInvalidValue(t06x); + + if (!checkNullOrInvalidValue(t00x) || !checkNullOrInvalidValue(t06x)) + return new Amount(NonSI.FAHRENHEIT); + + t00x = checkAndConvertInputAmountToExpectedUnits(t00x, SI.CELSIUS); + t06x = checkAndConvertInputAmountToExpectedUnits(t06x, SI.CELSIUS); + + if (tdxc != null && tdxc.doubleValue() > -9999) { + tdxc = checkAndConvertInputAmountToExpectedUnits(tdxc, SI.CELSIUS); + double[] tempArray = { t00x.doubleValue(), t06x.doubleValue(), + tdxc.doubleValue() }; + + Arrays.sort(tempArray); + double newTemp = SI.CELSIUS.getConverterTo(NonSI.FAHRENHEIT) + .convert(tempArray[2]); + return (new Amount(newTemp, NonSI.FAHRENHEIT)); + } else { + double t00xVal = t00x.doubleValue(); + double t06xVal = t06x.doubleValue(); + Amount dmax = (t00xVal > t06xVal ? checkAndConvertInputAmountToExpectedUnits( + t00x, NonSI.FAHRENHEIT) + : checkAndConvertInputAmountToExpectedUnits(t06x, + NonSI.FAHRENHEIT)); + return dmax; + } + + } - } - /** *
      * Computes the minimum temperature obtained by
      * comparing the 6-hour minimum at 12Z and the 6-hour minimum at 18Z.
      * if either of the 6-hour values is missing, the minimum is set to missing.
      * The inputs are in degrees C, the output in degrees F.
-     *  
- * @param t12n - 6-hour minimum temperature at 12Z, deg Celsius - * @param t18n - 6-hour minimum temperature at 18Z, deg Celsius - * @return the minimum temperature (in Farenheit) after comparing the two input values, if they exist - * @throws NullPointerException - * - */ - public static final Amount prDmin ( Amount t12n, Amount t18n ) throws InvalidValueException, NullPointerException{ - //System.out.println("From prDmin:"); - //System.out.println(" t12n = " + t12n.doubleValue()); - //System.out.println(" t18n = " + t18n.doubleValue()); -// checkNullOrInvalidValue( t12n ); -// checkNullOrInvalidValue( t18n ); - if ( !checkNullOrInvalidValue( t12n ) || !checkNullOrInvalidValue( t18n ) ) - return new Amount ( NonSI.FAHRENHEIT ); - - t12n = checkAndConvertInputAmountToExpectedUnits( t12n,SI.CELSIUS); - t18n = checkAndConvertInputAmountToExpectedUnits( t18n,SI.CELSIUS); - Amount minValue = ( t12n.doubleValue() < t18n.doubleValue() ? t12n : t18n); - return ( checkAndConvertInputAmountToExpectedUnits(minValue, NonSI.FAHRENHEIT) ); - - } - - /** - * Computes the dewpoint as the difference between the input temperature and dewpoint depression - * @param tmpx - temperature (in Celsius or Farenheit or Kelvin) - * @param dpdx - the dewpoint depression ( in the same units as the temperature) - * @return the dewpoint in the same units as ( in the same units as the temperature) - * @throws NullPointerException - * - */ - public static final Amount prDwdp( Amount tmpx, Amount dpdx ) throws InvalidValueException, NullPointerException{ - //System.out.println("From prDwdp:"); - //System.out.println(" tmpx = " + tmpx.doubleValue()); - //System.out.println(" dpdx = " + dpdx.doubleValue()); - -// checkNullOrInvalidValue(tmpx); -// checkNullOrInvalidValue(dpdx); - - if ( !checkNullOrInvalidValue( tmpx ) || !checkNullOrInvalidValue( dpdx ) ) - return new Amount ( tmpx.getUnit() ); - - Unit tempUnits = (Unit) tmpx.getUnit(); - Unit dewpointDepUnits = (Unit) dpdx.getUnit(); - if ( !tempUnits.equals( dewpointDepUnits) && tempUnits.isCompatible(dewpointDepUnits)){ - double dewpointDepValue= (double) dewpointDepUnits.getConverterTo(tempUnits).convert(dpdx.doubleValue()); - dpdx = new Amount ( dewpointDepValue, tempUnits); - } - - Amount dewpointTemperature = new Amount ( tmpx.doubleValue() - dpdx.doubleValue(), tempUnits ); - return dewpointTemperature; - } - - /** - * Computes the dewpoint ( in Celsius ) from the mixing ratio (in grams/kilogram) - * and the pressure (in mb) - * @param rmix - the mixing ratio (in grams/kilogram) - * @param pres - the pressure (in mb) - * @return the dewpoint (in Celsius), if both the input values are valid - * @throws InvalidRangeException - * @throws NullPointerException - * - */ - public static final Amount prDwpt( Amount rmix, Amount pres) throws InvalidValueException, NullPointerException{ - //System.out.println("From prDwpt:"); - //System.out.println(" rmix = " + rmix.doubleValue()); - //System.out.println(" pres = " + pres.doubleValue()); - Amount prDwpt = null; -// checkNullOrInvalidValue( rmix ); -// checkNullOrInvalidValue( pres ); - if ( !checkNullOrInvalidValue( rmix ) || !checkNullOrInvalidValue( pres ) ) - return new Amount ( SI.CELSIUS ); - - rmix = checkAndConvertInputAmountToExpectedUnits( rmix, Unit.ONE ); - pres = checkAndConvertInputAmountToExpectedUnits( pres, NcUnits.MILLIBAR ); - double mixingRatioValue = rmix.doubleValue() ; - double pressureValue = pres.doubleValue(); - if ( mixingRatioValue <= 0 ){ - System.out.println("From prDwpt() - mixing ratio must be greater than 0"); - return new Amount ( SI.CELSIUS ); -// throw new InvalidRangeException("From prDwpt() - mixing ratio must be greater than 0"); - } - if ( pressureValue <= 0 ){ - System.out.println("From prDwpt() - pres must be greater than 0"); - return new Amount ( SI.CELSIUS ); -// throw new InvalidRangeException("From prDwpt() - pres must be greater than 0"); - } - /*Convert gram/kilogram to gram/gram*/ - double ratio = mixingRatioValue / 1000; - - /*Calculate vapor pressure from mixing ratio and pressure*/ - double vaporPressure = ( pressureValue * ratio ) / ( 0.62197 + ratio ); - - /*Correct vapor pressure*/ - vaporPressure = vaporPressure / ( 1.001 + ( ( pressureValue - 100.0 ) / 900) * .0034 ) ; - - /*Calculate dewpoint*/ - double dewPointValue = ( double ) ( Math.log ( vaporPressure / 6.112 ) * 243.5 / ( 17.67 - Math.log( vaporPressure / 6.112 ) ) ) ; - prDwpt = new Amount ( dewPointValue, SI.CELSIUS); - return prDwpt; - } - - /*** - * Computes the Fosberg index from the temperature, relative humidity and wind speed - * at the surface. - * @param tmpc - Temperature in Celsius - * @param relh - Relative humidity in percent - * @param sped - Wind speed in meters/second - * @return the Fosberg index - * @throws NullPointerException - * - */ - public static final Amount prFosb( Amount tmpc, Amount relh, Amount sped) throws InvalidValueException, NullPointerException{ - //System.out.println("From prFosb:"); - //System.out.println("Temperature ( in K ) is: " + tmpc.doubleValue()); - //System.out.println("Relative Humidity is: " + relh.doubleValue()); - //System.out.println("Wind Speed is: " + sped.doubleValue()); -// checkNullOrInvalidValue( tmpc ); -// checkNullOrInvalidValue( relh ); -// checkNullOrInvalidValue( sped ); - if ( !checkNullOrInvalidValue( tmpc ) || !checkNullOrInvalidValue( relh ) - || !checkNullOrInvalidValue( sped )) - return new Amount ( Unit.ONE ); - - tmpc = checkAndConvertInputAmountToExpectedUnits( tmpc, SI.CELSIUS ); - relh = checkAndConvertInputAmountToExpectedUnits( relh, NonSI.PERCENT ); - sped = checkAndConvertInputAmountToExpectedUnits( sped, SI.METERS_PER_SECOND ); - - /*Change temperature to degrees Fahrenheit*/ - double tf = tmpc.getUnit().getConverterTo(NonSI.FAHRENHEIT).convert(tmpc.doubleValue()); - - /*Convert wind speed from meters/second to knots*/ - double smph = sped.getUnit().getConverterTo( NonSI.MILES_PER_HOUR ).convert( sped.doubleValue() ); - - - double A = 0.03229; - double B = 0.281073; - double C = 0.000578; - double D = 2.22749; - double E = 0.160107; - double F = 0.014784; - double G = 21.0606; - double H = 0.005565; - double P = 0.00035; - double Q = 0.483199; - double R = 0.3002; -// float T = 9.0f/5.0f; -// float U = 1.9425f; -// float V = 0.868976f; - double fw = GempakConstants.RMISSD; - double relhVal = relh.doubleValue(); - if ( relhVal <= 10 ) { - fw = A + B * relhVal - C * relhVal * tf; - } - else if ( relhVal <= 50 ) { - fw = D + E * relhVal - F * tf; - } - else{ - fw = G + H *relhVal*relhVal - P * relhVal * tf - Q * relhVal; - } - - double sss = ( double ) ( Math.sqrt ( 1. + ( smph * smph ) )); - double fwd = fw / 30; - double fwd2 = fwd * fwd; - double fwd3 = fwd2 * fwd; - double fire = 1 - 2 * fwd + 1.5f * fwd2 - 0.5f * fwd3; - - /*Find the Fosberg Index*/ - - double prfosb = ( fire * sss ) / R; - - return ( new Amount ( prfosb , Unit.ONE ) ); - } - - /** - *
-	 * Computes the Southern Region/CPC Rothfusz heat index.
-	 * 
-	 * The Rothfusz regression is optimal for TMPF > ~80 and RELH > ~40%.   
-	 * This code applies a simple heat index formula and then resorts to   
-	 * the Rothfusz regression only if the simple heat index exceeds 80,   
-	 * implying temperatures near, but slightly below 80.  To make the    
-	 * simple calculation continuous with the values obtained from the   
-	 * Rothfusz regression, the simple result is averaged with TMPF in    
-	 * computing the simple heat index value.                               
-	 * Source:  NWS Southern Region SSD Technical Attachment SR 90-23  7/1/90.  
-	 * Heat Index was originally known as the apparent temperature index 
-	 * (Steadman, JAM, July, 1979).                                                                  
-	 * This code includes adjustments made by the CPC for low RELH at high  
-	 * TMPF and high RELH for TMPF in the mid 80's.
-	 * 
-	 * 
-	 * @param tmpf  - the input air temperature
-	 * @param relh   - the relative humidity 
-	 * @return the heat index (in deg Farenheit) if both 
-	 * the input air temperature and relative humidity
-	 * are valid values 
-	 * 
- * @throws NullPointerException - * - */ - public static final Amount prHeat( Amount tmpf, Amount relh ) throws InvalidValueException, NullPointerException{ - //System.out.println("From prHeat:"); - //System.out.println(" tmpf = " + tmpf.doubleValue()); - //System.out.println(" relh = " + relh.doubleValue()); - - double prheat = GempakConstants.RMISSD; -// checkNullOrInvalidValue( tmpf ); -// checkNullOrInvalidValue( relh ); - if ( !checkNullOrInvalidValue( tmpf ) || !checkNullOrInvalidValue( relh ) ) - return new Amount ( Unit.ONE ); - - tmpf = checkAndConvertInputAmountToExpectedUnits( tmpf, NonSI.FAHRENHEIT ); - relh = checkAndConvertInputAmountToExpectedUnits( relh, NonSI.PERCENT ); - double tmpfVal = tmpf.doubleValue(); - double relhVal = relh.doubleValue(); - /*If the temperature is less than 40 degrees, set the heat index to the temperature*/ - if ( tmpfVal <= 40 ) - prheat = tmpfVal; - else{ - /* - * Compute a simple heat index. If the value is less than 80 deg F - * use it - */ - prheat = ( float ) ( 61 + ( tmpfVal - 68 ) * 1.2 + relhVal * 0.094); - prheat = ( float ) ( ( tmpfVal + prheat ) * 0.5); - /*Else compute the full regression value*/ - if ( prheat >= 80.0 ){ - double t2 = tmpfVal * tmpfVal; - double r2 = relhVal * relhVal; - prheat = ( float ) ( -42.379 - + 2.04901523 * tmpfVal - + 10.14333127 * relhVal - - 0.22475541 * tmpfVal * relhVal - - 0.00683783 * t2 - - 0.05481717 * r2 - + 0.00122874 * t2 * relhVal - + 0.00085282 * tmpfVal *r2 - - 0.00000199 * t2 * r2 ); - /* - * Adjust for high regression at low relative humidity for temperatures above 80 degrees F. - */ - if ( ( relhVal <= 13.0 ) && ( ( tmpfVal >= 80.0 ) &&( tmpfVal <= 112.0 ) ) ) { - float adj1 = ( float) ( ( 13. - relhVal ) / 4 ); - float adj2 = ( float ) ( Math.sqrt ( ( 17 - Math.abs (tmpfVal - 95) ) / 17 ) ); - float adj = adj1 * adj2; - prheat -= adj; - } - /* - * Adjust for low regression at high relative humidity and temperatures in the mid-80s - */ - else if ( ( relhVal > 85 ) && ( ( tmpfVal >= 80.0 ) &&( tmpfVal <= 87.0 ) ) ){ - float adj1 = ( float) ( ( relhVal - 85.0 ) / 10.0 ); - float adj2 = ( float ) ( ( 87.0 - tmpfVal ) / 5); - float adj = adj1 * adj2; - prheat += adj; - } - } - } - return ( new Amount ( prheat,NonSI.FAHRENHEIT ) ); - } - - /** - * Computes the humiture index from the air temperature and the dew point - * temperature using the equation: PR_HMTR = TMPF + ( PR_VAPR ( DWPC ) - 21 ) - * @param tmpf - the air temperature (in Farenheit) - * @param dwpf - the dew point (in Farenheit) - * @return the humiture index if both the air temperature and the dewpoint temperature are - * valid values - * @throws InvalidRangeException - * @throws NullPointerException - * - */ - public static final Amount prHmtr( Amount tmpf, Amount dwpf) throws InvalidValueException, NullPointerException{ - //System.out.println("From prHmtr:"); - //System.out.println(" tmpf = " + tmpf.doubleValue()); - //System.out.println(" dwpf = " + dwpf.doubleValue()); - - double prhmtr = GempakConstants.RMISSD; - if ( !checkNullOrInvalidValue( tmpf ) || !checkNullOrInvalidValue( dwpf )) - return new Amount ( Unit.ONE ); - - tmpf = checkAndConvertInputAmountToExpectedUnits( tmpf, NonSI.FAHRENHEIT ); - dwpf = checkAndConvertInputAmountToExpectedUnits( dwpf, NonSI.FAHRENHEIT ); - - Amount dwpc = checkAndConvertInputAmountToExpectedUnits(dwpf, SI.CELSIUS); - Amount vapr = prVapr( dwpc ); - if ( !checkNullOrInvalidValue( vapr ) ) - return new Amount ( Unit.ONE); - - prhmtr = tmpf.doubleValue() + (vapr.doubleValue() - 21 ); - - return ( new Amount ( prhmtr, Unit.ONE)); - } - - /** - * Computes the rate of ice accretion/growth of ice - * on a vessel in salt water, in units of inches per 3 hours (the WMO standard) - * The formula used is - * IGRO = ( A*pr + B*pr*pr + *pr*pr*pr ) * CVFAC - * where - * A = 2.73 * 10e-2 - * B = 2.91 * 10e-4 - * C = 1.84 * 10e-6 - * pr = ( sped * ( -1.7 - tmpc ) ) / ( 1 + 0.4 * ( sstc + 1.7 ) ) - * (priesendorfer regression) - * and - * CVFAC = 1.1811, to convert cm/hr to in/3hr. - * - * @param tmpc - the observed surface air temperature in Celsius - * @param sstc - the observed surface sea temperature in Celsius - * @param sped - the observed wind speed - * @return the rate of ice growth if all the input values are valid and lie between specific limits - * and if the rate of ice growth that is computed is greater than or equal to 0, - * @throws NullPointerException - * - * @throws InvalidRangeException - */ - public static final Amount prIgro ( Amount tmpc, Amount sstc, Amount sped) throws InvalidValueException, NullPointerException{ - //System.out.println("From prIgro:"); - //System.out.println(" tmpc = " + tmpc.doubleValue()); - //System.out.println(" sstc = " + sstc.doubleValue()); - //System.out.println(" sped = " + sped.doubleValue()); - - double prigro = GempakConstants.RMISSD; -// checkNullOrInvalidValue( tmpc ) ; -// checkNullOrInvalidValue( sstc ) ; -// checkNullOrInvalidValue( sped ) ; - - if ( !checkNullOrInvalidValue( tmpc ) || !checkNullOrInvalidValue( sstc ) - || !checkNullOrInvalidValue( sped )) - return new Amount ( NcUnits.INCHES_PER_THREE_HOURS ); - - checkAndConvertInputAmountToExpectedUnits( tmpc, SI.CELSIUS ); - checkAndConvertInputAmountToExpectedUnits( sstc, SI.CELSIUS ); - - //TODO: verify that wind speed can have any unit - double tmpcVal = tmpc.doubleValue(); - double sstcVal = sstc.doubleValue(); - double spedVal = sped.doubleValue(); - - /* Check that these values are within the valid range */ - - if ( spedVal < 0 || spedVal > 50){ -// throw new InvalidRangeException("The wind speed must lie between 0 and 50. Both limits inclusive"); - System.out.println("The wind speed must lie between 0 and 50. Both limits inclusive"); - return new Amount ( NcUnits.INCHES_PER_THREE_HOURS ); - } - if ( tmpcVal < -20 || tmpcVal > 0 ){ -// throw new InvalidRangeException("The observed surface air temperature must lie between -20 and 0. Both limits inclusive"); - System.out.println("The observed surface air temperature must lie between -20 and 0. Both limits inclusive"); - return new Amount ( NcUnits.INCHES_PER_THREE_HOURS ); - } - if ( sstcVal < -1.7f || sstcVal > 12 ){ -// throw new InvalidRangeException("The observed surface sea temperature must lie between -1.7 and 12. Both limits inclusive"); - } - double A = 0.0273f; - double B = 0.000291f; - double C = 0.00000184f; - double cvfac = 1.1811f; // to convert cm/hr to in per 3 hours - double pr = ( ( spedVal * ( -1.7 - tmpcVal ) ) / ( 1 + 0.4 * ( sstcVal + 1.7 ) ) ); // Compute the Priesendorfer regression - double pr2 = pr * pr; - prigro = ( A * pr + B * pr2 + C * pr * pr2 ) * cvfac; - if ( prigro < 0 ){ -// throw new InvalidRangeException("The rate of ice growth must be greater than or equal to 0"); - System.out.println("The rate of ice growth must be greater than or equal to 0"); - return new Amount ( NcUnits.INCHES_PER_THREE_HOURS ); - } - return ( new Amount ( prigro, NcUnits.INCHES_PER_THREE_HOURS ) ); - } - - /** - * Computes the latent heat of vaporization at constant pressure - * from the input temperature (in Celsius) using the equation: - * LHVP = ( 2.500 - .00237 * TMPC ) * 10E6 - * LHVP is in J/kg. - * @param tmpc - the input temperature (in Celsius) - * @return the latent heat of vaporization at constant pressure if - * the input temperature is valid - * @throws NullPointerException - * - */ - public static final Amount prLhvp( Amount tmpc) throws InvalidValueException, NullPointerException{ - - //System.out.println("From prLhvp:"); - //System.out.println(" tmpc = " + tmpc.doubleValue()); - -// checkNullOrInvalidValue(tmpc); - if ( !checkNullOrInvalidValue( tmpc ) ) - return new Amount ( NcUnits.JOULES_PER_KILOGRAM ); - - tmpc = checkAndConvertInputAmountToExpectedUnits(tmpc, SI.CELSIUS); - double latentHeatOfVapr = ( float) ( (2.500 - 0.00237 * tmpc.doubleValue()) * 1000000); - return ( new Amount ( latentHeatOfVapr, NcUnits.JOULES_PER_KILOGRAM ) ); - } - - /** - * Computes the temperature of a parcel lifted (or sunk) - * adiabatically to a given pressure. - * @param thta - Potential temperature in Kelvin - * @param thte - Equivalent potential temp in Kelvin - * @param pres - Lifted pressure in millibar - * @return the lifted temperature in Celsius, if all the input parameters are valid - * @throws NullPointerException - * - * @throws InvalidRangeException - */ - public static final Amount prLtmp ( Amount thta, Amount thte, Amount pres ) throws InvalidValueException, NullPointerException{ - //System.out.println("From prLtmp:"); - //System.out.println(" thta = " + thta.doubleValue()); - //System.out.println(" thte = " + thte.doubleValue()); - //System.out.println(" pres = " + pres.doubleValue()); - - double prltmp = GempakConstants.RMISSD; -// checkNullOrInvalidValue(thta); -// checkNullOrInvalidValue(thte); -// checkNullOrInvalidValue(pres); - - if ( !checkNullOrInvalidValue( thta ) || !checkNullOrInvalidValue( thte ) - || !checkNullOrInvalidValue( pres )) - return new Amount ( SI.CELSIUS ); - - thta = checkAndConvertInputAmountToExpectedUnits(thta, SI.KELVIN); - thte = checkAndConvertInputAmountToExpectedUnits(thte, SI.KELVIN); - - if ( pres.doubleValue() <= 0 ) - pres = new Amount ( 500, NcUnits.MILLIBAR ); - - /*Compute parcel temperatures on moist and dry adiabats*/ - Amount tmpe = prTmst ( thte, pres, new Amount (0, SI.KELVIN )); - Amount tmpd = prTmpk ( pres, thta); - checkNullOrInvalidValue(tmpe); - checkNullOrInvalidValue(tmpd); - /* - * ( Non-Javadoc ) - * The correct parcel temperature is the warmer of the - * temperature on the dry adiabat and the temperature on the - * moist adiabat. - */ - - double tmpeVal = tmpe.doubleValue(); - double tmpdVal = tmpd.doubleValue(); - if ( tmpeVal > tmpdVal ){ - prltmp = SI.KELVIN.getConverterTo(SI.CELSIUS).convert( tmpeVal ); - }else{ - prltmp = SI.KELVIN.getConverterTo(SI.CELSIUS).convert( tmpdVal ); - } - - return ( new Amount ( prltmp, SI.CELSIUS )); - } - - /** - * Computes the mountain obscuration threshold met indicator - * @param cmsl - Ceiling converted to MSL in 100's of ft - * @param otval - Mountain obscuration threshold in 100's of ft - * @return The mountain obscuration threshold met indicator if - * the input values are valid - * @throws NullPointerException - * - */ - public static final Amount prMobs ( Amount cmsl, Amount otval) throws InvalidValueException, NullPointerException{ - //System.out.println("From prMobs:"); - //System.out.println(" cmsl = " + cmsl.doubleValue()); - //System.out.println(" otval = " + otval.doubleValue()); - -// checkNullOrInvalidValue( cmsl ); -// checkNullOrInvalidValue( otval ); - - if ( !checkNullOrInvalidValue( cmsl ) || !checkNullOrInvalidValue( otval ) ) - return new Amount ( Unit.ONE ); - - cmsl = checkAndConvertInputAmountToExpectedUnits( cmsl, NcUnits.HUNDREDS_OF_FEET ); - otval = checkAndConvertInputAmountToExpectedUnits( otval, NcUnits.HUNDREDS_OF_FEET ); - return ( cmsl.doubleValue() < otval.doubleValue() ? new Amount ( 1, Unit.ONE) : new Amount ( 1, Unit.ONE) ); - } - - /** - * Computes the mixing ratio in grams/kilograms from the dewpoint ( in Celsius ) - * and the pressure ( in mb) using the equation: - * MIXR = .62197 * ( e / ( PRES - e ) ) * 1000. - * where - * e = VAPR * corr - * corr = (1.001 + ( ( PRES - 100. ) / 900. ) * .0034) - * ( University of Wisconsin green sheet ). - * This method can also be used for the folloiwng computations: - * MIXS from TMPC and PRES - * SMXR from DWPC and PALT - * SMXS from TMPC and PALT - * - * @param dwpc - the dewpoint ( in Celsius ) - * @param pres - the pressure ( in mb) - * @return the missing ratio ( in grams / kilograms ) if both the input - * parameters are valid - * @throws NullPointerException - * - */ - public static final Amount prMixr ( Amount dwpc, Amount pres ) { - //System.out.println("From prMixr:"); - //System.out.println(" dwpc = " + dwpc.doubleValue()); - //System.out.println(" pres = " + pres.doubleValue()); - - Amount prmixr = new Amount ( -9999.0, Unit.ONE); -// checkNullOrInvalidValue(pres); -// checkNullOrInvalidValue(dwpc); - - if ( !checkNullOrInvalidValue( pres ) || !checkNullOrInvalidValue( dwpc ) ) - return new Amount ( NcUnits.GRAMS_PER_KILOGRAM ); - - pres = checkAndConvertInputAmountToExpectedUnits(pres, NcUnits.MILLIBAR); - dwpc = checkAndConvertInputAmountToExpectedUnits(dwpc, SI.CELSIUS); - - /*Calculate vapor pressure*/ - Amount vapr = prVapr ( dwpc ); - - if ( !checkNullOrInvalidValue(vapr) ) - return new Amount ( NcUnits.GRAMS_PER_KILOGRAM ); - - vapr = checkAndConvertInputAmountToExpectedUnits(vapr, NcUnits.MILLIBAR); - double pressureValue = pres.doubleValue(); - double vaporPressureValue = vapr.doubleValue(); - /* - * (Non-Javadoc) - * corr is a correction to the vapor pressure since the atmosphere is not an ideal gas. - */ - double corr = ( double ) (1.001 + ( ( pressureValue - 100 ) / 900 ) * 0.0034 ); - double e = corr * vaporPressureValue; - - /* - * Test for unphysical case of large E at low PRES - */ - if ( e <= ( 0.5 * pressureValue ) ){ - /*Calculate mixing ratio */ - prmixr = new Amount ( ( double ) ( 0.62197 * ( e / ( pressureValue - e ) ) * 1000 ) , NcUnits.GRAMS_PER_KILOGRAM ); - } - return prmixr; - } - - /** - * Extracts the pressure change ( in millibars ) from - * the pressure tendency information - * @param p03d - Pressure tendency information - * @return the pressure change ( in mb ) - * @throws NullPointerException - * - */ - //TODO : remove it to make it a part of display options or let it stay? - public static final Amount prP03c( Amount p03d) throws InvalidValueException, NullPointerException{ - //System.out.println("From prP03c:"); - //System.out.println(" p03d = " + p03d.doubleValue()); - - - double prp03c = GempakConstants.RMISSD; -// checkNullOrInvalidValue( p03d ); - if ( !checkNullOrInvalidValue( p03d ) ) - return new Amount ( NcUnits.MILLIBAR ); - - double p03dVal = p03d.doubleValue(); - float[] psign = {1, 1, 1, 1, 0, -1, -1, -1, -1}; - int itendc = ( int ) ( p03dVal / 1000); - float ptend = ( float ) ( ( ( int ) p03dVal ) % 1000 ) / 10f; - // TODO: compare tests with legacy - if ( itendc < psign.length ) - prp03c = psign[itendc] * ptend; - - return ( new Amount ( prp03c , NcUnits.MILLIBAR ) ); - } - - - /** - * Computes station pressure from altimeter and station elevation using - * the equation - * PALT = ALTM * ( 1 - ( SELK * GAMUSD / To ) ) ** expo - * where - * SELK = SELV / 1000 - * To = US Std. Atmos. sea level temp in Kelvin - * = TMCK + 15 - * expo = GRAVTY / ( GAMUSD * RDGAS ) * 1000 - * Wallace and Hobbs. - * - * @param altm - Altimeter in millibars - * @param selv - Station elevation in meters - * @return the pressure in millibars if none of the input values are missing - * @throws NullPointerException - * - */ - public static final Amount prPalt ( Amount altm, Amount selv) throws InvalidValueException, NullPointerException{ - //System.out.println("From prPalt:"); - //System.out.println(" altm = " + altm.doubleValue()); - //System.out.println(" selv = " + selv.doubleValue()); - - // checkNullOrInvalidValue( altm ); -// checkNullOrInvalidValue( selv ); - - if ( !checkNullOrInvalidValue( altm ) || !checkNullOrInvalidValue( selv ) ) - return new Amount ( NcUnits.MILLIBAR ); - - altm = checkAndConvertInputAmountToExpectedUnits( altm, NcUnits.MILLIBAR ); - selv = checkAndConvertInputAmountToExpectedUnits( selv, SI.METER ); - double hgtk = selv.getUnit().getConverterTo( SI.KILOMETER ).convert( selv.doubleValue() ); - - /*Calculate the exponent*/ - double expo = ( GempakConstants.GRAVTY / ( GempakConstants.GAMUSD * GempakConstants.RDGAS ) * 1000.0f); - - /*Calculate pressure*/ - double prpalt = ( altm.doubleValue() * Math.pow( ( 1 - ( hgtk * GempakConstants.GAMUSD/ ( GempakConstants.TMCK + 15 ) ) ) , expo ) ); - - return ( new Amount ( prpalt, NcUnits.MILLIBAR ) ); - } - - /** - * Computes the lifted condensation level pressure ( in mb ) for a parcel of air - * from TMPC, PRES, and TLCL. TLCL may be computed using PR_TLCL. The equation - * used is a modified Poisson equation: - * PLCL = PRES * ( TLCL / TMPK ) ** ( 1 / RKAPPA ) - * @param tmpc - Temperature ( in Celsius ) before lifting the air parcel - * @param pres - Pressure ( in mb ) before lifting the air parcel - * @param tlcl - Temperature ( in Kelvin ) at the lifted condensation level - * @return the pressure at the lifted condensation level, if all the inputs are valid - * @throws NullPointerException - * - */ - public static final Amount prPlcl ( Amount tmpc, Amount pres, Amount tlcl) throws InvalidValueException, NullPointerException{ - double prplcl = GempakConstants.RMISSD; - //System.out.println("From prPlcl:"); - //System.out.println(" tmpc = " + tmpc.doubleValue()); - //System.out.println(" pres = " + pres.doubleValue()); - //System.out.println(" tlcl = " + tlcl.doubleValue()); - -// checkNullOrInvalidValue(tmpc); -// checkNullOrInvalidValue(pres); -// checkNullOrInvalidValue(tlcl); - if ( !checkNullOrInvalidValue( tmpc ) || !checkNullOrInvalidValue( pres ) - || !checkNullOrInvalidValue( tlcl )) - return new Amount ( NcUnits.MILLIBAR ); - - tmpc = checkAndConvertInputAmountToExpectedUnits(tmpc, SI.CELSIUS); - pres = checkAndConvertInputAmountToExpectedUnits(pres, NcUnits.MILLIBAR); - tlcl = checkAndConvertInputAmountToExpectedUnits(tlcl, SI.KELVIN); - Amount tmpk = checkAndConvertInputAmountToExpectedUnits(tmpc, SI.KELVIN) ; - double tclValue = tlcl.doubleValue(); - double tmpkValue = tmpk.doubleValue(); - double presValue = pres.doubleValue(); - prplcl = ( double ) ( presValue * Math.pow( ( tclValue / tmpkValue ) , ( 1 / GempakConstants.RKAPPA ) ) ); - return new Amount ( prplcl, NcUnits.MILLIBAR ); - } - - /** - *
-	 *  Computes the mean sea level pressure ( in mb ) from the station pressure ( in mb ),
-	 *  the temperature ( in deg Celsius), the dewpoint ( in deg Celsius ) and 
-	 *  the station elevation ( in meters ) using the equation:
-	 *  	PMSL = PRES * EXP ( ( GRAVTY * SELV ) / ( RDGAS * TVAVE ) ) 
-	 *     where
-	 *     		 TVAVE = avg virtual temp between station and sea level 
-	 *     		        = TVRK + ( DELTV / 2 )
-	 *     		 DELTV = GAMUSD * SELV / 1000
-	 *  Wallace and Hobbs.
-	 * @param pres - the station pressure ( in mb )
-	 * @param tmpc - the temperature ( in deg Celsius)
-	 * @param dwpc - the dewpoint ( in deg Celsius )
-	 * @param selv - the station elevation ( in meters )
-	 * @return the mean sea level pressure ( in mb ) if all the inputs are valid
      * 
- * @throws NullPointerException - * - * @throws InvalidRangeException - */ - public static final Amount prPmsl ( Amount pres, Amount tmpc, Amount dwpc, Amount selv ) throws InvalidValueException, NullPointerException{ - //System.out.println("From prPmsl:"); - //System.out.println(" tmpc = " + tmpc.doubleValue()); - //System.out.println(" pres = " + pres.doubleValue()); - //System.out.println(" dwpc = " + dwpc.doubleValue()); - //System.out.println(" selv = " + selv.doubleValue()); -// checkNullOrInvalidValue( pres ); -// checkNullOrInvalidValue( tmpc ); -// checkNullOrInvalidValue( dwpc ); -// checkNullOrInvalidValue( selv ); - if ( !checkNullOrInvalidValue( tmpc ) - || !checkNullOrInvalidValue( pres ) - || !checkNullOrInvalidValue( dwpc ) - || !checkNullOrInvalidValue( selv ) ) - return new Amount ( NcUnits.MILLIBAR ); - - pres = checkAndConvertInputAmountToExpectedUnits(pres, NcUnits.MILLIBAR); - tmpc = checkAndConvertInputAmountToExpectedUnits(pres, SI.CELSIUS); - dwpc = checkAndConvertInputAmountToExpectedUnits(pres, SI.CELSIUS); - selv = checkAndConvertInputAmountToExpectedUnits(pres, SI.METER); - - /*Calculate virtual temperature*/ - Amount tv = prTvrk ( tmpc, dwpc, pres); - - /*deltaV and tVave*/ - double selvVal = selv.doubleValue(); - double deltaV = selvVal * GempakConstants.GAMUSD / 1000; - double tVave = tv.doubleValue() + ( deltaV / 2); - double mathFormula = ( GempakConstants.GRAVTY * selvVal ) / ( GempakConstants.RDGAS * tVave ); - double prpmsl = ( pres.doubleValue() * Math.exp(mathFormula)); - - return ( new Amount ( prpmsl, NcUnits.MILLIBAR ) ); - } - - /** - * Computes the maximum precipitation amount for upto 4 preciptiation values in inches - * @param p01 - First precipitation amount - * @param p02 - Second precipitation amount - * @param p03 - Third precipitation amount - * @param p04 - Fourth precipitation amount - * @return the maximum precipitation - * @throws NullPointerException - * - */ - - public static final Amount prPr6x ( Amount p01, Amount p02, Amount p03, Amount p04 ) throws InvalidValueException, NullPointerException{ - //System.out.println("From prPr6x:"); - //System.out.println(" p01 = " + p01.doubleValue()); - //System.out.println(" p02 = " + p02.doubleValue()); - //System.out.println(" p03 = " + p03.doubleValue()); - //System.out.println(" p04 = " + p04.doubleValue()); - Amount[] tempArray = {p01, p02, p03, p04 }; - int index = 0; - double[] tempDblArray = new double[ 4 ]; - for ( Amount thisAmount : tempArray){ - if (!checkNullOrInvalidValue(thisAmount)){ - return new Amount ( NonSI.INCH ); - } - - if ( thisAmount.getUnit() != NonSI.INCH ) { - thisAmount = checkAndConvertInputAmountToExpectedUnits(thisAmount, NonSI.INCH); - tempArray[index] = thisAmount; - } - tempDblArray[ index ] = thisAmount.doubleValue(); - index++; - } - - Arrays.sort(tempDblArray); - return ( new Amount ( tempDblArray[ 3 ], NonSI.INCH ) ); - } - - /** - * Computes PR24, the 24-hour precipitation calculated by - * summing four 6-hour precipitation values - * @param p01 - First 6-hour precipitation amount - * @param p02 - Second 6-hour precipitation amount - * @param p03 - Third 6-hour precipitation amount - * @param p04 - Fourth 6-hour precipitation amount - * @return the total 24-hour precipitation amount - * @throws InvalidRangeException - * @throws NullPointerException - * - */ - public static final Amount prPr24 ( Amount p01, Amount p02, Amount p03, Amount p04 ) throws InvalidValueException, NullPointerException{ - //System.out.println("From prPr24:"); - //System.out.println(" p01 = " + p01.doubleValue()); - //System.out.println(" p02 = " + p02.doubleValue()); - //System.out.println(" p03 = " + p03.doubleValue()); - //System.out.println(" p04 = " + p04.doubleValue()); - -// checkNullOrInvalidValue( p01 ); -// checkNullOrInvalidValue( p02 ); -// checkNullOrInvalidValue( p03 ); -// checkNullOrInvalidValue( p04 ); - - if ( !checkNullOrInvalidValue( p01 ) - || !checkNullOrInvalidValue( p02 ) - || !checkNullOrInvalidValue( p03 ) - || !checkNullOrInvalidValue( p04 ) ) - return new Amount ( NonSI.INCH ); - - Amount[] tempArray = {p01, p02, p03, p04 }; - Arrays.sort(tempArray); - - Amount p24 = tempArray[3]; - double p01Val = p01.doubleValue(); - double p02Val = p02.doubleValue(); - double p03Val = p03.doubleValue(); - double p04Val = p04.doubleValue(); - double p24Val = p24.doubleValue(); - - if ( p24Val > 0 ){ - p24Val = 0; - if ( p01Val > 0 ) - p24Val += p01Val; - - if ( p02Val > 0 ) - p24Val += p01Val; - - if ( p03Val > 0 ) - p24Val += p01Val; - - if ( p04Val > 0 ) - p24Val += p01Val; - - } - - if ( p24Val < 0 ){ -// throw new InvalidRangeException("From prPr24: the total 24 hour precipitation amount cannot be less than 0 inches"); - System.out.println("From prPr24: the total 24 hour precipitation amount cannot be less than 0 inches"); - return new Amount ( NonSI.INCH ); - } - return ( new Amount ( p24Val, NonSI.INCH ) ); - } - - /** - * Computes the station pressure ( in mb ) from the temperature ( in deg Celsius ) - * and the potential temperature ( in Kelvin ) using Poisson's equation: - * PRES = 1000. * ( PR_TMCK (TMPC) / THTA ) ** (1 / RKAPPA) - * @param tmpc - temperature (in deg Celsius) - * @param thta - potential temperature ( in Kelvin ) - * @return the station pressure ( in mb ) if both the inputs are valid - * @throws NullPointerException * - * @throws InvalidRangeException + * @param t12n + * - 6-hour minimum temperature at 12Z, deg Celsius + * @param t18n + * - 6-hour minimum temperature at 18Z, deg Celsius + * @return the minimum temperature (in Farenheit) after comparing the two + * input values, if they exist + * @throws NullPointerException + * */ - public static final Amount prPres ( Amount tmpc, Amount thta ) throws InvalidValueException, NullPointerException{ - //System.out.println("From prPres:"); - //System.out.println(" tmpc = " + tmpc.doubleValue()); - //System.out.println(" thta = " + thta.doubleValue()); + public static final Amount prDmin(Amount t12n, Amount t18n) + throws InvalidValueException, NullPointerException { + // System.out.println("From prDmin:"); + // System.out.println(" t12n = " + t12n.doubleValue()); + // System.out.println(" t18n = " + t18n.doubleValue()); + // checkNullOrInvalidValue( t12n ); + // checkNullOrInvalidValue( t18n ); + if (!checkNullOrInvalidValue(t12n) || !checkNullOrInvalidValue(t18n)) + return new Amount(NonSI.FAHRENHEIT); - -// checkNullOrInvalidValue( tmpc ); -// checkNullOrInvalidValue( thta ); - - if ( !checkNullOrInvalidValue( tmpc ) - || !checkNullOrInvalidValue( thta ) ) - return new Amount ( NcUnits.MILLIBAR ); - - tmpc = checkAndConvertInputAmountToExpectedUnits( tmpc, SI.CELSIUS ); - thta = checkAndConvertInputAmountToExpectedUnits( thta, SI.KELVIN ); - double tmpcVal = tmpc.doubleValue(); - double thtaVal = thta.doubleValue(); - if ( tmpcVal <= -GempakConstants.TMCK ){ - // throw new InvalidRangeException("From prPres: the temperature must be greater than -273.15"); - System.out.println("From prPres: the temperature must be greater than -273.15"); - return new Amount ( NcUnits.MILLIBAR ); - } - if ( thtaVal <= 0 ){ -// throw new InvalidRangeException("From prPres: the potential temperature must be greater than 0"); - System.out.println("From prPres: the potential temperature must be greater than 0"); - return new Amount ( NcUnits.MILLIBAR ); - } - double tmpkVal = tmpc.getUnit().getConverterTo( SI.KELVIN ).convert( tmpcVal ); - double prpres = ( float ) ( 1000 * Math.pow(tmpkVal / thtaVal, 1 / GempakConstants.RKAPPA ) ); + t12n = checkAndConvertInputAmountToExpectedUnits(t12n, SI.CELSIUS); + t18n = checkAndConvertInputAmountToExpectedUnits(t18n, SI.CELSIUS); + Amount minValue = (t12n.doubleValue() < t18n.doubleValue() ? t12n + : t18n); + return (checkAndConvertInputAmountToExpectedUnits(minValue, + NonSI.FAHRENHEIT)); - return ( new Amount ( prpres , NcUnits.MILLIBAR ) ); - } - - - /** - * Extracts the symbol code from the pressure tendency information. - * The code number is returned follow by 999 so that the output is a 4-digit number. - * @param p03d - the pressure tendency information - * @return the pressure tendency symbol code if the input is valid - * @throws NullPointerException - * - */ - //TODO add it to the Met Parameters or remove it and make it part of the display options instead? - public static final Amount prPtsy ( Amount p03d ) throws InvalidValueException, NullPointerException{ - //System.out.println("From prPtsy:"); - //System.out.println(" p03d = " + p03d.doubleValue()); - - if ( !checkNullOrInvalidValue( p03d )) - return new Amount ( Unit.ONE); - - double p03dVal = p03d.doubleValue(); - int prptsy = -9999; - if ( !( p03dVal < 0 ) & !( p03dVal >= 9000 ) ) { - prptsy = ( ( int ) ( p03dVal / 1000 ) ) * 1000 + 999 ; - } - return ( new Amount ( prptsy, Unit.ONE ) ); - } - -/** - * Computes the relative humidity ( in percent ) from the input temperature and dewpoint using - * the equation: - * RELH = VAPR / VAPS * 100 - * where - * VAPR = vapor pressure - * = PR_VAPR ( DWPC ) - * VAPS = saturation vapor pressure - * = PR_VAPR ( TMPC ) - * - * @param tmpc - temperature ( in Celsius ) - * @param dwpc - dewpoint ( in Celsius) - * @return the relative humidity ( in percent ) if both inputs are valid and RMISSD ( -9999.0 ) otherwise - * @throws NullPointerException - * - */ -public static final Amount prRelh ( Amount tmpc, Amount dwpc ) throws InvalidValueException, NullPointerException{ - //System.out.println("From prRelh:"); - //System.out.println(" tmpc = " + tmpc.doubleValue()); - //System.out.println(" dwpc = " + dwpc.doubleValue()); - - double prrelh = GempakConstants.RMISSD; -// checkNullOrInvalidValue(tmpc); -// checkNullOrInvalidValue(dwpc); - - if ( !checkNullOrInvalidValue( tmpc ) - || !checkNullOrInvalidValue( dwpc ) ) - return new Amount (NonSI.PERCENT ); - - tmpc = checkAndConvertInputAmountToExpectedUnits(tmpc, SI.CELSIUS); - dwpc = checkAndConvertInputAmountToExpectedUnits(dwpc, SI.CELSIUS); - - /* Find the vapor pressure */ - Amount e = prVapr ( dwpc ); - - if ( !checkNullOrInvalidValue( e ) ) - return new Amount ( NonSI.PERCENT ); - - /*Find the saturated vapor pressure*/ - Amount es = prVapr ( tmpc ); - - if ( !checkNullOrInvalidValue( es ) ) - return new Amount ( NonSI.PERCENT ); - - /*Calculate humidity*/ - prrelh = ( e.doubleValue()/es.doubleValue()) * 100; - - return new Amount(prrelh,NonSI.PERCENT); -} - - /** - * Computes the dewpoint (in Celsius) from the temperature ( in Celsius ) - * and the relative humidity ( in percent ). - * @param tmpc - the temperature ( in deg Celsius ) - * @param relh - the relative humidity ( in percent ) - * @return the dewpoint in ( deg Celsius), if both inputs are valid and the value of the vapor - * pressure computed is greater than ( 1* e^(-30)) - * @throws InvalidRangeException - * @throws NullPointerException - * - */ - public static final Amount prRhdp ( Amount tmpc, Amount relh) throws InvalidValueException, NullPointerException{ - //System.out.println("From prRhdp:"); - //System.out.println(" tmpc =" + tmpc.doubleValue()); - //System.out.println(" relh = " + relh.doubleValue()); - -// checkNullOrInvalidValue(tmpc); -// checkNullOrInvalidValue(relh); - - if ( !checkNullOrInvalidValue( tmpc ) - || !checkNullOrInvalidValue( relh ) ) - return new Amount ( SI.CELSIUS ); - - tmpc = checkAndConvertInputAmountToExpectedUnits(tmpc, SI.CELSIUS); - relh = checkAndConvertInputAmountToExpectedUnits(relh, NonSI.PERCENT); - - /*Calculate saturation vapor pressure; test for existence*/ - Amount vaps = prVapr ( tmpc); - - if ( !checkNullOrInvalidValue(vaps) ) - return new Amount ( SI.CELSIUS ); - - /*Calculate vapor pressure*/ - double relativeHumidity = relh.doubleValue(); - double saturationVaporPressure = vaps.doubleValue(); - double vapr = relativeHumidity * saturationVaporPressure / 100; - - /*Calculate dewpoint. The VAPR test prevents LOG blowups*/ - double prrhdp = -191; - Amount dewpointAmount = null; - if ( vapr >= ( Math.pow(Math.E, -30) ) ){//legacy checks for 1.E-30 - prrhdp = ( double) ( 243.5 * ( Math.log(6.112) - Math.log(vapr) ) / ( Math.log(vapr) - Math.log(6.112) - 17.67 ) ); - - /* If the dew-point is less than -190 degrees C, it is treated as missing data - * Note: Legacy documents it but does not implement it. - * However, in CAVE, it was decided to implement it. - * */ - - if ( prrhdp < -190 ){ - System.out.println(" From prRhdp: dewpoint is less than -190 C"); - return new Amount( SI.CELSIUS ); - } - } - dewpointAmount = new Amount(prrhdp, SI.CELSIUS); - return dewpointAmount; - } - - - public static class RZLL //implements ISerializableObject - { - // @DynamicSerializeElement - private static RZLL rzll; - - /**Station latitude in degrees*/ - // @DynamicSerializeElement - Amount stltdg = null; - - /**Station longitude in degrees*/ - // @DynamicSerializeElement - Amount stlndg = null; - - /**Range in kilometers*/ - // @DynamicSerializeElement - Amount range = null; - - /**Geographic azimuth in radians*/ - // @DynamicSerializeElement - Amount azim = null; - - /**Height above the ground in kilometers*/ - // @DynamicSerializeElement - Amount hght = null; - - /**Latitude in degrees*/ - // @DynamicSerializeElement - Amount xlat = null; - - /**Longitude in degrees*/ - // @DynamicSerializeElement - Amount xlon = null; - - /** - * @return the xlat - */ - public Amount getXlat() { - return xlat; - } - /** - * @return the xlon - */ - public Amount getXlon() { - return xlon; - } - - - - private static RZLL getInstance(){ - if (rzll == null) - {rzll = new RZLL();} - return rzll; - } - - /** - * Computes the actual latitude/longitude given the station latitude/longitude, elevation - * and azimuth. - * It uses equations developed for use in the AOIPS radar. - * @param instltdg - Station latitude in degrees - * @param instlndg - Station longitude in degrees - * @param inrange - Range in kilometers - * @param inazim - Geographic azimuth in radians - * @param inhght - Height above ground in km - * @throws NullPointerException - * - */ - public void prRzll ( Amount instltdg,Amount instlndg,Amount inrange,Amount inazim,Amount inhght) throws InvalidValueException, NullPointerException{ - //System.out.println("From prRzll:"); - //System.out.println(" instltdg = " + instltdg.doubleValue()); - //System.out.println(" instlndg = " + instlndg.doubleValue()); - //System.out.println(" inrange = " + inrange.doubleValue()); - //System.out.println(" inazim = " + inazim.doubleValue()); - //System.out.println(" inhght = " + inhght.doubleValue()); - -// checkNullOrInvalidValue( instltdg ); -// checkNullOrInvalidValue( instlndg ); -// checkNullOrInvalidValue(inrange); -// checkNullOrInvalidValue(inazim); -// checkNullOrInvalidValue(inhght); - - if ( !checkNullOrInvalidValue( instltdg ) - || !checkNullOrInvalidValue( instlndg ) - || !checkNullOrInvalidValue( inrange ) - || !checkNullOrInvalidValue( inazim ) - || !checkNullOrInvalidValue( inhght )) - return; - - instltdg = checkAndConvertInputAmountToExpectedUnits( instltdg, NonSI.DEGREE_ANGLE ); - instlndg = checkAndConvertInputAmountToExpectedUnits( instlndg, NonSI.DEGREE_ANGLE ); - inrange = checkAndConvertInputAmountToExpectedUnits(inrange, SI.KILOMETER ); - inazim = checkAndConvertInputAmountToExpectedUnits(inazim, SI.RADIAN ); - inhght = checkAndConvertInputAmountToExpectedUnits(inhght, SI.KILOMETER ); - - this.stltdg = new Amount ( instltdg.doubleValue(), NonSI.DEGREE_ANGLE ); - this.stlndg = new Amount ( instlndg.doubleValue(), NonSI.DEGREE_ANGLE ); - this.range = new Amount ( inrange.doubleValue(), SI.KILOMETER ); - this.azim = new Amount ( inazim.doubleValue(), SI.RADIAN ); - this.hght = new Amount ( inhght.doubleValue(), SI.KILOMETER ); - - double hdr = GempakConstants.RMISSD; - double elev = GempakConstants.RMISSD; - double rad = GempakConstants.RMISSD; - double radp= GempakConstants.RMISSD; - - /*Convert the station lat/lon to radians*/ - Amount stlat = checkAndConvertInputAmountToExpectedUnits( stltdg, NonSI.DEGREE_ANGLE ); - Amount stlon = checkAndConvertInputAmountToExpectedUnits( stlndg, NonSI.DEGREE_ANGLE ); - - - /*Get the elevation angle*/ - hdr = ( range.doubleValue() == 0.0f ? 0.0f : hght.doubleValue() / range.doubleValue() ); -// elev = (float) ( Math.abs(hdr) < 1.0f ? Math.asin(hdr) : 0.0f ); - elev = ( Math.abs(hdr) <= 1.0f ? Math.asin(hdr) : 0.0f ); - - double temp = (Math.pow( Math.sin(stlat.doubleValue()), 2 ) ) ; - - /*Get the earth's corrected radius*/ - rad = (6378.4 / Math.sqrt( 1 + ( 0.00677 * temp ) )); - radp = 4* ( rad / 3 ); - - double dist = GempakConstants.RMISSD; - double cx = GempakConstants.RMISSD; - double cy = GempakConstants.RMISSD; - double mathFormula1 = GempakConstants.RMISSD; - double mathFormula2 = GempakConstants.RMISSD; - - /*Calculate the distance*/ - double rangeVal = range.doubleValue(); - if ( elev > 0.2618f ) - dist = ( double ) ( rangeVal * Math.cos( elev )); - else{ - mathFormula1 = ( double ) ( (1 - ( Math.pow( elev, 2 ) / 2 ) ) - rangeVal * elev / radp); - dist = rangeVal * mathFormula1; - } - - /*Calculate the latitude and longitude*/ - double azimVal = azim.doubleValue(); - cx = ( double ) ( dist * Math.sin( azimVal ) ); - cy = ( double ) ( dist * Math.cos( azimVal ) ); - -// mathFormula2 = ( float ) ( ( ( 2 * Math.pow( rad, 2 ) ) * Math.tan( stlat ) )); -// xlat = ( float ) ( stlat + ( cy / rad ) - ( Math.pow(cx, 2) / mathFormula2 ) ); - double stlatVal = stlat.doubleValue(); - mathFormula2 = (double) ( ( Math.pow(cx, 2) / ( 2 * Math.pow( rad, 2 ) ) * Math.tan( stlatVal ) )); - double xlatVal = ( double ) ( stlatVal + ( cy / rad ) - mathFormula2 ); - double xlonVal = ( double ) ( stlon.doubleValue() + ( cx / ( rad * Math.cos( xlat.doubleValue() ) ) ) ) ; - - /*Change lat/lon to degrees*/ - xlatVal = SI.RADIAN.getConverterTo(NonSI.DEGREE_ANGLE).convert( xlatVal ); - xlonVal = SI.RADIAN.getConverterTo(NonSI.DEGREE_ANGLE).convert( xlonVal ); - - this.xlat = new Amount ( xlatVal, NonSI.DEGREE_ANGLE ); - this.xlon = new Amount ( xlonVal, NonSI.DEGREE_ANGLE ); - } - } - - - /** - * Computes the wind speed from the 'U' and 'V' components of - * the wind velocity. The formula is the square root of ( u^2 + v^2 ) - * - * @param uWnd - U component of velocity - * @param vWnd - V component of velocity - * @return the computed windspeed if both inputs are valid - * @throws NullPointerException - * - */ - public static final Amount prSped ( Amount uWnd, Amount vWnd) throws InvalidValueException, NullPointerException{ - //System.out.println("From prSped:"); - //System.out.println(" uWnd = " +uWnd.doubleValue()); - //System.out.println(" vWnd = " + vWnd.doubleValue()); - -// checkNullOrInvalidValue( uWnd ); -// checkNullOrInvalidValue( vWnd ); - if ( !checkNullOrInvalidValue( uWnd ) - || !checkNullOrInvalidValue( vWnd ) ) - return new Amount ( uWnd.getUnit() ); - - Unit uWndUnits = uWnd.getUnit(); - Unit vWndUnits = vWnd.getUnit(); - if ( uWndUnits != vWndUnits && uWndUnits.isCompatible(vWndUnits)){ - double vWndVal = vWndUnits.getConverterTo( uWndUnits ).convert( vWnd.doubleValue() ); - vWnd = new Amount ( vWndVal, uWndUnits ); - } - double prsped = ( Math.sqrt( ( Math.pow(uWnd.doubleValue(), 2) + Math.pow(vWnd.doubleValue(), 2) ) ) ); - return new Amount ( prsped, uWndUnits ); - } - - /** - * Computes the potential temperature ( in Kelvin ) from the - * temperature (in Celsius ) and the pressure ( in mb ). - * @param tmpc - The temperature ( in Celsius ) - * @param pres - The pressure ( in mb ) - * @return the potential temperature ( in Kelvin ), if both inputs are valid - * . - * @throws InvalidRangeException - * @throws NullPointerException - * - */ - public static Amount prThta ( Amount tmpc, Amount pres) throws InvalidValueException, NullPointerException{ - checkNullOrInvalidValue(tmpc); - checkNullOrInvalidValue(pres); - - if ( !checkNullOrInvalidValue( tmpc ) - || !checkNullOrInvalidValue( pres )) - return new Amount ( SI.KELVIN ); - - tmpc = checkAndConvertInputAmountToExpectedUnits(tmpc, SI.CELSIUS); - pres = checkAndConvertInputAmountToExpectedUnits(pres, NcUnits.MILLIBAR); - double pressureValue = pres.doubleValue(); - if ( pressureValue <= 0 ){ - System.out.println("From prThta( ) - pressure must be > 0 "); - return new Amount ( SI.KELVIN ); -// throw new InvalidRangeException("From prThta( ) - pressure must be > 0 "); - } - - /*Change temperature in degrees Celsius to Kelvin.*/ - double temperatureInKelvin = (double) tmpc.getUnit().getConverterTo(SI.KELVIN).convert(tmpc.doubleValue() ); - - /*Calculate theta using Poisson's equation*/ - double prthta = ( double ) ( temperatureInKelvin * Math.pow( ( 1000 / pres.doubleValue()) , GempakConstants.RKAPPA) ); - return new Amount ( prthta , SI.KELVIN ); - } - - - /** - * Computes the equivalent potential temperature ( in Kelvin ) from - * the pressure ( in mb ), the temperature ( in Celsius ) and the dewpoint ( in Celsius ) - * using the equation: - * THTE = THTAM * EXP [ ( 3.376/TLCL - .00254 ) * - * ( MIXR * ( 1 + .81*.001*MIXR ) ) ] - * where - * THTAM = potential temperature of moist air - * = TMPK * (1000 / PRES) ** E - * E = RKAPPA * ( 1 - ( .28 * .001 * MIXR ) ) - * Bolton. - * - * @param pres - the pressure ( in mb ) - * @param tmpc - the temperature ( in Celsius ) - * @param dwpc - the dewpoint ( in Celsius ) - * @return the the equivalent potential temperature ( in Kelvin ), if all the input values - * are valid - * @throws NullPointerException - * - * @throws InvalidRangeException - */ - public static final Amount prThte ( Amount pres, Amount tmpc, Amount dwpc ) { - //System.out.println("From prThte:"); - //System.out.println(" pres = " + pres.doubleValue()); - //System.out.println(" tmpc = " + tmpc.doubleValue()); - //System.out.println(" dwpc = " + dwpc.doubleValue()); - -// checkNullOrInvalidValue(pres); -// checkNullOrInvalidValue(tmpc); -// checkNullOrInvalidValue(dwpc); - if ( !checkNullOrInvalidValue( tmpc ) - || !checkNullOrInvalidValue( pres ) - || !checkNullOrInvalidValue( dwpc ) ) - return new Amount ( SI.KELVIN ); - - if ( pres.doubleValue() <= 0){ - System.out.println("From prThte() - Input pressure must be greater than 0 "); - return new Amount ( SI.KELVIN ); -// throw new InvalidRangeException("From prThte() - Input pressure must be greater than 0 "); - } - - pres = checkAndConvertInputAmountToExpectedUnits( pres, NcUnits.MILLIBAR ); - dwpc = checkAndConvertInputAmountToExpectedUnits( dwpc, SI.CELSIUS ); - tmpc = checkAndConvertInputAmountToExpectedUnits( tmpc, SI.CELSIUS ); - - /*Find mixing ratio*/ - Amount rmix = prMixr ( dwpc, pres); - if ( !checkNullOrInvalidValue(rmix) ) - return new Amount ( SI.KELVIN ); - /*Change degrees Celsius to Kelvin*/ - Amount tmpk = checkAndConvertInputAmountToExpectedUnits(tmpc, SI.KELVIN); - - - /*Calculate theta for moist air (thtam) */ - double mixingRatioVal = rmix.doubleValue(); - double pressureVal = pres.doubleValue(); - double tempVal = tmpk.doubleValue(); - - double e = ( double) ( GempakConstants.RKAPPA * (1 - (0.28 * 0.001 * mixingRatioVal) )); - double thtam = ( double ) ( tempVal * Math.pow(1000 / pressureVal, e)); - - /*Find the temperature at the lifted condensation level */ - Amount tlcl = prTlcl ( tmpc, dwpc ); - - if ( ! checkNullOrInvalidValue(tlcl) ) - return new Amount ( SI.KELVIN ); - - double lclTemp = tlcl.doubleValue(); - e = ( ( 3.376f / lclTemp ) - 0.00254f ) * ( mixingRatioVal * ( 1 + 0.81f * 0.001f * mixingRatioVal )); - double prthte = ( double ) ( thtam * Math.exp(e)); - Amount equivPotentialTempAmount = new Amount(prthte, SI.KELVIN); - return equivPotentialTempAmount; - } - - /** - * Computes wet bulb potential temperature ( in Celsius ) from the - * pressure, temperature and dewpoint. The result is obtained by first - * computing the equivalent potential temperature (thte) of the the air parcel at level - * pres. Then the air parcel is brought to 1000 mb moist adiabatically to get the - * wet bulb potential temperature. - * @param pres - Pressure ( in millibars ) - * @param tmpc - Temperature ( in Celsius ) - * @param dwpc - Dewpoint ( in Celsius ) - * @return The wet bulb potential temperature ( in Celsius ) if all inputs are valid - * @throws NullPointerException - * - * @throws InvalidRangeException - */ - public static final Amount prThwc ( Amount pres, Amount tmpc, Amount dwpc) throws InvalidValueException, NullPointerException { - //System.out.println("From prThwc:"); - //System.out.println(" press = " + pres.doubleValue()); - //System.out.println(" tmpc = " + tmpc.doubleValue()); - //System.out.println(" dwpc = " + dwpc.doubleValue()); - - /*Check for missing and invalid data*/ -// checkNullOrInvalidValue( pres ); -// checkNullOrInvalidValue( tmpc ); -// checkNullOrInvalidValue( dwpc ); - - if ( !checkNullOrInvalidValue( tmpc ) - || !checkNullOrInvalidValue( pres ) - || !checkNullOrInvalidValue( dwpc ) ) - return new Amount ( SI.CELSIUS ); - - pres = checkAndConvertInputAmountToExpectedUnits( pres , NcUnits.MILLIBAR ); - tmpc = checkAndConvertInputAmountToExpectedUnits( tmpc , SI.CELSIUS ); - dwpc = checkAndConvertInputAmountToExpectedUnits( dwpc , SI.CELSIUS ); - double presVal = pres.doubleValue(); - if ( presVal <= 0 ){ - System.out.println("From prThwc: Pressure must be greater than 0 mb"); - return new Amount ( SI.CELSIUS ); -// throw new InvalidRangeException("From prThwc: Pressure must be greater than 0 mb"); - } - /*Compute the thte*/ - Amount thte = prThte(pres, tmpc, dwpc); - - /*Check for missing 'thte' and compute wet bulb temperature.*/ - if ( ! checkNullOrInvalidValue( thte ) ) - return new Amount ( SI.CELSIUS ); - /*Compute the parcel temperature (in Kelvin)*/ - - Amount prthwc = prTmst ( thte, - new Amount ( 1000, NcUnits.MILLIBAR ), - new Amount ( 0, SI.KELVIN ) ); - if ( ! checkNullOrInvalidValue( prthwc ) ) - return new Amount ( SI.CELSIUS ); - /*Convert the parcel temperature to Celsius*/ - prthwc = checkAndConvertInputAmountToExpectedUnits(prthwc, SI.CELSIUS); - - return prthwc; - } - - - /** - * Computes the temperature at the lifted condensation level for a parcel of air - * given the temperature ( in Celsius ) and the dewpoint (in Celsius) using the - * equation: - * TLCL = [ 1 / ( 1 / (DWPK-56) + ALOG (TMPK/DWPK) / 800 ) ] + 56 - * Bolton. - * @param tmpc - the temperature ( in Celsius ) - * @param dwpc - the dewpoint ( in Celsius ) - * @return the lifted condensation level temperature In Kelvin, if both input values are valid - * - * @throws NullPointerException - * - * @throws InvalidRangeException - */ - public static final Amount prTlcl ( Amount tmpc, Amount dwpc ) { - //System.out.println("From prTlcl:"); - //System.out.println(" tmpc = " + tmpc.doubleValue()); - //System.out.println(" dwpc = " + dwpc.doubleValue()); - - -// checkNullOrInvalidValue(tmpc); -// checkNullOrInvalidValue(dwpc); - if ( !checkNullOrInvalidValue( tmpc ) - || !checkNullOrInvalidValue( dwpc ) ) - return new Amount ( SI.KELVIN ); - - if ( tmpc.doubleValue() < -GempakConstants.TMCK || dwpc.doubleValue() < -GempakConstants.TMCK){ - System.out.println("From prTlcl: Input temperature cannot be less than -273.15"); - return new Amount (SI.KELVIN ); - } - Amount tmpk = checkAndConvertInputAmountToExpectedUnits(tmpc, SI.KELVIN); - Amount dwpk = checkAndConvertInputAmountToExpectedUnits(dwpc, SI.KELVIN); - double tempVal = tmpk.doubleValue(); - double dewpointVal = dwpk.doubleValue(); - double lclTemp = ( double ) ( ( 800 * ( dewpointVal - 56 ) / ( 800 + ( dewpointVal - 56 ) * Math.log ( tempVal / dewpointVal ) ) ) + 56 ); - Amount prtlcl = new Amount ( lclTemp, SI.KELVIN ); - - return prtlcl; - } - - /** - * Computes the temperature ( in Kelvin ) from the pressure ( in mb ) and - * the potential temperature ( in Kelvin ) using the Poisson equation: - * TMPK = THTA * ( PRES / 1000 ) ** RKAPPA - * - * @param pres - the pressure ( in mb ) - * @param thta - the potential temperature ( in Kelvin ) - * @return the temperature ( in Kelvin ) - * @throws InvalidRangeException - * @throws NullPointerException - * - */ - public static final Amount prTmpk ( Amount pres, Amount thta ) throws InvalidValueException, NullPointerException{ - //System.out.println("From prTmpk:"); - //System.out.println(" pres = " + pres.doubleValue()); - //System.out.println("thta = " + thta.doubleValue()); - - Amount prtmpk = new Amount ( SI.KELVIN ); - if ( !checkNullOrInvalidValue(pres) - || !checkNullOrInvalidValue(thta) ){ - return new Amount ( SI.KELVIN ); - } - - pres = checkAndConvertInputAmountToExpectedUnits(pres, NcUnits.MILLIBAR); - thta = checkAndConvertInputAmountToExpectedUnits(thta, SI.KELVIN); - double pressureValue = pres.doubleValue(); - double thtaValue = thta.doubleValue(); - if ( pressureValue >= 0){ - double temperature = ( double ) ( thtaValue * ( Math.pow( pressureValue / 1000f, GempakConstants.RKAPPA ) ) ); - prtmpk = new Amount ( temperature , SI.KELVIN ); - return prtmpk; - } - else{ - System.out.println("From prTmpk() - pressure cannot be less than 0 mb"); - return new Amount ( SI.KELVIN ); -// throw new InvalidRangeException("From prTmpk() - pressure cannot be less than 0 mb"); - } - } - - /** - *
-	 * Computes the parcel temperature ( in Kelvin ) from the equivalent potential temp ( in Kelvin ),
-	 * pressure ( in millibars ) and the first guess temperature ( in Kelvin ). 
-	 * The parcel temperature at level pres on a specified moist adiabat ( thte ). 
-	 * The computation is an iterative Newton-Raphson technique of the form:
-	 * 
-	 * x = x(guess) + [ f( x ) - f( x(guess) ) ] / f'( x(guess) )
-	 * f' is approximated with finite differences
-	 * f' = [ f( x(guess) + 1 ) - f( x(guess) ) ] / 1
-	 * 
-	 * If tguess is 0, a reasonable first guess will be made.
-	 * Convergence is not guaranteed for extreme input values.  If the
-	 * computation does not converge after 100 iterations, the missing 
-	 * data value will be returned. 
-	 * @param thte      - Equivalent potential temp ( in Kelvin )
-	 * @param pres      - Pressure ( in millibars )
-	 * @param tguess   - First guess temperature ( in Kelvin )
-	 * @return the Parcel temperature in Kelvin if all the input values are valid 
-	 * (without being extreme) and if a convergence is obtained within 100 iterations 
-	 * 
- * @throws NullPointerException - * - */ - public static final Amount prTmst ( Amount thte, Amount pres, Amount tguess) { - double prtmst = GempakConstants.RMISSD; - //System.out.println("From prTmst:"); - //System.out.println(" thte = " + thte.doubleValue()); - //System.out.println(" pres = " + pres.doubleValue()); - //System.out.println(" tguess = " + tguess.doubleValue()); - if ( !checkNullOrInvalidValue(pres) - || !checkNullOrInvalidValue(thte) - || !checkNullOrInvalidValue(tguess) ){ - return new Amount ( SI.KELVIN ); - } -// checkNullOrInvalidValue( thte ); -// checkNullOrInvalidValue( pres ); -// checkNullOrInvalidValue( tguess ); - thte = checkAndConvertInputAmountToExpectedUnits( thte, SI.KELVIN ); - pres = checkAndConvertInputAmountToExpectedUnits( pres, NcUnits.MILLIBAR ); - tguess = checkAndConvertInputAmountToExpectedUnits( tguess, SI.KELVIN ); - double thteVal = thte.doubleValue(); - double presVal = pres.doubleValue(); - double tguessVal = tguess.doubleValue(); - - if ( thteVal <= 0 ){ - System.out.println(" From prTmst(): Potential temperature must be greater than 0"); - return new Amount ( SI.KELVIN ); -// throw new InvalidRangeException(" From prTmst(): Potential temperature must be greater than 0"); - } - else if ( presVal <= 0 ){ - System.out.println(" From prTmst(): Pressure must be greater than 0"); - return new Amount ( SI.KELVIN ); -// throw new InvalidRangeException(" From prTmst(): Pressure must be greater than 0"); - } - else if ( tguessVal < 0 ){ - System.out.println(" From prTmst(): First guess temperature must be greater than or equal to 0"); - return new Amount ( SI.KELVIN ); -// throw new InvalidRangeException(" From prTmst(): First guess temperature must be greater than 0"); - } - double tg = tguess.doubleValue(); - /* - * If tguess is passed as 0. it is computed from an MIT scheme - */ - if ( tg == 0 ){ - double diffVar = thte.doubleValue() - 270; - double mathFormula1 = (double) ( diffVar > 0 ? diffVar : 0.0 ); - tg = (double) ( ( thte.doubleValue() - 5.0f * ( Math.pow ( mathFormula1, 1.05f) ) ) - * ( Math.pow ( pres.doubleValue() / 1000.0f, 0.2f ) ) ); - } - - /*Set convergence and initial guess in degrees Celsius*/ - double epsi = 0.01f; - double tgnu = SI.KELVIN.getConverterTo(SI.CELSIUS).convert(tg) ; - - /* - * Set a limit of 100 iterations. Compute tenu,tenup, the - * thte's at one degree above the guess temperature. - */ - int index = 0; - while( index < 100 ){ - double tgnup = tgnu + 1; - Amount tgnuAmount = new Amount ( tgnu, SI.CELSIUS ); - Amount tgnupAmount = new Amount ( tgnup, SI.CELSIUS ); - Amount tenu = prThte ( pres, tgnuAmount, tgnuAmount ); - Amount tenup = prThte ( pres, tgnupAmount, tgnupAmount ); - /*Check that the THTE's exist.*/ - - if (( ! checkNullOrInvalidValue(tenu) - || !checkNullOrInvalidValue(tenup) ) ){ - return new Amount ( SI.KELVIN); -// index++; -// continue; - } - - /*Compute the correction*/ - double tenuVal = tenu.doubleValue(); - double tenupVal = tenup.doubleValue(); - double cor = ( thteVal - tenuVal ) / ( tenupVal - tenuVal ); - tgnu += cor; - - if ( ( cor < epsi ) && (-cor < epsi) ){ - - /*return on convergence*/ - prtmst = tgnuAmount.getUnit().getConverterTo(SI.KELVIN).convert(tgnu); - break; - } - - index++; - } - return new Amount ( prtmst, SI.KELVIN); - } - - /** - *
-	 * Computes wet bulb temperature from the temperature, mixing ratio, and pressure.
-	 * The result is obtained by solving for the temperature at which saturation occurs,
-	 *  when the latent heat required to vaporize the water is provided by a cooling of the air.
-	 *  The equation representing the process is:
-	 *   ( tmpk - tmwb ) * cp - ( Rsat (tmwb) - rmix ) * lvap = 0  
-	 *  This implicit equation is solved by Newton's method, since the 
-	 *  saturation mixing ratio Rsat is a transcendental function of tmwb.
-	 *  The expressions for the heat of vaporization (LVAP) and saturation 
-	 *   vapor pressure are equations (2) and (10) from Bolton (MWR, 1980).
-	 *   
- * @param tmpk - Temperature (K) - * @param rmix - Mixing ratio (g/kg) - * @param pres - Pressure (mb) - * @return Wet bulb temperature (K) if all inputs are valid - * @throws NullPointerException - * - */ - public static final Amount prTmwb ( Amount tmpk, Amount rmix, Amount pres) throws InvalidValueException, NullPointerException{ - //System.out.println("From prTmwb:"); - //System.out.println(" tmpk = " + tmpk.doubleValue()); - //System.out.println(" rmix = " + rmix.doubleValue()); - //System.out.println(" pres = " + pres.doubleValue()); - - Amount prtmwb = null; - /*Check for missing and invalid data*/ -// checkNullOrInvalidValue( tmpk ); -// checkNullOrInvalidValue( rmix ); -// checkNullOrInvalidValue( pres ); - if ( !checkNullOrInvalidValue(pres) - || !checkNullOrInvalidValue(tmpk) - || !checkNullOrInvalidValue(rmix) ){ - return new Amount ( SI.KELVIN ); - } - tmpk = checkAndConvertInputAmountToExpectedUnits( tmpk, SI.KELVIN ); - rmix = checkAndConvertInputAmountToExpectedUnits( rmix , NcUnits.GRAMS_PER_KILOGRAM ); - pres = checkAndConvertInputAmountToExpectedUnits( pres , NcUnits.MILLIBAR ); - double presVal = pres.doubleValue(); - if ( presVal <= 0 ){ - System.out.println("From prTmwb - pressure value must be greater than 0 "); - return new Amount ( SI.KELVIN ); -// throw new InvalidRangeException("From prTmwb - pressure value must be greater than 0 "); - } - /*Change temperature to degrees Celsius.*/ - Amount tmp = checkAndConvertInputAmountToExpectedUnits(tmpk, SI.CELSIUS); - - /*Compute the latent heat of vaporization.*/ - Amount lvap = prLhvp ( tmp ); - if ( !checkNullOrInvalidValue( lvap ) ) - return new Amount ( SI.KELVIN ); - /*Compute the specific heat of moist air*/ - double rmixVal = rmix.doubleValue()/1000; - double cp = ( 1005.7 * ( 1.0 + 0.887 * rmixVal ) ); - - double rlocp = lvap.doubleValue() / cp; - - /*Do Newton iteration*/ - int iter = 0; - double twb = tmp.doubleValue(); - boolean isConvrg = false; - - double A = 6.112; - double B = 17.67; - double C = 243.5; - double EPSI = 0.622; - double G = B * C; - double ERRMAX = 0.001; - double tmpVal = tmp.doubleValue(); - while ( iter <= 50 && !isConvrg ){ - iter++; - double bt = B * twb; - double tpc = twb + C; - double d = ( ( presVal / A ) * Math.exp( ( -bt ) / tpc ) ); - double dm1 = d - 1; - double f = (tmpVal - twb ) - rlocp * ( EPSI / dm1 - rmixVal ); - double df = (-G) / ( tpc * tpc ); - df = d * df * rlocp * EPSI / ( dm1 * dm1 ) - 1; - double cor = f / df; - twb = twb - cor; - if ( Math.abs ( cor ) <= ERRMAX ) - isConvrg = true; - } - - if ( isConvrg ){ - Amount twk = new Amount ( twb , SI.KELVIN ); - if ( twk.doubleValue() > tmpk.doubleValue() ) - twk = new Amount ( tmpk.doubleValue(), SI.KELVIN ) ; - - prtmwb = twk; - } -// } - return prtmwb; - } - - - /** - * Computes the virtual temperature ( in Kelvin ) from the temperature ( in Celsius ), - * dewpoint ( in Celsius ) and pressure ( in mb ) where DWPC and PRES are used to compute - * MIXR. The following equation is used: - * TVRK = TMPK * (1 + .001 * MIXR / .62197) / (1 + .001 * MIXR) - * If DWPC is missing, dry air is assumed and TMPK is returned. - * - * @param tmpc - Temperature ( in Celsius ) - * @param dwpc - Dewpoint ( in Celsius ) - * @param pres - Pressure ( in mb ) - * @return the virtual temperature ( in Kelvin ) - * @throws NullPointerException - * - */ - public static final Amount prTvrk( Amount tmpc, Amount dwpc, Amount pres ) throws InvalidValueException, NullPointerException{ - //System.out.println("From prTvrk:"); - //System.out.println(" tmpc = " + tmpc.doubleValue()); - //System.out.println(" dwpc = " + dwpc.doubleValue()); - //System.out.println(" pres = " + pres.doubleValue()); - - Amount prtvrk = null; -// checkNullOrInvalidValue(tmpc); -// checkNullOrInvalidValue(pres); - - if ( !checkNullOrInvalidValue( pres ) - || !checkNullOrInvalidValue( tmpc ) ){ - return new Amount ( SI.KELVIN ); - } - - /*If dewpoint is missing, return temperature*/ - - if ( !checkNullOrInvalidValue(dwpc )) - return checkAndConvertInputAmountToExpectedUnits(tmpc, SI.KELVIN); - - else { - /*Change temperature to Kelvin.*/ - Amount tmpk = checkAndConvertInputAmountToExpectedUnits(tmpc, SI.KELVIN); - - /* Find mixing ratio in g/kg; if missing, return temperature */ - Amount rmix = prMixr ( dwpc, pres ); - - double virtualTemp; - if (rmix.doubleValue() == GempakConstants.RMISSD ) - virtualTemp = (double) tmpc.getUnit().getConverterTo(SI.KELVIN).convert(tmpc.doubleValue()); - else{ - double mixingRatioVal = rmix.doubleValue(); - double temp = tmpk.doubleValue(); - virtualTemp =( double ) ( temp * ( 1 + 0.001 * mixingRatioVal / 0.62197 ) / ( 1 + 0.001 * mixingRatioVal ) ); - - } - prtvrk = new Amount (virtualTemp, SI.KELVIN); - } - return prtvrk; - } - - /** - * Computes the 'U' component of the wind from its speed and direction - * @param sped - wind speed - * @param drct - wind direction - * @return The 'U' component of the wind if both inputs are valid - * @throws NullPointerException - * - */ - public static final Amount prUwnd ( Amount sped, Amount drct) throws InvalidValueException, NullPointerException { - //System.out.println("From prUwnd:"); - //System.out.println(" sped = " + sped.doubleValue()); - //System.out.println(" drct = " + drct.doubleValue()); - if ( !checkNullOrInvalidValue( drct ) - || !checkNullOrInvalidValue( sped ) ){ - return new Amount (SI.METERS_PER_SECOND ); - } - drct = checkAndConvertInputAmountToExpectedUnits(drct, NonSI.DEGREE_ANGLE ); - double pruwnd = ( ( -Math.sin( drct.doubleValue() * GempakConstants.DTR ) ) * sped.doubleValue() ); - return new Amount ( pruwnd, sped.getUnit() ); //TODO :verify the units - } - - /** - * Computes the 'V' component of the wind from its speed and direction - * @param sped - wind speed - * @param drct - wind direction - * @return The 'V' component of the wind if both inputs are valid - * @throws NullPointerException - * - */ - public static final Amount prVwnd ( Amount sped, Amount drct) throws InvalidValueException, NullPointerException { - //System.out.println("From prVwnd:"); - //System.out.println(" sped = " + sped.doubleValue()); - //System.out.println(" drct = " + drct.doubleValue()); - if ( !checkNullOrInvalidValue( drct ) - || !checkNullOrInvalidValue( sped ) ){ - return new Amount (SI.METERS_PER_SECOND ); - } - drct = checkAndConvertInputAmountToExpectedUnits(drct, NonSI.DEGREE_ANGLE ); - double prvwnd = ( ( -Math.cos( drct.doubleValue() * GempakConstants.DTR ) ) * sped.doubleValue() ); - return new Amount ( prvwnd, sped.getUnit() ); //TODO :verify the units - } - - - /** - * Computes the vapor pressure ( in mb) from the input - * dewpoint temperature in Celsius using the equation: - * VAPR = 6.112 * EXP [ (17.67 * dewpointValue) / (dewpointValue + 243.5) ] - * @param dwpc - the dewpoint temperature ( in Celsius ) - * @return the vapor pressure ( in mb) from the dewpoint temperature if it is valid - * @throws NullPointerException - * - */ - public static final Amount prVapr ( Amount dwpc) { - //System.out.println("From prVapr:"); - //System.out.println(" dwpc = " + dwpc.doubleValue()); - - if ( !checkNullOrInvalidValue(dwpc) ) - return new Amount ( NcUnits.MILLIBAR ); - dwpc = checkAndConvertInputAmountToExpectedUnits(dwpc, SI.CELSIUS); - double dewpointValue = dwpc.doubleValue(); - if ( dewpointValue >= -240.0f ) - return ( new Amount ( ( 6.112 * ( Math.exp ( ( 17.67 * dewpointValue ) / ( dewpointValue + 243.5) ) ) ) , - NcUnits.MILLIBAR ) ); - else{ -// throw new InvalidRangeException("Exception from prVapr() - dewpoint cannot be less than -240 "); - System.out.println("From prVapr() - dewpoint cannot be less than -240 "); - return new Amount ( NcUnits.MILLIBAR ); - } - } - -// /** -// * Computes the visibility ( in nautical miles ) from the input visibility ( in kilometers ) -// * @param vsbk - visibility ( in kilometers ) -// * @return visibility ( in nautical miles ) if the input is valid -// * @throws NullPointerException -// * -// */ -// //TODO: remove this - since the getValueAs(Unit) offers the same facility? -// public static final Amount prVskn ( Amount vsbk) throws InvalidValueException, NullPointerException { -// //System.out.println("From prVskn:"); -// //System.out.println(" vsbk = " + vsbk.doubleValue()); -// -// checkNullOrInvalidValue( vsbk ); -// vsbk = checkAndConvertInputAmountToExpectedUnits( vsbk, SI.KILOMETER ); -// return ( checkAndConvertInputAmountToExpectedUnits(vsbk, NonSI.NAUTICAL_MILE ) ); -// } - - /** - * Computes the wind chill equivalent temperature ( the temperature with calm winds that produces the same - * cooling effect as the given temperature with the given wind speed) - * @param tmpf - Air temperature ( in Farenheit ) - * @param sknt - Wind speed ( in knots ) - * @return the wind chill equivalent temperature ( in Farenheit ), - * if the inputs are valid - * @throws NullPointerException - * - */ - public static final Amount prWceq ( Amount tmpf, Amount sknt ) throws InvalidValueException, NullPointerException{ - //System.out.println("From prWceq:"); - //System.out.println(" tmpf = " + tmpf.doubleValue()); - //System.out.println(" sknt = " + sknt.doubleValue()); - - double prwceq = GempakConstants.RMISSD; - if ( !checkNullOrInvalidValue( tmpf ) - || !checkNullOrInvalidValue( sknt ) ){ - return new Amount (NonSI.FAHRENHEIT ); - } - - /*Convert input variables to Celsius and meters/second.*/ - Amount tmpc = checkAndConvertInputAmountToExpectedUnits(tmpf, SI.CELSIUS); - Amount sped = checkAndConvertInputAmountToExpectedUnits(sknt, SI.METERS_PER_SECOND) ; - - - if ( sped.doubleValue() <= 1.34) - /*If the wind speed does not exceed 1.34 m/s ( not much wind to contribute to the wind chill), - * return the input temperature as the wind chill temperature*/ - prwceq = tmpc.getUnit().getConverterTo(NonSI.FAHRENHEIT).convert(tmpc.doubleValue()); - else{ - /* - * Compute the wind chill temp if the inputs are not missing and - * and the wind speed is greater than 1.34 m/s. - * Equations for wind chill computation - * from R. Falconer, "Windchill, A Useful Wintertime Weather Variable", Weatherwise, Dec 1968. - */ - if ( sped.getUnit() == SI.METERS_PER_SECOND ){ - float windChill = ( float ) ( 33.0 - ( ( 33.0 - tmpc.doubleValue() ) * wci( sped.doubleValue() ) / wci( 1.34f ) ) ); - prwceq = tmpc.getUnit().getConverterTo(NonSI.FAHRENHEIT).convert(windChill); - } - } - - return ( new Amount ( prwceq, NonSI.FAHRENHEIT)); - } - - -// /** -// * Computes the numeric total cloud cover for the worst case aviation flight condition, -// * based on the categorical identification of flight rules for prevailing and temporary / probability conditions. -// * @param xvfr - Prevailing categorical id of flight rules -// * @param txvf - Temporary / Probability categorical id of flight rules -// * @param cfrt - Prevailing numeric total cloud cover -// * @param tcfr - Temporary / Probability numeric total cloud cover -// * @return Worst case numeric total cloud cover or RMISSD (-9999) if the computation does not fall through -// * @throws NullPointerException -// * -// */ -// public static final Amount prWcfr ( Amount xvfr, Amount txvf, Amount cfrt, Amount tcfr) throws InvalidValueException, NullPointerException { -// double prwcfr = GempakConstants.RMISSD; -// checkNullOrInvalidValue( tcfr ); -// checkNullOrInvalidValue( cfrt ); -// double cfrtVal = cfrt.doubleValue(); -// double tcfrVal = tcfr.doubleValue(); -// if ( ( xvfr == null || xvfr.doubleValue() == GempakConstants.RMISSD ) -// || ( txvf == null || txvf.doubleValue() == GempakConstants.RMISSD )) -// prwcfr = ( cfrtVal > tcfrVal ? cfrtVal : tcfrVal ); -// -// else { -// double txvfVal = txvf.doubleValue(); -// double xvfrVal = xvfr.doubleValue(); -// if ( txvfVal < xvfrVal ) -// prwcfr = tcfrVal; -// else if ( txvfVal == xvfrVal) -// prwcfr = ( cfrtVal > tcfrVal ? cfrtVal : tcfrVal ); -// else -// prwcfr = cfrtVal; -// } -// return ( new Amount ( prwcfr ,Unit.ONE)); -// } - - - /** - * Computes the wind chill temperature from the air temperature and the wind speed - * @param tmpf - Air temperature ( in degree Farenheit ) - * @param sknt - Wind speed ( in knots ) - * @return the wind chill temperature ( in Farenheit ) if none of the inputs are missing - * @throws NullPointerException - * - */ - public static final Amount prWcht ( Amount tmpf, Amount sknt) throws InvalidValueException, NullPointerException{ - //System.out.println("From prWcht:"); - //System.out.println(" tmpf = " + tmpf.doubleValue()); - //System.out.println(" sknt = " + sknt.doubleValue()); - double prwrcht = GempakConstants.RMISSD; - if ( !checkNullOrInvalidValue( tmpf ) - || !checkNullOrInvalidValue( sknt ) ){ - return new Amount (NonSI.FAHRENHEIT ); - } - - /*Convert the speed to miles per hour*/ - Amount smph = checkAndConvertInputAmountToExpectedUnits(sknt, NonSI.MILES_PER_HOUR); - - /*If the inputs are not missing , check if the wind speed is <= 3 miles per hour*/ - - double smphVal = smph.doubleValue(); - double tmpfVal = tmpf.doubleValue(); - if( smphVal <= 3 ) - prwrcht = tmpfVal ; - else{ - /*Compute the wind-chill temperature for wind speeds that exceed 3 miles per hour*/ - float wcht = ( float ) ( 35.74 + 0.6215 * tmpfVal -35.75 * Math.pow(smphVal, 0.16) - + 0.4275 * tmpfVal * Math.pow(smphVal, 0.16) ); - prwrcht = ( wcht > tmpfVal ? tmpfVal : wcht); - } - return ( new Amount ( prwrcht , NonSI.FAHRENHEIT ) ); - } - - - /** - * Computes the wind component towards a specific direction from the - * wind direction, wind speed and direction of desired component. - * @param drct - the wind direction in degrees - * @param sped - the wind speed in m/s - * @param dcmp - the direction of the desired component - * @return the component of the wind (in m/s) if none of the input parameters are missing - * @throws NullPointerException - * - */ - public static final Amount prWcmp ( Amount drct, Amount sped, Amount dcmp ) throws InvalidValueException, NullPointerException{ - //System.out.println("From prWcmp:"); - //System.out.println(" sped = " + sped.doubleValue()); - //System.out.println(" drct = " + drct.doubleValue()); - //System.out.println(" dcmp = " + dcmp.doubleValue()); - /*Check for missing input parameters*/ -// checkNullOrInvalidValue( drct ); -// checkNullOrInvalidValue( sped ); -// checkNullOrInvalidValue( dcmp ); - if ( !checkNullOrInvalidValue( drct ) - || !checkNullOrInvalidValue( sped ) - || !checkNullOrInvalidValue( dcmp ) ){ - return new Amount (SI.METERS_PER_SECOND ); - } - - drct = checkAndConvertInputAmountToExpectedUnits( drct , NonSI.DEGREE_ANGLE ); - dcmp = checkAndConvertInputAmountToExpectedUnits( dcmp , NonSI.DEGREE_ANGLE ); - sped = checkAndConvertInputAmountToExpectedUnits( sped , SI.METERS_PER_SECOND ); - - /*Calculate wind speed toward specified direction*/ - double prwcmp = sped.doubleValue() * ( -Math.cos( ( drct.doubleValue() - dcmp.doubleValue()) *GempakConstants.DTR ) ) ; - - return new Amount ( prwcmp , SI.METERS_PER_SECOND); - } - - /** - * Computes the wind component toward a direction 90 degrees counterclockwise of a specified direction. - * If no direction is specified, the component toward north is returned. - * @param drct - wind direction ( in degrees ) - * @param sped - wind speed ( in knots or m/s ) - * @param dcmp - specified wind direction ( in degrees ) - * @return a component of the wind in m/s if the input wind speed and direction are valid and if - * the specified wind direction is between 0 degrees and 360 degrees. - * @throws NullPointerException - * - * @throws InvalidRangeException - */ - public static final Amount prWnml ( Amount drct, Amount sped, Amount dcmp) throws InvalidValueException, NullPointerException{ - //System.out.println("From prWnml:"); - //System.out.println(" sped = " + sped.doubleValue()); - //System.out.println(" drct = " + drct.doubleValue()); - //System.out.println(" dcmp = " + dcmp.doubleValue()); -// checkNullOrInvalidValue(sped); -// checkNullOrInvalidValue(drct); -// checkNullOrInvalidValue(dcmp); - if ( !checkNullOrInvalidValue( drct ) - || !checkNullOrInvalidValue( sped ) - || !checkNullOrInvalidValue( dcmp ) ){ - return new Amount (SI.METERS_PER_SECOND ); - } - - drct = checkAndConvertInputAmountToExpectedUnits( drct , NonSI.DEGREE_ANGLE ); - dcmp = checkAndConvertInputAmountToExpectedUnits( dcmp , NonSI.DEGREE_ANGLE ); - sped = checkAndConvertInputAmountToExpectedUnits( sped , SI.METERS_PER_SECOND ); - if ( ( dcmp.doubleValue() < 0 ) && ( dcmp.doubleValue() > 360 ) ){ -// throw new InvalidRangeException("From prWnml - the wind direction 'dcmp' mus be greater than or equal to 0 and less than or equal to 360"); - System.out.println("From prWnml - the wind direction 'dcmp' mus be greater than or equal to 0 and less than or equal to 360"); - return new Amount ( SI.METERS_PER_SECOND); - } - /* - * Calculate wind speed 90 degrees to left of given direction. - */ - double prwnml = ( float ) ( sped.doubleValue() * ( -Math.cos( ( drct.doubleValue() - dcmp.doubleValue() - 90 ) * GempakConstants.DTR ) ) ); - return ( new Amount ( prwnml , SI.METERS_PER_SECOND ) ); - } - -// /** -// * Computes the packed wind speed and direction from the input wind speed and wind direction -// * @param drct - wind direction ( in degrees ) -// * @param sped - wind speed ( in knots or m/s ) -// * @return the packed speed and direction -// */ -// public static final Amount prWind ( Amount drct, Amount sped ){ -// float prwind = GempakConstants.RMISSD; -//// if ( !MissingValueTester.isDataValueMissing(drct) -//// && !MissingValueTester.isDataValueMissing(sped)){ -// /* -// * (Non-Javadoc) -// * The packed wind speed and direction are of the form: -// * SSSDDD, where SSS - wind speed ( in knots or m/s ) and -// * DDD - wind direction in degrees -// * -// */ -// int jdrct = (int ) Math.round( drct.doubleValue() ); -// int jsped = (int) Math.round( sped.doubleValue() ); -// prwind = jdrct + jsped * 1000; -//// } -// return prwind; -// } - - /** - * Computes the worst case categorical identification of flight rules for prevailing - * and temporary / probability conditions. - * @param xvfr - Prevailing categorical id of flight rules - * @param txvf - Temporary / probability categorical id of flight rules - * @return The worst case categorical id of flight rules - * @throws NullPointerException - * - */ - public static final Amount prWxvf ( Amount xvfr, Amount txvf ) throws InvalidValueException, NullPointerException{ - //System.out.println("From prWxvf:"); - //System.out.println(" xvfr = " + xvfr.doubleValue()); - //System.out.println(" txvf = " + txvf.doubleValue()); - - double prwxvf = GempakConstants.RMISSD; - if ( txvf != null && xvfr != null ){ - - double xvfrVal = xvfr.doubleValue(); - double txvfVal = txvf.doubleValue(); - - if ( txvfVal != GempakConstants.RMISSD && xvfrVal != GempakConstants.RMISSD ) - prwxvf = ( xvfrVal < txvfVal ? xvfrVal : txvfVal ); - - else if (xvfrVal == GempakConstants.RMISSD && txvfVal != GempakConstants.RMISSD ) - prwxvf = xvfrVal; - - else if ( txvfVal != GempakConstants.RMISSD && xvfrVal != GempakConstants.RMISSD ) - prwxvf = txvfVal; - } - - return ( new Amount ( prwxvf , Unit.ONE ) ); - } - - - /** - *
-      * Computes LIFR/IFR/MVFR/VFR flight conditions based on ceiling and visibility.
-      * @param ceil - Ceiling in hundreds of feet
-      * @param vsby - Visibility in statute miles
-      * @return Flight conditions index value: 
-      *     0 - LIFR
-      *     1 - IFR
-      *     2 - MVFR
-      *     3 - VFR 
-      *  
- * @throws NullPointerException - * - */ - public static final Amount prXvfr ( Amount ceil, Amount vsby ) throws InvalidValueException, NullPointerException{ - //System.out.println("From prXvfr:"); - //System.out.println(" ceil = " + ceil.doubleValue()); - //System.out.println(" vsby = " + vsby.doubleValue()); - - - double prxvfr = GempakConstants.RMISSD; - double vc = GempakConstants.RMISSD; - double vs = GempakConstants.RMISSD; - if ( vsby == null ) - return null; - - if ( !checkNullOrInvalidValue( ceil ) ) - return new Amount ( Unit.ONE ); - ceil = checkAndConvertInputAmountToExpectedUnits( ceil, NcUnits.HUNDREDS_OF_FEET ); - vsby = checkAndConvertInputAmountToExpectedUnits(vsby, NonSI.MILE ); - /*Compute categorical flight rules*/ - - //Check the ceiling value - - double ceilVal = ceil.doubleValue(); - - double vsbyVal = vsby.doubleValue(); - - if ( ceilVal < 0){ - //no-op. So vc retains its RMISSD value - } - else if ( ceilVal < 5 ) - vc = 0; - else if ( ceilVal < 10 ) - vc = 1; - else if ( ceilVal <= 30 ) - vc = 2; - else if ( ( vsbyVal > 5 ) - || ( vsbyVal < 0 ) - || ( vsbyVal == GempakConstants.RMISSD ) ){ - prxvfr = 3; - } - - /*Check the visibility value.*/ - if ( vsbyVal != GempakConstants.RMISSD ){ - if ( vsbyVal < 0 ){ - //no-op. So vs retains it RMISSD value - } - else if ( vsbyVal < 1 ) - vs = 0; - else if ( vsbyVal < 3) - vs = 1; - else if ( vsbyVal <= 5) - vs = 2; - else - vs = 3; - } - - /*Determine the more restrictive of the two values.*/ - if ( vc == GempakConstants.RMISSD ) - prxvfr = vs; - else if ( vs == GempakConstants.RMISSD ) - prxvfr = vc; - else - prxvfr = ( vc < vs ? vc : vs ); - - return ( new Amount ( prxvfr , Unit.ONE ) ) ; - - } - - /** - * Computes station elevation from altimeter and station pressure. - * It is also used to estimate height at various pressure levels from the altimeter in millibars. - * The PC library computes zmsl, Z000, Z950, Z850, Z800 by calling this function with pres - * equal to PMSL, 1000, 950, 850 and 800 respectively. - * @param altm - Altimeter in millibars - * @param pres - Pressure in millibars - * @return the height ( in meters ) if neither input value is missing and both input values - * are greater than zero. - * @throws NullPointerException - * - * @throws InvalidRangeException - */ - public static final Amount prZalt ( Amount altm, Amount pres ) throws InvalidValueException, NullPointerException{ - //System.out.println("From prZalt:"); - //System.out.println(" altm = " + altm.doubleValue()); - //System.out.println(" pres = " + pres.doubleValue()); - -// checkNullOrInvalidValue( pres ); -// checkNullOrInvalidValue( altm ); - - if ( !checkNullOrInvalidValue( pres ) - || !checkNullOrInvalidValue( altm ) ){ - return new Amount (SI.METER ); - } - - pres = checkAndConvertInputAmountToExpectedUnits( pres, NcUnits.MILLIBAR ); - altm = checkAndConvertInputAmountToExpectedUnits( altm, NcUnits.MILLIBAR ); - if ( altm.doubleValue() <= 0 ){ - // throw new InvalidRangeException("From prZalt: altm must be greater than 0 mb"); - System.out.println("From prZalt: altm must be greater than 0 mb"); - return new Amount (SI.METER ); - } - if ( pres.doubleValue() <= 0 ){ -// throw new InvalidRangeException("From prZalt: pres must be greater than 0 mb"); - System.out.println("From prZalt: pres must be greater than 0 mb"); - return new Amount (SI.METER ); - } - double to = GempakConstants.TMCK + 15; - double gamma = GempakConstants.GAMUSD / 1000 ; - - /*Calculate the exponent and pressure ratio.*/ - double expo = ( gamma * GempakConstants.RDGAS ) / GempakConstants.GRAVTY; - double prat = pres.doubleValue() / altm.doubleValue() ; - double przalt = ( to * ( 1 - Math.pow ( prat, expo) ) ) / gamma ; - - return ( new Amount ( przalt , SI.METER) ) ; - } - - - - /** - * Computes the windchill from the wind velocity ( part of the Falconer equation - refer method prWceq) - * @param d - wind velocity ( in meters per second ) - * @return the windchill temperature - */ - private static double wci ( double d){ - - /* from R. Falconer, "Windchill, A Useful Wintertime Weather Variable", Weatherwise, Dec 1968.*/ - return ( ( double ) (10 * Math.sqrt(d) + 10.45 - d )); - - - } - -public static final Amount checkAndConvertInputAmountToExpectedUnits(Amount amountIn, Unit expectedUnit){ - Amount amountOut = null; - if ( ! amountIn.getUnit().equals(expectedUnit) - && amountIn.getUnit().isCompatible(expectedUnit)){ - double newValue = amountIn.getUnit().getConverterTo(expectedUnit).convert(amountIn.doubleValue()); - amountOut = new Amount(newValue,expectedUnit); - }else -// throw new ConversionException("Unable to convert " + amountIn.getUnit().toString() + " to " + expectedUnit.toString() ); - amountOut = amountIn; - - return amountOut; - } - -// public static final void checkNullOrInvalidValue( Amount amountToCheck ) throws InvalidValueException, NullPointerException{ -// if (amountToCheck == null ) -// throw new NullPointerException(); -// else { -// double amountValue = amountToCheck.doubleValue(); -// if ( amountValue == GempakConstants.RMISSD){ -// throw new InvalidValueException( new String ("Input amount cannot be -9999")); -// } -// else if ( Double.isNaN(amountValue)) -// throw new InvalidValueException( new String ("Input amount cannot be NaN" )); -// } -// } - -public static final boolean checkNullOrInvalidValue( Amount amountToCheck ) { - if (amountToCheck == null ){ - return false; - // throw new NullPointerException(); - } - else { - double amountValue = amountToCheck.doubleValue(); - if ( amountValue == GempakConstants.RMISSD){ - System.out.println("Input amount cannot be -9999"); - return false; -// throw new InvalidValueException( new String ("Input amount cannot be -9999")); - } - else if ( Double.isNaN(amountValue)){ - System.out.println("Input amount cannot be NaN"); -// throw new InvalidValueException( new String ("Input amount cannot be NaN" )); - return false; - } - else - return true; } -} -// public static final class InvalidRangeException extends Exception { -// /** -// * -// */ -// private static final long serialVersionUID = -4962228676211688262L; -// -// /** -// * -// */ -// public InvalidRangeException( String msg) { -// super( msg ); -// } -// } - - public static final class InvalidValueException extends Exception { - /** + /** + * Computes the dewpoint as the difference between the input temperature and + * dewpoint depression + * + * @param tmpx + * - temperature (in Celsius or Farenheit or Kelvin) + * @param dpdx + * - the dewpoint depression ( in the same units as the + * temperature) + * @return the dewpoint in the same units as ( in the same units as the + * temperature) + * @throws NullPointerException + * + */ + public static final Amount prDwdp(Amount tmpx, Amount dpdx) + throws InvalidValueException, NullPointerException { + // System.out.println("From prDwdp:"); + // System.out.println(" tmpx = " + tmpx.doubleValue()); + // System.out.println(" dpdx = " + dpdx.doubleValue()); + + // checkNullOrInvalidValue(tmpx); + // checkNullOrInvalidValue(dpdx); + + if (!checkNullOrInvalidValue(tmpx) || !checkNullOrInvalidValue(dpdx)) + return new Amount(tmpx.getUnit()); + + Unit tempUnits = (Unit) tmpx.getUnit(); + Unit dewpointDepUnits = (Unit) dpdx.getUnit(); + if (!tempUnits.equals(dewpointDepUnits) + && tempUnits.isCompatible(dewpointDepUnits)) { + double dewpointDepValue = (double) dewpointDepUnits.getConverterTo( + tempUnits).convert(dpdx.doubleValue()); + dpdx = new Amount(dewpointDepValue, tempUnits); + } + + Amount dewpointTemperature = new Amount(tmpx.doubleValue() + - dpdx.doubleValue(), tempUnits); + return dewpointTemperature; + } + + /** + * Computes the dewpoint ( in Celsius ) from the mixing ratio (in + * grams/kilogram) and the pressure (in mb) + * + * @param rmix + * - the mixing ratio (in grams/kilogram) + * @param pres + * - the pressure (in mb) + * @return the dewpoint (in Celsius), if both the input values are valid + * @throws InvalidRangeException + * @throws NullPointerException + * + */ + public static final Amount prDwpt(Amount rmix, Amount pres) + throws InvalidValueException, NullPointerException { + // System.out.println("From prDwpt:"); + // System.out.println(" rmix = " + rmix.doubleValue()); + // System.out.println(" pres = " + pres.doubleValue()); + Amount prDwpt = null; + // checkNullOrInvalidValue( rmix ); + // checkNullOrInvalidValue( pres ); + if (!checkNullOrInvalidValue(rmix) || !checkNullOrInvalidValue(pres)) + return new Amount(SI.CELSIUS); + + rmix = checkAndConvertInputAmountToExpectedUnits(rmix, Unit.ONE); + pres = checkAndConvertInputAmountToExpectedUnits(pres, NcUnits.MILLIBAR); + double mixingRatioValue = rmix.doubleValue(); + double pressureValue = pres.doubleValue(); + if (mixingRatioValue <= 0) { + System.out + .println("From prDwpt() - mixing ratio must be greater than 0"); + return new Amount(SI.CELSIUS); + // throw new + // InvalidRangeException("From prDwpt() - mixing ratio must be greater than 0"); + } + if (pressureValue <= 0) { + System.out.println("From prDwpt() - pres must be greater than 0"); + return new Amount(SI.CELSIUS); + // throw new + // InvalidRangeException("From prDwpt() - pres must be greater than 0"); + } + /* Convert gram/kilogram to gram/gram */ + double ratio = mixingRatioValue / 1000; + + /* Calculate vapor pressure from mixing ratio and pressure */ + double vaporPressure = (pressureValue * ratio) / (0.62197 + ratio); + + /* Correct vapor pressure */ + vaporPressure = vaporPressure + / (1.001 + ((pressureValue - 100.0) / 900) * .0034); + + /* Calculate dewpoint */ + double dewPointValue = (double) (Math.log(vaporPressure / 6.112) * 243.5 / (17.67 - Math + .log(vaporPressure / 6.112))); + prDwpt = new Amount(dewPointValue, SI.CELSIUS); + return prDwpt; + } + + /*** + * Computes the Fosberg index from the temperature, relative humidity and + * wind speed at the surface. + * + * @param tmpc + * - Temperature in Celsius + * @param relh + * - Relative humidity in percent + * @param sped + * - Wind speed in meters/second + * @return the Fosberg index + * @throws NullPointerException + * + */ + public static final Amount prFosb(Amount tmpc, Amount relh, Amount sped) + throws InvalidValueException, NullPointerException { + // System.out.println("From prFosb:"); + // System.out.println("Temperature ( in K ) is: " + tmpc.doubleValue()); + // System.out.println("Relative Humidity is: " + relh.doubleValue()); + // System.out.println("Wind Speed is: " + sped.doubleValue()); + // checkNullOrInvalidValue( tmpc ); + // checkNullOrInvalidValue( relh ); + // checkNullOrInvalidValue( sped ); + if (!checkNullOrInvalidValue(tmpc) || !checkNullOrInvalidValue(relh) + || !checkNullOrInvalidValue(sped)) + return new Amount(Unit.ONE); + + tmpc = checkAndConvertInputAmountToExpectedUnits(tmpc, SI.CELSIUS); + relh = checkAndConvertInputAmountToExpectedUnits(relh, NonSI.PERCENT); + sped = checkAndConvertInputAmountToExpectedUnits(sped, + SI.METERS_PER_SECOND); + + /* Change temperature to degrees Fahrenheit */ + double tf = tmpc.getUnit().getConverterTo(NonSI.FAHRENHEIT) + .convert(tmpc.doubleValue()); + + /* Convert wind speed from meters/second to knots */ + double smph = sped.getUnit().getConverterTo(NonSI.MILES_PER_HOUR) + .convert(sped.doubleValue()); + + double A = 0.03229; + double B = 0.281073; + double C = 0.000578; + double D = 2.22749; + double E = 0.160107; + double F = 0.014784; + double G = 21.0606; + double H = 0.005565; + double P = 0.00035; + double Q = 0.483199; + double R = 0.3002; + // float T = 9.0f/5.0f; + // float U = 1.9425f; + // float V = 0.868976f; + double fw = GempakConstants.RMISSD; + double relhVal = relh.doubleValue(); + if (relhVal <= 10) { + fw = A + B * relhVal - C * relhVal * tf; + } else if (relhVal <= 50) { + fw = D + E * relhVal - F * tf; + } else { + fw = G + H * relhVal * relhVal - P * relhVal * tf - Q * relhVal; + } + + double sss = (double) (Math.sqrt(1. + (smph * smph))); + double fwd = fw / 30; + double fwd2 = fwd * fwd; + double fwd3 = fwd2 * fwd; + double fire = 1 - 2 * fwd + 1.5f * fwd2 - 0.5f * fwd3; + + /* Find the Fosberg Index */ + + double prfosb = (fire * sss) / R; + + return (new Amount(prfosb, Unit.ONE)); + } + + /** + *
+     * Computes the Southern Region/CPC Rothfusz heat index.
+     * 
+     * The Rothfusz regression is optimal for TMPF > ~80 and RELH > ~40%.   
+     * This code applies a simple heat index formula and then resorts to   
+     * the Rothfusz regression only if the simple heat index exceeds 80,   
+     * implying temperatures near, but slightly below 80.  To make the    
+     * simple calculation continuous with the values obtained from the   
+     * Rothfusz regression, the simple result is averaged with TMPF in    
+     * computing the simple heat index value.                               
+     * Source:  NWS Southern Region SSD Technical Attachment SR 90-23  7/1/90.  
+     * Heat Index was originally known as the apparent temperature index 
+     * (Steadman, JAM, July, 1979).                                                                  
+     * This code includes adjustments made by the CPC for low RELH at high  
+     * TMPF and high RELH for TMPF in the mid 80's.
+     * 
+     * 
+     * @param tmpf  - the input air temperature
+     * @param relh   - the relative humidity 
+     * @return the heat index (in deg Farenheit) if both 
+     * the input air temperature and relative humidity
+     * are valid values
+     * 
+ * + * @throws NullPointerException + * + */ + public static final Amount prHeat(Amount tmpf, Amount relh) + throws InvalidValueException, NullPointerException { + // System.out.println("From prHeat:"); + // System.out.println(" tmpf = " + tmpf.doubleValue()); + // System.out.println(" relh = " + relh.doubleValue()); + + double prheat = GempakConstants.RMISSD; + // checkNullOrInvalidValue( tmpf ); + // checkNullOrInvalidValue( relh ); + if (!checkNullOrInvalidValue(tmpf) || !checkNullOrInvalidValue(relh)) + return new Amount(Unit.ONE); + + tmpf = checkAndConvertInputAmountToExpectedUnits(tmpf, NonSI.FAHRENHEIT); + relh = checkAndConvertInputAmountToExpectedUnits(relh, NonSI.PERCENT); + double tmpfVal = tmpf.doubleValue(); + double relhVal = relh.doubleValue(); + /* + * If the temperature is less than 40 degrees, set the heat index to the + * temperature + */ + if (tmpfVal <= 40) + prheat = tmpfVal; + else { + /* + * Compute a simple heat index. If the value is less than 80 deg F + * use it + */ + prheat = (float) (61 + (tmpfVal - 68) * 1.2 + relhVal * 0.094); + prheat = (float) ((tmpfVal + prheat) * 0.5); + /* Else compute the full regression value */ + if (prheat >= 80.0) { + double t2 = tmpfVal * tmpfVal; + double r2 = relhVal * relhVal; + prheat = (float) (-42.379 + 2.04901523 * tmpfVal + 10.14333127 + * relhVal - 0.22475541 * tmpfVal * relhVal - 0.00683783 + * t2 - 0.05481717 * r2 + 0.00122874 * t2 * relhVal + + 0.00085282 * tmpfVal * r2 - 0.00000199 * t2 * r2); + /* + * Adjust for high regression at low relative humidity for + * temperatures above 80 degrees F. + */ + if ((relhVal <= 13.0) + && ((tmpfVal >= 80.0) && (tmpfVal <= 112.0))) { + float adj1 = (float) ((13. - relhVal) / 4); + float adj2 = (float) (Math.sqrt((17 - Math + .abs(tmpfVal - 95)) / 17)); + float adj = adj1 * adj2; + prheat -= adj; + } + /* + * Adjust for low regression at high relative humidity and + * temperatures in the mid-80s + */ + else if ((relhVal > 85) + && ((tmpfVal >= 80.0) && (tmpfVal <= 87.0))) { + float adj1 = (float) ((relhVal - 85.0) / 10.0); + float adj2 = (float) ((87.0 - tmpfVal) / 5); + float adj = adj1 * adj2; + prheat += adj; + } + } + } + return (new Amount(prheat, NonSI.FAHRENHEIT)); + } + + /** + * Computes the humiture index from the air temperature and the dew point + * temperature using the equation: PR_HMTR = TMPF + ( PR_VAPR ( DWPC ) - 21 + * ) + * + * @param tmpf + * - the air temperature (in Farenheit) + * @param dwpf + * - the dew point (in Farenheit) + * @return the humiture index if both the air temperature and the dewpoint + * temperature are valid values + * @throws InvalidRangeException + * @throws NullPointerException + * + */ + public static final Amount prHmtr(Amount tmpf, Amount dwpf) + throws InvalidValueException, NullPointerException { + // System.out.println("From prHmtr:"); + // System.out.println(" tmpf = " + tmpf.doubleValue()); + // System.out.println(" dwpf = " + dwpf.doubleValue()); + + double prhmtr = GempakConstants.RMISSD; + if (!checkNullOrInvalidValue(tmpf) || !checkNullOrInvalidValue(dwpf)) + return new Amount(Unit.ONE); + + tmpf = checkAndConvertInputAmountToExpectedUnits(tmpf, NonSI.FAHRENHEIT); + dwpf = checkAndConvertInputAmountToExpectedUnits(dwpf, NonSI.FAHRENHEIT); + + Amount dwpc = checkAndConvertInputAmountToExpectedUnits(dwpf, + SI.CELSIUS); + Amount vapr = prVapr(dwpc); + if (!checkNullOrInvalidValue(vapr)) + return new Amount(Unit.ONE); + + prhmtr = tmpf.doubleValue() + (vapr.doubleValue() - 21); + + return (new Amount(prhmtr, Unit.ONE)); + } + + /** + * Computes the rate of ice accretion/growth of ice on a vessel in salt + * water, in units of inches per 3 hours (the WMO standard) The formula used + * is IGRO = ( A*pr + B*pr*pr + *pr*pr*pr ) * CVFAC where A = 2.73 * 10e-2 B + * = 2.91 * 10e-4 C = 1.84 * 10e-6 pr = ( sped * ( -1.7 - tmpc ) ) / ( 1 + + * 0.4 * ( sstc + 1.7 ) ) (priesendorfer regression) and CVFAC = 1.1811, to + * convert cm/hr to in/3hr. + * + * @param tmpc + * - the observed surface air temperature in Celsius + * @param sstc + * - the observed surface sea temperature in Celsius + * @param sped + * - the observed wind speed + * @return the rate of ice growth if all the input values are valid and lie + * between specific limits and if the rate of ice growth that is + * computed is greater than or equal to 0, + * @throws NullPointerException + * + * @throws InvalidRangeException + */ + public static final Amount prIgro(Amount tmpc, Amount sstc, Amount sped) + throws InvalidValueException, NullPointerException { + // System.out.println("From prIgro:"); + // System.out.println(" tmpc = " + tmpc.doubleValue()); + // System.out.println(" sstc = " + sstc.doubleValue()); + // System.out.println(" sped = " + sped.doubleValue()); + + double prigro = GempakConstants.RMISSD; + // checkNullOrInvalidValue( tmpc ) ; + // checkNullOrInvalidValue( sstc ) ; + // checkNullOrInvalidValue( sped ) ; + + if (!checkNullOrInvalidValue(tmpc) || !checkNullOrInvalidValue(sstc) + || !checkNullOrInvalidValue(sped)) + return new Amount(NcUnits.INCHES_PER_THREE_HOURS); + + checkAndConvertInputAmountToExpectedUnits(tmpc, SI.CELSIUS); + checkAndConvertInputAmountToExpectedUnits(sstc, SI.CELSIUS); + + // TODO: verify that wind speed can have any unit + double tmpcVal = tmpc.doubleValue(); + double sstcVal = sstc.doubleValue(); + double spedVal = sped.doubleValue(); + + /* Check that these values are within the valid range */ + + if (spedVal < 0 || spedVal > 50) { + // throw new + // InvalidRangeException("The wind speed must lie between 0 and 50. Both limits inclusive"); + System.out + .println("The wind speed must lie between 0 and 50. Both limits inclusive"); + return new Amount(NcUnits.INCHES_PER_THREE_HOURS); + } + if (tmpcVal < -20 || tmpcVal > 0) { + // throw new + // InvalidRangeException("The observed surface air temperature must lie between -20 and 0. Both limits inclusive"); + System.out + .println("The observed surface air temperature must lie between -20 and 0. Both limits inclusive"); + return new Amount(NcUnits.INCHES_PER_THREE_HOURS); + } + if (sstcVal < -1.7f || sstcVal > 12) { + // throw new + // InvalidRangeException("The observed surface sea temperature must lie between -1.7 and 12. Both limits inclusive"); + } + double A = 0.0273f; + double B = 0.000291f; + double C = 0.00000184f; + double cvfac = 1.1811f; // to convert cm/hr to in per 3 hours + double pr = ((spedVal * (-1.7 - tmpcVal)) / (1 + 0.4 * (sstcVal + 1.7))); // Compute + // the + // Priesendorfer + // regression + double pr2 = pr * pr; + prigro = (A * pr + B * pr2 + C * pr * pr2) * cvfac; + if (prigro < 0) { + // throw new + // InvalidRangeException("The rate of ice growth must be greater than or equal to 0"); + System.out + .println("The rate of ice growth must be greater than or equal to 0"); + return new Amount(NcUnits.INCHES_PER_THREE_HOURS); + } + return (new Amount(prigro, NcUnits.INCHES_PER_THREE_HOURS)); + } + + /** + * Computes the latent heat of vaporization at constant pressure from the + * input temperature (in Celsius) using the equation: LHVP = ( 2.500 - + * .00237 * TMPC ) * 10E6 LHVP is in J/kg. + * + * @param tmpc + * - the input temperature (in Celsius) + * @return the latent heat of vaporization at constant pressure if the input + * temperature is valid + * @throws NullPointerException + * + */ + public static final Amount prLhvp(Amount tmpc) + throws InvalidValueException, NullPointerException { + + // System.out.println("From prLhvp:"); + // System.out.println(" tmpc = " + tmpc.doubleValue()); + + // checkNullOrInvalidValue(tmpc); + if (!checkNullOrInvalidValue(tmpc)) + return new Amount(NcUnits.JOULES_PER_KILOGRAM); + + tmpc = checkAndConvertInputAmountToExpectedUnits(tmpc, SI.CELSIUS); + double latentHeatOfVapr = (float) ((2.500 - 0.00237 * tmpc + .doubleValue()) * 1000000); + return (new Amount(latentHeatOfVapr, NcUnits.JOULES_PER_KILOGRAM)); + } + + /** + * Computes the temperature of a parcel lifted (or sunk) adiabatically to a + * given pressure. + * + * @param thta + * - Potential temperature in Kelvin + * @param thte + * - Equivalent potential temp in Kelvin + * @param pres + * - Lifted pressure in millibar + * @return the lifted temperature in Celsius, if all the input parameters + * are valid + * @throws NullPointerException + * + * @throws InvalidRangeException + */ + public static final Amount prLtmp(Amount thta, Amount thte, Amount pres) + throws InvalidValueException, NullPointerException { + // System.out.println("From prLtmp:"); + // System.out.println(" thta = " + thta.doubleValue()); + // System.out.println(" thte = " + thte.doubleValue()); + // System.out.println(" pres = " + pres.doubleValue()); + + double prltmp = GempakConstants.RMISSD; + // checkNullOrInvalidValue(thta); + // checkNullOrInvalidValue(thte); + // checkNullOrInvalidValue(pres); + + if (!checkNullOrInvalidValue(thta) || !checkNullOrInvalidValue(thte) + || !checkNullOrInvalidValue(pres)) + return new Amount(SI.CELSIUS); + + thta = checkAndConvertInputAmountToExpectedUnits(thta, SI.KELVIN); + thte = checkAndConvertInputAmountToExpectedUnits(thte, SI.KELVIN); + + if (pres.doubleValue() <= 0) + pres = new Amount(500, NcUnits.MILLIBAR); + + /* Compute parcel temperatures on moist and dry adiabats */ + Amount tmpe = prTmst(thte, pres, new Amount(0, SI.KELVIN)); + Amount tmpd = prTmpk(pres, thta); + checkNullOrInvalidValue(tmpe); + checkNullOrInvalidValue(tmpd); + /* + * ( Non-Javadoc ) The correct parcel temperature is the warmer of the + * temperature on the dry adiabat and the temperature on the moist + * adiabat. + */ + + double tmpeVal = tmpe.doubleValue(); + double tmpdVal = tmpd.doubleValue(); + if (tmpeVal > tmpdVal) { + prltmp = SI.KELVIN.getConverterTo(SI.CELSIUS).convert(tmpeVal); + } else { + prltmp = SI.KELVIN.getConverterTo(SI.CELSIUS).convert(tmpdVal); + } + + return (new Amount(prltmp, SI.CELSIUS)); + } + + /** + * Computes the mountain obscuration threshold met indicator + * + * @param cmsl + * - Ceiling converted to MSL in 100's of ft + * @param otval + * - Mountain obscuration threshold in 100's of ft + * @return The mountain obscuration threshold met indicator if the input + * values are valid + * @throws NullPointerException + * + */ + public static final Amount prMobs(Amount cmsl, Amount otval) + throws InvalidValueException, NullPointerException { + // System.out.println("From prMobs:"); + // System.out.println(" cmsl = " + cmsl.doubleValue()); + // System.out.println(" otval = " + otval.doubleValue()); + + // checkNullOrInvalidValue( cmsl ); + // checkNullOrInvalidValue( otval ); + + if (!checkNullOrInvalidValue(cmsl) || !checkNullOrInvalidValue(otval)) + return new Amount(Unit.ONE); + + cmsl = checkAndConvertInputAmountToExpectedUnits(cmsl, + NcUnits.HUNDREDS_OF_FEET); + otval = checkAndConvertInputAmountToExpectedUnits(otval, + NcUnits.HUNDREDS_OF_FEET); + return (cmsl.doubleValue() < otval.doubleValue() ? new Amount(1, + Unit.ONE) : new Amount(1, Unit.ONE)); + } + + /** + * Computes the mixing ratio in grams/kilograms from the dewpoint ( in + * Celsius ) and the pressure ( in mb) using the equation: MIXR = .62197 * ( + * e / ( PRES - e ) ) * 1000. where e = VAPR * corr corr = (1.001 + ( ( PRES + * - 100. ) / 900. ) * .0034) ( University of Wisconsin green sheet ). This + * method can also be used for the folloiwng computations: MIXS from TMPC + * and PRES SMXR from DWPC and PALT SMXS from TMPC and PALT + * + * @param dwpc + * - the dewpoint ( in Celsius ) + * @param pres + * - the pressure ( in mb) + * @return the missing ratio ( in grams / kilograms ) if both the input + * parameters are valid + * @throws NullPointerException + * + */ + public static final Amount prMixr(Amount dwpc, Amount pres) { + // System.out.println("From prMixr:"); + // System.out.println(" dwpc = " + dwpc.doubleValue()); + // System.out.println(" pres = " + pres.doubleValue()); + + Amount prmixr = new Amount(-9999.0, Unit.ONE); + // checkNullOrInvalidValue(pres); + // checkNullOrInvalidValue(dwpc); + + if (!checkNullOrInvalidValue(pres) || !checkNullOrInvalidValue(dwpc)) + return new Amount(NcUnits.GRAMS_PER_KILOGRAM); + + pres = checkAndConvertInputAmountToExpectedUnits(pres, NcUnits.MILLIBAR); + dwpc = checkAndConvertInputAmountToExpectedUnits(dwpc, SI.CELSIUS); + + /* Calculate vapor pressure */ + Amount vapr = prVapr(dwpc); + + if (!checkNullOrInvalidValue(vapr)) + return new Amount(NcUnits.GRAMS_PER_KILOGRAM); + + vapr = checkAndConvertInputAmountToExpectedUnits(vapr, NcUnits.MILLIBAR); + double pressureValue = pres.doubleValue(); + double vaporPressureValue = vapr.doubleValue(); + /* + * (Non-Javadoc) corr is a correction to the vapor pressure since the + * atmosphere is not an ideal gas. + */ + double corr = (double) (1.001 + ((pressureValue - 100) / 900) * 0.0034); + double e = corr * vaporPressureValue; + + /* + * Test for unphysical case of large E at low PRES + */ + if (e <= (0.5 * pressureValue)) { + /* Calculate mixing ratio */ + prmixr = new Amount( + (double) (0.62197 * (e / (pressureValue - e)) * 1000), + NcUnits.GRAMS_PER_KILOGRAM); + } + return prmixr; + } + + /** + * Extracts the pressure change ( in millibars ) from the pressure tendency + * information + * + * @param p03d + * - Pressure tendency information + * @return the pressure change ( in mb ) + * @throws NullPointerException + * + */ + // TODO : remove it to make it a part of display options or let it stay? + public static final Amount prP03c(Amount p03d) + throws InvalidValueException, NullPointerException { + // System.out.println("From prP03c:"); + // System.out.println(" p03d = " + p03d.doubleValue()); + + double prp03c = GempakConstants.RMISSD; + // checkNullOrInvalidValue( p03d ); + if (!checkNullOrInvalidValue(p03d)) + return new Amount(NcUnits.MILLIBAR); + + double p03dVal = p03d.doubleValue(); + float[] psign = { 1, 1, 1, 1, 0, -1, -1, -1, -1 }; + int itendc = (int) (p03dVal / 1000); + float ptend = (float) (((int) p03dVal) % 1000) / 10f; + // TODO: compare tests with legacy + if (itendc < psign.length) + prp03c = psign[itendc] * ptend; + + return (new Amount(prp03c, NcUnits.MILLIBAR)); + } + + /** + * Computes station pressure from altimeter and station elevation using the + * equation PALT = ALTM * ( 1 - ( SELK * GAMUSD / To ) ) ** expo where SELK + * = SELV / 1000 To = US Std. Atmos. sea level temp in Kelvin = TMCK + 15 + * expo = GRAVTY / ( GAMUSD * RDGAS ) * 1000 Wallace and Hobbs. + * + * @param altm + * - Altimeter in millibars + * @param selv + * - Station elevation in meters + * @return the pressure in millibars if none of the input values are missing + * @throws NullPointerException + * + */ + public static final Amount prPalt(Amount altm, Amount selv) + throws InvalidValueException, NullPointerException { + // System.out.println("From prPalt:"); + // System.out.println(" altm = " + altm.doubleValue()); + // System.out.println(" selv = " + selv.doubleValue()); + + // checkNullOrInvalidValue( altm ); + // checkNullOrInvalidValue( selv ); + + if (!checkNullOrInvalidValue(altm) || !checkNullOrInvalidValue(selv)) + return new Amount(NcUnits.MILLIBAR); + + altm = checkAndConvertInputAmountToExpectedUnits(altm, NcUnits.MILLIBAR); + selv = checkAndConvertInputAmountToExpectedUnits(selv, SI.METER); + double hgtk = selv.getUnit().getConverterTo(SI.KILOMETER) + .convert(selv.doubleValue()); + + /* Calculate the exponent */ + double expo = (GempakConstants.GRAVTY + / (GempakConstants.GAMUSD * GempakConstants.RDGAS) * 1000.0f); + + /* Calculate pressure */ + double prpalt = (altm.doubleValue() * Math.pow((1 - (hgtk + * GempakConstants.GAMUSD / (GempakConstants.TMCK + 15))), expo)); + + return (new Amount(prpalt, NcUnits.MILLIBAR)); + } + + /** + * Computes the lifted condensation level pressure ( in mb ) for a parcel of + * air from TMPC, PRES, and TLCL. TLCL may be computed using PR_TLCL. The + * equation used is a modified Poisson equation: PLCL = PRES * ( TLCL / TMPK + * ) ** ( 1 / RKAPPA ) + * + * @param tmpc + * - Temperature ( in Celsius ) before lifting the air parcel + * @param pres + * - Pressure ( in mb ) before lifting the air parcel + * @param tlcl + * - Temperature ( in Kelvin ) at the lifted condensation level + * @return the pressure at the lifted condensation level, if all the inputs + * are valid + * @throws NullPointerException + * + */ + public static final Amount prPlcl(Amount tmpc, Amount pres, Amount tlcl) + throws InvalidValueException, NullPointerException { + double prplcl = GempakConstants.RMISSD; + // System.out.println("From prPlcl:"); + // System.out.println(" tmpc = " + tmpc.doubleValue()); + // System.out.println(" pres = " + pres.doubleValue()); + // System.out.println(" tlcl = " + tlcl.doubleValue()); + + // checkNullOrInvalidValue(tmpc); + // checkNullOrInvalidValue(pres); + // checkNullOrInvalidValue(tlcl); + if (!checkNullOrInvalidValue(tmpc) || !checkNullOrInvalidValue(pres) + || !checkNullOrInvalidValue(tlcl)) + return new Amount(NcUnits.MILLIBAR); + + tmpc = checkAndConvertInputAmountToExpectedUnits(tmpc, SI.CELSIUS); + pres = checkAndConvertInputAmountToExpectedUnits(pres, NcUnits.MILLIBAR); + tlcl = checkAndConvertInputAmountToExpectedUnits(tlcl, SI.KELVIN); + Amount tmpk = checkAndConvertInputAmountToExpectedUnits(tmpc, SI.KELVIN); + double tclValue = tlcl.doubleValue(); + double tmpkValue = tmpk.doubleValue(); + double presValue = pres.doubleValue(); + prplcl = (double) (presValue * Math.pow((tclValue / tmpkValue), + (1 / GempakConstants.RKAPPA))); + return new Amount(prplcl, NcUnits.MILLIBAR); + } + + /** + *
+     *  Computes the mean sea level pressure ( in mb ) from the station pressure ( in mb ),
+     *  the temperature ( in deg Celsius), the dewpoint ( in deg Celsius ) and 
+     *  the station elevation ( in meters ) using the equation:
+     *  	PMSL = PRES * EXP ( ( GRAVTY * SELV ) / ( RDGAS * TVAVE ) ) 
+     *     where
+     *     		 TVAVE = avg virtual temp between station and sea level 
+     *     		        = TVRK + ( DELTV / 2 )
+     *     		 DELTV = GAMUSD * SELV / 1000
+     *  Wallace and Hobbs.
+     * @param pres - the station pressure ( in mb )
+     * @param tmpc - the temperature ( in deg Celsius)
+     * @param dwpc - the dewpoint ( in deg Celsius )
+     * @param selv - the station elevation ( in meters )
+     * @return the mean sea level pressure ( in mb ) if all the inputs are valid
+     * 
+ * + * @throws NullPointerException + * + * @throws InvalidRangeException + */ + public static final Amount prPmsl(Amount pres, Amount tmpc, Amount dwpc, + Amount selv) throws InvalidValueException, NullPointerException { + // System.out.println("From prPmsl:"); + // System.out.println(" tmpc = " + tmpc.doubleValue()); + // System.out.println(" pres = " + pres.doubleValue()); + // System.out.println(" dwpc = " + dwpc.doubleValue()); + // System.out.println(" selv = " + selv.doubleValue()); + // checkNullOrInvalidValue( pres ); + // checkNullOrInvalidValue( tmpc ); + // checkNullOrInvalidValue( dwpc ); + // checkNullOrInvalidValue( selv ); + if (!checkNullOrInvalidValue(tmpc) || !checkNullOrInvalidValue(pres) + || !checkNullOrInvalidValue(dwpc) + || !checkNullOrInvalidValue(selv)) + return new Amount(NcUnits.MILLIBAR); + + pres = checkAndConvertInputAmountToExpectedUnits(pres, NcUnits.MILLIBAR); + tmpc = checkAndConvertInputAmountToExpectedUnits(pres, SI.CELSIUS); + dwpc = checkAndConvertInputAmountToExpectedUnits(pres, SI.CELSIUS); + selv = checkAndConvertInputAmountToExpectedUnits(pres, SI.METER); + + /* Calculate virtual temperature */ + Amount tv = prTvrk(tmpc, dwpc, pres); + + /* deltaV and tVave */ + double selvVal = selv.doubleValue(); + double deltaV = selvVal * GempakConstants.GAMUSD / 1000; + double tVave = tv.doubleValue() + (deltaV / 2); + double mathFormula = (GempakConstants.GRAVTY * selvVal) + / (GempakConstants.RDGAS * tVave); + double prpmsl = (pres.doubleValue() * Math.exp(mathFormula)); + + return (new Amount(prpmsl, NcUnits.MILLIBAR)); + } + + /** + * Computes the maximum precipitation amount for upto 4 preciptiation values + * in inches + * + * @param p01 + * - First precipitation amount + * @param p02 + * - Second precipitation amount + * @param p03 + * - Third precipitation amount + * @param p04 + * - Fourth precipitation amount + * @return the maximum precipitation + * @throws NullPointerException + * + */ + + public static final Amount prPr6x(Amount p01, Amount p02, Amount p03, + Amount p04) throws InvalidValueException, NullPointerException { + // System.out.println("From prPr6x:"); + // System.out.println(" p01 = " + p01.doubleValue()); + // System.out.println(" p02 = " + p02.doubleValue()); + // System.out.println(" p03 = " + p03.doubleValue()); + // System.out.println(" p04 = " + p04.doubleValue()); + Amount[] tempArray = { p01, p02, p03, p04 }; + int index = 0; + double[] tempDblArray = new double[4]; + for (Amount thisAmount : tempArray) { + if (!checkNullOrInvalidValue(thisAmount)) { + return new Amount(NonSI.INCH); + } + + if (thisAmount.getUnit() != NonSI.INCH) { + thisAmount = checkAndConvertInputAmountToExpectedUnits( + thisAmount, NonSI.INCH); + tempArray[index] = thisAmount; + } + tempDblArray[index] = thisAmount.doubleValue(); + index++; + } + + Arrays.sort(tempDblArray); + return (new Amount(tempDblArray[3], NonSI.INCH)); + } + + /** + * Computes PR24, the 24-hour precipitation calculated by summing four + * 6-hour precipitation values + * + * @param p01 + * - First 6-hour precipitation amount + * @param p02 + * - Second 6-hour precipitation amount + * @param p03 + * - Third 6-hour precipitation amount + * @param p04 + * - Fourth 6-hour precipitation amount + * @return the total 24-hour precipitation amount + * @throws InvalidRangeException + * @throws NullPointerException + * + */ + public static final Amount prPr24(Amount p01, Amount p02, Amount p03, + Amount p04) throws InvalidValueException, NullPointerException { + // System.out.println("From prPr24:"); + // System.out.println(" p01 = " + p01.doubleValue()); + // System.out.println(" p02 = " + p02.doubleValue()); + // System.out.println(" p03 = " + p03.doubleValue()); + // System.out.println(" p04 = " + p04.doubleValue()); + + // checkNullOrInvalidValue( p01 ); + // checkNullOrInvalidValue( p02 ); + // checkNullOrInvalidValue( p03 ); + // checkNullOrInvalidValue( p04 ); + + if (!checkNullOrInvalidValue(p01) || !checkNullOrInvalidValue(p02) + || !checkNullOrInvalidValue(p03) + || !checkNullOrInvalidValue(p04)) + return new Amount(NonSI.INCH); + + Amount[] tempArray = { p01, p02, p03, p04 }; + Arrays.sort(tempArray); + + Amount p24 = tempArray[3]; + double p01Val = p01.doubleValue(); + double p02Val = p02.doubleValue(); + double p03Val = p03.doubleValue(); + double p04Val = p04.doubleValue(); + double p24Val = p24.doubleValue(); + + if (p24Val > 0) { + p24Val = 0; + if (p01Val > 0) + p24Val += p01Val; + + if (p02Val > 0) + p24Val += p01Val; + + if (p03Val > 0) + p24Val += p01Val; + + if (p04Val > 0) + p24Val += p01Val; + + } + + if (p24Val < 0) { + // throw new + // InvalidRangeException("From prPr24: the total 24 hour precipitation amount cannot be less than 0 inches"); + System.out + .println("From prPr24: the total 24 hour precipitation amount cannot be less than 0 inches"); + return new Amount(NonSI.INCH); + } + return (new Amount(p24Val, NonSI.INCH)); + } + + /** + * Computes the station pressure ( in mb ) from the temperature ( in deg + * Celsius ) and the potential temperature ( in Kelvin ) using Poisson's + * equation: PRES = 1000. * ( PR_TMCK (TMPC) / THTA ) ** (1 / RKAPPA) + * + * @param tmpc + * - temperature (in deg Celsius) + * @param thta + * - potential temperature ( in Kelvin ) + * @return the station pressure ( in mb ) if both the inputs are valid + * @throws NullPointerException + * + * @throws InvalidRangeException + */ + public static final Amount prPres(Amount tmpc, Amount thta) + throws InvalidValueException, NullPointerException { + // System.out.println("From prPres:"); + // System.out.println(" tmpc = " + tmpc.doubleValue()); + // System.out.println(" thta = " + thta.doubleValue()); + + // checkNullOrInvalidValue( tmpc ); + // checkNullOrInvalidValue( thta ); + + if (!checkNullOrInvalidValue(tmpc) || !checkNullOrInvalidValue(thta)) + return new Amount(NcUnits.MILLIBAR); + + tmpc = checkAndConvertInputAmountToExpectedUnits(tmpc, SI.CELSIUS); + thta = checkAndConvertInputAmountToExpectedUnits(thta, SI.KELVIN); + double tmpcVal = tmpc.doubleValue(); + double thtaVal = thta.doubleValue(); + if (tmpcVal <= -GempakConstants.TMCK) { + // throw new + // InvalidRangeException("From prPres: the temperature must be greater than -273.15"); + System.out + .println("From prPres: the temperature must be greater than -273.15"); + return new Amount(NcUnits.MILLIBAR); + } + if (thtaVal <= 0) { + // throw new + // InvalidRangeException("From prPres: the potential temperature must be greater than 0"); + System.out + .println("From prPres: the potential temperature must be greater than 0"); + return new Amount(NcUnits.MILLIBAR); + } + double tmpkVal = tmpc.getUnit().getConverterTo(SI.KELVIN) + .convert(tmpcVal); + double prpres = (float) (1000 * Math.pow(tmpkVal / thtaVal, + 1 / GempakConstants.RKAPPA)); + + return (new Amount(prpres, NcUnits.MILLIBAR)); + } + + /** + * Extracts the symbol code from the pressure tendency information. The code + * number is returned follow by 999 so that the output is a 4-digit number. + * + * @param p03d + * - the pressure tendency information + * @return the pressure tendency symbol code if the input is valid + * @throws NullPointerException + * + */ + // TODO add it to the Met Parameters or remove it and make it part of the + // display options instead? + public static final Amount prPtsy(Amount p03d) + throws InvalidValueException, NullPointerException { + // System.out.println("From prPtsy:"); + // System.out.println(" p03d = " + p03d.doubleValue()); + + if (!checkNullOrInvalidValue(p03d)) + return new Amount(Unit.ONE); + + double p03dVal = p03d.doubleValue(); + int prptsy = -9999; + if (!(p03dVal < 0) & !(p03dVal >= 9000)) { + prptsy = ((int) (p03dVal / 1000)) * 1000 + 999; + } + return (new Amount(prptsy, Unit.ONE)); + } + + /** + * Computes the relative humidity ( in percent ) from the input temperature + * and dewpoint using the equation: RELH = VAPR / VAPS * 100 where VAPR = + * vapor pressure = PR_VAPR ( DWPC ) VAPS = saturation vapor pressure = + * PR_VAPR ( TMPC ) + * + * @param tmpc + * - temperature ( in Celsius ) + * @param dwpc + * - dewpoint ( in Celsius) + * @return the relative humidity ( in percent ) if both inputs are valid and + * RMISSD ( -9999.0 ) otherwise + * @throws NullPointerException + * + */ + public static final Amount prRelh(Amount tmpc, Amount dwpc) + throws InvalidValueException, NullPointerException { + // System.out.println("From prRelh:"); + // System.out.println(" tmpc = " + tmpc.doubleValue()); + // System.out.println(" dwpc = " + dwpc.doubleValue()); + + double prrelh = GempakConstants.RMISSD; + // checkNullOrInvalidValue(tmpc); + // checkNullOrInvalidValue(dwpc); + + if (!checkNullOrInvalidValue(tmpc) || !checkNullOrInvalidValue(dwpc)) + return new Amount(NonSI.PERCENT); + + tmpc = checkAndConvertInputAmountToExpectedUnits(tmpc, SI.CELSIUS); + dwpc = checkAndConvertInputAmountToExpectedUnits(dwpc, SI.CELSIUS); + + /* Find the vapor pressure */ + Amount e = prVapr(dwpc); + + if (!checkNullOrInvalidValue(e)) + return new Amount(NonSI.PERCENT); + + /* Find the saturated vapor pressure */ + Amount es = prVapr(tmpc); + + if (!checkNullOrInvalidValue(es)) + return new Amount(NonSI.PERCENT); + + /* Calculate humidity */ + prrelh = (e.doubleValue() / es.doubleValue()) * 100; + + return new Amount(prrelh, NonSI.PERCENT); + } + + /** + * Computes the dewpoint (in Celsius) from the temperature ( in Celsius ) + * and the relative humidity ( in percent ). + * + * @param tmpc + * - the temperature ( in deg Celsius ) + * @param relh + * - the relative humidity ( in percent ) + * @return the dewpoint in ( deg Celsius), if both inputs are valid and the + * value of the vapor pressure computed is greater than ( 1* + * e^(-30)) + * @throws InvalidRangeException + * @throws NullPointerException + * + */ + public static final Amount prRhdp(Amount tmpc, Amount relh) + throws InvalidValueException, NullPointerException { + // System.out.println("From prRhdp:"); + // System.out.println(" tmpc =" + tmpc.doubleValue()); + // System.out.println(" relh = " + relh.doubleValue()); + + // checkNullOrInvalidValue(tmpc); + // checkNullOrInvalidValue(relh); + + if (!checkNullOrInvalidValue(tmpc) || !checkNullOrInvalidValue(relh)) + return new Amount(SI.CELSIUS); + + tmpc = checkAndConvertInputAmountToExpectedUnits(tmpc, SI.CELSIUS); + relh = checkAndConvertInputAmountToExpectedUnits(relh, NonSI.PERCENT); + + /* Calculate saturation vapor pressure; test for existence */ + Amount vaps = prVapr(tmpc); + + if (!checkNullOrInvalidValue(vaps)) + return new Amount(SI.CELSIUS); + + /* Calculate vapor pressure */ + double relativeHumidity = relh.doubleValue(); + double saturationVaporPressure = vaps.doubleValue(); + double vapr = relativeHumidity * saturationVaporPressure / 100; + + /* Calculate dewpoint. The VAPR test prevents LOG blowups */ + double prrhdp = -191; + Amount dewpointAmount = null; + if (vapr >= (Math.pow(Math.E, -30))) {// legacy checks for 1.E-30 + prrhdp = (double) (243.5 * (Math.log(6.112) - Math.log(vapr)) / (Math + .log(vapr) - Math.log(6.112) - 17.67)); + + /* + * If the dew-point is less than -190 degrees C, it is treated as + * missing data Note: Legacy documents it but does not implement it. + * However, in CAVE, it was decided to implement it. + */ + + if (prrhdp < -190) { + System.out + .println(" From prRhdp: dewpoint is less than -190 C"); + return new Amount(SI.CELSIUS); + } + } + dewpointAmount = new Amount(prrhdp, SI.CELSIUS); + return dewpointAmount; + } + + public static class RZLL // implements ISerializableObject + { + // @DynamicSerializeElement + private static RZLL rzll; + + /** Station latitude in degrees */ + // @DynamicSerializeElement + Amount stltdg = null; + + /** Station longitude in degrees */ + // @DynamicSerializeElement + Amount stlndg = null; + + /** Range in kilometers */ + // @DynamicSerializeElement + Amount range = null; + + /** Geographic azimuth in radians */ + // @DynamicSerializeElement + Amount azim = null; + + /** Height above the ground in kilometers */ + // @DynamicSerializeElement + Amount hght = null; + + /** Latitude in degrees */ + // @DynamicSerializeElement + Amount xlat = null; + + /** Longitude in degrees */ + // @DynamicSerializeElement + Amount xlon = null; + + /** + * @return the xlat + */ + public Amount getXlat() { + return xlat; + } + + /** + * @return the xlon + */ + public Amount getXlon() { + return xlon; + } + + private static RZLL getInstance() { + if (rzll == null) { + rzll = new RZLL(); + } + return rzll; + } + + /** + * Computes the actual latitude/longitude given the station + * latitude/longitude, elevation and azimuth. It uses equations + * developed for use in the AOIPS radar. + * + * @param instltdg + * - Station latitude in degrees + * @param instlndg + * - Station longitude in degrees + * @param inrange + * - Range in kilometers + * @param inazim + * - Geographic azimuth in radians + * @param inhght + * - Height above ground in km + * @throws NullPointerException + * + */ + public void prRzll(Amount instltdg, Amount instlndg, Amount inrange, + Amount inazim, Amount inhght) throws InvalidValueException, + NullPointerException { + // System.out.println("From prRzll:"); + // System.out.println(" instltdg = " + instltdg.doubleValue()); + // System.out.println(" instlndg = " + instlndg.doubleValue()); + // System.out.println(" inrange = " + inrange.doubleValue()); + // System.out.println(" inazim = " + inazim.doubleValue()); + // System.out.println(" inhght = " + inhght.doubleValue()); + + // checkNullOrInvalidValue( instltdg ); + // checkNullOrInvalidValue( instlndg ); + // checkNullOrInvalidValue(inrange); + // checkNullOrInvalidValue(inazim); + // checkNullOrInvalidValue(inhght); + + if (!checkNullOrInvalidValue(instltdg) + || !checkNullOrInvalidValue(instlndg) + || !checkNullOrInvalidValue(inrange) + || !checkNullOrInvalidValue(inazim) + || !checkNullOrInvalidValue(inhght)) + return; + + instltdg = checkAndConvertInputAmountToExpectedUnits(instltdg, + NonSI.DEGREE_ANGLE); + instlndg = checkAndConvertInputAmountToExpectedUnits(instlndg, + NonSI.DEGREE_ANGLE); + inrange = checkAndConvertInputAmountToExpectedUnits(inrange, + SI.KILOMETER); + inazim = checkAndConvertInputAmountToExpectedUnits(inazim, + SI.RADIAN); + inhght = checkAndConvertInputAmountToExpectedUnits(inhght, + SI.KILOMETER); + + this.stltdg = new Amount(instltdg.doubleValue(), NonSI.DEGREE_ANGLE); + this.stlndg = new Amount(instlndg.doubleValue(), NonSI.DEGREE_ANGLE); + this.range = new Amount(inrange.doubleValue(), SI.KILOMETER); + this.azim = new Amount(inazim.doubleValue(), SI.RADIAN); + this.hght = new Amount(inhght.doubleValue(), SI.KILOMETER); + + double hdr = GempakConstants.RMISSD; + double elev = GempakConstants.RMISSD; + double rad = GempakConstants.RMISSD; + double radp = GempakConstants.RMISSD; + + /* Convert the station lat/lon to radians */ + Amount stlat = checkAndConvertInputAmountToExpectedUnits(stltdg, + NonSI.DEGREE_ANGLE); + Amount stlon = checkAndConvertInputAmountToExpectedUnits(stlndg, + NonSI.DEGREE_ANGLE); + + /* Get the elevation angle */ + hdr = (range.doubleValue() == 0.0f ? 0.0f : hght.doubleValue() + / range.doubleValue()); + // elev = (float) ( Math.abs(hdr) < 1.0f ? Math.asin(hdr) : 0.0f ); + elev = (Math.abs(hdr) <= 1.0f ? Math.asin(hdr) : 0.0f); + + double temp = (Math.pow(Math.sin(stlat.doubleValue()), 2)); + + /* Get the earth's corrected radius */ + rad = (6378.4 / Math.sqrt(1 + (0.00677 * temp))); + radp = 4 * (rad / 3); + + double dist = GempakConstants.RMISSD; + double cx = GempakConstants.RMISSD; + double cy = GempakConstants.RMISSD; + double mathFormula1 = GempakConstants.RMISSD; + double mathFormula2 = GempakConstants.RMISSD; + + /* Calculate the distance */ + double rangeVal = range.doubleValue(); + if (elev > 0.2618f) + dist = (double) (rangeVal * Math.cos(elev)); + else { + mathFormula1 = (double) ((1 - (Math.pow(elev, 2) / 2)) - rangeVal + * elev / radp); + dist = rangeVal * mathFormula1; + } + + /* Calculate the latitude and longitude */ + double azimVal = azim.doubleValue(); + cx = (double) (dist * Math.sin(azimVal)); + cy = (double) (dist * Math.cos(azimVal)); + + // mathFormula2 = ( float ) ( ( ( 2 * Math.pow( rad, 2 ) ) * + // Math.tan( stlat ) )); + // xlat = ( float ) ( stlat + ( cy / rad ) - ( Math.pow(cx, 2) / + // mathFormula2 ) ); + double stlatVal = stlat.doubleValue(); + mathFormula2 = (double) ((Math.pow(cx, 2) / (2 * Math.pow(rad, 2)) * Math + .tan(stlatVal))); + double xlatVal = (double) (stlatVal + (cy / rad) - mathFormula2); + double xlonVal = (double) (stlon.doubleValue() + (cx / (rad * Math + .cos(xlat.doubleValue())))); + + /* Change lat/lon to degrees */ + xlatVal = SI.RADIAN.getConverterTo(NonSI.DEGREE_ANGLE).convert( + xlatVal); + xlonVal = SI.RADIAN.getConverterTo(NonSI.DEGREE_ANGLE).convert( + xlonVal); + + this.xlat = new Amount(xlatVal, NonSI.DEGREE_ANGLE); + this.xlon = new Amount(xlonVal, NonSI.DEGREE_ANGLE); + } + } + + /** + * Computes the wind speed from the 'U' and 'V' components of the wind + * velocity. The formula is the square root of ( u^2 + v^2 ) + * + * @param uWnd + * - U component of velocity + * @param vWnd + * - V component of velocity + * @return the computed windspeed if both inputs are valid + * @throws NullPointerException + * + */ + public static final Amount prSped(Amount uWnd, Amount vWnd) + throws InvalidValueException, NullPointerException { + // System.out.println("From prSped:"); + // System.out.println(" uWnd = " +uWnd.doubleValue()); + // System.out.println(" vWnd = " + vWnd.doubleValue()); + + // checkNullOrInvalidValue( uWnd ); + // checkNullOrInvalidValue( vWnd ); + if (!checkNullOrInvalidValue(uWnd) || !checkNullOrInvalidValue(vWnd)) + return new Amount(uWnd.getUnit()); + + Unit uWndUnits = uWnd.getUnit(); + Unit vWndUnits = vWnd.getUnit(); + if (uWndUnits != vWndUnits && uWndUnits.isCompatible(vWndUnits)) { + double vWndVal = vWndUnits.getConverterTo(uWndUnits).convert( + vWnd.doubleValue()); + vWnd = new Amount(vWndVal, uWndUnits); + } + double prsped = (Math.sqrt((Math.pow(uWnd.doubleValue(), 2) + Math.pow( + vWnd.doubleValue(), 2)))); + return new Amount(prsped, uWndUnits); + } + + /** + * Computes the potential temperature ( in Kelvin ) from the temperature (in + * Celsius ) and the pressure ( in mb ). + * + * @param tmpc + * - The temperature ( in Celsius ) + * @param pres + * - The pressure ( in mb ) + * @return the potential temperature ( in Kelvin ), if both inputs are valid + * . + * @throws InvalidRangeException + * @throws NullPointerException + * + */ + public static Amount prThta(Amount tmpc, Amount pres) + throws InvalidValueException, NullPointerException { + checkNullOrInvalidValue(tmpc); + checkNullOrInvalidValue(pres); + + if (!checkNullOrInvalidValue(tmpc) || !checkNullOrInvalidValue(pres)) + return new Amount(SI.KELVIN); + + tmpc = checkAndConvertInputAmountToExpectedUnits(tmpc, SI.CELSIUS); + pres = checkAndConvertInputAmountToExpectedUnits(pres, NcUnits.MILLIBAR); + double pressureValue = pres.doubleValue(); + if (pressureValue <= 0) { + System.out.println("From prThta( ) - pressure must be > 0 "); + return new Amount(SI.KELVIN); + // throw new + // InvalidRangeException("From prThta( ) - pressure must be > 0 "); + } + + /* Change temperature in degrees Celsius to Kelvin. */ + double temperatureInKelvin = (double) tmpc.getUnit() + .getConverterTo(SI.KELVIN).convert(tmpc.doubleValue()); + + /* Calculate theta using Poisson's equation */ + double prthta = (double) (temperatureInKelvin * Math.pow( + (1000 / pres.doubleValue()), GempakConstants.RKAPPA)); + return new Amount(prthta, SI.KELVIN); + } + + /** + * Computes the equivalent potential temperature ( in Kelvin ) from the + * pressure ( in mb ), the temperature ( in Celsius ) and the dewpoint ( in + * Celsius ) using the equation: THTE = THTAM * EXP [ ( 3.376/TLCL - .00254 + * ) * ( MIXR * ( 1 + .81*.001*MIXR ) ) ] where THTAM = potential + * temperature of moist air = TMPK * (1000 / PRES) ** E E = RKAPPA * ( 1 - ( + * .28 * .001 * MIXR ) ) Bolton. + * + * @param pres + * - the pressure ( in mb ) + * @param tmpc + * - the temperature ( in Celsius ) + * @param dwpc + * - the dewpoint ( in Celsius ) + * @return the the equivalent potential temperature ( in Kelvin ), if all + * the input values are valid + * @throws NullPointerException + * + * @throws InvalidRangeException + */ + public static final Amount prThte(Amount pres, Amount tmpc, Amount dwpc) { + // System.out.println("From prThte:"); + // System.out.println(" pres = " + pres.doubleValue()); + // System.out.println(" tmpc = " + tmpc.doubleValue()); + // System.out.println(" dwpc = " + dwpc.doubleValue()); + + // checkNullOrInvalidValue(pres); + // checkNullOrInvalidValue(tmpc); + // checkNullOrInvalidValue(dwpc); + if (!checkNullOrInvalidValue(tmpc) || !checkNullOrInvalidValue(pres) + || !checkNullOrInvalidValue(dwpc)) + return new Amount(SI.KELVIN); + + if (pres.doubleValue() <= 0) { + System.out + .println("From prThte() - Input pressure must be greater than 0 "); + return new Amount(SI.KELVIN); + // throw new + // InvalidRangeException("From prThte() - Input pressure must be greater than 0 "); + } + + pres = checkAndConvertInputAmountToExpectedUnits(pres, NcUnits.MILLIBAR); + dwpc = checkAndConvertInputAmountToExpectedUnits(dwpc, SI.CELSIUS); + tmpc = checkAndConvertInputAmountToExpectedUnits(tmpc, SI.CELSIUS); + + /* Find mixing ratio */ + Amount rmix = prMixr(dwpc, pres); + if (!checkNullOrInvalidValue(rmix)) + return new Amount(SI.KELVIN); + /* Change degrees Celsius to Kelvin */ + Amount tmpk = checkAndConvertInputAmountToExpectedUnits(tmpc, SI.KELVIN); + + /* Calculate theta for moist air (thtam) */ + double mixingRatioVal = rmix.doubleValue(); + double pressureVal = pres.doubleValue(); + double tempVal = tmpk.doubleValue(); + + double e = (double) (GempakConstants.RKAPPA * (1 - (0.28 * 0.001 * mixingRatioVal))); + double thtam = (double) (tempVal * Math.pow(1000 / pressureVal, e)); + + /* Find the temperature at the lifted condensation level */ + Amount tlcl = prTlcl(tmpc, dwpc); + + if (!checkNullOrInvalidValue(tlcl)) + return new Amount(SI.KELVIN); + + double lclTemp = tlcl.doubleValue(); + e = ((3.376f / lclTemp) - 0.00254f) + * (mixingRatioVal * (1 + 0.81f * 0.001f * mixingRatioVal)); + double prthte = (double) (thtam * Math.exp(e)); + Amount equivPotentialTempAmount = new Amount(prthte, SI.KELVIN); + return equivPotentialTempAmount; + } + + /** + * Computes wet bulb potential temperature ( in Celsius ) from the pressure, + * temperature and dewpoint. The result is obtained by first computing the + * equivalent potential temperature (thte) of the the air parcel at level + * pres. Then the air parcel is brought to 1000 mb moist adiabatically to + * get the wet bulb potential temperature. + * + * @param pres + * - Pressure ( in millibars ) + * @param tmpc + * - Temperature ( in Celsius ) + * @param dwpc + * - Dewpoint ( in Celsius ) + * @return The wet bulb potential temperature ( in Celsius ) if all inputs + * are valid + * @throws NullPointerException + * + * @throws InvalidRangeException + */ + public static final Amount prThwc(Amount pres, Amount tmpc, Amount dwpc) + throws InvalidValueException, NullPointerException { + // System.out.println(" PRLibrary/prThwc:"); + // System.out.println(" PRLibrary/prThwc. press = " + + // pres.doubleValue()); + // System.out.println(" PRLibrary/prThwc.tmpc = " + tmpc.doubleValue()); + // System.out.println(" PRLibrary/prThwc.dwpc = " + dwpc.doubleValue()); + + /* Check for missing and invalid data */ + // checkNullOrInvalidValue( pres ); + // checkNullOrInvalidValue( tmpc ); + // checkNullOrInvalidValue( dwpc ); + + if (!checkNullOrInvalidValue(tmpc) || !checkNullOrInvalidValue(pres) + || !checkNullOrInvalidValue(dwpc)) + return new Amount(SI.CELSIUS); + + pres = checkAndConvertInputAmountToExpectedUnits(pres, NcUnits.MILLIBAR); + tmpc = checkAndConvertInputAmountToExpectedUnits(tmpc, SI.CELSIUS); + dwpc = checkAndConvertInputAmountToExpectedUnits(dwpc, SI.CELSIUS); + + // System.out + // .println(" PRLibrary/prThwc. press 2 = " + pres.doubleValue()); + // System.out.println(" PRLibrary/prThwc.tmpc 2 = " + + // tmpc.doubleValue()); + // System.out.println(" PRLibrary/prThwc.dwpc 2 = " + + // dwpc.doubleValue()); + + double presVal = pres.doubleValue(); + // System.out + // .println(" PRLibrary/prThwc. press 3 = " + pres.doubleValue()); + + if (presVal <= 0) { + System.out + .println("From prThwc: Pressure must be greater than 0 mb"); + return new Amount(SI.CELSIUS); + // throw new + // InvalidRangeException("From prThwc: Pressure must be greater than 0 mb"); + } + /* Compute the thte */ + Amount thte = prThte(pres, tmpc, dwpc); + // System.out.println(" PRLibrary/prThwc. thte 4 = " + + // thte.doubleValue()); + + /* Check for missing 'thte' and compute wet bulb temperature. */ + if (!checkNullOrInvalidValue(thte)) + return new Amount(SI.CELSIUS); + /* Compute the parcel temperature (in Kelvin) */ + + Amount prthwc = prTmst(thte, new Amount(1000, NcUnits.MILLIBAR), + new Amount(0, SI.KELVIN)); + // System.out.println(" PRLibrary/prThwc. prthwc (K) 5 = " + // + prthwc.doubleValue()); + + if (!checkNullOrInvalidValue(prthwc)) + return new Amount(SI.CELSIUS); + /* Convert the parcel temperature to Celsius */ + prthwc = checkAndConvertInputAmountToExpectedUnits(prthwc, SI.CELSIUS); + // System.out.println(" PRLibrary/prThwc. prthwc (C) 6 = " + // + prthwc.doubleValue()); + return prthwc; + } + + /** + * Computes the temperature at the lifted condensation level for a parcel of + * air given the temperature ( in Celsius ) and the dewpoint (in Celsius) + * using the equation: TLCL = [ 1 / ( 1 / (DWPK-56) + ALOG (TMPK/DWPK) / 800 + * ) ] + 56 Bolton. + * + * @param tmpc + * - the temperature ( in Celsius ) + * @param dwpc + * - the dewpoint ( in Celsius ) + * @return the lifted condensation level temperature In Kelvin, if both + * input values are valid + * + * @throws NullPointerException + * + * @throws InvalidRangeException + */ + public static final Amount prTlcl(Amount tmpc, Amount dwpc) { + // System.out.println("From prTlcl:"); + // System.out.println(" tmpc = " + tmpc.doubleValue()); + // System.out.println(" dwpc = " + dwpc.doubleValue()); + + // checkNullOrInvalidValue(tmpc); + // checkNullOrInvalidValue(dwpc); + if (!checkNullOrInvalidValue(tmpc) || !checkNullOrInvalidValue(dwpc)) + return new Amount(SI.KELVIN); + + if (tmpc.doubleValue() < -GempakConstants.TMCK + || dwpc.doubleValue() < -GempakConstants.TMCK) { + System.out + .println("From prTlcl: Input temperature cannot be less than -273.15"); + return new Amount(SI.KELVIN); + } + Amount tmpk = checkAndConvertInputAmountToExpectedUnits(tmpc, SI.KELVIN); + Amount dwpk = checkAndConvertInputAmountToExpectedUnits(dwpc, SI.KELVIN); + double tempVal = tmpk.doubleValue(); + double dewpointVal = dwpk.doubleValue(); + double lclTemp = (double) ((800 * (dewpointVal - 56) / (800 + (dewpointVal - 56) + * Math.log(tempVal / dewpointVal))) + 56); + Amount prtlcl = new Amount(lclTemp, SI.KELVIN); + + return prtlcl; + } + + /** + * Computes the temperature ( in Kelvin ) from the pressure ( in mb ) and + * the potential temperature ( in Kelvin ) using the Poisson equation: TMPK + * = THTA * ( PRES / 1000 ) ** RKAPPA + * + * @param pres + * - the pressure ( in mb ) + * @param thta + * - the potential temperature ( in Kelvin ) + * @return the temperature ( in Kelvin ) + * @throws InvalidRangeException + * @throws NullPointerException + * + */ + public static final Amount prTmpk(Amount pres, Amount thta) + throws InvalidValueException, NullPointerException { + // System.out.println("From prTmpk:"); + // System.out.println(" pres = " + pres.doubleValue()); + // System.out.println("thta = " + thta.doubleValue()); + + Amount prtmpk = new Amount(SI.KELVIN); + if (!checkNullOrInvalidValue(pres) || !checkNullOrInvalidValue(thta)) { + return new Amount(SI.KELVIN); + } + + pres = checkAndConvertInputAmountToExpectedUnits(pres, NcUnits.MILLIBAR); + thta = checkAndConvertInputAmountToExpectedUnits(thta, SI.KELVIN); + double pressureValue = pres.doubleValue(); + double thtaValue = thta.doubleValue(); + if (pressureValue >= 0) { + double temperature = (double) (thtaValue * (Math.pow( + pressureValue / 1000f, GempakConstants.RKAPPA))); + prtmpk = new Amount(temperature, SI.KELVIN); + return prtmpk; + } else { + System.out + .println("From prTmpk() - pressure cannot be less than 0 mb"); + return new Amount(SI.KELVIN); + // throw new + // InvalidRangeException("From prTmpk() - pressure cannot be less than 0 mb"); + } + } + + /** + *
+     * Computes the parcel temperature ( in Kelvin ) from the equivalent potential temp ( in Kelvin ),
+     * pressure ( in millibars ) and the first guess temperature ( in Kelvin ). 
+     * The parcel temperature at level pres on a specified moist adiabat ( thte ). 
+     * The computation is an iterative Newton-Raphson technique of the form:
+     * 
+     * x = x(guess) + [ f( x ) - f( x(guess) ) ] / f'( x(guess) )
+     * f' is approximated with finite differences
+     * f' = [ f( x(guess) + 1 ) - f( x(guess) ) ] / 1
+     * 
+     * If tguess is 0, a reasonable first guess will be made.
+     * Convergence is not guaranteed for extreme input values.  If the
+     * computation does not converge after 100 iterations, the missing 
+     * data value will be returned. 
+     * @param thte      - Equivalent potential temp ( in Kelvin )
+     * @param pres      - Pressure ( in millibars )
+     * @param tguess   - First guess temperature ( in Kelvin )
+     * @return the Parcel temperature in Kelvin if all the input values are valid 
+     * (without being extreme) and if a convergence is obtained within 100 iterations
+     * 
+ * + * @throws NullPointerException + * + */ + public static final Amount prTmst(Amount thte, Amount pres, Amount tguess) { + double prtmst = GempakConstants.RMISSD; + // System.out.println(" PRLibrary/prTmst:"); + // System.out.println(" PRLibrary/prTmst. thte = " + + // thte.doubleValue()); + // System.out.println(" PRLibrary/prTmst. pres = " + + // pres.doubleValue()); + // System.out.println(" PRLibrary/prTmst. tguess = " + // + tguess.doubleValue()); + if (!checkNullOrInvalidValue(pres) || !checkNullOrInvalidValue(thte) + || !checkNullOrInvalidValue(tguess)) { + return new Amount(SI.KELVIN); + } + // checkNullOrInvalidValue( thte ); + // checkNullOrInvalidValue( pres ); + // checkNullOrInvalidValue( tguess ); + thte = checkAndConvertInputAmountToExpectedUnits(thte, SI.KELVIN); + pres = checkAndConvertInputAmountToExpectedUnits(pres, NcUnits.MILLIBAR); + tguess = checkAndConvertInputAmountToExpectedUnits(tguess, SI.KELVIN); + double thteVal = thte.doubleValue(); + double presVal = pres.doubleValue(); + double tguessVal = tguess.doubleValue(); + + if (thteVal <= 0) { + System.out + .println(" From prTmst(): Potential temperature must be greater than 0"); + return new Amount(SI.KELVIN); + // throw new + // InvalidRangeException(" From prTmst(): Potential temperature must be greater than 0"); + } else if (presVal <= 0) { + System.out + .println(" From prTmst(): Pressure must be greater than 0"); + return new Amount(SI.KELVIN); + // throw new + // InvalidRangeException(" From prTmst(): Pressure must be greater than 0"); + } else if (tguessVal < 0) { + System.out + .println(" From prTmst(): First guess temperature must be greater than or equal to 0"); + return new Amount(SI.KELVIN); + // throw new + // InvalidRangeException(" From prTmst(): First guess temperature must be greater than 0"); + } + double tg = tguess.doubleValue(); + // System.out.println(" PRLibrary/prTmst. thteVal 2 = " + thteVal); + // System.out.println(" PRLibrary/prTmst. presVal 2 = " + presVal); + // System.out.println(" PRLibrary/prTmst. tguessVal 2 = " + tguessVal); + // System.out.println(" PRLibrary/prTmst. tg 2 = " + tg); + + /* + * If tguess is passed as 0. it is computed from an MIT scheme + */ + if (tg == 0) { + double diffVar = thte.doubleValue() - 270; + double mathFormula1 = (double) (diffVar > 0 ? diffVar : 0.0); + tg = (double) ((thte.doubleValue() - .5f * (Math.pow(mathFormula1, + 1.05f))) * (Math.pow(pres.doubleValue() / 1000.0f, 0.2f))); + } + + /* Set convergence and initial guess in degrees Celsius */ + double epsi = 0.01f; + double tgnu = SI.KELVIN.getConverterTo(SI.CELSIUS).convert(tg); + + /* + * Set a limit of 100 iterations. Compute tenu,tenup, the thte's at one + * degree above the guess temperature. + */ + int index = 0; + while (index < 100) { + double tgnup = tgnu + 1; + Amount tgnuAmount = new Amount(tgnu, SI.CELSIUS); + Amount tgnupAmount = new Amount(tgnup, SI.CELSIUS); + Amount tenu = prThte(pres, tgnuAmount, tgnuAmount); + Amount tenup = prThte(pres, tgnupAmount, tgnupAmount); + // System.out.println(" PRLibrary/prTmst. tgnuAmount 5 = " + // + tgnuAmount.getValue().floatValue()); + // System.out.println(" PRLibrary/prTmst. tgnupAmount 5 = " + // + tgnupAmount.getValue().floatValue()); + // System.out.println(" PRLibrary/prTmst. tenu 5 = " + // + tenu.getValue().floatValue()); + // System.out.println(" PRLibrary/prTmst. tgnup 5 = " + // + tenup.getValue().floatValue()); + /* Check that the THTE's exist. */ + + if ((!checkNullOrInvalidValue(tenu) || !checkNullOrInvalidValue(tenup))) { + return new Amount(SI.KELVIN); + // index++; + // continue; + } + + /* Compute the correction */ + double tenuVal = tenu.doubleValue(); + double tenupVal = tenup.doubleValue(); + double cor = (thteVal - tenuVal) / (tenupVal - tenuVal); + tgnu += cor; + // System.out.println(" PRLibrary/prTmst. tenuVal 6 = " + tenuVal); + // System.out.println(" PRLibrary/prTmst. tenupVal 6 = " + + // tenupVal); + + // System.out.println(" PRLibrary/prTmst. cor 6 = " + cor); + // System.out.println(" PRLibrary/prTmst. tgnu 6 = " + tgnu); + + if ((cor < epsi) && (-cor < epsi)) { + + /* return on convergence */ + prtmst = tgnuAmount.getUnit().getConverterTo(SI.KELVIN) + .convert(tgnu); + // System.out.println(" PRLibrary/prTmst. prtmst 7 = " + + // prtmst); + + break; + } + + index++; + } + // System.out.println(" PRLibrary/prTmst. prtmst 8 = " + // + new Amount(prtmst, SI.KELVIN).getValue().floatValue()); + + return new Amount(prtmst, SI.KELVIN); + } + + /** + *
+     * Computes wet bulb temperature from the temperature, mixing ratio, and pressure.
+     * The result is obtained by solving for the temperature at which saturation occurs,
+     *  when the latent heat required to vaporize the water is provided by a cooling of the air.
+     *  The equation representing the process is:
+     *   ( tmpk - tmwb ) * cp - ( Rsat (tmwb) - rmix ) * lvap = 0  
+     *  This implicit equation is solved by Newton's method, since the 
+     *  saturation mixing ratio Rsat is a transcendental function of tmwb.
+     *  The expressions for the heat of vaporization (LVAP) and saturation 
+     *   vapor pressure are equations (2) and (10) from Bolton (MWR, 1980).
+     * 
+ * + * @param tmpk + * - Temperature (K) + * @param rmix + * - Mixing ratio (g/kg) + * @param pres + * - Pressure (mb) + * @return Wet bulb temperature (K) if all inputs are valid + * @throws NullPointerException + * + */ + public static final Amount prTmwb(Amount tmpk, Amount rmix, Amount pres) + throws InvalidValueException, NullPointerException { + // System.out.println("From prTmwb:"); + // System.out.println(" tmpk = " + tmpk.doubleValue()); + // System.out.println(" rmix = " + rmix.doubleValue()); + // System.out.println(" pres = " + pres.doubleValue()); + + Amount prtmwb = null; + /* Check for missing and invalid data */ + // checkNullOrInvalidValue( tmpk ); + // checkNullOrInvalidValue( rmix ); + // checkNullOrInvalidValue( pres ); + if (!checkNullOrInvalidValue(pres) || !checkNullOrInvalidValue(tmpk) + || !checkNullOrInvalidValue(rmix)) { + return new Amount(SI.KELVIN); + } + tmpk = checkAndConvertInputAmountToExpectedUnits(tmpk, SI.KELVIN); + rmix = checkAndConvertInputAmountToExpectedUnits(rmix, + NcUnits.GRAMS_PER_KILOGRAM); + pres = checkAndConvertInputAmountToExpectedUnits(pres, NcUnits.MILLIBAR); + double presVal = pres.doubleValue(); + if (presVal <= 0) { + // System.out + // .println("From prTmwb - pressure value must be greater than 0 "); + return new Amount(SI.KELVIN); + // throw new + // InvalidRangeException("From prTmwb - pressure value must be greater than 0 "); + } + /* Change temperature to degrees Celsius. */ + Amount tmp = checkAndConvertInputAmountToExpectedUnits(tmpk, SI.CELSIUS); + + /* Compute the latent heat of vaporization. */ + Amount lvap = prLhvp(tmp); + if (!checkNullOrInvalidValue(lvap)) + return new Amount(SI.KELVIN); + /* Compute the specific heat of moist air */ + double rmixVal = rmix.doubleValue() / 1000; + double cp = (1005.7 * (1.0 + 0.887 * rmixVal)); + + double rlocp = lvap.doubleValue() / cp; + + /* Do Newton iteration */ + int iter = 0; + double twb = tmp.doubleValue(); + boolean isConvrg = false; + + double A = 6.112; + double B = 17.67; + double C = 243.5; + double EPSI = 0.622; + double G = B * C; + double ERRMAX = 0.001; + double tmpVal = tmp.doubleValue(); + while (iter <= 50 && !isConvrg) { + iter++; + double bt = B * twb; + double tpc = twb + C; + double d = ((presVal / A) * Math.exp((-bt) / tpc)); + double dm1 = d - 1; + double f = (tmpVal - twb) - rlocp * (EPSI / dm1 - rmixVal); + double df = (-G) / (tpc * tpc); + df = d * df * rlocp * EPSI / (dm1 * dm1) - 1; + double cor = f / df; + twb = twb - cor; + if (Math.abs(cor) <= ERRMAX) + isConvrg = true; + } + + if (isConvrg) { + Amount twk = new Amount(twb, SI.KELVIN); + if (twk.doubleValue() > tmpk.doubleValue()) + twk = new Amount(tmpk.doubleValue(), SI.KELVIN); + + prtmwb = twk; + } + // } + return prtmwb; + } + + /** + * Computes the virtual temperature ( in Kelvin ) from the temperature ( in + * Celsius ), dewpoint ( in Celsius ) and pressure ( in mb ) where DWPC and + * PRES are used to compute MIXR. The following equation is used: TVRK = + * TMPK * (1 + .001 * MIXR / .62197) / (1 + .001 * MIXR) If DWPC is missing, + * dry air is assumed and TMPK is returned. + * + * @param tmpc + * - Temperature ( in Celsius ) + * @param dwpc + * - Dewpoint ( in Celsius ) + * @param pres + * - Pressure ( in mb ) + * @return the virtual temperature ( in Kelvin ) + * @throws NullPointerException + * + */ + public static final Amount prTvrk(Amount tmpc, Amount dwpc, Amount pres) + throws InvalidValueException, NullPointerException { + // System.out.println("From prTvrk:"); + // System.out.println(" tmpc = " + tmpc.doubleValue()); + // System.out.println(" dwpc = " + dwpc.doubleValue()); + // System.out.println(" pres = " + pres.doubleValue()); + + Amount prtvrk = null; + // checkNullOrInvalidValue(tmpc); + // checkNullOrInvalidValue(pres); + + if (!checkNullOrInvalidValue(pres) || !checkNullOrInvalidValue(tmpc)) { + return new Amount(SI.KELVIN); + } + + /* If dewpoint is missing, return temperature */ + + if (!checkNullOrInvalidValue(dwpc)) + return checkAndConvertInputAmountToExpectedUnits(tmpc, SI.KELVIN); + + else { + /* Change temperature to Kelvin. */ + Amount tmpk = checkAndConvertInputAmountToExpectedUnits(tmpc, + SI.KELVIN); + + /* Find mixing ratio in g/kg; if missing, return temperature */ + Amount rmix = prMixr(dwpc, pres); + + double virtualTemp; + if (rmix.doubleValue() == GempakConstants.RMISSD) + virtualTemp = (double) tmpc.getUnit().getConverterTo(SI.KELVIN) + .convert(tmpc.doubleValue()); + else { + double mixingRatioVal = rmix.doubleValue(); + double temp = tmpk.doubleValue(); + virtualTemp = (double) (temp + * (1 + 0.001 * mixingRatioVal / 0.62197) / (1 + 0.001 * mixingRatioVal)); + + } + prtvrk = new Amount(virtualTemp, SI.KELVIN); + } + return prtvrk; + } + + /** + * Computes the 'U' component of the wind from its speed and direction + * + * @param sped + * - wind speed + * @param drct + * - wind direction + * @return The 'U' component of the wind if both inputs are valid + * @throws NullPointerException + * + */ + public static final Amount prUwnd(Amount sped, Amount drct) + throws InvalidValueException, NullPointerException { + // System.out.println("From prUwnd:"); + // System.out.println(" sped = " + sped.doubleValue()); + // System.out.println(" drct = " + drct.doubleValue()); + if (!checkNullOrInvalidValue(drct) || !checkNullOrInvalidValue(sped)) { + return new Amount(SI.METERS_PER_SECOND); + } + drct = checkAndConvertInputAmountToExpectedUnits(drct, + NonSI.DEGREE_ANGLE); + double pruwnd = ((-Math.sin(drct.doubleValue() * GempakConstants.DTR)) * sped + .doubleValue()); + return new Amount(pruwnd, sped.getUnit()); // TODO :verify the units + } + + /** + * Computes the 'V' component of the wind from its speed and direction + * + * @param sped + * - wind speed + * @param drct + * - wind direction + * @return The 'V' component of the wind if both inputs are valid + * @throws NullPointerException + * + */ + public static final Amount prVwnd(Amount sped, Amount drct) + throws InvalidValueException, NullPointerException { + // System.out.println("From prVwnd:"); + // System.out.println(" sped = " + sped.doubleValue()); + // System.out.println(" drct = " + drct.doubleValue()); + if (!checkNullOrInvalidValue(drct) || !checkNullOrInvalidValue(sped)) { + return new Amount(SI.METERS_PER_SECOND); + } + drct = checkAndConvertInputAmountToExpectedUnits(drct, + NonSI.DEGREE_ANGLE); + double prvwnd = ((-Math.cos(drct.doubleValue() * GempakConstants.DTR)) * sped + .doubleValue()); + return new Amount(prvwnd, sped.getUnit()); // TODO :verify the units + } + + /** + * Computes the vapor pressure ( in mb) from the input dewpoint temperature + * in Celsius using the equation: VAPR = 6.112 * EXP [ (17.67 * + * dewpointValue) / (dewpointValue + 243.5) ] + * + * @param dwpc + * - the dewpoint temperature ( in Celsius ) + * @return the vapor pressure ( in mb) from the dewpoint temperature if it + * is valid + * @throws NullPointerException + * + */ + public static final Amount prVapr(Amount dwpc) { + // System.out.println("From prVapr:"); + // System.out.println(" dwpc = " + dwpc.doubleValue()); + + if (!checkNullOrInvalidValue(dwpc)) + return new Amount(NcUnits.MILLIBAR); + dwpc = checkAndConvertInputAmountToExpectedUnits(dwpc, SI.CELSIUS); + double dewpointValue = dwpc.doubleValue(); + if (dewpointValue >= -240.0f) + return (new Amount((6.112 * (Math.exp((17.67 * dewpointValue) + / (dewpointValue + 243.5)))), NcUnits.MILLIBAR)); + else { + // throw new + // InvalidRangeException("Exception from prVapr() - dewpoint cannot be less than -240 "); + System.out + .println("From prVapr() - dewpoint cannot be less than -240 "); + return new Amount(NcUnits.MILLIBAR); + } + } + + // /** + // * Computes the visibility ( in nautical miles ) from the input visibility + // ( in kilometers ) + // * @param vsbk - visibility ( in kilometers ) + // * @return visibility ( in nautical miles ) if the input is valid + // * @throws NullPointerException + // * + // */ + // //TODO: remove this - since the getValueAs(Unit) offers the same + // facility? + // public static final Amount prVskn ( Amount vsbk) throws + // InvalidValueException, NullPointerException { + // //System.out.println("From prVskn:"); + // //System.out.println(" vsbk = " + vsbk.doubleValue()); + // + // checkNullOrInvalidValue( vsbk ); + // vsbk = checkAndConvertInputAmountToExpectedUnits( vsbk, SI.KILOMETER ); + // return ( checkAndConvertInputAmountToExpectedUnits(vsbk, + // NonSI.NAUTICAL_MILE ) ); + // } + + /** + * Computes the wind chill equivalent temperature ( the temperature with + * calm winds that produces the same cooling effect as the given temperature + * with the given wind speed) + * + * @param tmpf + * - Air temperature ( in Farenheit ) + * @param sknt + * - Wind speed ( in knots ) + * @return the wind chill equivalent temperature ( in Farenheit ), if the + * inputs are valid + * @throws NullPointerException + * + */ + public static final Amount prWceq(Amount tmpf, Amount sknt) + throws InvalidValueException, NullPointerException { + // System.out.println("From prWceq:"); + // System.out.println(" tmpf = " + tmpf.doubleValue()); + // System.out.println(" sknt = " + sknt.doubleValue()); + + double prwceq = GempakConstants.RMISSD; + if (!checkNullOrInvalidValue(tmpf) || !checkNullOrInvalidValue(sknt)) { + return new Amount(NonSI.FAHRENHEIT); + } + + /* Convert input variables to Celsius and meters/second. */ + Amount tmpc = checkAndConvertInputAmountToExpectedUnits(tmpf, + SI.CELSIUS); + Amount sped = checkAndConvertInputAmountToExpectedUnits(sknt, + SI.METERS_PER_SECOND); + + if (sped.doubleValue() <= 1.34) + /* + * If the wind speed does not exceed 1.34 m/s ( not much wind to + * contribute to the wind chill), return the input temperature as + * the wind chill temperature + */ + prwceq = tmpc.getUnit().getConverterTo(NonSI.FAHRENHEIT) + .convert(tmpc.doubleValue()); + else { + /* + * Compute the wind chill temp if the inputs are not missing and and + * the wind speed is greater than 1.34 m/s. Equations for wind chill + * computation from R. Falconer, + * "Windchill, A Useful Wintertime Weather Variable", Weatherwise, + * Dec 1968. + */ + if (sped.getUnit() == SI.METERS_PER_SECOND) { + float windChill = (float) (33.0 - ((33.0 - tmpc.doubleValue()) + * wci(sped.doubleValue()) / wci(1.34f))); + prwceq = tmpc.getUnit().getConverterTo(NonSI.FAHRENHEIT) + .convert(windChill); + } + } + + return (new Amount(prwceq, NonSI.FAHRENHEIT)); + } + + // /** + // * Computes the numeric total cloud cover for the worst case aviation + // flight condition, + // * based on the categorical identification of flight rules for prevailing + // and temporary / probability conditions. + // * @param xvfr - Prevailing categorical id of flight rules + // * @param txvf - Temporary / Probability categorical id of flight rules + // * @param cfrt - Prevailing numeric total cloud cover + // * @param tcfr - Temporary / Probability numeric total cloud cover + // * @return Worst case numeric total cloud cover or RMISSD (-9999) if the + // computation does not fall through + // * @throws NullPointerException + // * + // */ + // public static final Amount prWcfr ( Amount xvfr, Amount txvf, Amount + // cfrt, Amount tcfr) throws InvalidValueException, NullPointerException { + // double prwcfr = GempakConstants.RMISSD; + // checkNullOrInvalidValue( tcfr ); + // checkNullOrInvalidValue( cfrt ); + // double cfrtVal = cfrt.doubleValue(); + // double tcfrVal = tcfr.doubleValue(); + // if ( ( xvfr == null || xvfr.doubleValue() == GempakConstants.RMISSD ) + // || ( txvf == null || txvf.doubleValue() == GempakConstants.RMISSD )) + // prwcfr = ( cfrtVal > tcfrVal ? cfrtVal : tcfrVal ); + // + // else { + // double txvfVal = txvf.doubleValue(); + // double xvfrVal = xvfr.doubleValue(); + // if ( txvfVal < xvfrVal ) + // prwcfr = tcfrVal; + // else if ( txvfVal == xvfrVal) + // prwcfr = ( cfrtVal > tcfrVal ? cfrtVal : tcfrVal ); + // else + // prwcfr = cfrtVal; + // } + // return ( new Amount ( prwcfr ,Unit.ONE)); + // } + + /** + * Computes the wind chill temperature from the air temperature and the wind + * speed + * + * @param tmpf + * - Air temperature ( in degree Farenheit ) + * @param sknt + * - Wind speed ( in knots ) + * @return the wind chill temperature ( in Farenheit ) if none of the inputs + * are missing + * @throws NullPointerException + * + */ + public static final Amount prWcht(Amount tmpf, Amount sknt) + throws InvalidValueException, NullPointerException { + // System.out.println("From prWcht:"); + // System.out.println(" tmpf = " + tmpf.doubleValue()); + // System.out.println(" sknt = " + sknt.doubleValue()); + double prwrcht = GempakConstants.RMISSD; + if (!checkNullOrInvalidValue(tmpf) || !checkNullOrInvalidValue(sknt)) { + return new Amount(NonSI.FAHRENHEIT); + } + + /* Convert the speed to miles per hour */ + Amount smph = checkAndConvertInputAmountToExpectedUnits(sknt, + NonSI.MILES_PER_HOUR); + + /* + * If the inputs are not missing , check if the wind speed is <= 3 miles + * per hour + */ + + double smphVal = smph.doubleValue(); + double tmpfVal = tmpf.doubleValue(); + if (smphVal <= 3) + prwrcht = tmpfVal; + else { + /* + * Compute the wind-chill temperature for wind speeds that exceed 3 + * miles per hour + */ + float wcht = (float) (35.74 + 0.6215 * tmpfVal - 35.75 + * Math.pow(smphVal, 0.16) + 0.4275 * tmpfVal + * Math.pow(smphVal, 0.16)); + prwrcht = (wcht > tmpfVal ? tmpfVal : wcht); + } + return (new Amount(prwrcht, NonSI.FAHRENHEIT)); + } + + /** + * Computes the wind component towards a specific direction from the wind + * direction, wind speed and direction of desired component. + * + * @param drct + * - the wind direction in degrees + * @param sped + * - the wind speed in m/s + * @param dcmp + * - the direction of the desired component + * @return the component of the wind (in m/s) if none of the input + * parameters are missing + * @throws NullPointerException + * + */ + public static final Amount prWcmp(Amount drct, Amount sped, Amount dcmp) + throws InvalidValueException, NullPointerException { + // System.out.println("From prWcmp:"); + // System.out.println(" sped = " + sped.doubleValue()); + // System.out.println(" drct = " + drct.doubleValue()); + // System.out.println(" dcmp = " + dcmp.doubleValue()); + /* Check for missing input parameters */ + // checkNullOrInvalidValue( drct ); + // checkNullOrInvalidValue( sped ); + // checkNullOrInvalidValue( dcmp ); + if (!checkNullOrInvalidValue(drct) || !checkNullOrInvalidValue(sped) + || !checkNullOrInvalidValue(dcmp)) { + return new Amount(SI.METERS_PER_SECOND); + } + + drct = checkAndConvertInputAmountToExpectedUnits(drct, + NonSI.DEGREE_ANGLE); + dcmp = checkAndConvertInputAmountToExpectedUnits(dcmp, + NonSI.DEGREE_ANGLE); + sped = checkAndConvertInputAmountToExpectedUnits(sped, + SI.METERS_PER_SECOND); + + /* Calculate wind speed toward specified direction */ + double prwcmp = sped.doubleValue() + * (-Math.cos((drct.doubleValue() - dcmp.doubleValue()) + * GempakConstants.DTR)); + + return new Amount(prwcmp, SI.METERS_PER_SECOND); + } + + /** + * Computes the wind component toward a direction 90 degrees + * counterclockwise of a specified direction. If no direction is specified, + * the component toward north is returned. + * + * @param drct + * - wind direction ( in degrees ) + * @param sped + * - wind speed ( in knots or m/s ) + * @param dcmp + * - specified wind direction ( in degrees ) + * @return a component of the wind in m/s if the input wind speed and + * direction are valid and if the specified wind direction is + * between 0 degrees and 360 degrees. + * @throws NullPointerException + * + * @throws InvalidRangeException + */ + public static final Amount prWnml(Amount drct, Amount sped, Amount dcmp) + throws InvalidValueException, NullPointerException { + // System.out.println("From prWnml:"); + // System.out.println(" sped = " + sped.doubleValue()); + // System.out.println(" drct = " + drct.doubleValue()); + // System.out.println(" dcmp = " + dcmp.doubleValue()); + // checkNullOrInvalidValue(sped); + // checkNullOrInvalidValue(drct); + // checkNullOrInvalidValue(dcmp); + if (!checkNullOrInvalidValue(drct) || !checkNullOrInvalidValue(sped) + || !checkNullOrInvalidValue(dcmp)) { + return new Amount(SI.METERS_PER_SECOND); + } + + drct = checkAndConvertInputAmountToExpectedUnits(drct, + NonSI.DEGREE_ANGLE); + dcmp = checkAndConvertInputAmountToExpectedUnits(dcmp, + NonSI.DEGREE_ANGLE); + sped = checkAndConvertInputAmountToExpectedUnits(sped, + SI.METERS_PER_SECOND); + if ((dcmp.doubleValue() < 0) && (dcmp.doubleValue() > 360)) { + // throw new + // InvalidRangeException("From prWnml - the wind direction 'dcmp' mus be greater than or equal to 0 and less than or equal to 360"); + System.out + .println("From prWnml - the wind direction 'dcmp' mus be greater than or equal to 0 and less than or equal to 360"); + return new Amount(SI.METERS_PER_SECOND); + } + /* + * Calculate wind speed 90 degrees to left of given direction. + */ + double prwnml = (float) (sped.doubleValue() * (-Math.cos((drct + .doubleValue() - dcmp.doubleValue() - 90) + * GempakConstants.DTR))); + return (new Amount(prwnml, SI.METERS_PER_SECOND)); + } + + // /** + // * Computes the packed wind speed and direction from the input wind speed + // and wind direction + // * @param drct - wind direction ( in degrees ) + // * @param sped - wind speed ( in knots or m/s ) + // * @return the packed speed and direction + // */ + // public static final Amount prWind ( Amount drct, Amount sped ){ + // float prwind = GempakConstants.RMISSD; + // // if ( !MissingValueTester.isDataValueMissing(drct) + // // && !MissingValueTester.isDataValueMissing(sped)){ + // /* + // * (Non-Javadoc) + // * The packed wind speed and direction are of the form: + // * SSSDDD, where SSS - wind speed ( in knots or m/s ) and + // * DDD - wind direction in degrees + // * + // */ + // int jdrct = (int ) Math.round( drct.doubleValue() ); + // int jsped = (int) Math.round( sped.doubleValue() ); + // prwind = jdrct + jsped * 1000; + // // } + // return prwind; + // } + + /** + * Computes the worst case categorical identification of flight rules for + * prevailing and temporary / probability conditions. + * + * @param xvfr + * - Prevailing categorical id of flight rules + * @param txvf + * - Temporary / probability categorical id of flight rules + * @return The worst case categorical id of flight rules + * @throws NullPointerException + * + */ + public static final Amount prWxvf(Amount xvfr, Amount txvf) + throws InvalidValueException, NullPointerException { + // System.out.println("From prWxvf:"); + // System.out.println(" xvfr = " + xvfr.doubleValue()); + // System.out.println(" txvf = " + txvf.doubleValue()); + + double prwxvf = GempakConstants.RMISSD; + if (txvf != null && xvfr != null) { + + double xvfrVal = xvfr.doubleValue(); + double txvfVal = txvf.doubleValue(); + + if (txvfVal != GempakConstants.RMISSD + && xvfrVal != GempakConstants.RMISSD) + prwxvf = (xvfrVal < txvfVal ? xvfrVal : txvfVal); + + else if (xvfrVal == GempakConstants.RMISSD + && txvfVal != GempakConstants.RMISSD) + prwxvf = xvfrVal; + + else if (txvfVal != GempakConstants.RMISSD + && xvfrVal != GempakConstants.RMISSD) + prwxvf = txvfVal; + } + + return (new Amount(prwxvf, Unit.ONE)); + } + + /** + *
+     * Computes LIFR/IFR/MVFR/VFR flight conditions based on ceiling and visibility.
+     * @param ceil - Ceiling in hundreds of feet
+     * @param vsby - Visibility in statute miles
+     * @return Flight conditions index value: 
+     *     0 - LIFR
+     *     1 - IFR
+     *     2 - MVFR
+     *     3 - VFR
+     * 
+ * + * @throws NullPointerException + * + */ + public static final Amount prXvfr(Amount ceil, Amount vsby) + throws InvalidValueException, NullPointerException { + // System.out.println("From prXvfr:"); + // System.out.println(" ceil = " + ceil.doubleValue()); + // System.out.println(" vsby = " + vsby.doubleValue()); + + double prxvfr = GempakConstants.RMISSD; + double vc = GempakConstants.RMISSD; + double vs = GempakConstants.RMISSD; + if (vsby == null) + return null; + + if (!checkNullOrInvalidValue(ceil)) + return new Amount(Unit.ONE); + ceil = checkAndConvertInputAmountToExpectedUnits(ceil, + NcUnits.HUNDREDS_OF_FEET); + vsby = checkAndConvertInputAmountToExpectedUnits(vsby, NonSI.MILE); + /* Compute categorical flight rules */ + + // Check the ceiling value + + double ceilVal = ceil.doubleValue(); + + double vsbyVal = vsby.doubleValue(); + + if (ceilVal < 0) { + // no-op. So vc retains its RMISSD value + } else if (ceilVal < 5) + vc = 0; + else if (ceilVal < 10) + vc = 1; + else if (ceilVal <= 30) + vc = 2; + else if ((vsbyVal > 5) || (vsbyVal < 0) + || (vsbyVal == GempakConstants.RMISSD)) { + prxvfr = 3; + } + + /* Check the visibility value. */ + if (vsbyVal != GempakConstants.RMISSD) { + if (vsbyVal < 0) { + // no-op. So vs retains it RMISSD value + } else if (vsbyVal < 1) + vs = 0; + else if (vsbyVal < 3) + vs = 1; + else if (vsbyVal <= 5) + vs = 2; + else + vs = 3; + } + + /* Determine the more restrictive of the two values. */ + if (vc == GempakConstants.RMISSD) + prxvfr = vs; + else if (vs == GempakConstants.RMISSD) + prxvfr = vc; + else + prxvfr = (vc < vs ? vc : vs); + + return (new Amount(prxvfr, Unit.ONE)); + + } + + /** + * Computes station elevation from altimeter and station pressure. It is + * also used to estimate height at various pressure levels from the + * altimeter in millibars. The PC library computes zmsl, Z000, Z950, Z850, + * Z800 by calling this function with pres equal to PMSL, 1000, 950, 850 and + * 800 respectively. + * + * @param altm + * - Altimeter in millibars + * @param pres + * - Pressure in millibars + * @return the height ( in meters ) if neither input value is missing and + * both input values are greater than zero. + * @throws NullPointerException + * + * @throws InvalidRangeException + */ + public static final Amount prZalt(Amount altm, Amount pres) + throws InvalidValueException, NullPointerException { + // System.out.println("From prZalt:"); + // System.out.println(" altm = " + altm.doubleValue()); + // System.out.println(" pres = " + pres.doubleValue()); + + // checkNullOrInvalidValue( pres ); + // checkNullOrInvalidValue( altm ); + + if (!checkNullOrInvalidValue(pres) || !checkNullOrInvalidValue(altm)) { + return new Amount(SI.METER); + } + + pres = checkAndConvertInputAmountToExpectedUnits(pres, NcUnits.MILLIBAR); + altm = checkAndConvertInputAmountToExpectedUnits(altm, NcUnits.MILLIBAR); + if (altm.doubleValue() <= 0) { + // throw new + // InvalidRangeException("From prZalt: altm must be greater than 0 mb"); + System.out.println("From prZalt: altm must be greater than 0 mb"); + return new Amount(SI.METER); + } + if (pres.doubleValue() <= 0) { + // throw new + // InvalidRangeException("From prZalt: pres must be greater than 0 mb"); + System.out.println("From prZalt: pres must be greater than 0 mb"); + return new Amount(SI.METER); + } + double to = GempakConstants.TMCK + 15; + double gamma = GempakConstants.GAMUSD / 1000; + + /* Calculate the exponent and pressure ratio. */ + double expo = (gamma * GempakConstants.RDGAS) / GempakConstants.GRAVTY; + double prat = pres.doubleValue() / altm.doubleValue(); + double przalt = (to * (1 - Math.pow(prat, expo))) / gamma; + + return (new Amount(przalt, SI.METER)); + } + + /** + * Computes the windchill from the wind velocity ( part of the Falconer + * equation - refer method prWceq) + * + * @param d + * - wind velocity ( in meters per second ) + * @return the windchill temperature + */ + private static double wci(double d) { + + /* + * from R. Falconer, "Windchill, A Useful Wintertime Weather Variable", + * Weatherwise, Dec 1968. + */ + return ((double) (10 * Math.sqrt(d) + 10.45 - d)); + + } + + public static final Amount checkAndConvertInputAmountToExpectedUnits( + Amount amountIn, Unit expectedUnit) { + Amount amountOut = null; + if (!amountIn.getUnit().equals(expectedUnit) + && amountIn.getUnit().isCompatible(expectedUnit)) { + double newValue = amountIn.getUnit().getConverterTo(expectedUnit) + .convert(amountIn.doubleValue()); + amountOut = new Amount(newValue, expectedUnit); + } else + // throw new ConversionException("Unable to convert " + + // amountIn.getUnit().toString() + " to " + expectedUnit.toString() + // ); + amountOut = amountIn; + + return amountOut; + } + + // public static final void checkNullOrInvalidValue( Amount amountToCheck ) + // throws InvalidValueException, NullPointerException{ + // if (amountToCheck == null ) + // throw new NullPointerException(); + // else { + // double amountValue = amountToCheck.doubleValue(); + // if ( amountValue == GempakConstants.RMISSD){ + // throw new InvalidValueException( new String + // ("Input amount cannot be -9999")); + // } + // else if ( Double.isNaN(amountValue)) + // throw new InvalidValueException( new String ("Input amount cannot be NaN" + // )); + // } + // } + + public static final boolean checkNullOrInvalidValue(Amount amountToCheck) { + if (amountToCheck == null) { + return false; + // throw new NullPointerException(); + } else { + double amountValue = amountToCheck.doubleValue(); + if (amountValue == GempakConstants.RMISSD) { + System.out.println("Input amount cannot be -9999"); + return false; + // throw new InvalidValueException( new String + // ("Input amount cannot be -9999")); + } else if (Double.isNaN(amountValue)) { + System.out.println("Input amount cannot be NaN"); + // throw new InvalidValueException( new String + // ("Input amount cannot be NaN" )); + return false; + } else + return true; + } + } + + // public static final class InvalidRangeException extends Exception { + // /** + // * + // */ + // private static final long serialVersionUID = -4962228676211688262L; + // + // /** + // * + // */ + // public InvalidRangeException( String msg) { + // super( msg ); + // } + // } + + public static final class InvalidValueException extends Exception { + /** * */ - private static final long serialVersionUID = 3844655201015825508L; + private static final long serialVersionUID = 3844655201015825508L; - /** + /** * */ - public InvalidValueException( String msg) { - super( msg ); - } -} + public InvalidValueException(String msg) { + super(msg); + } + } - - /** -* This function computes parcel PRES from THTE and TMPC, where TMPC -* is the parcel temperature at PRES on a specified moist adiabat -* (THTE). The computation is an iterative Newton-Raphson technique -* of the form: -* -* x = x(guess) + [ f( x ) - f( x(guess) ) ] / f'( x(guess) ) -* -* f' is approximated with finite differences -* f' = [ f( x(guess) + 1 ) - f( x(guess) ) ] / 1 -* -* Convergence is not guaranteed for extreme input values. If the -* computation does not converge after 100 iterations, the missing -* data value will be returned. -* @param thte - Equivalent potential temp in K -* @param tmpk - Parcel temperature in Kelvin -* @return Pressure in millibars -* -* @throws NullPointerException -* @throws InvalidRangeException -*/ + /** + * This function computes parcel PRES from THTE and TMPC, where TMPC is the + * parcel temperature at PRES on a specified moist adiabat (THTE). The + * computation is an iterative Newton-Raphson technique of the form: + * + * x = x(guess) + [ f( x ) - f( x(guess) ) ] / f'( x(guess) ) + * + * f' is approximated with finite differences f' = [ f( x(guess) + 1 ) - f( + * x(guess) ) ] / 1 + * + * Convergence is not guaranteed for extreme input values. If the + * computation does not converge after 100 iterations, the missing data + * value will be returned. + * + * @param thte + * - Equivalent potential temp in K + * @param tmpk + * - Parcel temperature in Kelvin + * @return Pressure in millibars + * + * @throws NullPointerException + * @throws InvalidRangeException + */ - public static Amount prPmst(Amount thte, Amount tmpk) throws InvalidValueException, NullPointerException { -// checkNullOrInvalidValue(thte); -// checkNullOrInvalidValue(tmpk); - - if ( !checkNullOrInvalidValue( thte ) - || !checkNullOrInvalidValue( tmpk ) ){ - return new Amount (SI.KELVIN ); - } - - thte = checkAndConvertInputAmountToExpectedUnits(thte, SI.KELVIN); - tmpk = checkAndConvertInputAmountToExpectedUnits(tmpk, SI.KELVIN); - - if ( thte.getValue().doubleValue() <= 0){ - System.out.println("From prPmst(): The equivalent potential temperature must be greater than 0"); - return new Amount ( SI.KELVIN ); -// throw new InvalidRangeException("The equivalent potential temperature must be greater than 0"); - } - Amount prpmst = new Amount(NcUnits.MILLIBAR); - /*Set convergence and initial guess of pressure.*/ - double epsi = 0.01; - Amount tmpc = new Amount ( tmpk.getValueAs(SI.CELSIUS), SI.CELSIUS ); - double tempVal = 1000 * Math.pow ( tmpk.getValue().doubleValue() / thte.getValue().doubleValue(), GempakConstants.AKAPPA ); - Amount pgdn = new Amount ( tempVal, NcUnits.MILLIBAR ); - boolean done = false; - int i = 1; - while ( !done ) { -// Amount pgdn = new Amount ( tempVal, NcUnits.MILLIBAR ); - Amount pgup = new Amount ( pgdn.getValueAs(NcUnits.MILLIBAR).doubleValue() + 1, NcUnits.MILLIBAR ); - - Amount tedn = prThte ( pgdn, tmpc, tmpc); - Amount teup = prThte ( pgup, tmpc, tmpc); - - if ( ! tedn.hasValidValue() || ! teup.hasValidValue() ) - return prpmst; - - /*Compute the correction; return on convergence.*/ - double cor = ( thte.getValueAs (SI.KELVIN ).doubleValue() - - tedn.getValueAs (SI.KELVIN ).doubleValue() ) / ( teup.getValueAs (SI.KELVIN ).doubleValue() - - tedn.getValueAs (SI.KELVIN ).doubleValue() ); - - double pgdnVal = ( pgdn.getValueAs(NcUnits.MILLIBAR ).doubleValue() + cor ); - pgdn = new Amount (pgdnVal, NcUnits.MILLIBAR); - if ( Math.abs( cor ) < epsi ){ - prpmst = new Amount ( pgdnVal, NcUnits.MILLIBAR ) ; - return prpmst; - } - - i++; - if ( i > 100 ) - done = true; - } - return prpmst; - } + public static Amount prPmst(Amount thte, Amount tmpk) + throws InvalidValueException, NullPointerException { + // checkNullOrInvalidValue(thte); + // checkNullOrInvalidValue(tmpk); + if (!checkNullOrInvalidValue(thte) || !checkNullOrInvalidValue(tmpk)) { + return new Amount(SI.KELVIN); + } + thte = checkAndConvertInputAmountToExpectedUnits(thte, SI.KELVIN); + tmpk = checkAndConvertInputAmountToExpectedUnits(tmpk, SI.KELVIN); + if (thte.getValue().doubleValue() <= 0) { + // System.out + // .println("From prPmst(): The equivalent potential temperature must be greater than 0"); + return new Amount(SI.KELVIN); + // throw new + // InvalidRangeException("The equivalent potential temperature must be greater than 0"); + } + Amount prpmst = new Amount(NcUnits.MILLIBAR); + /* Set convergence and initial guess of pressure. */ + double epsi = 0.01; + Amount tmpc = new Amount(tmpk.getValueAs(SI.CELSIUS), SI.CELSIUS); + double tempVal = 1000 * Math.pow(tmpk.getValue().doubleValue() + / thte.getValue().doubleValue(), GempakConstants.AKAPPA); + Amount pgdn = new Amount(tempVal, NcUnits.MILLIBAR); + boolean done = false; + int i = 1; + while (!done) { + // Amount pgdn = new Amount ( tempVal, NcUnits.MILLIBAR ); + Amount pgup = new Amount(pgdn.getValueAs(NcUnits.MILLIBAR) + .doubleValue() + 1, NcUnits.MILLIBAR); + + Amount tedn = prThte(pgdn, tmpc, tmpc); + Amount teup = prThte(pgup, tmpc, tmpc); + + if (!tedn.hasValidValue() || !teup.hasValidValue()) + return prpmst; + + /* Compute the correction; return on convergence. */ + double cor = (thte.getValueAs(SI.KELVIN).doubleValue() - tedn + .getValueAs(SI.KELVIN).doubleValue()) + / (teup.getValueAs(SI.KELVIN).doubleValue() - tedn + .getValueAs(SI.KELVIN).doubleValue()); + + double pgdnVal = (pgdn.getValueAs(NcUnits.MILLIBAR).doubleValue() + cor); + pgdn = new Amount(pgdnVal, NcUnits.MILLIBAR); + if (Math.abs(cor) < epsi) { + prpmst = new Amount(pgdnVal, NcUnits.MILLIBAR); + return prpmst; + } + + i++; + if (i > 100) + done = true; + } + return prpmst; + } } - - - - - - - - - diff --git a/ncep/gov.noaa.nws.ncep.edex.common/src/gov/noaa/nws/ncep/edex/common/metparameters/parameterconversion/PSLibrary.java b/ncep/gov.noaa.nws.ncep.edex.common/src/gov/noaa/nws/ncep/edex/common/metparameters/parameterconversion/PSLibrary.java index 71f1331684..5e334dab88 100644 --- a/ncep/gov.noaa.nws.ncep.edex.common/src/gov/noaa/nws/ncep/edex/common/metparameters/parameterconversion/PSLibrary.java +++ b/ncep/gov.noaa.nws.ncep.edex.common/src/gov/noaa/nws/ncep/edex/common/metparameters/parameterconversion/PSLibrary.java @@ -3,388 +3,490 @@ */ package gov.noaa.nws.ncep.edex.common.metparameters.parameterconversion; -import java.util.Comparator; - -import java.util.List; +import gov.noaa.nws.ncep.edex.common.metparameters.Amount; +import gov.noaa.nws.ncep.edex.common.metparameters.PressureLevel; +import gov.noaa.nws.ncep.edex.common.metparameters.WetBulbPotentialTemp; +import gov.noaa.nws.ncep.edex.common.metparameters.parameterconversion.PRLibrary.InvalidValueException; +import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingLayer2; import java.util.Collections; +import java.util.Comparator; +import java.util.List; import javax.measure.unit.NonSI; import javax.measure.unit.SI; import javax.measure.unit.Unit; -import gov.noaa.nws.ncep.edex.common.metparameters.AirTemperature; -import gov.noaa.nws.ncep.edex.common.metparameters.Amount; -import gov.noaa.nws.ncep.edex.common.metparameters.DewPointTemp; -import gov.noaa.nws.ncep.edex.common.metparameters.PressureLevel; -import gov.noaa.nws.ncep.edex.common.metparameters.WetBulbPotentialTemp; ////import gov.noaa.nws.ncep.edex.common.metparameters.parameterconversion.PRLibrary.InvalidRangeException; -import gov.noaa.nws.ncep.edex.common.metparameters.parameterconversion.PRLibrary.InvalidValueException; -import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingLayer; -import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingLayer2; /** * @author archana - * + * */ public final class PSLibrary { - /** - * Computes the cross totals index - * @param td850 - dewpoint at 850 mb ( in Celsius ) - * @param t500 - temperature at 500 mb ( in Celsius ) - * @return the difference between the dewpoint and the temperature if neither of them are missing - * and RMISSD ( -9999 ) otherwise. - * @throws InvalidValueException - * @throws NullPointerException - */ - - public final static Amount psCtot ( Amount td850, Amount t500) { + /** + * Computes the cross totals index + * + * @param td850 + * - dewpoint at 850 mb ( in Celsius ) + * @param t500 + * - temperature at 500 mb ( in Celsius ) + * @return the difference between the dewpoint and the temperature if + * neither of them are missing and RMISSD ( -9999 ) otherwise. + * @throws InvalidValueException + * @throws NullPointerException + */ - /* - * Compute the cross totals index by subtracting 500 mb - * temperature from the 850 mb dewpoint. - */ -if ( !PRLibrary.checkNullOrInvalidValue( td850 ) - || ! PRLibrary.checkNullOrInvalidValue( t500 ) ){ - return new Amount ( Unit.ONE ); - } - Amount psCtot = new Amount( td850.getValue().floatValue() - t500.getValue().floatValue() , Unit.ONE ); - return psCtot; - } - - /** - * Computes low, middle, and high elevation Haines indices - * from the temperature and the dewpoint. - * @param tc1 - temperature ( in Celsius ) - * @param tc2 - temperature ( in Celsius ) - * @param dwpc - dewpoint ( in Celsius ) - * @param itype - Haines index: - * 1- Low - * 2 - Middle - * 3 - High - * - * @return - * @throws InvalidValueException - * @throws NullPointerException - */ - public static Amount psHans ( Amount tc1Amt, Amount tc2Amt, Amount dwpcAmt, Amount itypeAmt) { - Amount pshans =new Amount(); - if ( ! PRLibrary.checkNullOrInvalidValue( tc1Amt ) - || !PRLibrary.checkNullOrInvalidValue( tc2Amt ) - || !PRLibrary.checkNullOrInvalidValue( dwpcAmt ) - || !PRLibrary.checkNullOrInvalidValue( itypeAmt ) ) - return new Amount ( Unit.ONE ); - float a = GempakConstants.RMISSD; - float b = GempakConstants.RMISSD; - float tc1 = tc1Amt.getValue().floatValue(); - float tc2 = tc2Amt.getValue().floatValue(); - float dwpc = dwpcAmt.getValue().floatValue(); - float itype = itypeAmt.getValue().floatValue(); - /* Compute the Haines index*/ - if ( itype == 1 ) { - a = ( ( tc2 - tc1 ) - 3 ) * ( 2 / 5 ) + 1; - b = ( ( tc1 - dwpc ) - 5 ) * ( 2 / 5 ) + 1; - } - else if ( itype == 2 ) { - a = ( ( tc1 - tc2 ) - 5 ) * ( 2 / 6 ) + 1; - b = ( ( tc1 - dwpc ) - 5 ) * ( 2 / 8 ) + 1; - } - else if ( itype == 3 ) { - a = ( ( tc1 - tc2 ) - 17 ) * ( 2 / 5 ) + 1; - b = ( ( tc1 - dwpc ) - 14 ) * ( 2 / 7 ) + 1; - } - - a = ( a > 0.9f ? a : 0.9f ); - a = ( a < 3.1f ? a : 3.1f ); - b = ( b > 0.9f ? b : 0.9f ); - b = ( b < 3.1f ? b : 3.1f ); - pshans = new Amount ( a + b,Unit.ONE ); -// } - return pshans; - } + public final static Amount psCtot(Amount td850, Amount t500) { - /** - * - * Computes the 'K' index - * @param t850 - 850 mb temperature ( in Celsius ) - * @param t700 - 700 mb temperature ( in Celsius ) - * @param t500 - 500 mb temperature ( in Celsius ) - * @param td850 - 850 mb dewpoint ( in Celsius ) - * @param td700 - 700 mb dewpoint ( in Celsius ) - * @return returns the 'K' index if all the input values are valid and - * RMISSD ( -9999 ) otherwise - * @throws InvalidValueException - * @throws NullPointerException - */ - public final static Amount pskinx ( Amount t850, Amount t700, Amount t500, Amount td850, Amount td700) { - Amount pskinx = new Amount(); - if ( !PRLibrary.checkNullOrInvalidValue(t850) - || !PRLibrary.checkNullOrInvalidValue(t700) - || !PRLibrary.checkNullOrInvalidValue(t500) - || !PRLibrary.checkNullOrInvalidValue(td850) - || !PRLibrary.checkNullOrInvalidValue(td700) ) - return new Amount ( Unit.ONE ); - pskinx = new Amount ( ( t850.getValue().floatValue() - t500.getValue().floatValue() ) - + td850.getValue().floatValue() - ( t700.getValue().floatValue() - td700.getValue().floatValue() ) , Unit.ONE); + /* + * Compute the cross totals index by subtracting 500 mb temperature from + * the 850 mb dewpoint. + */ + if (!PRLibrary.checkNullOrInvalidValue(td850) + || !PRLibrary.checkNullOrInvalidValue(t500)) { + return new Amount(Unit.ONE); + } + Amount psCtot = new Amount(td850.getValue().floatValue() + - t500.getValue().floatValue(), Unit.ONE); + return psCtot; + } - return pskinx; - } - - - /** - * Computes the Showalter index - * @param t850 - 850 mb temperature ( in Celsius ) - * @param td850 - 850 mb dewpoint ( in Celsius ) - * @param t500 - 500 mb temperature ( in Celsius ) - * @return the Showalter index if all the three input parameters are valid and the parcel temperature is computed correctly. - * Otherwise, it returns RMISSD (-9999). - */ - public final static Amount psShow ( Amount t850Amt, Amount td850Amt, Amount t500Amt ) { - float psshow = GempakConstants.RMISSD; - - if ( !PRLibrary.checkNullOrInvalidValue(t850Amt) - || !PRLibrary.checkNullOrInvalidValue(td850Amt) - || !PRLibrary.checkNullOrInvalidValue(t500Amt) ) - return new Amount ( Unit.ONE ); - float p850 = 850; - float p500 = 500; - float guess = 0; - /* - * Find equivalent potential temperature at the LCL using 850 mb - * temperature and dewpoint. - */ - Amount thtlcl = PRLibrary.prThte ( new Amount ( p850, NcUnits.MILLIBAR ), t850Amt, td850Amt ); - if ( !PRLibrary.checkNullOrInvalidValue(thtlcl) ) - return new Amount ( Unit.ONE ); - /*Find parcel temperature along pseudoadiabat at 500 mb. - * The parcel temperature tp is the temperature in Celsius at 500 mb of a parcel, - * which lies on the moist adiabat determined by the sounding at 850 mb - */ - Amount tp = PRLibrary.prTmst ( thtlcl, - new Amount( p500, NcUnits.MILLIBAR ), - new Amount ( 0, Unit.ONE ) ); - - /*Subtract the parcel temperature from the temperature at 500 mb, is the parcel temperature is valid*/ - - if ( !PRLibrary.checkNullOrInvalidValue(tp) ) - return new Amount ( Unit.ONE ); - t500Amt = PRLibrary.checkAndConvertInputAmountToExpectedUnits(t500Amt, SI.KELVIN); - float t500 = t500Amt.getValue().floatValue(); - psshow = t500 - tp.getValue().floatValue(); + /** + * Computes low, middle, and high elevation Haines indices from the + * temperature and the dewpoint. + * + * @param tc1 + * - temperature ( in Celsius ) + * @param tc2 + * - temperature ( in Celsius ) + * @param dwpc + * - dewpoint ( in Celsius ) + * @param itype + * - Haines index: 1- Low 2 - Middle 3 - High + * + * @return + * @throws InvalidValueException + * @throws NullPointerException + */ + public static Amount psHans(Amount tc1Amt, Amount tc2Amt, Amount dwpcAmt, + Amount itypeAmt) { + Amount pshans = new Amount(); + if (!PRLibrary.checkNullOrInvalidValue(tc1Amt) + || !PRLibrary.checkNullOrInvalidValue(tc2Amt) + || !PRLibrary.checkNullOrInvalidValue(dwpcAmt) + || !PRLibrary.checkNullOrInvalidValue(itypeAmt)) + return new Amount(Unit.ONE); + float a = GempakConstants.RMISSD; + float b = GempakConstants.RMISSD; + float tc1 = tc1Amt.getValue().floatValue(); + float tc2 = tc2Amt.getValue().floatValue(); + float dwpc = dwpcAmt.getValue().floatValue(); + float itype = itypeAmt.getValue().floatValue(); + /* Compute the Haines index */ + if (itype == 1) { + a = ((tc2 - tc1) - 3) * (2 / 5) + 1; + b = ((tc1 - dwpc) - 5) * (2 / 5) + 1; + } else if (itype == 2) { + a = ((tc1 - tc2) - 5) * (2 / 6) + 1; + b = ((tc1 - dwpc) - 5) * (2 / 8) + 1; + } else if (itype == 3) { + a = ((tc1 - tc2) - 17) * (2 / 5) + 1; + b = ((tc1 - dwpc) - 14) * (2 / 7) + 1; + } - return new Amount ( psshow, Unit.ONE); - } - - /** - * Computes the vertical totals index - * @param t850 - 850 mb temperature ( in Celsius ) - * @param t500 - 500 mb temperature ( in Celsius ) - * @return the vertical totals index as a difference of the temperature at 850 mb and the temperature at 500 mb, if neither value is missing. - * Else it returns RMISSD (-9999) - * @throws InvalidValueException - * @throws NullPointerException - */ - public final static Amount psVtot ( Amount t850, Amount t500 ) { - if ( ! PRLibrary.checkNullOrInvalidValue(t850 ) - || ! PRLibrary.checkNullOrInvalidValue(t500 ) ) - return new Amount ( Unit.ONE ); - - return new Amount ( t850.getValue().floatValue() - t500.getValue().floatValue() , Unit.ONE ); - } - - /** - * Computes the total Totals index from the temperature and dewpoint at 850 mb and the temperature at 500 mb - * - * @param t850 - 850 mb temperature ( in Celsius ) - * @param td850 - 850 mb dewpoint ( in Celsius ) - * @param t500 - 500 mb temperature ( in Celsius ) - * @return the total totals index if none of the input parameters are missing and - * RMISSD (-9999) otherwise - * @throws InvalidValueException - * @throws NullPointerException - */ - public final static Amount psTotl ( Amount t850, Amount td850, Amount t500 ) { - float pstotl = GempakConstants.RMISSD; - - if ( !PRLibrary.checkNullOrInvalidValue(t500) - || !PRLibrary.checkNullOrInvalidValue(td850) - || !PRLibrary.checkNullOrInvalidValue(t850) ) - return new Amount ( Unit.ONE ); - - /*Compute the vertical totals*/ - Amount vtot = psVtot ( t850, t500 ); - - /*Compute the cross totals*/ - Amount ctot = psCtot ( td850, t500 ); + a = (a > 0.9f ? a : 0.9f); + a = (a < 3.1f ? a : 3.1f); + b = (b > 0.9f ? b : 0.9f); + b = (b < 3.1f ? b : 3.1f); + pshans = new Amount(a + b, Unit.ONE); + // } + return pshans; + } - if ( !PRLibrary.checkNullOrInvalidValue( vtot ) - || ! PRLibrary.checkNullOrInvalidValue( ctot ) ) - return new Amount ( Unit.ONE ); - pstotl = vtot.getValue().floatValue() + ctot .getValue().floatValue(); + /** + * + * Computes the 'K' index + * + * @param t850 + * - 850 mb temperature ( in Celsius ) + * @param t700 + * - 700 mb temperature ( in Celsius ) + * @param t500 + * - 500 mb temperature ( in Celsius ) + * @param td850 + * - 850 mb dewpoint ( in Celsius ) + * @param td700 + * - 700 mb dewpoint ( in Celsius ) + * @return returns the 'K' index if all the input values are valid and + * RMISSD ( -9999 ) otherwise + * @throws InvalidValueException + * @throws NullPointerException + */ + public final static Amount pskinx(Amount t850, Amount t700, Amount t500, + Amount td850, Amount td700) { + Amount pskinx = new Amount(); + if (!PRLibrary.checkNullOrInvalidValue(t850) + || !PRLibrary.checkNullOrInvalidValue(t700) + || !PRLibrary.checkNullOrInvalidValue(t500) + || !PRLibrary.checkNullOrInvalidValue(td850) + || !PRLibrary.checkNullOrInvalidValue(td700)) + return new Amount(Unit.ONE); + pskinx = new Amount( + (t850.getValue().floatValue() - t500.getValue().floatValue()) + + td850.getValue().floatValue() + - (t700.getValue().floatValue() - td700.getValue() + .floatValue()), Unit.ONE); - return new Amount ( pstotl, Unit.ONE ); - } - - /** - * Computes the SWEAT index. Winds must be input in m/sec - * @param t850 - 850 mb temperature - * @param td850 - 850 mb dewpoint - * @param t500 - 500 mb temperature - * @param spd850 - 850 mb windspeed ( in m/sec ) - * @param spd500 - 500 mb windspeed ( in m/sec ) - * @param dir850 - 850 mb wind direction - * @param dir500 - 500 mb wind direction - * @return the SWEAT index if none of the inputs are missing and RMISSD ( -9999 ) otherwise - * @throws InvalidValueException - * @throws NullPointerException - */ - public final static Amount psSwet ( Amount t850, Amount td850, Amount t500, - Amount spd850, Amount spd500, - Amount dir850, Amount dir500 ) { - float pssweat = GempakConstants.RMISSD; - if ( !PRLibrary.checkNullOrInvalidValue( t500 ) - || !PRLibrary.checkNullOrInvalidValue( td850 ) - || !PRLibrary.checkNullOrInvalidValue( t500 ) - || !PRLibrary.checkNullOrInvalidValue( spd850 ) - || !PRLibrary.checkNullOrInvalidValue( spd500 ) - || !PRLibrary.checkNullOrInvalidValue( dir850 ) - || !PRLibrary.checkNullOrInvalidValue( dir500 ) ) - return new Amount ( Unit.ONE ); - /* - * (Non-Javadoc): - * All computations are from - * Miller, R.C., 1972: Notes on Severe Storm Forecasting Procedures of - * the Air Force Global Weather Central, AWS Tech. Report 200 - */ - /*Convert meters per second to knots*/ - Amount skt850 = PRLibrary.checkAndConvertInputAmountToExpectedUnits(spd850, NonSI.KNOT) ; - Amount skt500 = PRLibrary.checkAndConvertInputAmountToExpectedUnits(spd500, NonSI.KNOT) ; - - /* Compute the total totals index. If < 49, set term to zero.*/ - float total = psTotl ( t850, td850, t500 ).getValue().floatValue(); - float term2 = total - 49; - if ( total < 49 ) - term2 = 0; - - /* Compute shear term.*/ - - float dif = dir500.getValue().floatValue() - dir850.getValue().floatValue(); - float s = ( float ) ( Math.sin ( dif * GempakConstants.DTR ) ); - float shear = 125 * ( s + 0.2f ); - - /*Make various wind checks.*/ - float dir850Val = dir850.getValue().floatValue(); - float dir500Val = dir500.getValue().floatValue(); - float skt500Val = skt500.getValue().floatValue(); - float skt850Val = skt850.getValue().floatValue(); - - if ((dir850Val < 130.) || (dir850Val > 250.)) - shear = 0; - if ((dir500Val < 210.) || (dir500Val > 310.)) - shear = 0; - if ((skt500Val < 15.) || (skt850Val < 15. )) - shear = 0; - if (dif <= 0) - shear = 0; - - /*Check for sub-zero dewpoint*/ - float dwp850 = td850.getValue().floatValue(); - if ( dwp850 < 0 ) - dwp850 = 0; - - /*Calculate SWEAT index*/ - pssweat = 12 * dwp850 + 20 * term2 + 2 * skt850Val + skt500Val + shear; - return new Amount ( pssweat , Unit.ONE); - } - - /** - * Finds the most unstable level of a sounding from the surface to the input pressure level. - * @param listOfNcSoundingLayer - the list of NcSoundingLayer to search - * @param plev - input pressure level - * @return the most unstable level of a sounding from the surface to the input pressure level (plev), - * if plev is not -1 and all computations fall through correctly.Else it returns an empty NcSoundingLayer object - * @throws Exception - */ - public static NcSoundingLayer2 psUstb(List listOfNcSoundingLayer, PressureLevel plev ) throws Exception{ - //TODO: update to find pressure value between 2 levels - NcSoundingLayer2 outputNcSoundingLayer = new NcSoundingLayer2(); - class PressureComparator implements Comparator < NcSoundingLayer2>{ - public int compare(NcSoundingLayer2 n1, NcSoundingLayer2 n2){ - return Float.compare(n2.getPressure().getValue().floatValue(), n1.getPressure().getValue().floatValue()); - } - } - if ( listOfNcSoundingLayer != null && listOfNcSoundingLayer.size() > 0 ){ - if ( listOfNcSoundingLayer.size() > 1 ) - Collections.sort(listOfNcSoundingLayer, new PressureComparator() ); - - NcSoundingLayer2 surfaceLevelNcSoundingLayer = listOfNcSoundingLayer.get( 0 ); - PressureLevel pressureAtSurfaceLevel = surfaceLevelNcSoundingLayer.getPressure(); - NcSoundingLayer2 topLevelNcSoundingLayer = PCLibrary.pcFtop( listOfNcSoundingLayer ); - PressureLevel pressureAtTopLevel = topLevelNcSoundingLayer.getPressure(); - float plevVal = plev.getValue().floatValue(); - float presAtSurfaceLevelValue = pressureAtSurfaceLevel.getValue().floatValue(); - float presAtTopLevelVal = pressureAtTopLevel.getValue().floatValue(); - if( plevVal > presAtSurfaceLevelValue) - return outputNcSoundingLayer; - else if ( plevVal == -1 || plevVal <= presAtTopLevelVal ) - plev = pressureAtTopLevel; - + return pskinx; + } + + /** + * Computes the Showalter index + * + * @param t850 + * - 850 mb temperature ( in Celsius ) + * @param td850 + * - 850 mb dewpoint ( in Celsius ) + * @param t500 + * - 500 mb temperature ( in Celsius ) + * @return the Showalter index if all the three input parameters are valid + * and the parcel temperature is computed correctly. Otherwise, it + * returns RMISSD (-9999). + */ + public final static Amount psShow(Amount t850Amt, Amount td850Amt, + Amount t500Amt) { + float psshow = GempakConstants.RMISSD; + + if (!PRLibrary.checkNullOrInvalidValue(t850Amt) + || !PRLibrary.checkNullOrInvalidValue(td850Amt) + || !PRLibrary.checkNullOrInvalidValue(t500Amt)) + return new Amount(Unit.ONE); + float p850 = 850; + float p500 = 500; + float guess = 0; + /* + * Find equivalent potential temperature at the LCL using 850 mb + * temperature and dewpoint. + */ + Amount thtlcl = PRLibrary.prThte(new Amount(p850, NcUnits.MILLIBAR), + t850Amt, td850Amt); + if (!PRLibrary.checkNullOrInvalidValue(thtlcl)) + return new Amount(Unit.ONE); + /* + * Find parcel temperature along pseudoadiabat at 500 mb. The parcel + * temperature tp is the temperature in Celsius at 500 mb of a parcel, + * which lies on the moist adiabat determined by the sounding at 850 mb + */ + Amount tp = PRLibrary.prTmst(thtlcl, + new Amount(p500, NcUnits.MILLIBAR), new Amount(0, Unit.ONE)); + + /* + * Subtract the parcel temperature from the temperature at 500 mb, is + * the parcel temperature is valid + */ + + if (!PRLibrary.checkNullOrInvalidValue(tp)) + return new Amount(Unit.ONE); + t500Amt = PRLibrary.checkAndConvertInputAmountToExpectedUnits(t500Amt, + SI.KELVIN); + float t500 = t500Amt.getValue().floatValue(); + psshow = t500 - tp.getValue().floatValue(); + + return new Amount(psshow, Unit.ONE); + } + + /** + * Computes the vertical totals index + * + * @param t850 + * - 850 mb temperature ( in Celsius ) + * @param t500 + * - 500 mb temperature ( in Celsius ) + * @return the vertical totals index as a difference of the temperature at + * 850 mb and the temperature at 500 mb, if neither value is + * missing. Else it returns RMISSD (-9999) + * @throws InvalidValueException + * @throws NullPointerException + */ + public final static Amount psVtot(Amount t850, Amount t500) { + if (!PRLibrary.checkNullOrInvalidValue(t850) + || !PRLibrary.checkNullOrInvalidValue(t500)) + return new Amount(Unit.ONE); + + return new Amount(t850.getValue().floatValue() + - t500.getValue().floatValue(), Unit.ONE); + } + + /** + * Computes the total Totals index from the temperature and dewpoint at 850 + * mb and the temperature at 500 mb + * + * @param t850 + * - 850 mb temperature ( in Celsius ) + * @param td850 + * - 850 mb dewpoint ( in Celsius ) + * @param t500 + * - 500 mb temperature ( in Celsius ) + * @return the total totals index if none of the input parameters are + * missing and RMISSD (-9999) otherwise + * @throws InvalidValueException + * @throws NullPointerException + */ + public final static Amount psTotl(Amount t850, Amount td850, Amount t500) { + float pstotl = GempakConstants.RMISSD; + + if (!PRLibrary.checkNullOrInvalidValue(t500) + || !PRLibrary.checkNullOrInvalidValue(td850) + || !PRLibrary.checkNullOrInvalidValue(t850)) + return new Amount(Unit.ONE); + + /* Compute the vertical totals */ + Amount vtot = psVtot(t850, t500); + + /* Compute the cross totals */ + Amount ctot = psCtot(td850, t500); + + if (!PRLibrary.checkNullOrInvalidValue(vtot) + || !PRLibrary.checkNullOrInvalidValue(ctot)) + return new Amount(Unit.ONE); + pstotl = vtot.getValue().floatValue() + ctot.getValue().floatValue(); + + return new Amount(pstotl, Unit.ONE); + } + + /** + * Computes the SWEAT index. Winds must be input in m/sec + * + * @param t850 + * - 850 mb temperature + * @param td850 + * - 850 mb dewpoint + * @param t500 + * - 500 mb temperature + * @param spd850 + * - 850 mb windspeed ( in m/sec ) + * @param spd500 + * - 500 mb windspeed ( in m/sec ) + * @param dir850 + * - 850 mb wind direction + * @param dir500 + * - 500 mb wind direction + * @return the SWEAT index if none of the inputs are missing and RMISSD ( + * -9999 ) otherwise + * @throws InvalidValueException + * @throws NullPointerException + */ + public final static Amount psSwet(Amount t850, Amount td850, Amount t500, + Amount spd850, Amount spd500, Amount dir850, Amount dir500) { + float pssweat = GempakConstants.RMISSD; + if (!PRLibrary.checkNullOrInvalidValue(t500) + || !PRLibrary.checkNullOrInvalidValue(td850) + || !PRLibrary.checkNullOrInvalidValue(t500) + || !PRLibrary.checkNullOrInvalidValue(spd850) + || !PRLibrary.checkNullOrInvalidValue(spd500) + || !PRLibrary.checkNullOrInvalidValue(dir850) + || !PRLibrary.checkNullOrInvalidValue(dir500)) + return new Amount(Unit.ONE); + /* + * (Non-Javadoc): All computations are from Miller, R.C., 1972: Notes on + * Severe Storm Forecasting Procedures of the Air Force Global Weather + * Central, AWS Tech. Report 200 + */ + /* Convert meters per second to knots */ + Amount skt850 = PRLibrary.checkAndConvertInputAmountToExpectedUnits( + spd850, NonSI.KNOT); + Amount skt500 = PRLibrary.checkAndConvertInputAmountToExpectedUnits( + spd500, NonSI.KNOT); + + /* Compute the total totals index. If < 49, set term to zero. */ + float total = psTotl(t850, td850, t500).getValue().floatValue(); + float term2 = total - 49; + if (total < 49) + term2 = 0; + + /* Compute shear term. */ + + float dif = dir500.getValue().floatValue() + - dir850.getValue().floatValue(); + float s = (float) (Math.sin(dif * GempakConstants.DTR)); + float shear = 125 * (s + 0.2f); + + /* Make various wind checks. */ + float dir850Val = dir850.getValue().floatValue(); + float dir500Val = dir500.getValue().floatValue(); + float skt500Val = skt500.getValue().floatValue(); + float skt850Val = skt850.getValue().floatValue(); + + if ((dir850Val < 130.) || (dir850Val > 250.)) + shear = 0; + if ((dir500Val < 210.) || (dir500Val > 310.)) + shear = 0; + if ((skt500Val < 15.) || (skt850Val < 15.)) + shear = 0; + if (dif <= 0) + shear = 0; + + /* Check for sub-zero dewpoint */ + float dwp850 = td850.getValue().floatValue(); + if (dwp850 < 0) + dwp850 = 0; + + /* Calculate SWEAT index */ + pssweat = 12 * dwp850 + 20 * term2 + 2 * skt850Val + skt500Val + shear; + return new Amount(pssweat, Unit.ONE); + } + + /** + * Finds the most unstable level of a sounding from the surface to the input + * pressure level. + * + * @param listOfNcSoundingLayer + * - the list of NcSoundingLayer to search + * @param plev + * - input pressure level + * @return the most unstable level of a sounding from the surface to the + * input pressure level (plev), if plev is not -1 and all + * computations fall through correctly.Else it returns an empty + * NcSoundingLayer object + * @throws Exception + */ + public static NcSoundingLayer2 psUstb( + List listOfNcSoundingLayer, PressureLevel plev) + throws Exception { + // System.out.println(" PSLibrary/psUstb !!!!!!!!! "); + // TODO: update to find pressure value between 2 levels + NcSoundingLayer2 outputNcSoundingLayer = new NcSoundingLayer2(); + class PressureComparator implements Comparator { + public int compare(NcSoundingLayer2 n1, NcSoundingLayer2 n2) { + return Float.compare(n2.getPressure().getValue().floatValue(), + n1.getPressure().getValue().floatValue()); + } + } + + // System.out.println(" PSLibrary/psUstb 1 "); + + if (listOfNcSoundingLayer != null && listOfNcSoundingLayer.size() > 0) { + if (listOfNcSoundingLayer.size() > 1) + Collections.sort(listOfNcSoundingLayer, + new PressureComparator()); + // System.out.println(" PSLibrary/psUstb 2 "); + + NcSoundingLayer2 surfaceLevelNcSoundingLayer = listOfNcSoundingLayer + .get(0); + PressureLevel pressureAtSurfaceLevel = surfaceLevelNcSoundingLayer + .getPressure(); + NcSoundingLayer2 topLevelNcSoundingLayer = PCLibrary + .pcFtop(listOfNcSoundingLayer); + PressureLevel pressureAtTopLevel = topLevelNcSoundingLayer + .getPressure(); + float plevVal = plev.getValue().floatValue(); + float presAtSurfaceLevelValue = pressureAtSurfaceLevel.getValue() + .floatValue(); + float presAtTopLevelVal = pressureAtTopLevel.getValue() + .floatValue(); + if (plevVal > presAtSurfaceLevelValue) + return outputNcSoundingLayer; + else if (plevVal == -1 || plevVal <= presAtTopLevelVal) + plev = pressureAtTopLevel; + // System.out.println(" PSLibrary/psUstb 3 "); + + int sizeOfList = listOfNcSoundingLayer.size(); + boolean done = false; + int lev = 0; + float eps = GempakConstants.RMISSD; + + while (!done && lev < sizeOfList) { + NcSoundingLayer2 currNcSoundingLayer = listOfNcSoundingLayer + .get(lev); + // System.out.println(" PSLibrary/psUstb 4 "); + + Amount pressure = new Amount(currNcSoundingLayer.getPressure() + .getValue(), NcUnits.MILLIBAR); + Amount tmpc = new Amount(currNcSoundingLayer.getTemperature() + .getValue(), SI.CELSIUS); + Amount dwpc = new Amount(currNcSoundingLayer.getDewpoint() + .getValue(), SI.CELSIUS); + if (pressure.hasValidValue() && tmpc.hasValidValue() + && dwpc.hasValidValue()) { + WetBulbPotentialTemp thwc = new WetBulbPotentialTemp(); + // System.out.println(" PSLibrary/thwc " + + // thwc.doubleValue() + // + " pressure " + pressure.doubleValue() + " tmpc " + // + tmpc.doubleValue() + " dwpc " + // + dwpc.doubleValue()); + + thwc.setValue(PRLibrary.prThwc(pressure, tmpc, dwpc)); + if (thwc.getValue().floatValue() > eps + && (pressure.getValue().floatValue() >= plevVal)) { + eps = thwc.getValue().floatValue(); + outputNcSoundingLayer.setPressure(currNcSoundingLayer + .getPressure()); + outputNcSoundingLayer + .setTemperature(currNcSoundingLayer + .getTemperature()); + outputNcSoundingLayer.setDewpoint(currNcSoundingLayer + .getDewpoint()); + outputNcSoundingLayer.setWindSpeed(currNcSoundingLayer + .getWindSpeed()); + outputNcSoundingLayer + .setWindDirection(currNcSoundingLayer + .getWindDirection()); + outputNcSoundingLayer.setWindU(currNcSoundingLayer + .getWindU()); + outputNcSoundingLayer.setWindV(currNcSoundingLayer + .getWindV()); + outputNcSoundingLayer.setGeoHeight(currNcSoundingLayer + .getGeoHeight()); + outputNcSoundingLayer.setOmega(currNcSoundingLayer + .getOmega()); + outputNcSoundingLayer + .setSpecificHumidity(currNcSoundingLayer + .getSpecificHumidity()); + // System.out.println("Outdat: " + // + outputNcSoundingLayer.getPressure().getValueAs( + // NcUnits.MILLIBAR ).floatValue() + " " + // + outputNcSoundingLayer.getTemperature().getValueAs( + // SI.CELSIUS ).floatValue() + " " + // + outputNcSoundingLayer.getDewpoint().getValueAs( + // SI.CELSIUS ).floatValue() + " " + // + outputNcSoundingLayer.getWindSpeed().getValueAs( + // SI.METERS_PER_SECOND ).floatValue() + " " + // + + // outputNcSoundingLayer.getWindDirection().getValueAs( + // NonSI.DEGREE_ANGLE ).floatValue() + " " + // + outputNcSoundingLayer.getGeoHeight().getValueAs( + // SI.METER ).floatValue() ); + } + + } + // System.out.println("Pressure value is " + + // pressure.getValue().floatValue() + " " + + // pressure.getUnit().toString() ); + // System.out.println("lev is " + lev ); + lev++; + if (pressure.hasValidValue() + && pressure.getValue().floatValue() <= plevVal) { + done = true; + break; + } + } + } + //System.out.println("PSLibrary/psUstb Outdat: " + // + outputNcSoundingLayer.getPressure().getValue().floatValue() + // + " " + // + outputNcSoundingLayer.getTemperature().getValue() + // .floatValue() + // + " " + // + outputNcSoundingLayer.getDewpoint().getValue().floatValue() + // + " " + // + outputNcSoundingLayer.getWindSpeed().getValue().floatValue() + // + " " + // + outputNcSoundingLayer.getWindDirection().getValue() + // .floatValue() + " " + // + outputNcSoundingLayer.getGeoHeight().getValue().floatValue()); + + return outputNcSoundingLayer; + } - int sizeOfList = listOfNcSoundingLayer.size(); - boolean done = false; - int lev = 0; - float eps = GempakConstants.RMISSD; - - while ( !done && lev < sizeOfList){ - NcSoundingLayer2 currNcSoundingLayer = listOfNcSoundingLayer.get( lev ); - - Amount pressure = new Amount ( currNcSoundingLayer.getPressure().getValue(), NcUnits.MILLIBAR ); - Amount tmpc = new Amount ( currNcSoundingLayer.getTemperature().getValue(), SI.CELSIUS ); - Amount dwpc = new Amount ( currNcSoundingLayer.getDewpoint().getValue(), SI.CELSIUS ); - if ( pressure.hasValidValue() && tmpc.hasValidValue() && dwpc.hasValidValue() ){ - WetBulbPotentialTemp thwc = new WetBulbPotentialTemp(); - thwc.setValue( PRLibrary.prThwc ( pressure, tmpc, dwpc ) ); - if ( thwc.getValue().floatValue() > eps && ( pressure.getValue().floatValue() >= plevVal ) ){ - eps = thwc.getValue().floatValue(); - outputNcSoundingLayer.setPressure( currNcSoundingLayer.getPressure() ); - outputNcSoundingLayer.setTemperature( currNcSoundingLayer.getTemperature() ); - outputNcSoundingLayer.setDewpoint( currNcSoundingLayer.getDewpoint() ); - outputNcSoundingLayer.setWindSpeed( currNcSoundingLayer.getWindSpeed() ); - outputNcSoundingLayer.setWindDirection( currNcSoundingLayer.getWindDirection() ); - outputNcSoundingLayer.setWindU( currNcSoundingLayer.getWindU() ); - outputNcSoundingLayer.setWindV( currNcSoundingLayer.getWindV() ); - outputNcSoundingLayer.setGeoHeight( currNcSoundingLayer.getGeoHeight() ); - outputNcSoundingLayer.setOmega( currNcSoundingLayer.getOmega() ); - outputNcSoundingLayer.setSpecificHumidity( currNcSoundingLayer.getSpecificHumidity() ); -// System.out.println("Outdat: " -// + outputNcSoundingLayer.getPressure().getValueAs( NcUnits.MILLIBAR ).floatValue() + " " -// + outputNcSoundingLayer.getTemperature().getValueAs( SI.CELSIUS ).floatValue() + " " -// + outputNcSoundingLayer.getDewpoint().getValueAs( SI.CELSIUS ).floatValue() + " " -// + outputNcSoundingLayer.getWindSpeed().getValueAs( SI.METERS_PER_SECOND ).floatValue() + " " -// + outputNcSoundingLayer.getWindDirection().getValueAs( NonSI.DEGREE_ANGLE ).floatValue() + " " -// + outputNcSoundingLayer.getGeoHeight().getValueAs( SI.METER ).floatValue() ); - } - - } -// System.out.println("Pressure value is " + pressure.getValue().floatValue() + " " + pressure.getUnit().toString() ); -// System.out.println("lev is " + lev ); - lev++; - if ( pressure.hasValidValue() && pressure.getValue().floatValue() <= plevVal ){ - done = true; - break; - } - } - } - System.out.println("From PS_USTB Outdat: " - + outputNcSoundingLayer.getPressure().getValue().floatValue() + " " - + outputNcSoundingLayer.getTemperature().getValue().floatValue() + " " - + outputNcSoundingLayer.getDewpoint().getValue().floatValue() + " " - + outputNcSoundingLayer.getWindSpeed().getValue().floatValue() + " " - + outputNcSoundingLayer.getWindDirection().getValue().floatValue() + " " - + outputNcSoundingLayer.getGeoHeight().getValue().floatValue() ); - - return outputNcSoundingLayer; - } - - } diff --git a/ncep/gov.noaa.nws.ncep.edex.common/utility/common_static/base/ncep/hold/NcInventoryDefinitions/NotUsed/QSCT.xml b/ncep/gov.noaa.nws.ncep.edex.common/utility/common_static/base/ncep/hold/NcInventoryDefinitions/NotUsed/QSCT.xml deleted file mode 100644 index e88b70b40c..0000000000 --- a/ncep/gov.noaa.nws.ncep.edex.common/utility/common_static/base/ncep/hold/NcInventoryDefinitions/NotUsed/QSCT.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - QSCT - pluginName,dataTime - - - - - - - - - diff --git a/ncep/gov.noaa.nws.ncep.edex.common/utility/edex_static/base/ncep/stns/vors.xml b/ncep/gov.noaa.nws.ncep.edex.common/utility/edex_static/base/ncep/stns/vors.xml index 80239cf1d0..7453bdf5f4 100755 --- a/ncep/gov.noaa.nws.ncep.edex.common/utility/edex_static/base/ncep/stns/vors.xml +++ b/ncep/gov.noaa.nws.ncep.edex.common/utility/edex_static/base/ncep/stns/vors.xml @@ -1,7049 +1,7097 @@ - - - - - YSJ - 000395 - ST_JOHN - NB - CN - 45.32 - -65.88 - 0 - 0 - - - - HUL - 000341 - HOULTON - ME - US - 46.04 - -67.83 - 0 - 0 - - - - PQI - 000367 - PRESQUE_ISLE - ME - US - 46.77 - -68.09 - 0 - 0 - - - - MLT - 000183 - MILLINOCKET - ME - US - 45.58 - -68.52 - 0 - 0 - - - - BGR - 000029 - BANGOR - ME - US - 44.84 - -68.87 - 0 - 0 - - - - ACK - 000005 - NANTUCKET - MA - US - 41.28 - -70.03 - 0 - 0 - - - - ENE - 000322 - KENNEBUNK - ME - US - 43.43 - -70.61 - 0 - 0 - - - - BOS - 000289 - BOSTON - MA - US - 42.36 - -70.99 - 0 - 0 - - - - YQB - 000391 - QUEBEC - QB - CN - 46.80 - -71.38 - 0 - 0 - - - - PVD - 000221 - PROVIDENCE - RI - US - 41.72 - -71.43 - 0 - 0 - - - - CON - 000062 - CONCORD - NH - US - 43.22 - -71.58 - 0 - 0 - - - - YSC - 000394 - SHERBROOKE - QB - CN - 45.43 - -71.68 - 0 - 0 - - - - HTO - 000340 - EAST_HAMPTON - NY - US - 40.92 - -72.32 - 0 - 0 - - - - MPV - 000188 - MONTPELIER - VT - US - 44.22 - -72.57 - 0 - 0 - - - - BDL - 000287 - WINSOR_LOCKS - CT - US - 41.94 - -72.69 - 0 - 0 - - - - PLB - 000365 - PLATTSBURGH - NY - US - 44.69 - -73.52 - 0 - 0 - - - - JFK - 000345 - NEW_YORK/JF_KENNEDY - NY - US - 40.63 - -73.77 - 0 - 0 - - - - ALB - 000012 - ALBANY - NY - US - 42.75 - -73.80 - 0 - 0 - - - - CYN - 000300 - COYLE - NJ - US - 39.82 - -74.43 - 0 - 0 - - - - SAX - 000376 - SPARTA - NJ - US - 41.07 - -74.54 - 0 - 0 - - - - MSS - 000353 - MASSENA - NY - US - 44.91 - -74.72 - 0 - 0 - - - - SIE - 000377 - SEA_ISLE - NJ - US - 39.10 - -74.80 - 0 - 0 - - - - HNK - 000338 - HANCOCK - NY - US - 42.06 - -75.32 - 0 - 0 - - - - SBY - 000242 - SALISBURY - MD - US - 38.35 - -75.52 - 0 - 0 - - - - YOW - 000390 - OTTAWA - ON - CN - 45.32 - -75.67 - 0 - 0 - - - - ETX - 000325 - EAST_TEXAS - PA - US - 40.58 - -75.68 - 0 - 0 - - - - ECG - 000086 - ELIZABETH_CITY - NC - US - 36.25 - -76.18 - 0 - 0 - - - - SYR - 000259 - SYRACUSE - NY - US - 43.16 - -76.20 - 0 - 0 - - - - ORF - 000203 - NORFOLK - VA - US - 36.89 - -76.20 - 0 - 0 - - - - EMI - 000320 - WESTMINSTER - MD - US - 39.50 - -76.98 - 0 - 0 - - - - HAR - 000126 - HARRISBURG - PA - US - 40.23 - -77.02 - 0 - 0 - - - - DCA - 000306 - WASHINGTON - DC - US - 38.86 - -77.04 - 0 - 0 - - - - RIC - 000229 - RICHMOND - VA - US - 37.50 - -77.32 - 0 - 0 - - - - CSN - 000299 - CASSANOVA - VA - US - 38.64 - -77.87 - 0 - 0 - - - - ILM - 000135 - WILMINGTON - NC - US - 34.35 - -77.87 - 0 - 0 - - - - SLT - 000252 - SLATE_RUN - PA - US - 41.51 - -77.97 - 0 - 0 - - - - PSB - 000368 - PHILLIPSBURG - PA - US - 40.92 - -77.99 - 0 - 0 - - - - BUF - 000044 - BUFFALO - NY - US - 42.93 - -78.65 - 0 - 0 - - - - RDU - 000372 - RALEIGH-DURHAM - NC - US - 35.87 - -78.78 - 0 - 0 - - - - JST - 000145 - JOHNSTOWN - PA - US - 40.32 - -78.83 - 0 - 0 - - - - JHW - 000346 - JAMESTOWN - NY - US - 42.19 - -79.12 - 0 - 0 - - - - LYH - 000166 - LYNCHBURG - VA - US - 37.25 - -79.23 - 0 - 0 - - - - YYZ - 000401 - TORONTO - ON - CN - 43.67 - -79.63 - 0 - 0 - - - - FLO - 000102 - FLORENCE - SC - US - 34.23 - -79.66 - 0 - 0 - - - - GSO - 000122 - GREENSBORO - NC - US - 36.05 - -79.98 - 0 - 0 - - - - CHS - 000056 - CHARLESTON - SC - US - 32.89 - -80.04 - 0 - 0 - - - - PBI - 000206 - WEST_PALM_BEACH - FL - US - 26.68 - -80.09 - 0 - 0 - - - - EKN - 000088 - ELKINS - WV - US - 38.92 - -80.10 - 0 - 0 - - - - EWC - 000326 - ELLWOOD_CITY - PA - US - 40.83 - -80.21 - 0 - 0 - - - - ERI - 000092 - ERIE - PA - US - 42.02 - -80.30 - 0 - 0 - - - - MIA - 000176 - MIAMI - FL - US - 25.80 - -80.30 - 0 - 0 - - - - VRB - 000276 - VERO_BEACH - FL - US - 27.68 - -80.49 - 0 - 0 - - - - PSK - 000369 - DUBLIN - VA - US - 37.09 - -80.71 - 0 - 0 - - - - AIR - 000280 - BELLAIRE - OH - US - 40.02 - -80.82 - 0 - 0 - - - - CLT - 000059 - CHARLOTTE - NC - US - 35.22 - -80.93 - 0 - 0 - - - - CAE - 000295 - COLUMBIA - SC - US - 33.86 - -81.05 - 0 - 0 - - - - YVV - 000396 - WIARTON - ON - CN - 44.75 - -81.10 - 0 - 0 - - - - SAV - 000239 - SAVANNAH - GA - US - 32.16 - -81.11 - 0 - 0 - - - - OMN - 000363 - ORMOND_BEACH - FL - US - 29.30 - -81.11 - 0 - 0 - - - - BKW - 000034 - BECKLEY - WV - US - 37.78 - -81.12 - 0 - 0 - - - - ORL - 000204 - ORLANDO - FL - US - 28.54 - -81.34 - 0 - 0 - - - - CRG - 000298 - JACKSONVILLE - FL - US - 30.34 - -81.51 - 0 - 0 - - - - EYW - 000096 - KEY_WEST - FL - US - 24.59 - -81.80 - 0 - 0 - - - - FMY - 000104 - FT_MEYERS - FL - US - 26.58 - -81.87 - 0 - 0 - - - - SPA - 000380 - SPARTANBURG - SC - US - 35.03 - -81.93 - 0 - 0 - - - - HNN - 000339 - HENDERSON - WV - US - 38.75 - -82.03 - 0 - 0 - - - - HMV - 000337 - HOLSTON_MOUNTAIN - TN - US - 36.44 - -82.13 - 0 - 0 - - - - CLE - 000058 - CLEVELAND - OH - US - 41.42 - -81.85 - 0 - 0 - - - - IRQ - 000344 - COLLIERS - SC - US - 33.71 - -82.16 - 0 - 0 - - - - AMG - 000015 - ALMA - GA - US - 31.54 - -82.51 - 0 - 0 - - - - SRQ - 000382 - SARASOTA - FL - US - 27.40 - -82.55 - 0 - 0 - - - - APE - 000283 - APPLETON - OH - US - 40.15 - -82.59 - 0 - 0 - - - - PIE - 000212 - SAINT_PETERSBURG - FL - US - 27.91 - -82.68 - 0 - 0 - - - - ECK - 000316 - PECK - MI - US - 43.26 - -82.72 - 0 - 0 - - - - CTY - 000066 - CROSS_CITY - FL - US - 29.60 - -83.05 - 0 - 0 - - - - ODF - 000360 - TOCCOA - GA - US - 34.70 - -83.30 - 0 - 0 - - - - DXO - 000315 - DETROIT - MI - US - 42.21 - -83.37 - 0 - 0 - - - - ASP - 000284 - OSCODA - MI - US - 44.45 - -83.39 - 0 - 0 - - - - MCN - 000170 - MACON - GA - US - 32.69 - -83.65 - 0 - 0 - - - - FNT - 000328 - FLINT - MI - US - 42.97 - -83.74 - 0 - 0 - - - - VXV - 000388 - KNOXVILLE - TN - US - 35.90 - -83.89 - 0 - 0 - - - - ROD - 000373 - ROSEWOOD - OH - US - 40.29 - -84.04 - 0 - 0 - - - - MBS - 000168 - SAGINAW - MI - US - 43.53 - -84.08 - 0 - 0 - - - - LOZ - 000160 - LONDON - KY - US - 37.03 - -84.12 - 0 - 0 - - - - ABY - 000004 - ALBANY - GA - US - 31.65 - -84.30 - 0 - 0 - - - - SSM - 000255 - SAULT_STE_MARIE - MI - US - 46.41 - -84.31 - 0 - 0 - - - - TLH - 000264 - TALLAHASSEE - FL - US - 30.56 - -84.37 - 0 - 0 - - - - ATL - 000019 - ATLANTA - GA - US - 33.63 - -84.44 - 0 - 0 - - - - CVG - 000067 - COVINGTON - KY - US - 39.02 - -84.70 - 0 - 0 - - - - GQO - 000331 - CHATTANOOGA - TN - US - 34.96 - -85.15 - 0 - 0 - - - - FWA - 000109 - FT_WAYNE - IN - US - 40.98 - -85.19 - 0 - 0 - - - - LGC - 000350 - LA_GRANGE - GA - US - 33.05 - -85.21 - 0 - 0 - - - - GRR - 000332 - GRAND_RAPIDS - MI - US - 42.79 - -85.50 - 0 - 0 - - - - TVC - 000270 - TRAVERSE_CITY - MI - US - 44.67 - -85.55 - 0 - 0 - - - - LOU - 000159 - LOUISVILLE - KY - US - 38.10 - -85.58 - 0 - 0 - - - - MKG - 000179 - MUSKEGON - MI - US - 43.17 - -86.04 - 0 - 0 - - - - PMM - 000366 - PULLMAN - MI - US - 42.47 - -86.11 - 0 - 0 - - - - GIJ - 000330 - NILES - MI - US - 41.77 - -86.32 - 0 - 0 - - - - MGM - 000175 - MONTGOMERY - AL - US - 32.22 - -86.32 - 0 - 0 - - - - IND - 000136 - INDIANAPOLIS - IN - US - 39.81 - -86.37 - 0 - 0 - - - - BWG - 000047 - BOWLING_GREEN - KY - US - 36.93 - -86.44 - 0 - 0 - - - - BNA - 000037 - NASHVILLE - TN - US - 36.14 - -86.68 - 0 - 0 - - - - CEW - 000052 - CRESTVIEW - FL - US - 30.83 - -86.68 - 0 - 0 - - - - VUZ - 000387 - VULCAN - AL - US - 33.67 - -86.90 - 0 - 0 - - - - BVT - 000293 - LAFAYETTE - IN - US - 40.56 - -87.07 - 0 - 0 - - - - TTH - 000384 - TERRE_HAUTE - IN - US - 39.49 - -87.25 - 0 - 0 - - - - MSL - 000191 - MUSCLE_SHOALS - AL - US - 34.70 - -87.48 - 0 - 0 - - - - SAW - 000189 - SAWYER - MI - US - 46.35 - -87.38 - 0 - 0 - - - - PXV - 000370 - POCKET_CITY - IN - US - 37.93 - -87.76 - 0 - 0 - - - - ORD - 000202 - O'HARE_INTERNATIONAL - IL - US - 41.98 - -87.90 - 0 - 0 - - - - GRB - 000119 - GREEN_BAY - WI - US - 44.56 - -88.19 - 0 - 0 - - - - BAE - 000285 - MILWAUKEE - WI - US - 43.12 - -88.28 - 0 - 0 - - - - JOT - 000348 - JOLIET - IL - US - 41.55 - -88.32 - 0 - 0 - - - - SJI - 000378 - SEMMNES - AL - US - 30.73 - -88.36 - 0 - 0 - - - - IGB - 000133 - BIGBEE - MS - US - 33.48 - -88.52 - 0 - 0 - - - - MEI - 000172 - MERIDIAN - MS - US - 32.38 - -88.80 - 0 - 0 - - - - DEC - 000070 - DECATUR - IL - US - 39.74 - -88.86 - 0 - 0 - - - - YQT - 000393 - THUNDER_BAY - ON - CN - 48.37 - -89.32 - 0 - 0 - - - - DYR - 000083 - DYERSBURG - TN - US - 36.02 - -89.32 - 0 - 0 - - - - RHI - 000228 - RHINELANDER - WI - US - 45.63 - -89.45 - 0 - 0 - - - - BDF - 000024 - BRADFORD - IL - US - 41.16 - -89.59 - 0 - 0 - - - - DLL - 000310 - DELLS - WI - US - 43.55 - -89.76 - 0 - 0 - - - - MEM - 000173 - MEMPHIS - TN - US - 35.06 - -89.98 - 0 - 0 - - - - LEV - 000349 - GRAND_ISLE - LA - US - 29.18 - -90.10 - 0 - 0 - - - - JAN - 000142 - JACKSON - MS - US - 32.51 - -90.17 - 0 - 0 - - - - MSY - 000195 - NEW_ORLEANS - LA - US - 30.00 - -90.27 - 0 - 0 - - - - FAM - 000097 - FARMINGTON - MO - US - 37.67 - -90.23 - 0 - 0 - - - - MCB - 000169 - MC_COMB - MS - US - 31.30 - -90.26 - 0 - 0 - - - - SQS - 000381 - SIDON - MS - US - 33.46 - -90.28 - 0 - 0 - - - - STL - 000257 - ST_LOUIS - MO - US - 38.86 - -90.48 - 0 - 0 - - - - DBQ - 000069 - DUBUQUE - IA - US - 42.40 - -90.71 - 0 - 0 - - - - ARG - 000018 - WALNUT_RIDGE - AR - US - 36.11 - -90.95 - 0 - 0 - - - - UIN - 000386 - QUINCY - IL - US - 39.85 - -91.28 - 0 - 0 - - - - BTR - 000042 - BATON_ROUGE - LA - US - 30.48 - -91.30 - 0 - 0 - - - - ODI - 000361 - NODINE - MN - US - 43.91 - -91.47 - 0 - 0 - - - - EAU - 000085 - EAU_CLAIRE - WI - US - 44.90 - -91.48 - 0 - 0 - - - - IOW - 000343 - IOWA_CITY - IA - US - 41.52 - -91.61 - 0 - 0 - - - - MLU - 000184 - MONROE - LA - US - 32.52 - -92.03 - 0 - 0 - - - - LIT - 000156 - LITTLE_ROCK - AR - US - 34.68 - -92.18 - 0 - 0 - - - - DLH - 000075 - DULUTH - MN - US - 46.80 - -92.20 - 0 - 0 - - - - COU - 000063 - COLUMBIA - MO - US - 38.82 - -92.22 - 0 - 0 - - - - AEX - 000009 - ALEXANDRIA - LA - US - 31.26 - -92.50 - 0 - 0 - - - - IRK - 000139 - KIRKSVILLE - MO - US - 40.14 - -92.59 - 0 - 0 - - - - ELD - 000319 - EL_DORADO - AR - US - 33.26 - -92.74 - 0 - 0 - - - - LCH - 000154 - LAKE_CHARLES - LA - US - 30.14 - -93.11 - 0 - 0 - - - - MSP - 000194 - MINNEAPOLIS - MN - US - 44.88 - -93.23 - 0 - 0 - - - - MCW - 000171 - MASON_CITY - IA - US - 43.09 - -93.33 - 0 - 0 - - - - SGF - 000245 - SPRINGFIELD - MO - US - 37.36 - -93.33 - 0 - 0 - - - - INL - 000137 - INTERNATIONAL_FALLS - MN - US - 48.57 - -93.40 - 0 - 0 - - - - DSM - 000079 - DES_MOINES - IA - US - 41.44 - -93.65 - 0 - 0 - - - - EIC - 000318 - SHREVEPORT - LA - US - 32.77 - -93.81 - 0 - 0 - - - - BRD - 000292 - BRAINERD - MN - US - 46.35 - -94.03 - 0 - 0 - - - - TXK - 000272 - TEXARKANA - AR - US - 33.51 - -94.07 - 0 - 0 - - - - RZC - 000374 - RAZORBACK - AR - US - 36.25 - -94.12 - 0 - 0 - - - - FSM - 000108 - FT_SMITH - AR - US - 35.38 - -94.27 - 0 - 0 - - - - FOD - 000105 - FT_DODGE - IA - US - 42.61 - -94.29 - 0 - 0 - - - - BUM - 000045 - BUTLER - MO - US - 38.27 - -94.49 - 0 - 0 - - - - MKC - 000177 - KANSAS_CITY - MO - US - 39.28 - -94.59 - 0 - 0 - - - - LFK - 000155 - LUFKIN - TX - US - 31.16 - -94.72 - 0 - 0 - - - - GGG - 000115 - LONGVIEW - TX - US - 32.42 - -94.75 - 0 - 0 - - - - BJI - 000033 - BEMIDJI - MN - US - 47.58 - -95.02 - 0 - 0 - - - - RWF - 000234 - REDWWOD_FALLS - MN - US - 44.47 - -95.13 - 0 - 0 - - - - OSW - 000205 - OSWEGO - KS - US - 37.15 - -95.20 - 0 - 0 - - - - IAH - 000131 - HOUSTON_INTERNATIONAL - TX - US - 29.96 - -95.35 - 0 - 0 - - - - OVR - 000364 - OMAHA - NE - US - 41.17 - -95.74 - 0 - 0 - - - - MLC - 000180 - MC_CALESTER - OK - US - 34.85 - -95.78 - 0 - 0 - - - - TUL - 000268 - TULSA - OK - US - 36.20 - -95.79 - 0 - 0 - - - - PWE - 000222 - PAWNEE_CITY - NE - US - 40.20 - -96.21 - 0 - 0 - - - - PSX - 000219 - PALACIOS - TX - US - 28.76 - -96.31 - 0 - 0 - - - - FSD - 000107 - SIOUX_FALLS - SD - US - 43.65 - -96.78 - 0 - 0 - - - - FAR - 000098 - FARGO - ND - US - 46.75 - -96.85 - 0 - 0 - - - - DFW - 000072 - DALLAS-FT_WORTH - TX - US - 32.87 - -97.03 - 0 - 0 - - - - ADM - 000008 - ARDMORE - OK - US - 34.21 - -97.17 - 0 - 0 - - - - GFK - 000114 - GRAND_FORKS - ND - US - 47.95 - -97.19 - 0 - 0 - - - - YWG - 000397 - WINNIPEG - MB - CN - 49.90 - -97.23 - 0 - 0 - - - - ACT - 000006 - WACO - TX - US - 31.66 - -97.27 - 0 - 0 - - - - BRO - 000041 - BROWNSVILLE - TX - US - 25.92 - -97.38 - 0 - 0 - - - - CRP - 000065 - CORPUS_CHRISTI - TX - US - 27.90 - -97.45 - 0 - 0 - - - - ICT - 000132 - WICHITA - KS - US - 37.75 - -97.58 - 0 - 0 - - - - OKC - 000198 - OKLAHOMA_CITY - OK - US - 35.36 - -97.61 - 0 - 0 - - - - SLN - 000251 - SALINA - KS - US - 38.93 - -97.62 - 0 - 0 - - - - AUS - 000020 - AUSTIN - TX - US - 30.30 - -97.70 - 0 - 0 - - - - END - 000321 - VANCE_AFB - OK - US - 36.35 - -97.92 - 0 - 0 - - - - OBH - 000358 - WOLBACH - NE - US - 41.38 - -98.35 - 0 - 0 - - - - ABR - 000003 - ABERDEEN - SD - US - 45.42 - -98.37 - 0 - 0 - - - - SAT - 000238 - SAN_ANTONIO - TX - US - 29.64 - -98.46 - 0 - 0 - - - - SPS - 000254 - WICHITA_FALLS - TX - US - 33.99 - -98.59 - 0 - 0 - - - - ONL - 000200 - ONEILL - NE - US - 42.47 - -98.69 - 0 - 0 - - - - LRD - 000161 - LAREDO - TX - US - 27.48 - -99.42 - 0 - 0 - - - - JCT - 000144 - JUNCTION - TX - US - 30.60 - -99.82 - 0 - 0 - - - - ABI - 000001 - ABILENE - TX - US - 32.48 - -99.86 - 0 - 0 - - - - GAG - 000110 - GAGE - OK - US - 36.34 - -99.88 - 0 - 0 - - - - ANW - 000282 - AINSWORTH - NE - US - 42.57 - -99.99 - 0 - 0 - - - - PIR - 000214 - PIERRE - SD - US - 44.40 - -100.17 - 0 - 0 - - - - HLC - 000335 - HILL_CITY - KS - US - 39.26 - -100.23 - 0 - 0 - - - - CDS - 000051 - CHILDRESS - TX - US - 34.37 - -100.28 - 0 - 0 - - - - SJT - 000248 - SAN_ANGELO - TX - US - 31.38 - -100.46 - 0 - 0 - - - - MCK - 000351 - MC_COOK - NE - US - 40.20 - -100.59 - 0 - 0 - - - - BIS - 000032 - BISMARK - ND - US - 46.77 - -100.67 - 0 - 0 - - - - LBF - 000152 - NORTH_PLATTE - NE - US - 41.13 - -100.72 - 0 - 0 - - - - GCK - 000112 - GARDEN_CITY - KS - US - 37.92 - -100.73 - 0 - 0 - - - - DLF - 000309 - LAUGHLIN_AFB - TX - US - 29.36 - -100.77 - 0 - 0 - - - - LBL - 000153 - LIBERAL - KS - US - 37.04 - -100.97 - 0 - 0 - - - - MOT - 000187 - MINOT - ND - US - 48.26 - -101.29 - 0 - 0 - - - - AMA - 000014 - AMARILLO - TX - US - 35.29 - -101.64 - 0 - 0 - - - - GLD - 000118 - GOODLAND - KS - US - 39.39 - -101.69 - 0 - 0 - - - - DPR - 000077 - DUPREE - SD - US - 45.08 - -101.72 - 0 - 0 - - - - LBB - 000151 - LUBBOCK_INTERNATIONAL - TX - US - 33.70 - -101.92 - 0 - 0 - - - - MAF - 000167 - MIDLAND - TX - US - 32.02 - -102.18 - 0 - 0 - - - - LAA - 000146 - LAMAR - CO - US - 38.20 - -102.69 - 0 - 0 - - - - DIK - 000074 - DICKINSIN - ND - US - 46.86 - -102.77 - 0 - 0 - - - - TXO - 000385 - TEXICO_NM/BOVINA - TX - US - 34.50 - -102.84 - 0 - 0 - - - - SNY - 000379 - SIDNEY - NE - US - 41.10 - -102.98 - 0 - 0 - - - - FST - 000329 - FT_STOCKTON - TX - US - 30.95 - -102.98 - 0 - 0 - - - - RAP - 000224 - RAPID_CITY - SD - US - 43.98 - -103.01 - 0 - 0 - - - - AKO - 000011 - AKRON - CO - US - 40.16 - -103.18 - 0 - 0 - - - - INK - 000342 - WINK - TX - US - 31.87 - -103.24 - 0 - 0 - - - - BFF - 000026 - SCOTTSBLUFF - NE - US - 41.89 - -103.48 - 0 - 0 - - - - TBE - 000261 - TOBE - CO - US - 37.27 - -103.60 - 0 - 0 - - - - TCC - 000262 - TUCUMCARI - NM - US - 35.18 - -103.60 - 0 - 0 - - - - ISN - 000140 - WILLISTON - ND - US - 48.18 - -103.63 - 0 - 0 - - - - MRF - 000190 - MARFA - TX - US - 30.30 - -103.95 - 0 - 0 - - - - PUB - 000220 - PUEBLO - CO - US - 38.29 - -104.43 - 0 - 0 - - - - ROW - 000233 - ROSWELL - NM - US - 33.34 - -104.62 - 0 - 0 - - - - DEN - 000071 - DENVER - CO - US - 39.81 - -104.66 - 0 - 0 - - - - CYS - 000301 - CHEYENNE - WY - US - 41.21 - -104.77 - 0 - 0 - - - - CIM - 000297 - CIMARRON - NM - US - 36.49 - -104.87 - 0 - 0 - - - - LVS - 000163 - LAS_VEGAS - NM - US - 35.66 - -105.14 - 0 - 0 - - - - LAR - 000148 - LARAMIE - WY - US - 41.33 - -105.72 - 0 - 0 - - - - ALS - 000013 - ALAMOSA - CO - US - 37.35 - -105.82 - 0 - 0 - - - - MLS - 000182 - MILES_CITY - MT - US - 46.38 - -105.95 - 0 - 0 - - - - DDY - 000307 - CASPER - WY - US - 43.09 - -106.28 - 0 - 0 - - - - ELP - 000090 - EL_PASO - TX - US - 31.82 - -106.28 - 0 - 0 - - - - CZI - 000302 - CRAZY_WOMAN - WY - US - 44.00 - -106.44 - 0 - 0 - - - - GGW - 000116 - GLASGOW - MT - US - 48.22 - -106.63 - 0 - 0 - - - - ABQ - 000002 - ALBUQUERQUE - NM - US - 35.04 - -106.82 - 0 - 0 - - - - DBL - 000304 - EAGLE - CO - US - 39.44 - -106.90 - 0 - 0 - - - - HBU - 000333 - GUNNISON - CO - US - 38.45 - -107.04 - 0 - 0 - - - - SHR - 000246 - SHERIDAN - WY - US - 44.84 - -107.06 - 0 - 0 - - - - TCS - 000263 - TRUTH_OR_CONSEQUENCES - NM - US - 33.28 - -107.28 - 0 - 0 - - - - CHE - 000054 - HAYDEN - CO - US - 40.52 - -107.31 - 0 - 0 - - - - DMN - 000076 - DEMING - NM - US - 32.28 - -107.60 - 0 - 0 - - - - YYN - 000400 - SWIFT_CURRENT - SA - CN - 50.28 - -107.68 - 0 - 0 - - - - FMN - 000103 - FARMINGTON - NM - US - 36.75 - -108.10 - 0 - 0 - - - - BOY - 000290 - BOYSEN_RESV. - WY - US - 43.46 - -108.30 - 0 - 0 - - - - BIL - 000031 - BILLINGS - MT - US - 45.81 - -108.63 - 0 - 0 - - - - JNC - 000347 - GRAND_JUNCTION - CO - US - 39.06 - -108.79 - 0 - 0 - - - - DVC - 000082 - DOVE_CREEK - CO - US - 37.81 - -108.93 - 0 - 0 - - - - OCS - 000359 - ROCKSPRINGS - WY - US - 41.59 - -109.02 - 0 - 0 - - - - SJN - 000247 - ST_JOHNS - AZ - US - 34.42 - -109.14 - 0 - 0 - - - - SSO - 000256 - SAN_SIMON - AZ - US - 32.27 - -109.26 - 0 - 0 - - - - LWT - 000165 - LEWISTOWN - MT - US - 47.05 - -109.61 - 0 - 0 - - - - HVR - 000129 - HAVRE - MT - US - 48.54 - -109.77 - 0 - 0 - - - - BPI - 000291 - BIG_PINEY - WY - US - 42.58 - -110.11 - 0 - 0 - - - - MTU - 000196 - MYTON - UT - US - 40.15 - -110.13 - 0 - 0 - - - - HVE - 000128 - HANKSVILLE - UT - US - 38.42 - -110.70 - 0 - 0 - - - - YXH - 000399 - MEDICINE_HAT - AB - CN - 50.02 - -110.72 - 0 - 0 - - - - JAC - 000141 - JACKSON - WY - US - 43.62 - -110.73 - 0 - 0 - - - - INW - 000138 - WINSLOW - AZ - US - 35.06 - -110.80 - 0 - 0 - - - - TUS - 000269 - TUCSON - AZ - US - 32.10 - -110.92 - 0 - 0 - - - - TBC - 000260 - TUBA_CITY - AZ - US - 36.12 - -111.27 - 0 - 0 - - - - GTF - 000123 - GREAT_FALLS - MT - US - 47.45 - -111.41 - 0 - 0 - - - - HLN - 000336 - HELENA - MT - US - 46.61 - -111.95 - 0 - 0 - - - - PHX - 000211 - PHOENIX - AZ - US - 33.43 - -112.02 - 0 - 0 - - - - SLC - 000249 - SALT_LAKE_CITY - UT - US - 40.85 - -111.98 - 0 - 0 - - - - DBS - 000305 - DUBOIS - ID - US - 44.09 - -112.21 - 0 - 0 - - - - BCE - 000023 - BRYCE_CANYON - UT - US - 37.69 - -112.30 - 0 - 0 - - - - MLD - 000352 - MALAD_CITY - ID - US - 42.20 - -112.45 - 0 - 0 - - - - DRK - 000313 - PRESCOTT - AZ - US - 34.70 - -112.48 - 0 - 0 - - - - DTA - 000080 - DELTA - UT - US - 39.30 - -112.51 - 0 - 0 - - - - DLN - 000311 - DILLON - MT - US - 45.25 - -112.55 - 0 - 0 - - - - PIH - 000213 - POCATELLO - ID - US - 42.87 - -112.65 - 0 - 0 - - - - YQL - 000392 - LETHBRIDGE - AB - CN - 49.63 - -112.80 - 0 - 0 - - - - PGS - 000210 - PEACH_SPRINGS - AZ - US - 35.62 - -113.54 - 0 - 0 - - - - BVL - 000046 - BOONEVILLE - UT - US - 40.73 - -113.76 - 0 - 0 - - - - LKT - 000157 - SALMON - ID - US - 45.02 - -114.08 - 0 - 0 - - - - FCA - 000100 - KALISPELL - MT - US - 48.21 - -114.18 - 0 - 0 - - - - ILC - 000134 - WILSON_CREEK - NV - US - 38.25 - -114.39 - 0 - 0 - - - - EED - 000087 - NEEDLES - CA - US - 34.77 - -114.47 - 0 - 0 - - - - TWF - 000271 - TWIN_FALLS - ID - US - 42.48 - -114.49 - 0 - 0 - - - - BZA - 000294 - YUMA - AZ - US - 32.77 - -114.60 - 0 - 0 - - - - ELY - 000091 - ELY - NV - US - 39.30 - -114.85 - 0 - 0 - - - - LAS - 000149 - LAS_VEGAS - NV - US - 36.08 - -115.16 - 0 - 0 - - - - MLP - 000181 - MULLAN_PASS - ID - US - 47.46 - -115.65 - 0 - 0 - - - - YXC - 000398 - CRANBROOK - BC - CN - 49.60 - -115.78 - 0 - 0 - - - - TRM - 000383 - THERMAL - CA - US - 33.63 - -116.16 - 0 - 0 - - - - BOI - 000039 - BOISE - ID - US - 43.55 - -116.19 - 0 - 0 - - - - DNJ - 000312 - MC_CALL - ID - US - 44.77 - -116.21 - 0 - 0 - - - - HEC - 000334 - HECTOR - CA - US - 34.80 - -116.46 - 0 - 0 - - - - BTY - 000043 - BEATTY - NV - US - 36.80 - -116.75 - 0 - 0 - - - - BAM - 000286 - BATTLE_MOUNTAIN - NV - US - 40.57 - -116.92 - 0 - 0 - - - - MZB - 000354 - MISSION_BAY - CA - US - 32.78 - -117.23 - 0 - 0 - - - - GEG - 000113 - SPOKANE - WA - US - 47.56 - -117.63 - 0 - 0 - - - - OAL - 000357 - COALDALE - NV - US - 38.00 - -117.77 - 0 - 0 - - - - BKE - 000288 - BAKER - OR - US - 44.84 - -117.81 - 0 - 0 - - - - REO - 000227 - ROME - OR - US - 42.59 - -117.87 - 0 - 0 - - - - LAX - 000150 - LOS_ANGELES_INTL - CA - US - 33.93 - -118.43 - 0 - 0 - - - - PDT - 000207 - PENDLETON - OR - US - 45.70 - -118.94 - 0 - 0 - - - - EHF - 000317 - BAKERSFIELD - CA - US - 35.48 - -119.10 - 0 - 0 - - - - EPH - 000324 - EPHRATA - WA - US - 47.38 - -119.42 - 0 - 0 - - - - FMG - 000327 - RENO - NV - US - 39.53 - -119.66 - 0 - 0 - - - - RZS - 000375 - SANTA_BARBARA - CA - US - 34.51 - -119.77 - 0 - 0 - - - - CZQ - 000303 - FRESNO - CA - US - 36.88 - -119.82 - 0 - 0 - - - - YKM - 000279 - YAKIMA - WA - US - 46.57 - -120.45 - 0 - 0 - - - - LKV - 000158 - LAKEVIEW - OR - US - 42.49 - -120.51 - 0 - 0 - - - - YDC - 000389 - PRINCETON - BC - CN - 49.47 - -120.52 - 0 - 0 - - - - MOD - 000186 - MODESTO - CA - US - 37.63 - -120.96 - 0 - 0 - - - - DSD - 000314 - REDMOND - WA - US - 44.25 - -121.30 - 0 - 0 - - - - SAC - 000236 - SACRAMENTO - CA - US - 38.44 - -121.55 - 0 - 0 - - - - SNS - 000253 - SALINAS - CA - US - 36.66 - -121.60 - 0 - 0 - - - - OAK - 000356 - OAKLAND - CA - US - 37.73 - -122.22 - 0 - 0 - - - - RBL - 000225 - RED_BLUFF - CA - US - 40.10 - -122.24 - 0 - 0 - - - - SEA - 000243 - SEATTLE - WA - US - 47.44 - -122.31 - 0 - 0 - - - - BLI - 000035 - BELLINGHAM - WA - US - 48.95 - -122.58 - 0 - 0 - - - - PDX - 000208 - PORTLAND - OR - US - 45.58 - -122.60 - 0 - 0 - - - - PYE - 000371 - POINT_REYES - CA - US - 38.08 - -122.87 - 0 - 0 - - - - OED - 000362 - MEDFORD - OR - US - 42.48 - -122.91 - 0 - 0 - - - - EUG - 000093 - EUGENE - OR - US - 44.12 - -123.22 - 0 - 0 - - - - ENI - 000323 - UKIAH - CA - US - 39.05 - -123.27 - 0 - 0 - - - - ONP - 000201 - NEWPORT - OR - US - 44.58 - -124.06 - 0 - 0 - - - - HQM - 000127 - HOQUIAM - WA - US - 46.95 - -124.15 - 0 - 0 - - - - FOT - 000106 - FORTUNA - CA - US - 40.67 - -124.23 - 0 - 0 - - - - TOU - 000265 - NEAH_BAY - WA - US - 48.30 - -124.63 - 0 - 0 - - - - YQV - 000402 - YORKTON - SA - CN - 51.27 - -102.47 - 0 - 0 - - - - ANN - 0 - ANNETTE_ISLAND - AK - US - 55.05 - -131.57 - 0 - 0 - - - - LVD - 0 - LEVEL_ISLAND - AK - US - 56.47 - -133.08 - 0 - 0 - - - - BKA - 0 - BIORKA_ISLAND - AK - US - 56.86 - -135.55 - 0 - 0 - - - - SSR - 0 - SISTERS_ISLAND - AK - US - 58.17 - -135.25 - 0 - 0 - - - - JNU - 0 - JUNEAU - AK - US - 58.35 - -134.58 - 0 - 0 - - - - YAK - 0 - YAKUTAT - AK - US - 59.50 - -139.67 - 0 - 0 - - - - MDO - 0 - MIDDLETON_ISLAND - AK - US - 59.45 - -146.30 - 0 - 0 - - - - JOH - 0 - JOHNSTONE_POINT - AK - US - 60.48 - -146.60 - 0 - 0 - - - - ODK - 0 - KODIAK - AK - US - 57.75 - -152.50 - 0 - 0 - - - - HOM - 0 - HOMER - AK - US - 59.65 - -151.48 - 0 - 0 - - - - ENA - 0 - KENAI - AK - US - 60.57 - -151.25 - 0 - 0 - - - - ANC - 0 - ANCHORAGE - AK - US - 61.17 - -150.00 - 0 - 0 - - - - BGQ - 0 - BIG_LAKE - AK - US - 61.53 - -149.82 - 0 - 0 - - - - ORT - 0 - NORTHWAY - AK - US - 62.97 - -141.93 - 0 - 0 - - - - GKN - 0 - GULKANA - AK - US - 62.15 - -145.45 - 0 - 0 - - - - TKA - 0 - TALKEETNA - AK - US - 62.32 - -150.10 - 0 - 0 - - - - SQA - 0 - SPARREVOHN - AK - US - 61.10 - -155.63 - 0 - 0 - - - - DLG - 0 - DILLINGHAM - AK - US - 59.05 - -158.50 - 0 - 0 - - - - AKN - 0 - KING_SALMON - AK - US - 58.68 - -156.65 - 0 - 0 - - - - PDN - 0 - PORT_HEIDEN - AK - US - 56.95 - -158.65 - 0 - 0 - - - - CDB - 0 - COLD_BAY - AK - US - 55.20 - -162.73 - 0 - 0 - - - - DUT - 0 - DUTCH_HARBOR - AK - US - 53.90 - -166.55 - 0 - 0 - - - - NUD - 0 - ADAK - AK - US - 51.88 - -176.65 - 0 - 0 - - - - SYA - 0 - SHEMYA - AK - US - 52.72 - 174.12 - 0 - 0 - - - - SPY - 0 - ST_PAUL_ISLAND - AK - US - 57.17 - -170.22 - 0 - 0 - - - - EHM - 0 - CAPE_NEWENHAM - AK - US - 58.66 - -162.07 - 0 - 0 - - - - HPB - 0 - HOOPER_BAY - AK - US - 61.52 - -166.14 - 0 - 0 - - - - BET - 0 - BETHEL - AK - US - 60.78 - -161.83 - 0 - 0 - - - - ANI - 0 - ANIAK - AK - US - 61.59 - -159.61 - 0 - 0 - - - - SMA - 0 - ST_MARYS - AK - US - 62.06 - -163.30 - 0 - 0 - - - - UNK - 0 - UNALAKLEET - AK - US - 63.88 - -160.80 - 0 - 0 - - - - ULL - 0 - KUKULIAK - AK - US - 63.70 - -170.48 - 0 - 0 - - - - MCG - 0 - MC_GRATH - AK - US - 62.95 - -155.60 - 0 - 0 - - - - ENN - 0 - NENANA - AK - US - 64.55 - -149.07 - 0 - 0 - - - - FAI - 0 - FAIRBANKS - AK - US - 64.82 - -147.85 - 0 - 0 - - - - BIG - 0 - BIG_DELTA - AK - US - 64.00 - -145.72 - 0 - 0 - - - - FYU - 0 - FORT_YUKON - AK - US - 66.57 - -145.25 - 0 - 0 - - - - BTT - 0 - BETTLES - AK - US - 66.92 - -151.53 - 0 - 0 - - - - TAL - 0 - TANANA - AK - US - 65.18 - -152.18 - 0 - 0 - - - - CQR - 0 - CHANDALAR_LAKE - AK - US - 67.50 - -148.47 - 0 - 0 - - - - SCC - 0 - DEADHORSE - AK - US - 70.20 - -148.47 - 0 - 0 - - - - BTI - 0 - BARTER_ISLAND - AK - US - 70.13 - -143.57 - 0 - 0 - - - - BRW - 0 - BARROW - AK - US - 71.28 - -156.77 - 0 - 0 - - - - GAL - 0 - GALENA - AK - US - 64.73 - -156.93 - 0 - 0 - - - - OME - 0 - NOME - AK - US - 64.52 - -165.45 - 0 - 0 - - - - OTZ - 0 - KOTZEBUE - AK - US - 66.88 - -162.60 - 0 - 0 - - - - WLK - 0 - SELAWIK - AK - US - 66.60 - -160.00 - 0 - 0 - - - - HSL - 0 - HUSLIA - AK - US - 65.71 - -156.37 - 0 - 0 - - - - BSF - 0 - BRADSHAW - HI - US - 19.76 - -155.39 - 0 - 0 - - - - UPP - 0 - UPOLU_POINT - HI - US - 20.20 - -155.84 - 0 - 0 - - - - ITO - 0 - HILO - HI - US - 19.72 - -155.01 - 0 - 0 - - - - HNL - 0 - HONOLULU - HI - US - 21.33 - -157.93 - 0 - 0 - - - - OGG - 0 - MAUI - HI - US - 20.91 - -156.42 - 0 - 0 - - - - NDB - 0 - VALLEY_ISLAND - HI - US - 20.88 - -156.44 - 0 - 0 - - - - MUE - 0 - KAMUELA - HI - US - 20.00 - -155.67 - 0 - 0 - - - - NGF - 0 - KANEOHE_BAY - HI - US - 21.45 - -157.76 - 0 - 0 - - - - MKK - 0 - MOLOKAI - HI - US - 21.14 - -157.17 - 0 - 0 - - - - NBS - 0 - BARKING_SANDS - HI - US - 22.04 - -159.79 - 0 - 0 - - - - CKH - 0 - KOKO_HEAD - HI - US - 21.27 - -157.70 - 0 - 0 - - - - IAI - 0 - KONA - HI - US - 19.65 - -156.02 - 0 - 0 - - - - LLD - 0 - LANAI - HI - US - 20.77 - -156.97 - 0 - 0 - - - - LNY - 0 - LANAI_CITY - HI - US - 20.76 - -156.97 - 0 - 0 - - - - LIH - 0 - LIHUE - HI - US - 21.97 - -159.34 - 0 - 0 - - - - SOK - 0 - SOUTH_KAUAI - HI - US - 21.90 - -159.53 - 0 - 0 - - - - RSW - 0 - LEE_COUNTY - FL - US - 26.53 - -81.78 - 0 - 0 - - - - PZD - 0 - PECAN - GA - US - 31.66 - -84.29 - 0 - 0 - - - - IIU - 0 - LOUISVILLE - KY - US - 38.10 - -85.58 - 0 - 0 - - - - HRV - 0 - HARVEY - LA - US - 29.85 - -90.00 - 0 - 0 - - - - MCI - 0 - KANSAS_CITY - MO - US - 39.29 - -94.74 - 0 - 0 - - - - TTT - 0 - MAVERICK - TX - US - 32.87 - -97.04 - 0 - 0 - - - - CWK - 0 - CENTEX - TX - US - 30.38 - -97.53 - 0 - 0 - - - - CME - 0 - CHISUM - NM - US - 33.34 - -104.62 - 0 - 0 - - - - FTI - 0 - FT_UNION - NM - US - 35.66 - -105.14 - 0 - 0 - - - - RSK - 0 - RATTLESNAKE - NM - US - 36.75 - -108.10 - 0 - 0 - - - - HUH - 0 - WHATCOM - WA - US - 48.95 - -122.58 - 0 - 0 - - - - ASRF - 948640 - MELBOURNE - VC - AU - -37.73 - 144.90 - 81 - 0 - - - - AYPY - 940350 - PORT_MORESBY_INTL - - NG - -9.43 - 147.22 - 47 - 0 - - - - BGSF - 042310 - SONDRE_STROMFJORD - - GL - 67.00 - -50.80 - 53 - 0 - - - - BIRK - 040300 - REYKJAVIK - - IL - 64.13 - -21.90 - 61 - 0 - - - - CWEG - 999999 - ALBERTA_WEATHER_CENTRE - - CN - 53.50 - -113.50 - -9999 - 0 - - - - CWLW - 712030 - KELOWNA - BC - CN - 49.95 - -119.40 - 456 - 0 - - - - CWNT - 712500 - TURTLE_MOUNTAIN - AB - CN - 49.58 - -114.42 - 2164 - 0 - - - - CWTO - 716380 - TORONTO_A_E_S__HQ - ON - CN - 43.78 - -79.47 - 187 - 0 - - - - CWUL - 999999 - QUEBEC_FCST_OFFICE - - CN - 45.50 - -73.68 - -9999 - 0 - - - - CYQX - 718030 - GANDER_INTL_AIRPORT - NF - CN - 48.95 - -54.57 - 151 - 0 - - - - DTTA - 607150 - TUNIS/CARTHAGE - - TS - 36.83 - 10.23 - 4 - 0 - - - - EBBR - 064510 - BRUSSELS_NATIONAL - - BX - 50.90 - 4.53 - 58 - 0 - - - - EDMM - 108680 - MUENCHEN - - DL - 48.25 - 11.58 - 484 - 0 - - - - EDZB - 102380 - BERGEN/HOHNE - - DL - 52.82 - 9.93 - 70 - 0 - - - - EDZE - 104100 - ESSEN/MULHEIM - - DL - 51.40 - 6.97 - 161 - 0 - - - - EDZF - 106370 - FRANKFURT/MAIN - - DL - 50.05 - 8.58 - 112 - 0 - - - - EDZH - 107710 - GAERMERSDORF - - DL - 49.43 - 11.90 - 419 - 0 - - - - EDZM - 108680 - MUENCHEN - - DL - 48.25 - 11.58 - 484 - 0 - - - - EETN - 260380 - TALLIN - - BY - 59.35 - 24.80 - 44 - 0 - - - - EFHK - 029740 - HELSINKI/VANTAA - - FI - 60.32 - 24.97 - 56 - 0 - - - - EFRO - 028450 - ROVANIEMI(CIV/MIL) - - FI - 66.57 - 25.83 - 201 - 0 - - - - EGJJ - 038950 - JERSEY_AIRPORT - - UK - 49.22 - -2.20 - 84 - 0 - - - - EHAM - 062400 - AMSTERDAM/SCHIPHOL - - NL - 52.30 - 4.77 - -2 - 0 - - - - EHDB - 062600 - DE_BILT - - NL - 52.10 - 5.18 - 4 - 0 - - - - EINN - 039620 - SHANNON_AIRPORT - - IE - 52.70 - -8.92 - 20 - 0 - - - - EKCH - 061800 - COPENHAGEN/KASTRUP - - DN - 55.63 - 12.67 - 5 - 0 - - - - ENMI - 999999 - OSLO - - NO - 59.50 - 10.70 - -9999 - 0 - - - - ENVN - 011520 - BODO - - NO - 67.25 - 14.40 - 8 - 0 - - - - ENVV - 014150 - STAVANGER - - NO - 58.87 - 5.67 - 34 - 0 - - - - EPWA - 123750 - WARSAW/OKECIE - - PL - 52.17 - 20.97 - 107 - 0 - - - - ESNN - 023660 - SUNDSVALL/HARNOSAND - - SN - 62.53 - 17.45 - 10 - 0 - - - - ESSA - 024600 - STOCKHOLM/ARLANDA - - SN - 59.65 - 17.95 - 61 - 0 - - - - EVRA - 999999 - RIGA_AIRPORT - LE - BY - 56.92 - 23.97 - 10 - 0 - - - - EYVI - 267300 - VILNIUS_INTL - MI - BY - 54.63 - 25.28 - 156 - 0 - - - - FAJS - 683680 - JAN_SMUTS - - ZA - -26.13 - 28.23 - 1700 - 0 - - - - FCBB - 644500 - BRAZZAVILLE/MAYA-MA - - CG - -4.25 - 15.25 - 316 - 0 - - - - FTTJ - 647000 - NDJAMENA(CIV/MIL) - - CD - 12.13 - 15.03 - 295 - 0 - - - - GCGC - 999999 - CANARY_ISLANDS - - CR - 28.50 - -16.00 - -9999 - 0 - - - - GMMC - 601550 - CASABLANCA - - MC - 33.57 - -7.67 - 62 - 0 - - - - HECA - 623660 - CAIRO_INTL_AIRPORT - - EG - 30.13 - 31.40 - 74 - 0 - - - - LBSF - 156140 - SOFIA - - BU - 42.65 - 23.38 - 595 - 0 - - - - LBWN - 155520 - VARNA - - BU - 43.20 - 27.92 - 43 - 0 - - - - LCLK - 176090 - LARNACA/LARNAX_ARPT - - CY - 34.88 - 33.63 - 2 - 0 - - - - LDZA - 131310 - ZAGREB/PLESO - - RH - 45.73 - 16.07 - 107 - 0 - - - - LDZO - 999999 - ZAGREB/PLESO - - RH - 45.73 - 16.07 - 107 - 0 - - - - LECB - 081810 - BARCELONA - - SP - 41.28 - 2.07 - 6 - 0 - - - - LEMM - 999999 - MADRID_CNM - - SP - 40.12 - -3.53 - -9999 - 0 - - - - LFBD - 075100 - BORDEAUX/MERIGNAC - - FR - 44.83 - -.70 - 61 - 0 - - - - LFMM - 076500 - MARSEILLE - - FR - 43.45 - 5.22 - 20 - 0 - - - - LFPW - 999999 - PARIS_MET_CENTER - - FR - 48.83 - 2.33 - 75 - 0 - - - - LFRN - 071300 - RENNES/ST.JACQUES - - FR - 48.07 - -1.73 - 37 - 0 - - - - LFST - 071900 - STRASBOURG/ENTZHEIM - - FR - 48.55 - 7.63 - 154 - 0 - - - - LGAT - 167160 - ATHENS/HELLENKION - - GR - 37.90 - 23.73 - 15 - 0 - - - - LHBP - 128390 - BUDAPEST/FERIHEGY - - HU - 47.43 - 19.27 - 185 - 0 - - - - LIMM - 160800 - MILANO/LINATE - - IY - 45.43 - 9.27 - 103 - 0 - - - - LJLJ - 130140 - LJUBLJANA/BRNIK - - LJ - 46.22 - 14.48 - 385 - 0 - - - - LKPR - 115180 - PRAGUE/RUZYNE - - CZ - 50.10 - 14.28 - 365 - 0 - - - - LLBG - 401800 - BEN-GURION(CIV/MIL) - - IS - 32.00 - 34.90 - 49 - 0 - - - - LMML - 165970 - LUQA/MALTA - - ML - 35.85 - 14.48 - 91 - 0 - - - - LOWW - 110360 - VIENNA/SCHWECHAT - - OS - 48.12 - 16.57 - 190 - 0 - - - - LPPT - 085360 - LISBON/PORTELA - - PO - 38.78 - -9.13 - 123 - 0 - - - - LROM - 154210 - BUCHAREST/OTOPENI - - RO - 44.55 - 26.10 - 95 - 0 - - - - LROP - 154210 - BUCHAREST/OTOPENI - - RO - 44.55 - 26.10 - 95 - 0 - - - - LSZH - 066700 - ZURICH-KLOTEN_(AUT) - - SW - 47.48 - 8.53 - 432 - 0 - - - - LTAC - 171280 - ANKARA/ESENBOGA - - TU - 40.11 - 32.97 - 949 - 0 - - - - LTBA - 170600 - ISTANBUL/ATATURK_AB - - TU - 40.97 - 28.82 - 37 - 0 - - - - LUKK - 338387 - KISHINAU - - UR - 46.93 - 28.93 - 122 - 0 - - - - LWSK - 135860 - SKOPJE/PETROVAC - - MK - 41.97 - 21.65 - 239 - 0 - - - - LYBE - 132720 - BELGRADE/SURCIN - - YG - 44.82 - 20.28 - 99 - 0 - - - - LZIB - 118160 - BRATISLAVA_IVANKA - - CZ - 48.20 - 17.20 - 130 - 0 - - - - NFFN - 916800 - NANDI/NADI_INTL - - FJ - -17.75 - 177.45 - 18 - 0 - - - - NZDT - 999999 - NEW_ZEALAND - - NZ - -41.00 - 172.50 - -9999 - 0 - - - - NZKL - 999999 - AUCKLAND - - NZ - -37.02 - 174.80 - 6 - 0 - - - - MHTG - 787200 - TEGUCIGALPA/TONCONT - - HO - 14.05 - -87.22 - 994 - 0 - - - - MPTO - 787920 - TOCUMEN/GEN._OMAR - - PM - 9.05 - -79.37 - 11 - 0 - - - - OBBB - 999999 - BAHRAIN_INTL_ARPT - - BN - 26.27 - 50.65 - 2 - 0 - - - - OBBI - 411500 - BAHRAIN_INTL_ARPT - - BN - 26.27 - 50.65 - 2 - 0 - - - - OEJD - 999999 - JEDDAH - - SD - 21.30 - 39.20 - -9999 - 0 - - - - OEJN - 410240 - JEDDAH/KING_ABD - - SD - 21.67 - 39.15 - 12 - 0 - - - - OIII - 407540 - TEHRAN/MEHRABAD_AFB - - IR - 35.68 - 51.35 - 1191 - 0 - - - - OIIX - 999999 - TEHRAN - - IR - 35.68 - 51.35 - 1191 - 0 - - - - OLBA - 401000 - BEIRUT_(CIV/MIL) - - LB - 33.82 - 35.48 - 19 - 0 - - - - OPKC - 417800 - KARACHI_INTL_ARPT - - PK - 24.90 - 67.13 - 22 - 0 - - - - OPLA - 416410 - LAHORE(CIV/MIL) - - PK - 31.52 - 74.40 - 217 - 0 - - - - OYSN - 413440 - SANA'A - - YE - 15.52 - 44.18 - 2190 - 0 - - - - PAFA - 702610 - FAIRBANKS_INTL_ARPT_(ASOS) - AK - US - 64.82 - -147.87 - 138 - 0 - - - - PAJN - 703810 - JUNEAU_INTL_AIRPORT_(ASOS) - AK - US - 58.37 - -134.58 - 7 - 0 - - - - PANC - 702730 - ANCHORAGE_INTL_ARPT_(ASOS) - AK - US - 61.17 - -150.02 - 40 - 0 - - - - RKSI - 470699 - CHAJANG_NI_(K-ARMY) - - KO - 37.87 - 127.18 - 100 - 0 - - - - RCTP - 466860 - TAIPEI/CHIANG_KAI_SHEK - - TW - 25.08 - 121.22 - 33 - 0 - - - - SABE - 875820 - AEROPARQUE(CIV/MIL) - - AG - -34.57 - -58.42 - 6 - 0 - - - - SACO - 873440 - CORDOBA_AIRPORT - - AG - -31.32 - -64.22 - 474 - 0 - - - - SAEZ - 875760 - BUENOS_AIRES/EZEIZA - - AG - -34.82 - -58.53 - 20 - 0 - - - - SAME - 874180 - MENDOZA/EL_PLUMERIL - - AG - -32.83 - -68.78 - 704 - 0 - - - - SARE - 871550 - RESISTENCIA_AIRPORT - - AG - -27.45 - -59.05 - 52 - 0 - - - - SBBE - 821930 - BELEM/VAL_DE_CAES - - BZ - -1.38 - -48.48 - 16 - 0 - - - - SBBR - 833780 - BRASILIA_(CIV/MIL) - - BZ - -15.87 - -47.93 - 1061 - 0 - - - - SBBS - 833780 - BRASILIA - - BZ - -15.87 - -47.93 - 1061 - 0 - - - - SBCT - 838400 - CURITIBA/AFONSO_PEN - - BZ - -25.52 - -49.17 - 908 - 0 - - - - SBCW - 838400 - CURITIBA/AFONSO_PEN - - BZ - -25.52 - -49.17 - 908 - 0 - - - - SBEG - 821110 - EDUARDO_GOMES_INTL - - BZ - -3.03 - -60.05 - 2 - 0 - - - - SBGL - 837460 - GALEAO/RIO(CIV/MIL) - - BZ - -22.82 - -43.25 - 6 - 0 - - - - SBGR - 837753 - GUARULHOS_(CIV/MIL) - - BZ - -23.43 - -46.47 - 750 - 0 - - - - SBRF - 828990 - RECIFE/GUARARAPES - - BZ - -8.07 - -34.85 - 19 - 0 - - - - SCCI - 859340 - PUNTA_ARENAS/PRES_C - - CH - -53.00 - -70.85 - 37 - 0 - - - - SCEL - 855740 - PUDAHUEL/ARTURO_MER - - CH - -33.38 - -70.78 - 476 - 0 - - - - SCFA - 854420 - ANTOFAGASTA/CERRO - - CH - -23.43 - -70.43 - 120 - 0 - - - - SCTE - 857990 - PUERTO_MONTT/TEPUAL - - CH - -41.42 - -73.08 - 86 - 0 - - - - SLLP - 852010 - LA_PAZ/JFK_INTL - - BO - -16.52 - -68.18 - 4014 - 0 - - - - SOCA - 814050 - CAYENNE/ROCHAMBEAU - - FG - 4.83 - -52.37 - 9 - 0 - - - - SPIM - 846280 - LIMA/JORGE_CHAVEZ - - PR - -12.00 - -77.12 - 13 - 0 - - - - TNCC - 789880 - HATO_ARPT_(CIV/MIL) - - NU - 12.20 - -68.97 - 67 - 0 - - - - TTPP - 789700 - PIARCO_INTL_AIRPORT - - TD - 10.62 - -61.35 - 15 - 0 - - - - UAAA - 368700 - ALMA-ATA - AL - RA - 43.23 - 76.93 - 847 - 0 - - - - UAFM - 835300 - FRUNZE - - RA - 42.85 - 74.53 - 760 - 0 - - - - UATT - 352290 - AKTJUBINSK - AL - KZ - 50.30 - 57.23 - 227 - 0 - - - - UBBB - 378640 - BAKU/BINE_ARPT - TB - AJ - 40.45 - 50.07 - -1 - 0 - - - - UGEE - 377890 - YEREVAN/ZAPADNY - TB - RS - 40.13 - 44.47 - 907 - 0 - - - - UGGG - 375490 - TBILISI/NOVO-AL - TB - RS - 41.68 - 44.95 - 490 - 0 - - - - UHBB - 315100 - BLAGOVESHCHENSK - HA - RA - 50.27 - 127.50 - 137 - 0 - - - - UHHH - 317350 - KHABAROVSK/NOVY - HA - RA - 48.52 - 135.16 - 72 - 0 - - - - UHNN - 999999 - NIKOLAEVSK-NA-AMURE_CENTER - HA - RA - 53.15 - 140.70 - 68 - 0 - - - - UHWW - 319600 - VLADIVOSTOK - HA - RA - 43.12 - 131.94 - 184 - 0 - - - - UHPP - 325400 - PETROPAVLOVSK-KAMCA - HA - RA - 52.97 - 158.75 - 24 - 0 - - - - UHSS - 321500 - JUZNO-SAHALINSK - HA - RA - 46.92 - 142.73 - 31 - 0 - - - - UIBB - 303090 - BRATSK - - RA - 56.07 - 101.83 - 489 - 0 - - - - UIII - 307100 - IRKUTSK - IR - RA - 52.27 - 104.35 - 513 - 0 - - - - UIKK - 302300 - KIRENSK - IR - RA - 57.77 - 108.07 - 258 - 0 - - - - UKBB - 333470 - BORISPOL'/KIEV - KV - UR - 50.33 - 30.97 - 119 - 0 - - - - UKFF - 339460 - SIMFEROPOL - - UR - 44.68 - 34.13 - 180 - 0 - - - - UKHH - 343000 - KHARKIV - KI - UR - 49.96 - 36.13 - 1550 - 0 - - - - UKLL - 333930 - LVOV - KI - UR - 49.82 - 23.95 - 325 - 0 - - - - UKOO - 338370 - ODESSA/TSENTRALNY - KI - UR - 46.43 - 30.77 - 35 - 0 - - - - ULAA - 225500 - ARHANGELSK - AR - RS - 64.53 - 40.47 - 13 - 0 - - - - ULLI - 260630 - ST.PETERSBURG(VOEJKOVO) - LE - RS - 59.95 - 30.70 - 78 - 0 - - - - ULLL - 260630 - ST.PETERSBURG - LE - RS - 59.95 - 30.70 - 78 - 0 - - - - ULWW - 270370 - VOLOGDA - AR - RS - 59.23 - 39.87 - 131 - 0 - - - - ULMM - 221130 - MURMANSK - AR - RS - 68.97 - 33.05 - 51 - 0 - - - - UMKK - 267020 - KALININGRAD - - BY - 54.70 - 20.62 - 27 - 0 - - - - UMMS - 268500 - MINSK - MI - BY - 53.87 - 27.53 - 234 - 0 - - - - UNBB - 298380 - BARNAUL - NO - RA - 53.40 - 83.70 - 252 - 0 - - - - UNIT - 245070 - TURA - NO - RA - 64.27 - 100.23 - 186 - 0 - - - - UNKB - 292820 - BOGUCHANY - NO - RA - 58.42 - 97.40 - 134 - 0 - - - - UNKL - 284935 - KRASNOYARSK - - RS - 56.18 - 92.52 - -9999 - 0 - - - - UNLL - 999999 - KOLPASHEVO - NO - RA - 58.30 - 82.90 - 76 - 0 - - - - UNNT - 296340 - NOVOSIBIRSK/TOLMACH - - RA - 55.03 - 82.90 - 177 - 0 - - - - UNOO - 286980 - OMSK - NO - RA - 54.93 - 73.40 - 123 - 0 - - - - UODD - 206740 - DIKSON_ISLAND - DK - RA - 73.53 - 80.40 - 47 - 0 - - - - UOHH - 208910 - KHATANGA - DK - RA - 71.98 - 102.47 - 24 - 0 - - - - UOTT - 234720 - TURUKHANSK - - RA - 65.78 - 087.95 - 37 - 0 - - - - URRV - 273290 - ROSTOV - MS - RS - 57.20 - 39.42 - 102 - 0 - - - - URWA - 999999 - ASTRAKHAN - - RS - 46.35 - 47.97 - -22 - 0 - - - - URWW - 345600 - VOLGOGRAD - TB - RS - 48.68 - 44.35 - 145 - 0 - - - - USCC - 286420 - CHELYABINSK/BALANDI - SV - RA - 55.18 - 61.32 - -9999 - 0 - - - - USDD - 999999 - SALEKHARD - NO - RA - 66.53 - 66.53 - 358 - 0 - - - - USDS - 235520 - TARKO-SALE - NO - RA - 64.92 - 77.82 - 27 - 0 - - - - USHB - 236310 - BEREZOVO - NO - RA - 63.93 - 65.05 - 27 - 0 - - - - USHH - 239330 - HANTY-MANSIJSK - NO - RA - 60.97 - 69.07 - 40 - 0 - - - - USKK - 999999 - KIROV - MS - RS - 58.60 - 49.63 - 158 - 0 - - - - USPP - 282250 - PERM - SV - RA - 58.02 - 56.30 - 172 - 0 - - - - USRR - 238490 - SURGUT - NO - RA - 61.25 - 73.50 - 44 - 0 - - - - USSS - 284400 - SVERDLOVSK - SV - RA - 56.80 - 60.63 - 237 - 0 - - - - USUU - 286610 - KURGAN - SV - RA - 55.47 - 65.40 - 79 - 0 - - - - UTAA - 388800 - ASHABAD - TA - RA - 37.97 - 58.33 - 210 - 0 - - - - UTTT - 384570 - TASHKENT/YUZNI - TA - RA - 41.27 - 69.27 - 489 - 0 - - - - UUWW - 275185 - MOSCOW/VNUKOVO - MS - RS - 55.65 - 37.27 - 203 - 0 - - - - UUYP - 234180 - PECHORA - AR - RS - 65.11 - 57.10 - 61 - 0 - - - - UUYW - 232260 - VORKUTA - AR - RA - 67.48 - 64.02 - 180 - 0 - - - - UUYY - 238040 - SYKTYVKAR - AR - RA - 61.72 - 50.83 - 119 - 0 - - - - UWKD - 275950 - KAZAN' - MS - RS - 55.78 - 49.18 - 116 - 0 - - - - UWUU - 287220 - UFA - SV - RA - 54.75 - 56.00 - 105 - 0 - - - - VABB - 430030 - BOMBAY/SANTA_CR - - IN - 19.12 - 72.84 - 14 - 0 - - - - VCBI - 434500 - COLOMBO/KATUNAYAKE - - SB - 7.17 - 79.88 - 8 - 0 - - - - VGZR - 419220 - KURMITOLA/ZIA_INTL - - BW - 23.85 - 90.40 - 10 - 0 - - - - VHHH - 450070 - HONG_KONG_INTL_ARPT - - HK - 22.33 - 114.18 - 24 - 0 - - - - VIDP - 421810 - INDIRA_GANDHI/DELHI - - IN - 28.57 - 77.12 - 233 - 0 - - - - WSSS - 486980 - SINGAPORE/CHANG - - SR - 1.37 - 103.98 - 16 - 0 - - - - YBRF - 945780 - BRISBANE - QU - AU - -27.43 - 153.08 - 2 - 0 - - - - YBTL - 942940 - TOWNSVILLE(CIV/MIL) - QU - AU - -19.25 - 146.75 - 6 - 0 - - - - YMHF - 948640 - MELBOURNE - VC - AU - -37.73 - 144.90 - 81 - 0 - - - - YMMB - 948700 - MOORABBIN_AIRPORT - VC - AU - -37.98 - 145.10 - 13 - 0 - - - - YMMC - 948640 - MELBOURNE - VC - AU - -37.73 - 144.90 - 81 - 0 - - - - YMRF - 948640 - MELBOURNE - VC - AU - -37.73 - 144.90 - 81 - 0 - - - - YPDM - 948640 - MELBOURNE - VC - AU - -37.73 - 144.90 - 81 - 0 - - - - YPRF - 948640 - MELBOURNE - VC - AU - -37.73 - 144.90 - 81 - 0 - - - - YPRM - 948640 - MELBOURNE - VC - AU - -37.73 - 144.90 - 81 - 0 - - - - YSRF - 948640 - MELBOURNE - VC - AU - -37.73 - 144.90 - 81 - 0 - - - - ZPPP - 567780 - KUNMING/WUJIABA - CD - CI - 25.02 - 102.68 - 1892 - 0 - - - + + + + + YSJ + 000395 + ST_JOHN + NB + CN + 45.32 + -65.88 + 0 + 0 + + + + HUL + 000341 + HOULTON + ME + US + 46.04 + -67.83 + 0 + 0 + + + + PQI + 000367 + PRESQUE_ISLE + ME + US + 46.77 + -68.09 + 0 + 0 + + + + MLT + 000183 + MILLINOCKET + ME + US + 45.58 + -68.52 + 0 + 0 + + + + BGR + 000029 + BANGOR + ME + US + 44.84 + -68.87 + 0 + 0 + + + + ACK + 000005 + NANTUCKET + MA + US + 41.28 + -70.03 + 0 + 0 + + + + ENE + 000322 + KENNEBUNK + ME + US + 43.43 + -70.61 + 0 + 0 + + + + BOS + 000289 + BOSTON + MA + US + 42.36 + -70.99 + 0 + 0 + + + + YQB + 000391 + QUEBEC + QB + CN + 46.80 + -71.38 + 0 + 0 + + + + PVD + 000221 + PROVIDENCE + RI + US + 41.72 + -71.43 + 0 + 0 + + + + CON + 000062 + CONCORD + NH + US + 43.22 + -71.58 + 0 + 0 + + + + YSC + 000394 + SHERBROOKE + QB + CN + 45.43 + -71.68 + 0 + 0 + + + + HTO + 000340 + EAST_HAMPTON + NY + US + 40.92 + -72.32 + 0 + 0 + + + + MPV + 000188 + MONTPELIER + VT + US + 44.22 + -72.57 + 0 + 0 + + + + BDL + 000287 + WINSOR_LOCKS + CT + US + 41.94 + -72.69 + 0 + 0 + + + + PLB + 000365 + PLATTSBURGH + NY + US + 44.69 + -73.52 + 0 + 0 + + + + JFK + 000345 + NEW_YORK/JF_KENNEDY + NY + US + 40.63 + -73.77 + 0 + 0 + + + + ALB + 000012 + ALBANY + NY + US + 42.75 + -73.80 + 0 + 0 + + + + CYN + 000300 + COYLE + NJ + US + 39.82 + -74.43 + 0 + 0 + + + + SAX + 000376 + SPARTA + NJ + US + 41.07 + -74.54 + 0 + 0 + + + + MSS + 000353 + MASSENA + NY + US + 44.91 + -74.72 + 0 + 0 + + + + SIE + 000377 + SEA_ISLE + NJ + US + 39.10 + -74.80 + 0 + 0 + + + + HNK + 000338 + HANCOCK + NY + US + 42.06 + -75.32 + 0 + 0 + + + + SBY + 000242 + SALISBURY + MD + US + 38.35 + -75.52 + 0 + 0 + + + + YOW + 000390 + OTTAWA + ON + CN + 45.32 + -75.67 + 0 + 0 + + + + ETX + 000325 + EAST_TEXAS + PA + US + 40.58 + -75.68 + 0 + 0 + + + + ECG + 000086 + ELIZABETH_CITY + NC + US + 36.25 + -76.18 + 0 + 0 + + + + SYR + 000259 + SYRACUSE + NY + US + 43.16 + -76.20 + 0 + 0 + + + + ORF + 000203 + NORFOLK + VA + US + 36.89 + -76.20 + 0 + 0 + + + + EMI + 000320 + WESTMINSTER + MD + US + 39.50 + -76.98 + 0 + 0 + + + + HAR + 000126 + HARRISBURG + PA + US + 40.23 + -77.02 + 0 + 0 + + + + DCA + 000306 + WASHINGTON + DC + US + 38.86 + -77.04 + 0 + 0 + + + + RIC + 000229 + RICHMOND + VA + US + 37.50 + -77.32 + 0 + 0 + + + + CSN + 000299 + CASSANOVA + VA + US + 38.64 + -77.87 + 0 + 0 + + + + ILM + 000135 + WILMINGTON + NC + US + 34.35 + -77.87 + 0 + 0 + + + + SLT + 000252 + SLATE_RUN + PA + US + 41.51 + -77.97 + 0 + 0 + + + + PSB + 000368 + PHILLIPSBURG + PA + US + 40.92 + -77.99 + 0 + 0 + + + + BUF + 000044 + BUFFALO + NY + US + 42.93 + -78.65 + 0 + 0 + + + + RDU + 000372 + RALEIGH-DURHAM + NC + US + 35.87 + -78.78 + 0 + 0 + + + + JST + 000145 + JOHNSTOWN + PA + US + 40.32 + -78.83 + 0 + 0 + + + + JHW + 000346 + JAMESTOWN + NY + US + 42.19 + -79.12 + 0 + 0 + + + + LYH + 000166 + LYNCHBURG + VA + US + 37.25 + -79.23 + 0 + 0 + + + + YYZ + 000401 + TORONTO + ON + CN + 43.67 + -79.63 + 0 + 0 + + + + FLO + 000102 + FLORENCE + SC + US + 34.23 + -79.66 + 0 + 0 + + + + GSO + 000122 + GREENSBORO + NC + US + 36.05 + -79.98 + 0 + 0 + + + + CHS + 000056 + CHARLESTON + SC + US + 32.89 + -80.04 + 0 + 0 + + + + PBI + 000206 + WEST_PALM_BEACH + FL + US + 26.68 + -80.09 + 0 + 0 + + + + EKN + 000088 + ELKINS + WV + US + 38.92 + -80.10 + 0 + 0 + + + + EWC + 000326 + ELLWOOD_CITY + PA + US + 40.83 + -80.21 + 0 + 0 + + + + ERI + 000092 + ERIE + PA + US + 42.02 + -80.30 + 0 + 0 + + + + MIA + 000176 + MIAMI + FL + US + 25.80 + -80.30 + 0 + 0 + + + + TRV + 000276 + TREASURE + FL + US + 27.68 + -80.49 + 0 + 0 + + + + VRB + 000276 + VERO_BEACH + FL + US + 27.68 + -80.49 + 0 + 0 + + + + PSK + 000369 + DUBLIN + VA + US + 37.09 + -80.71 + 0 + 0 + + + + AIR + 000280 + BELLAIRE + OH + US + 40.02 + -80.82 + 0 + 0 + + + + CLT + 000059 + CHARLOTTE + NC + US + 35.22 + -80.93 + 0 + 0 + + + + CAE + 000295 + COLUMBIA + SC + US + 33.86 + -81.05 + 0 + 0 + + + + YVV + 000396 + WIARTON + ON + CN + 44.75 + -81.10 + 0 + 0 + + + + SAV + 000239 + SAVANNAH + GA + US + 32.16 + -81.11 + 0 + 0 + + + + OMN + 000363 + ORMOND_BEACH + FL + US + 29.30 + -81.11 + 0 + 0 + + + + BKW + 000034 + BECKLEY + WV + US + 37.78 + -81.12 + 0 + 0 + + + + ORL + 000204 + ORLANDO + FL + US + 28.54 + -81.34 + 0 + 0 + + + + CRG + 000298 + JACKSONVILLE + FL + US + 30.34 + -81.51 + 0 + 0 + + + + EYW + 000096 + KEY_WEST + FL + US + 24.59 + -81.80 + 0 + 0 + + + + RSW + 000104 + LEE_COUNTY + FL + US + 26.53 + -81.78 + 0 + 0 + + + + FMY + 000104 + FT_MEYERS + FL + US + 26.58 + -81.87 + 0 + 0 + + + + SPA + 000380 + SPARTANBURG + SC + US + 35.03 + -81.93 + 0 + 0 + + + + HNN + 000339 + HENDERSON + WV + US + 38.75 + -82.03 + 0 + 0 + + + + HMV + 000337 + HOLSTON_MOUNTAIN + TN + US + 36.44 + -82.13 + 0 + 0 + + + + CLE + 000058 + CLEVELAND + OH + US + 41.42 + -81.85 + 0 + 0 + + + + IRQ + 000344 + COLLIERS + SC + US + 33.71 + -82.16 + 0 + 0 + + + + AMG + 000015 + ALMA + GA + US + 31.54 + -82.51 + 0 + 0 + + + + SRQ + 000382 + SARASOTA + FL + US + 27.40 + -82.55 + 0 + 0 + + + + APE + 000283 + APPLETON + OH + US + 40.15 + -82.59 + 0 + 0 + + + + PIE + 000212 + SAINT_PETERSBURG + FL + US + 27.91 + -82.68 + 0 + 0 + + + + ECK + 000316 + PECK + MI + US + 43.26 + -82.72 + 0 + 0 + + + + CTY + 000066 + CROSS_CITY + FL + US + 29.60 + -83.05 + 0 + 0 + + + + ODF + 000360 + TOCCOA + GA + US + 34.70 + -83.30 + 0 + 0 + + + + DXO + 000315 + DETROIT + MI + US + 42.21 + -83.37 + 0 + 0 + + + + ASP + 000284 + OSCODA + MI + US + 44.45 + -83.39 + 0 + 0 + + + + MCN + 000170 + MACON + GA + US + 32.69 + -83.65 + 0 + 0 + + + + FNT + 000328 + FLINT + MI + US + 42.97 + -83.74 + 0 + 0 + + + + VXV + 000388 + KNOXVILLE + TN + US + 35.90 + -83.89 + 0 + 0 + + + + ROD + 000373 + ROSEWOOD + OH + US + 40.29 + -84.04 + 0 + 0 + + + + MBS + 000168 + SAGINAW + MI + US + 43.53 + -84.08 + 0 + 0 + + + + LOZ + 000160 + LONDON + KY + US + 37.03 + -84.12 + 0 + 0 + + + + PZD + 000004 + PECAN + GA + US + 31.66 + -84.29 + 0 + 0 + + + + ABY + 000004 + ALBANY + GA + US + 31.65 + -84.30 + 0 + 0 + + + + SSM + 000255 + SAULT_STE_MARIE + MI + US + 46.41 + -84.31 + 0 + 0 + + + + TLH + 000264 + TALLAHASSEE + FL + US + 30.56 + -84.37 + 0 + 0 + + + + ATL + 000019 + ATLANTA + GA + US + 33.63 + -84.44 + 0 + 0 + + + + CVG + 000067 + COVINGTON + KY + US + 39.02 + -84.70 + 0 + 0 + + + + GQO + 000331 + CHATTANOOGA + TN + US + 34.96 + -85.15 + 0 + 0 + + + + FWA + 000109 + FT_WAYNE + IN + US + 40.98 + -85.19 + 0 + 0 + + + + LGC + 000350 + LA_GRANGE + GA + US + 33.05 + -85.21 + 0 + 0 + + + + GRR + 000332 + GRAND_RAPIDS + MI + US + 42.79 + -85.50 + 0 + 0 + + + + TVC + 000270 + TRAVERSE_CITY + MI + US + 44.67 + -85.55 + 0 + 0 + + + + IIU + 000159 + LOUISVILLE + KY + US + 38.10 + -85.58 + 0 + 0 + + + + LOU + 000159 + LOUISVILLE + KY + US + 38.10 + -85.58 + 0 + 0 + + + + MKG + 000179 + MUSKEGON + MI + US + 43.17 + -86.04 + 0 + 0 + + + + PMM + 000366 + PULLMAN + MI + US + 42.47 + -86.11 + 0 + 0 + + + + GIJ + 000330 + NILES + MI + US + 41.77 + -86.32 + 0 + 0 + + + + MGM + 000175 + MONTGOMERY + AL + US + 32.22 + -86.32 + 0 + 0 + + + + IND + 000136 + INDIANAPOLIS + IN + US + 39.81 + -86.37 + 0 + 0 + + + + BWG + 000047 + BOWLING_GREEN + KY + US + 36.93 + -86.44 + 0 + 0 + + + + BNA + 000037 + NASHVILLE + TN + US + 36.14 + -86.68 + 0 + 0 + + + + CEW + 000052 + CRESTVIEW + FL + US + 30.83 + -86.68 + 0 + 0 + + + + VUZ + 000387 + VULCAN + AL + US + 33.67 + -86.90 + 0 + 0 + + + + BVT + 000293 + LAFAYETTE + IN + US + 40.56 + -87.07 + 0 + 0 + + + + TTH + 000384 + TERRE_HAUTE + IN + US + 39.49 + -87.25 + 0 + 0 + + + + MSL + 000191 + MUSCLE_SHOALS + AL + US + 34.70 + -87.48 + 0 + 0 + + + + SAW + 000189 + SAWYER + MI + US + 46.35 + -87.38 + 0 + 0 + + + + PXV + 000370 + POCKET_CITY + IN + US + 37.93 + -87.76 + 0 + 0 + + + + ORD + 000202 + O'HARE_INTERNATIONAL + IL + US + 41.98 + -87.90 + 0 + 0 + + + + GRB + 000119 + GREEN_BAY + WI + US + 44.56 + -88.19 + 0 + 0 + + + + BAE + 000285 + MILWAUKEE + WI + US + 43.12 + -88.28 + 0 + 0 + + + + JOT + 000348 + JOLIET + IL + US + 41.55 + -88.32 + 0 + 0 + + + + SJI + 000378 + SEMMNES + AL + US + 30.73 + -88.36 + 0 + 0 + + + + IGB + 000133 + BIGBEE + MS + US + 33.48 + -88.52 + 0 + 0 + + + + MEI + 000172 + MERIDIAN + MS + US + 32.38 + -88.80 + 0 + 0 + + + + AXC + 000070 + ADDERS + IL + US + 39.74 + -88.86 + 0 + 0 + + + + DEC + 000070 + DECATUR + IL + US + 39.74 + -88.86 + 0 + 0 + + + + YQT + 000393 + THUNDER_BAY + ON + CN + 48.37 + -89.32 + 0 + 0 + + + + DYR + 000083 + DYERSBURG + TN + US + 36.02 + -89.32 + 0 + 0 + + + + RHI + 000228 + RHINELANDER + WI + US + 45.63 + -89.45 + 0 + 0 + + + + BDF + 000024 + BRADFORD + IL + US + 41.16 + -89.59 + 0 + 0 + + + + DLL + 000310 + DELLS + WI + US + 43.55 + -89.76 + 0 + 0 + + + + MEM + 000173 + MEMPHIS + TN + US + 35.06 + -89.98 + 0 + 0 + + + + LEV + 000349 + GRAND_ISLE + LA + US + 29.18 + -90.10 + 0 + 0 + + + + MHZ + 000142 + MAGNOLIA + MS + US + 32.43 + -90.10 + 0 + 0 + + + + JAN + 000142 + JACKSON + MS + US + 32.51 + -90.17 + 0 + 0 + + + + HRV + 000195 + HARVEY + LA + US + 29.85 + -90.00 + 0 + 0 + + + + MSY + 000195 + NEW_ORLEANS + LA + US + 30.00 + -90.27 + 0 + 0 + + + + FAM + 000097 + FARMINGTON + MO + US + 37.67 + -90.23 + 0 + 0 + + + + MCB + 000169 + MC_COMB + MS + US + 31.30 + -90.26 + 0 + 0 + + + + SQS + 000381 + SIDON + MS + US + 33.46 + -90.28 + 0 + 0 + + + + STL + 000257 + ST_LOUIS + MO + US + 38.86 + -90.48 + 0 + 0 + + + + DBQ + 000069 + DUBUQUE + IA + US + 42.40 + -90.71 + 0 + 0 + + + + ARG + 000018 + WALNUT_RIDGE + AR + US + 36.11 + -90.95 + 0 + 0 + + + + UIN + 000386 + QUINCY + IL + US + 39.85 + -91.28 + 0 + 0 + + + + BTR + 000042 + BATON_ROUGE + LA + US + 30.48 + -91.30 + 0 + 0 + + + + ODI + 000361 + NODINE + MN + US + 43.91 + -91.47 + 0 + 0 + + + + EAU + 000085 + EAU_CLAIRE + WI + US + 44.90 + -91.48 + 0 + 0 + + + + IOW + 000343 + IOWA_CITY + IA + US + 41.52 + -91.61 + 0 + 0 + + + + MLU + 000184 + MONROE + LA + US + 32.52 + -92.03 + 0 + 0 + + + + LIT + 000156 + LITTLE_ROCK + AR + US + 34.68 + -92.18 + 0 + 0 + + + + DLH + 000075 + DULUTH + MN + US + 46.80 + -92.20 + 0 + 0 + + + + COU + 000063 + COLUMBIA + MO + US + 38.82 + -92.22 + 0 + 0 + + + + AEX + 000009 + ALEXANDRIA + LA + US + 31.26 + -92.50 + 0 + 0 + + + + IRK + 000139 + KIRKSVILLE + MO + US + 40.14 + -92.59 + 0 + 0 + + + + ELD + 000319 + EL_DORADO + AR + US + 33.26 + -92.74 + 0 + 0 + + + + LCH + 000154 + LAKE_CHARLES + LA + US + 30.14 + -93.11 + 0 + 0 + + + + MSP + 000194 + MINNEAPOLIS + MN + US + 44.88 + -93.23 + 0 + 0 + + + + MCW + 000171 + MASON_CITY + IA + US + 43.09 + -93.33 + 0 + 0 + + + + SGF + 000245 + SPRINGFIELD + MO + US + 37.36 + -93.33 + 0 + 0 + + + + INL + 000137 + INTERNATIONAL_FALLS + MN + US + 48.57 + -93.40 + 0 + 0 + + + + DSM + 000079 + DES_MOINES + IA + US + 41.44 + -93.65 + 0 + 0 + + + + EIC + 000318 + SHREVEPORT + LA + US + 32.77 + -93.81 + 0 + 0 + + + + BRD + 000292 + BRAINERD + MN + US + 46.35 + -94.03 + 0 + 0 + + + + TXK + 000272 + TEXARKANA + AR + US + 33.51 + -94.07 + 0 + 0 + + + + RZC + 000374 + RAZORBACK + AR + US + 36.25 + -94.12 + 0 + 0 + + + + FSM + 000108 + FT_SMITH + AR + US + 35.38 + -94.27 + 0 + 0 + + + + FOD + 000105 + FT_DODGE + IA + US + 42.61 + -94.29 + 0 + 0 + + + + BUM + 000045 + BUTLER + MO + US + 38.27 + -94.49 + 0 + 0 + + + + MCI + 000177 + KANSAS_CITY + MO + US + 39.29 + -94.74 + 0 + 0 + + + + MKC + 000177 + KANSAS_CITY + MO + US + 39.28 + -94.59 + 0 + 0 + + + + LFK + 000155 + LUFKIN + TX + US + 31.16 + -94.72 + 0 + 0 + + + + GGG + 000115 + LONGVIEW + TX + US + 32.42 + -94.75 + 0 + 0 + + + + BJI + 000033 + BEMIDJI + MN + US + 47.58 + -95.02 + 0 + 0 + + + + RWF + 000234 + REDWWOD_FALLS + MN + US + 44.47 + -95.13 + 0 + 0 + + + + OSW + 000205 + OSWEGO + KS + US + 37.15 + -95.20 + 0 + 0 + + + + IAH + 000131 + HOUSTON_INTERNATIONAL + TX + US + 29.96 + -95.35 + 0 + 0 + + + + OVR + 000364 + OMAHA + NE + US + 41.17 + -95.74 + 0 + 0 + + + + MLC + 000180 + MC_CALESTER + OK + US + 34.85 + -95.78 + 0 + 0 + + + + TUL + 000268 + TULSA + OK + US + 36.20 + -95.79 + 0 + 0 + + + + PWE + 000222 + PAWNEE_CITY + NE + US + 40.20 + -96.21 + 0 + 0 + + + + PSX + 000219 + PALACIOS + TX + US + 28.76 + -96.31 + 0 + 0 + + + + FSD + 000107 + SIOUX_FALLS + SD + US + 43.65 + -96.78 + 0 + 0 + + + + FAR + 000098 + FARGO + ND + US + 46.75 + -96.85 + 0 + 0 + + + + TTT + 000072 + MAVERICK + TX + US + 32.87 + -97.04 + 0 + 0 + + + + DFW + 000072 + DALLAS-FT_WORTH + TX + US + 32.87 + -97.03 + 0 + 0 + + + + ADM + 000008 + ARDMORE + OK + US + 34.21 + -97.17 + 0 + 0 + + + + GFK + 000114 + GRAND_FORKS + ND + US + 47.95 + -97.19 + 0 + 0 + + + + YWG + 000397 + WINNIPEG + MB + CN + 49.90 + -97.23 + 0 + 0 + + + + ACT + 000006 + WACO + TX + US + 31.66 + -97.27 + 0 + 0 + + + + BRO + 000041 + BROWNSVILLE + TX + US + 25.92 + -97.38 + 0 + 0 + + + + CRP + 000065 + CORPUS_CHRISTI + TX + US + 27.90 + -97.45 + 0 + 0 + + + + ICT + 000132 + WICHITA + KS + US + 37.75 + -97.58 + 0 + 0 + + + + OKC + 000198 + OKLAHOMA_CITY + OK + US + 35.36 + -97.61 + 0 + 0 + + + + SLN + 000251 + SALINA + KS + US + 38.93 + -97.62 + 0 + 0 + + + + CWK + 000020 + CENTEX + TX + US + 30.38 + -97.53 + 0 + 0 + + + + AUS + 000020 + AUSTIN + TX + US + 30.30 + -97.70 + 0 + 0 + + + + END + 000321 + VANCE_AFB + OK + US + 36.35 + -97.92 + 0 + 0 + + + + OBH + 000358 + WOLBACH + NE + US + 41.38 + -98.35 + 0 + 0 + + + + ABR + 000003 + ABERDEEN + SD + US + 45.42 + -98.37 + 0 + 0 + + + + SAT + 000238 + SAN_ANTONIO + TX + US + 29.64 + -98.46 + 0 + 0 + + + + SPS + 000254 + WICHITA_FALLS + TX + US + 33.99 + -98.59 + 0 + 0 + + + + ONL + 000200 + ONEILL + NE + US + 42.47 + -98.69 + 0 + 0 + + + + LRD + 000161 + LAREDO + TX + US + 27.48 + -99.42 + 0 + 0 + + + + JCT + 000144 + JUNCTION + TX + US + 30.60 + -99.82 + 0 + 0 + + + + ABI + 000001 + ABILENE + TX + US + 32.48 + -99.86 + 0 + 0 + + + + MMB + 000110 + MITBEE + OK + US + 36.34 + -99.88 + 0 + 0 + + + + GAG + 000110 + GAGE + OK + US + 36.34 + -99.88 + 0 + 0 + + + + ANW + 000282 + AINSWORTH + NE + US + 42.57 + -99.99 + 0 + 0 + + + + PIR + 000214 + PIERRE + SD + US + 44.40 + -100.17 + 0 + 0 + + + + HLC + 000335 + HILL_CITY + KS + US + 39.26 + -100.23 + 0 + 0 + + + + CDS + 000051 + CHILDRESS + TX + US + 34.37 + -100.28 + 0 + 0 + + + + SJT + 000248 + SAN_ANGELO + TX + US + 31.38 + -100.46 + 0 + 0 + + + + MCK + 000351 + MC_COOK + NE + US + 40.20 + -100.59 + 0 + 0 + + + + BIS + 000032 + BISMARK + ND + US + 46.77 + -100.67 + 0 + 0 + + + + LBF + 000152 + NORTH_PLATTE + NE + US + 41.13 + -100.72 + 0 + 0 + + + + GCK + 000112 + GARDEN_CITY + KS + US + 37.92 + -100.73 + 0 + 0 + + + + DLF + 000309 + LAUGHLIN_AFB + TX + US + 29.36 + -100.77 + 0 + 0 + + + + LBL + 000153 + LIBERAL + KS + US + 37.04 + -100.97 + 0 + 0 + + + + MOT + 000187 + MINOT + ND + US + 48.26 + -101.29 + 0 + 0 + + + + AMA + 000014 + AMARILLO + TX + US + 35.29 + -101.64 + 0 + 0 + + + + GLD + 000118 + GOODLAND + KS + US + 39.39 + -101.69 + 0 + 0 + + + + DPR + 000077 + DUPREE + SD + US + 45.08 + -101.72 + 0 + 0 + + + + LBB + 000151 + LUBBOCK_INTERNATIONAL + TX + US + 33.70 + -101.92 + 0 + 0 + + + + MAF + 000167 + MIDLAND + TX + US + 32.02 + -102.18 + 0 + 0 + + + + LAA + 000146 + LAMAR + CO + US + 38.20 + -102.69 + 0 + 0 + + + + DIK + 000074 + DICKINSIN + ND + US + 46.86 + -102.77 + 0 + 0 + + + + TXO + 000385 + TEXICO_NM/BOVINA + TX + US + 34.50 + -102.84 + 0 + 0 + + + + SNY + 000379 + SIDNEY + NE + US + 41.10 + -102.98 + 0 + 0 + + + + FST + 000329 + FT_STOCKTON + TX + US + 30.95 + -102.98 + 0 + 0 + + + + RAP + 000224 + RAPID_CITY + SD + US + 43.98 + -103.01 + 0 + 0 + + + + AKO + 000011 + AKRON + CO + US + 40.16 + -103.18 + 0 + 0 + + + + INK + 000342 + WINK + TX + US + 31.87 + -103.24 + 0 + 0 + + + + BFF + 000026 + SCOTTSBLUFF + NE + US + 41.89 + -103.48 + 0 + 0 + + + + TBE + 000261 + TOBE + CO + US + 37.27 + -103.60 + 0 + 0 + + + + TCC + 000262 + TUCUMCARI + NM + US + 35.18 + -103.60 + 0 + 0 + + + + ISN + 000140 + WILLISTON + ND + US + 48.18 + -103.63 + 0 + 0 + + + + MRF + 000190 + MARFA + TX + US + 30.30 + -103.95 + 0 + 0 + + + + PUB + 000220 + PUEBLO + CO + US + 38.29 + -104.43 + 0 + 0 + + + + CME + 000233 + CHISUM + NM + US + 33.34 + -104.62 + 0 + 0 + + + + ROW + 000233 + ROSWELL + NM + US + 33.34 + -104.62 + 0 + 0 + + + + DEN + 000071 + DENVER + CO + US + 39.81 + -104.66 + 0 + 0 + + + + CYS + 000301 + CHEYENNE + WY + US + 41.21 + -104.77 + 0 + 0 + + + + CIM + 000297 + CIMARRON + NM + US + 36.49 + -104.87 + 0 + 0 + + + + FTI + 000163 + FT_UNION + NM + US + 35.66 + -105.14 + 0 + 0 + + + + LVS + 000163 + LAS_VEGAS + NM + US + 35.66 + -105.14 + 0 + 0 + + + + LAR + 000148 + LARAMIE + WY + US + 41.33 + -105.72 + 0 + 0 + + + + ALS + 000013 + ALAMOSA + CO + US + 37.35 + -105.82 + 0 + 0 + + + + MLS + 000182 + MILES_CITY + MT + US + 46.38 + -105.95 + 0 + 0 + + + + DDY + 000307 + CASPER + WY + US + 43.09 + -106.28 + 0 + 0 + + + + ELP + 000090 + EL_PASO + TX + US + 31.82 + -106.28 + 0 + 0 + + + + CZI + 000302 + CRAZY_WOMAN + WY + US + 44.00 + -106.44 + 0 + 0 + + + + GGW + 000116 + GLASGOW + MT + US + 48.22 + -106.63 + 0 + 0 + + + + ABQ + 000002 + ALBUQUERQUE + NM + US + 35.04 + -106.82 + 0 + 0 + + + + DBL + 000304 + EAGLE + CO + US + 39.44 + -106.90 + 0 + 0 + + + + HBU + 000333 + GUNNISON + CO + US + 38.45 + -107.04 + 0 + 0 + + + + SHR + 000246 + SHERIDAN + WY + US + 44.84 + -107.06 + 0 + 0 + + + + TCS + 000263 + TRUTH_OR_CONSEQUENCES + NM + US + 33.28 + -107.28 + 0 + 0 + + + + CHE + 000054 + HAYDEN + CO + US + 40.52 + -107.31 + 0 + 0 + + + + DMN + 000076 + DEMING + NM + US + 32.28 + -107.60 + 0 + 0 + + + + YYN + 000400 + SWIFT_CURRENT + SA + CN + 50.28 + -107.68 + 0 + 0 + + + + RSK + 000103 + RATTLESNAKE + NM + US + 36.75 + -108.10 + 0 + 0 + + + + FMN + 000103 + FARMINGTON + NM + US + 36.75 + -108.10 + 0 + 0 + + + + BOY + 000290 + BOYSEN_RESV. + WY + US + 43.46 + -108.30 + 0 + 0 + + + + BIL + 000031 + BILLINGS + MT + US + 45.81 + -108.63 + 0 + 0 + + + + JNC + 000347 + GRAND_JUNCTION + CO + US + 39.06 + -108.79 + 0 + 0 + + + + DVC + 000082 + DOVE_CREEK + CO + US + 37.81 + -108.93 + 0 + 0 + + + + OCS + 000359 + ROCKSPRINGS + WY + US + 41.59 + -109.02 + 0 + 0 + + + + SJN + 000247 + ST_JOHNS + AZ + US + 34.42 + -109.14 + 0 + 0 + + + + SSO + 000256 + SAN_SIMON + AZ + US + 32.27 + -109.26 + 0 + 0 + + + + LWT + 000165 + LEWISTOWN + MT + US + 47.05 + -109.61 + 0 + 0 + + + + HVR + 000129 + HAVRE + MT + US + 48.54 + -109.77 + 0 + 0 + + + + BPI + 000291 + BIG_PINEY + WY + US + 42.58 + -110.11 + 0 + 0 + + + + MTU + 000196 + MYTON + UT + US + 40.15 + -110.13 + 0 + 0 + + + + HVE + 000128 + HANKSVILLE + UT + US + 38.42 + -110.70 + 0 + 0 + + + + YXH + 000399 + MEDICINE_HAT + AB + CN + 50.02 + -110.72 + 0 + 0 + + + + JAC + 000141 + JACKSON + WY + US + 43.62 + -110.73 + 0 + 0 + + + + INW + 000138 + WINSLOW + AZ + US + 35.06 + -110.80 + 0 + 0 + + + + TUS + 000269 + TUCSON + AZ + US + 32.10 + -110.92 + 0 + 0 + + + + TBC + 000260 + TUBA_CITY + AZ + US + 36.12 + -111.27 + 0 + 0 + + + + GTF + 000123 + GREAT_FALLS + MT + US + 47.45 + -111.41 + 0 + 0 + + + + HLN + 000336 + HELENA + MT + US + 46.61 + -111.95 + 0 + 0 + + + + PHX + 000211 + PHOENIX + AZ + US + 33.43 + -112.02 + 0 + 0 + + + + SLC + 000249 + SALT_LAKE_CITY + UT + US + 40.85 + -111.98 + 0 + 0 + + + + DBS + 000305 + DUBOIS + ID + US + 44.09 + -112.21 + 0 + 0 + + + + BCE + 000023 + BRYCE_CANYON + UT + US + 37.69 + -112.30 + 0 + 0 + + + + MLD + 000352 + MALAD_CITY + ID + US + 42.20 + -112.45 + 0 + 0 + + + + DRK + 000313 + PRESCOTT + AZ + US + 34.70 + -112.48 + 0 + 0 + + + + DTA + 000080 + DELTA + UT + US + 39.30 + -112.51 + 0 + 0 + + + + DLN + 000311 + DILLON + MT + US + 45.25 + -112.55 + 0 + 0 + + + + PIH + 000213 + POCATELLO + ID + US + 42.87 + -112.65 + 0 + 0 + + + + YQL + 000392 + LETHBRIDGE + AB + CN + 49.63 + -112.80 + 0 + 0 + + + + PGS + 000210 + PEACH_SPRINGS + AZ + US + 35.62 + -113.54 + 0 + 0 + + + + BVL + 000046 + BOONEVILLE + UT + US + 40.73 + -113.76 + 0 + 0 + + + + LKT + 000157 + SALMON + ID + US + 45.02 + -114.08 + 0 + 0 + + + + FCA + 000100 + KALISPELL + MT + US + 48.21 + -114.18 + 0 + 0 + + + + ILC + 000134 + WILSON_CREEK + NV + US + 38.25 + -114.39 + 0 + 0 + + + + EED + 000087 + NEEDLES + CA + US + 34.77 + -114.47 + 0 + 0 + + + + TWF + 000271 + TWIN_FALLS + ID + US + 42.48 + -114.49 + 0 + 0 + + + + BZA + 000294 + YUMA + AZ + US + 32.77 + -114.60 + 0 + 0 + + + + ELY + 000091 + ELY + NV + US + 39.30 + -114.85 + 0 + 0 + + + + LAS + 000149 + LAS_VEGAS + NV + US + 36.08 + -115.16 + 0 + 0 + + + + MLP + 000181 + MULLAN_PASS + ID + US + 47.46 + -115.65 + 0 + 0 + + + + YXC + 000398 + CRANBROOK + BC + CN + 49.60 + -115.78 + 0 + 0 + + + + TRM + 000383 + THERMAL + CA + US + 33.63 + -116.16 + 0 + 0 + + + + BOI + 000039 + BOISE + ID + US + 43.55 + -116.19 + 0 + 0 + + + + DNJ + 000312 + MC_CALL + ID + US + 44.77 + -116.21 + 0 + 0 + + + + HEC + 000334 + HECTOR + CA + US + 34.80 + -116.46 + 0 + 0 + + + + BTY + 000043 + BEATTY + NV + US + 36.80 + -116.75 + 0 + 0 + + + + BAM + 000286 + BATTLE_MOUNTAIN + NV + US + 40.57 + -116.92 + 0 + 0 + + + + MZB + 000354 + MISSION_BAY + CA + US + 32.78 + -117.23 + 0 + 0 + + + + GEG + 000113 + SPOKANE + WA + US + 47.56 + -117.63 + 0 + 0 + + + + OAL + 000357 + COALDALE + NV + US + 38.00 + -117.77 + 0 + 0 + + + + BKE + 000288 + BAKER + OR + US + 44.84 + -117.81 + 0 + 0 + + + + REO + 000227 + ROME + OR + US + 42.59 + -117.87 + 0 + 0 + + + + LAX + 000150 + LOS_ANGELES_INTL + CA + US + 33.93 + -118.43 + 0 + 0 + + + + PDT + 000207 + PENDLETON + OR + US + 45.70 + -118.94 + 0 + 0 + + + + EHF + 000317 + BAKERSFIELD + CA + US + 35.48 + -119.10 + 0 + 0 + + + + EPH + 000324 + EPHRATA + WA + US + 47.38 + -119.42 + 0 + 0 + + + + FMG + 000327 + RENO + NV + US + 39.53 + -119.66 + 0 + 0 + + + + RZS + 000375 + SANTA_BARBARA + CA + US + 34.51 + -119.77 + 0 + 0 + + + + CZQ + 000303 + FRESNO + CA + US + 36.88 + -119.82 + 0 + 0 + + + + YKM + 000279 + YAKIMA + WA + US + 46.57 + -120.45 + 0 + 0 + + + + LKV + 000158 + LAKEVIEW + OR + US + 42.49 + -120.51 + 0 + 0 + + + + YDC + 000389 + PRINCETON + BC + CN + 49.47 + -120.52 + 0 + 0 + + + + MOD + 000186 + MODESTO + CA + US + 37.63 + -120.96 + 0 + 0 + + + + DSD + 000314 + REDMOND + WA + US + 44.25 + -121.30 + 0 + 0 + + + + SAC + 000236 + SACRAMENTO + CA + US + 38.44 + -121.55 + 0 + 0 + + + + SNS + 000253 + SALINAS + CA + US + 36.66 + -121.60 + 0 + 0 + + + + OAK + 000356 + OAKLAND + CA + US + 37.73 + -122.22 + 0 + 0 + + + + RBL + 000225 + RED_BLUFF + CA + US + 40.10 + -122.24 + 0 + 0 + + + + SEA + 000243 + SEATTLE + WA + US + 47.44 + -122.31 + 0 + 0 + + + + HUH + 000035 + WHATCOM + WA + US + 48.95 + -122.58 + 0 + 0 + + + + BLI + 000035 + BELLINGHAM + WA + US + 48.95 + -122.58 + 0 + 0 + + + + PDX + 000208 + PORTLAND + OR + US + 45.58 + -122.60 + 0 + 0 + + + + PYE + 000371 + POINT_REYES + CA + US + 38.08 + -122.87 + 0 + 0 + + + + OED + 000362 + MEDFORD + OR + US + 42.48 + -122.91 + 0 + 0 + + + + EUG + 000093 + EUGENE + OR + US + 44.12 + -123.22 + 0 + 0 + + + + ENI + 000323 + UKIAH + CA + US + 39.05 + -123.27 + 0 + 0 + + + + ONP + 000201 + NEWPORT + OR + US + 44.58 + -124.06 + 0 + 0 + + + + HQM + 000127 + HOQUIAM + WA + US + 46.95 + -124.15 + 0 + 0 + + + + FOT + 000106 + FORTUNA + CA + US + 40.67 + -124.23 + 0 + 0 + + + + TOU + 000265 + NEAH_BAY + WA + US + 48.30 + -124.63 + 0 + 0 + + + + YQV + 000402 + YORKTON + SA + CN + 51.27 + -102.47 + 0 + 0 + + + + ANN + 0 + ANNETTE_ISLAND + AK + US + 55.05 + -131.57 + 0 + 0 + + + + LVD + 0 + LEVEL_ISLAND + AK + US + 56.47 + -133.08 + 0 + 0 + + + + BKA + 0 + BIORKA_ISLAND + AK + US + 56.86 + -135.55 + 0 + 0 + + + + SSR + 0 + SISTERS_ISLAND + AK + US + 58.17 + -135.25 + 0 + 0 + + + + JNU + 0 + JUNEAU + AK + US + 58.35 + -134.58 + 0 + 0 + + + + YAK + 0 + YAKUTAT + AK + US + 59.50 + -139.67 + 0 + 0 + + + + MDO + 0 + MIDDLETON_ISLAND + AK + US + 59.45 + -146.30 + 0 + 0 + + + + JOH + 0 + JOHNSTONE_POINT + AK + US + 60.48 + -146.60 + 0 + 0 + + + + ODK + 0 + KODIAK + AK + US + 57.75 + -152.50 + 0 + 0 + + + + HOM + 0 + HOMER + AK + US + 59.65 + -151.48 + 0 + 0 + + + + ENA + 0 + KENAI + AK + US + 60.57 + -151.25 + 0 + 0 + + + + ANC + 0 + ANCHORAGE + AK + US + 61.17 + -150.00 + 0 + 0 + + + + BGQ + 0 + BIG_LAKE + AK + US + 61.53 + -149.82 + 0 + 0 + + + + ORT + 0 + NORTHWAY + AK + US + 62.97 + -141.93 + 0 + 0 + + + + GKN + 0 + GULKANA + AK + US + 62.15 + -145.45 + 0 + 0 + + + + TKA + 0 + TALKEETNA + AK + US + 62.32 + -150.10 + 0 + 0 + + + + SQA + 0 + SPARREVOHN + AK + US + 61.10 + -155.63 + 0 + 0 + + + + DLG + 0 + DILLINGHAM + AK + US + 59.05 + -158.50 + 0 + 0 + + + + AKN + 0 + KING_SALMON + AK + US + 58.68 + -156.65 + 0 + 0 + + + + PDN + 0 + PORT_HEIDEN + AK + US + 56.95 + -158.65 + 0 + 0 + + + + CDB + 0 + COLD_BAY + AK + US + 55.20 + -162.73 + 0 + 0 + + + + DUT + 0 + DUTCH_HARBOR + AK + US + 53.90 + -166.55 + 0 + 0 + + + + NUD + 0 + ADAK + AK + US + 51.88 + -176.65 + 0 + 0 + + + + SYA + 0 + SHEMYA + AK + US + 52.72 + 174.12 + 0 + 0 + + + + SPY + 0 + ST_PAUL_ISLAND + AK + US + 57.17 + -170.22 + 0 + 0 + + + + EHM + 0 + CAPE_NEWENHAM + AK + US + 58.66 + -162.07 + 0 + 0 + + + + HPB + 0 + HOOPER_BAY + AK + US + 61.52 + -166.14 + 0 + 0 + + + + BET + 0 + BETHEL + AK + US + 60.78 + -161.83 + 0 + 0 + + + + ANI + 0 + ANIAK + AK + US + 61.59 + -159.61 + 0 + 0 + + + + SMA + 0 + ST_MARYS + AK + US + 62.06 + -163.30 + 0 + 0 + + + + UNK + 0 + UNALAKLEET + AK + US + 63.88 + -160.80 + 0 + 0 + + + + ULL + 0 + KUKULIAK + AK + US + 63.70 + -170.48 + 0 + 0 + + + + MCG + 0 + MC_GRATH + AK + US + 62.95 + -155.60 + 0 + 0 + + + + ENN + 0 + NENANA + AK + US + 64.55 + -149.07 + 0 + 0 + + + + FAI + 0 + FAIRBANKS + AK + US + 64.82 + -147.85 + 0 + 0 + + + + BIG + 0 + BIG_DELTA + AK + US + 64.00 + -145.72 + 0 + 0 + + + + FYU + 0 + FORT_YUKON + AK + US + 66.57 + -145.25 + 0 + 0 + + + + BTT + 0 + BETTLES + AK + US + 66.92 + -151.53 + 0 + 0 + + + + TAL + 0 + TANANA + AK + US + 65.18 + -152.18 + 0 + 0 + + + + CQR + 0 + CHANDALAR_LAKE + AK + US + 67.50 + -148.47 + 0 + 0 + + + + SCC + 0 + DEADHORSE + AK + US + 70.20 + -148.47 + 0 + 0 + + + + BTI + 0 + BARTER_ISLAND + AK + US + 70.13 + -143.57 + 0 + 0 + + + + BRW + 0 + BARROW + AK + US + 71.28 + -156.77 + 0 + 0 + + + + GAL + 0 + GALENA + AK + US + 64.73 + -156.93 + 0 + 0 + + + + OME + 0 + NOME + AK + US + 64.52 + -165.45 + 0 + 0 + + + + OTZ + 0 + KOTZEBUE + AK + US + 66.88 + -162.60 + 0 + 0 + + + + WLK + 0 + SELAWIK + AK + US + 66.60 + -160.00 + 0 + 0 + + + + HSL + 0 + HUSLIA + AK + US + 65.71 + -156.37 + 0 + 0 + + + + BSF + 0 + BRADSHAW + HI + US + 19.76 + -155.39 + 0 + 0 + + + + UPP + 0 + UPOLU_POINT + HI + US + 20.20 + -155.84 + 0 + 0 + + + + ITO + 0 + HILO + HI + US + 19.72 + -155.01 + 0 + 0 + + + + HNL + 0 + HONOLULU + HI + US + 21.33 + -157.93 + 0 + 0 + + + + OGG + 0 + MAUI + HI + US + 20.91 + -156.42 + 0 + 0 + + + + NDB + 0 + VALLEY_ISLAND + HI + US + 20.88 + -156.44 + 0 + 0 + + + + MUE + 0 + KAMUELA + HI + US + 20.00 + -155.67 + 0 + 0 + + + + NGF + 0 + KANEOHE_BAY + HI + US + 21.45 + -157.76 + 0 + 0 + + + + MKK + 0 + MOLOKAI + HI + US + 21.14 + -157.17 + 0 + 0 + + + + NBS + 0 + BARKING_SANDS + HI + US + 22.04 + -159.79 + 0 + 0 + + + + CKH + 0 + KOKO_HEAD + HI + US + 21.27 + -157.70 + 0 + 0 + + + + IAI + 0 + KONA + HI + US + 19.65 + -156.02 + 0 + 0 + + + + LLD + 0 + LANAI + HI + US + 20.77 + -156.97 + 0 + 0 + + + + LNY + 0 + LANAI_CITY + HI + US + 20.76 + -156.97 + 0 + 0 + + + + LIH + 0 + LIHUE + HI + US + 21.97 + -159.34 + 0 + 0 + + + + SOK + 0 + SOUTH_KAUAI + HI + US + 21.90 + -159.53 + 0 + 0 + + + + ASRF + 948640 + MELBOURNE + VC + AU + -37.73 + 144.90 + 81 + 0 + + + + AYPY + 940350 + PORT_MORESBY_INTL + + NG + -9.43 + 147.22 + 47 + 0 + + + + BGSF + 042310 + SONDRE_STROMFJORD + + GL + 67.00 + -50.80 + 53 + 0 + + + + BIRK + 040300 + REYKJAVIK + + IL + 64.13 + -21.90 + 61 + 0 + + + + CWEG + 999999 + ALBERTA_WEATHER_CENTRE + + CN + 53.50 + -113.50 + -9999 + 0 + + + + CWLW + 712030 + KELOWNA + BC + CN + 49.95 + -119.40 + 456 + 0 + + + + CWNT + 712500 + TURTLE_MOUNTAIN + AB + CN + 49.58 + -114.42 + 2164 + 0 + + + + CWTO + 716380 + TORONTO_A_E_S__HQ + ON + CN + 43.78 + -79.47 + 187 + 0 + + + + CWUL + 999999 + QUEBEC_FCST_OFFICE + + CN + 45.50 + -73.68 + -9999 + 0 + + + + CYQX + 718030 + GANDER_INTL_AIRPORT + NF + CN + 48.95 + -54.57 + 151 + 0 + + + + DTTA + 607150 + TUNIS/CARTHAGE + + TS + 36.83 + 10.23 + 4 + 0 + + + + EBBR + 064510 + BRUSSELS_NATIONAL + + BX + 50.90 + 4.53 + 58 + 0 + + + + EDMM + 108680 + MUENCHEN + + DL + 48.25 + 11.58 + 484 + 0 + + + + EDZB + 102380 + BERGEN/HOHNE + + DL + 52.82 + 9.93 + 70 + 0 + + + + EDZE + 104100 + ESSEN/MULHEIM + + DL + 51.40 + 6.97 + 161 + 0 + + + + EDZF + 106370 + FRANKFURT/MAIN + + DL + 50.05 + 8.58 + 112 + 0 + + + + EDZH + 107710 + GAERMERSDORF + + DL + 49.43 + 11.90 + 419 + 0 + + + + EDZM + 108680 + MUENCHEN + + DL + 48.25 + 11.58 + 484 + 0 + + + + EETN + 260380 + TALLIN + + BY + 59.35 + 24.80 + 44 + 0 + + + + EFHK + 029740 + HELSINKI/VANTAA + + FI + 60.32 + 24.97 + 56 + 0 + + + + EFRO + 028450 + ROVANIEMI(CIV/MIL) + + FI + 66.57 + 25.83 + 201 + 0 + + + + EGJJ + 038950 + JERSEY_AIRPORT + + UK + 49.22 + -2.20 + 84 + 0 + + + + EHAM + 062400 + AMSTERDAM/SCHIPHOL + + NL + 52.30 + 4.77 + -2 + 0 + + + + EHDB + 062600 + DE_BILT + + NL + 52.10 + 5.18 + 4 + 0 + + + + EINN + 039620 + SHANNON_AIRPORT + + IE + 52.70 + -8.92 + 20 + 0 + + + + EKCH + 061800 + COPENHAGEN/KASTRUP + + DN + 55.63 + 12.67 + 5 + 0 + + + + ENMI + 999999 + OSLO + + NO + 59.50 + 10.70 + -9999 + 0 + + + + ENVN + 011520 + BODO + + NO + 67.25 + 14.40 + 8 + 0 + + + + ENVV + 014150 + STAVANGER + + NO + 58.87 + 5.67 + 34 + 0 + + + + EPWA + 123750 + WARSAW/OKECIE + + PL + 52.17 + 20.97 + 107 + 0 + + + + ESNN + 023660 + SUNDSVALL/HARNOSAND + + SN + 62.53 + 17.45 + 10 + 0 + + + + ESSA + 024600 + STOCKHOLM/ARLANDA + + SN + 59.65 + 17.95 + 61 + 0 + + + + EVRA + 999999 + RIGA_AIRPORT + LE + BY + 56.92 + 23.97 + 10 + 0 + + + + EYVI + 267300 + VILNIUS_INTL + MI + BY + 54.63 + 25.28 + 156 + 0 + + + + FAJS + 683680 + JAN_SMUTS + + ZA + -26.13 + 28.23 + 1700 + 0 + + + + FCBB + 644500 + BRAZZAVILLE/MAYA-MA + + CG + -4.25 + 15.25 + 316 + 0 + + + + FTTJ + 647000 + NDJAMENA(CIV/MIL) + + CD + 12.13 + 15.03 + 295 + 0 + + + + GCGC + 999999 + CANARY_ISLANDS + + CR + 28.50 + -16.00 + -9999 + 0 + + + + GMMC + 601550 + CASABLANCA + + MC + 33.57 + -7.67 + 62 + 0 + + + + HECA + 623660 + CAIRO_INTL_AIRPORT + + EG + 30.13 + 31.40 + 74 + 0 + + + + LBSF + 156140 + SOFIA + + BU + 42.65 + 23.38 + 595 + 0 + + + + LBWN + 155520 + VARNA + + BU + 43.20 + 27.92 + 43 + 0 + + + + LCLK + 176090 + LARNACA/LARNAX_ARPT + + CY + 34.88 + 33.63 + 2 + 0 + + + + LDZA + 131310 + ZAGREB/PLESO + + RH + 45.73 + 16.07 + 107 + 0 + + + + LDZO + 999999 + ZAGREB/PLESO + + RH + 45.73 + 16.07 + 107 + 0 + + + + LECB + 081810 + BARCELONA + + SP + 41.28 + 2.07 + 6 + 0 + + + + LEMM + 999999 + MADRID_CNM + + SP + 40.12 + -3.53 + -9999 + 0 + + + + LFBD + 075100 + BORDEAUX/MERIGNAC + + FR + 44.83 + -.70 + 61 + 0 + + + + LFMM + 076500 + MARSEILLE + + FR + 43.45 + 5.22 + 20 + 0 + + + + LFPW + 999999 + PARIS_MET_CENTER + + FR + 48.83 + 2.33 + 75 + 0 + + + + LFRN + 071300 + RENNES/ST.JACQUES + + FR + 48.07 + -1.73 + 37 + 0 + + + + LFST + 071900 + STRASBOURG/ENTZHEIM + + FR + 48.55 + 7.63 + 154 + 0 + + + + LGAT + 167160 + ATHENS/HELLENKION + + GR + 37.90 + 23.73 + 15 + 0 + + + + LHBP + 128390 + BUDAPEST/FERIHEGY + + HU + 47.43 + 19.27 + 185 + 0 + + + + LIMM + 160800 + MILANO/LINATE + + IY + 45.43 + 9.27 + 103 + 0 + + + + LJLJ + 130140 + LJUBLJANA/BRNIK + + LJ + 46.22 + 14.48 + 385 + 0 + + + + LKPR + 115180 + PRAGUE/RUZYNE + + CZ + 50.10 + 14.28 + 365 + 0 + + + + LLBG + 401800 + BEN-GURION(CIV/MIL) + + IS + 32.00 + 34.90 + 49 + 0 + + + + LMML + 165970 + LUQA/MALTA + + ML + 35.85 + 14.48 + 91 + 0 + + + + LOWW + 110360 + VIENNA/SCHWECHAT + + OS + 48.12 + 16.57 + 190 + 0 + + + + LPPT + 085360 + LISBON/PORTELA + + PO + 38.78 + -9.13 + 123 + 0 + + + + LROM + 154210 + BUCHAREST/OTOPENI + + RO + 44.55 + 26.10 + 95 + 0 + + + + LROP + 154210 + BUCHAREST/OTOPENI + + RO + 44.55 + 26.10 + 95 + 0 + + + + LSZH + 066700 + ZURICH-KLOTEN_(AUT) + + SW + 47.48 + 8.53 + 432 + 0 + + + + LTAC + 171280 + ANKARA/ESENBOGA + + TU + 40.11 + 32.97 + 949 + 0 + + + + LTBA + 170600 + ISTANBUL/ATATURK_AB + + TU + 40.97 + 28.82 + 37 + 0 + + + + LUKK + 338387 + KISHINAU + + UR + 46.93 + 28.93 + 122 + 0 + + + + LWSK + 135860 + SKOPJE/PETROVAC + + MK + 41.97 + 21.65 + 239 + 0 + + + + LYBE + 132720 + BELGRADE/SURCIN + + YG + 44.82 + 20.28 + 99 + 0 + + + + LZIB + 118160 + BRATISLAVA_IVANKA + + CZ + 48.20 + 17.20 + 130 + 0 + + + + NFFN + 916800 + NANDI/NADI_INTL + + FJ + -17.75 + 177.45 + 18 + 0 + + + + NZDT + 999999 + NEW_ZEALAND + + NZ + -41.00 + 172.50 + -9999 + 0 + + + + NZKL + 999999 + AUCKLAND + + NZ + -37.02 + 174.80 + 6 + 0 + + + + MHTG + 787200 + TEGUCIGALPA/TONCONT + + HO + 14.05 + -87.22 + 994 + 0 + + + + MPTO + 787920 + TOCUMEN/GEN._OMAR + + PM + 9.05 + -79.37 + 11 + 0 + + + + OBBB + 999999 + BAHRAIN_INTL_ARPT + + BN + 26.27 + 50.65 + 2 + 0 + + + + OBBI + 411500 + BAHRAIN_INTL_ARPT + + BN + 26.27 + 50.65 + 2 + 0 + + + + OEJD + 999999 + JEDDAH + + SD + 21.30 + 39.20 + -9999 + 0 + + + + OEJN + 410240 + JEDDAH/KING_ABD + + SD + 21.67 + 39.15 + 12 + 0 + + + + OIII + 407540 + TEHRAN/MEHRABAD_AFB + + IR + 35.68 + 51.35 + 1191 + 0 + + + + OIIX + 999999 + TEHRAN + + IR + 35.68 + 51.35 + 1191 + 0 + + + + OLBA + 401000 + BEIRUT_(CIV/MIL) + + LB + 33.82 + 35.48 + 19 + 0 + + + + OPKC + 417800 + KARACHI_INTL_ARPT + + PK + 24.90 + 67.13 + 22 + 0 + + + + OPLA + 416410 + LAHORE(CIV/MIL) + + PK + 31.52 + 74.40 + 217 + 0 + + + + OYSN + 413440 + SANA'A + + YE + 15.52 + 44.18 + 2190 + 0 + + + + PAFA + 702610 + FAIRBANKS_INTL_ARPT_(ASOS) + AK + US + 64.82 + -147.87 + 138 + 0 + + + + PAJN + 703810 + JUNEAU_INTL_AIRPORT_(ASOS) + AK + US + 58.37 + -134.58 + 7 + 0 + + + + PANC + 702730 + ANCHORAGE_INTL_ARPT_(ASOS) + AK + US + 61.17 + -150.02 + 40 + 0 + + + + RKSI + 470699 + CHAJANG_NI_(K-ARMY) + + KO + 37.87 + 127.18 + 100 + 0 + + + + RCTP + 466860 + TAIPEI/CHIANG_KAI_SHEK + + TW + 25.08 + 121.22 + 33 + 0 + + + + SABE + 875820 + AEROPARQUE(CIV/MIL) + + AG + -34.57 + -58.42 + 6 + 0 + + + + SACO + 873440 + CORDOBA_AIRPORT + + AG + -31.32 + -64.22 + 474 + 0 + + + + SAEZ + 875760 + BUENOS_AIRES/EZEIZA + + AG + -34.82 + -58.53 + 20 + 0 + + + + SAME + 874180 + MENDOZA/EL_PLUMERIL + + AG + -32.83 + -68.78 + 704 + 0 + + + + SARE + 871550 + RESISTENCIA_AIRPORT + + AG + -27.45 + -59.05 + 52 + 0 + + + + SBBE + 821930 + BELEM/VAL_DE_CAES + + BZ + -1.38 + -48.48 + 16 + 0 + + + + SBBR + 833780 + BRASILIA_(CIV/MIL) + + BZ + -15.87 + -47.93 + 1061 + 0 + + + + SBBS + 833780 + BRASILIA + + BZ + -15.87 + -47.93 + 1061 + 0 + + + + SBCT + 838400 + CURITIBA/AFONSO_PEN + + BZ + -25.52 + -49.17 + 908 + 0 + + + + SBCW + 838400 + CURITIBA/AFONSO_PEN + + BZ + -25.52 + -49.17 + 908 + 0 + + + + SBEG + 821110 + EDUARDO_GOMES_INTL + + BZ + -3.03 + -60.05 + 2 + 0 + + + + SBGL + 837460 + GALEAO/RIO(CIV/MIL) + + BZ + -22.82 + -43.25 + 6 + 0 + + + + SBGR + 837753 + GUARULHOS_(CIV/MIL) + + BZ + -23.43 + -46.47 + 750 + 0 + + + + SBRF + 828990 + RECIFE/GUARARAPES + + BZ + -8.07 + -34.85 + 19 + 0 + + + + SCCI + 859340 + PUNTA_ARENAS/PRES_C + + CH + -53.00 + -70.85 + 37 + 0 + + + + SCEL + 855740 + PUDAHUEL/ARTURO_MER + + CH + -33.38 + -70.78 + 476 + 0 + + + + SCFA + 854420 + ANTOFAGASTA/CERRO + + CH + -23.43 + -70.43 + 120 + 0 + + + + SCTE + 857990 + PUERTO_MONTT/TEPUAL + + CH + -41.42 + -73.08 + 86 + 0 + + + + SLLP + 852010 + LA_PAZ/JFK_INTL + + BO + -16.52 + -68.18 + 4014 + 0 + + + + SOCA + 814050 + CAYENNE/ROCHAMBEAU + + FG + 4.83 + -52.37 + 9 + 0 + + + + SPIM + 846280 + LIMA/JORGE_CHAVEZ + + PR + -12.00 + -77.12 + 13 + 0 + + + + TNCC + 789880 + HATO_ARPT_(CIV/MIL) + + NU + 12.20 + -68.97 + 67 + 0 + + + + TTPP + 789700 + PIARCO_INTL_AIRPORT + + TD + 10.62 + -61.35 + 15 + 0 + + + + UAAA + 368700 + ALMA-ATA + AL + RA + 43.23 + 76.93 + 847 + 0 + + + + UAFM + 835300 + FRUNZE + + RA + 42.85 + 74.53 + 760 + 0 + + + + UATT + 352290 + AKTJUBINSK + AL + KZ + 50.30 + 57.23 + 227 + 0 + + + + UBBB + 378640 + BAKU/BINE_ARPT + TB + AJ + 40.45 + 50.07 + -1 + 0 + + + + UGEE + 377890 + YEREVAN/ZAPADNY + TB + RS + 40.13 + 44.47 + 907 + 0 + + + + UGGG + 375490 + TBILISI/NOVO-AL + TB + RS + 41.68 + 44.95 + 490 + 0 + + + + UHBB + 315100 + BLAGOVESHCHENSK + HA + RA + 50.27 + 127.50 + 137 + 0 + + + + UHHH + 317350 + KHABAROVSK/NOVY + HA + RA + 48.52 + 135.16 + 72 + 0 + + + + UHNN + 999999 + NIKOLAEVSK-NA-AMURE_CENTER + HA + RA + 53.15 + 140.70 + 68 + 0 + + + + UHWW + 319600 + VLADIVOSTOK + HA + RA + 43.12 + 131.94 + 184 + 0 + + + + UHPP + 325400 + PETROPAVLOVSK-KAMCA + HA + RA + 52.97 + 158.75 + 24 + 0 + + + + UHSS + 321500 + JUZNO-SAHALINSK + HA + RA + 46.92 + 142.73 + 31 + 0 + + + + UIBB + 303090 + BRATSK + + RA + 56.07 + 101.83 + 489 + 0 + + + + UIII + 307100 + IRKUTSK + IR + RA + 52.27 + 104.35 + 513 + 0 + + + + UIKK + 302300 + KIRENSK + IR + RA + 57.77 + 108.07 + 258 + 0 + + + + UKBB + 333470 + BORISPOL'/KIEV + KV + UR + 50.33 + 30.97 + 119 + 0 + + + + UKFF + 339460 + SIMFEROPOL + + UR + 44.68 + 34.13 + 180 + 0 + + + + UKHH + 343000 + KHARKIV + KI + UR + 49.96 + 36.13 + 1550 + 0 + + + + UKLL + 333930 + LVOV + KI + UR + 49.82 + 23.95 + 325 + 0 + + + + UKOO + 338370 + ODESSA/TSENTRALNY + KI + UR + 46.43 + 30.77 + 35 + 0 + + + + ULAA + 225500 + ARHANGELSK + AR + RS + 64.53 + 40.47 + 13 + 0 + + + + ULLI + 260630 + ST.PETERSBURG(VOEJKOVO) + LE + RS + 59.95 + 30.70 + 78 + 0 + + + + ULLL + 260630 + ST.PETERSBURG + LE + RS + 59.95 + 30.70 + 78 + 0 + + + + ULWW + 270370 + VOLOGDA + AR + RS + 59.23 + 39.87 + 131 + 0 + + + + ULMM + 221130 + MURMANSK + AR + RS + 68.97 + 33.05 + 51 + 0 + + + + UMKK + 267020 + KALININGRAD + + BY + 54.70 + 20.62 + 27 + 0 + + + + UMMS + 268500 + MINSK + MI + BY + 53.87 + 27.53 + 234 + 0 + + + + UNBB + 298380 + BARNAUL + NO + RA + 53.40 + 83.70 + 252 + 0 + + + + UNIT + 245070 + TURA + NO + RA + 64.27 + 100.23 + 186 + 0 + + + + UNKB + 292820 + BOGUCHANY + NO + RA + 58.42 + 97.40 + 134 + 0 + + + + UNKL + 284935 + KRASNOYARSK + + RS + 56.18 + 92.52 + -9999 + 0 + + + + UNLL + 999999 + KOLPASHEVO + NO + RA + 58.30 + 82.90 + 76 + 0 + + + + UNNT + 296340 + NOVOSIBIRSK/TOLMACH + + RA + 55.03 + 82.90 + 177 + 0 + + + + UNOO + 286980 + OMSK + NO + RA + 54.93 + 73.40 + 123 + 0 + + + + UODD + 206740 + DIKSON_ISLAND + DK + RA + 73.53 + 80.40 + 47 + 0 + + + + UOHH + 208910 + KHATANGA + DK + RA + 71.98 + 102.47 + 24 + 0 + + + + UOTT + 234720 + TURUKHANSK + + RA + 65.78 + 087.95 + 37 + 0 + + + + URRV + 273290 + ROSTOV + MS + RS + 57.20 + 39.42 + 102 + 0 + + + + URWA + 999999 + ASTRAKHAN + + RS + 46.35 + 47.97 + -22 + 0 + + + + URWW + 345600 + VOLGOGRAD + TB + RS + 48.68 + 44.35 + 145 + 0 + + + + USCC + 286420 + CHELYABINSK/BALANDI + SV + RA + 55.18 + 61.32 + -9999 + 0 + + + + USDD + 999999 + SALEKHARD + NO + RA + 66.53 + 66.53 + 358 + 0 + + + + USDS + 235520 + TARKO-SALE + NO + RA + 64.92 + 77.82 + 27 + 0 + + + + USHB + 236310 + BEREZOVO + NO + RA + 63.93 + 65.05 + 27 + 0 + + + + USHH + 239330 + HANTY-MANSIJSK + NO + RA + 60.97 + 69.07 + 40 + 0 + + + + USKK + 999999 + KIROV + MS + RS + 58.60 + 49.63 + 158 + 0 + + + + USPP + 282250 + PERM + SV + RA + 58.02 + 56.30 + 172 + 0 + + + + USRR + 238490 + SURGUT + NO + RA + 61.25 + 73.50 + 44 + 0 + + + + USSS + 284400 + SVERDLOVSK + SV + RA + 56.80 + 60.63 + 237 + 0 + + + + USUU + 286610 + KURGAN + SV + RA + 55.47 + 65.40 + 79 + 0 + + + + UTAA + 388800 + ASHABAD + TA + RA + 37.97 + 58.33 + 210 + 0 + + + + UTTT + 384570 + TASHKENT/YUZNI + TA + RA + 41.27 + 69.27 + 489 + 0 + + + + UUWW + 275185 + MOSCOW/VNUKOVO + MS + RS + 55.65 + 37.27 + 203 + 0 + + + + UUYP + 234180 + PECHORA + AR + RS + 65.11 + 57.10 + 61 + 0 + + + + UUYW + 232260 + VORKUTA + AR + RA + 67.48 + 64.02 + 180 + 0 + + + + UUYY + 238040 + SYKTYVKAR + AR + RA + 61.72 + 50.83 + 119 + 0 + + + + UWKD + 275950 + KAZAN' + MS + RS + 55.78 + 49.18 + 116 + 0 + + + + UWUU + 287220 + UFA + SV + RA + 54.75 + 56.00 + 105 + 0 + + + + VABB + 430030 + BOMBAY/SANTA_CR + + IN + 19.12 + 72.84 + 14 + 0 + + + + VCBI + 434500 + COLOMBO/KATUNAYAKE + + SB + 7.17 + 79.88 + 8 + 0 + + + + VGZR + 419220 + KURMITOLA/ZIA_INTL + + BW + 23.85 + 90.40 + 10 + 0 + + + + VHHH + 450070 + HONG_KONG_INTL_ARPT + + HK + 22.33 + 114.18 + 24 + 0 + + + + VIDP + 421810 + INDIRA_GANDHI/DELHI + + IN + 28.57 + 77.12 + 233 + 0 + + + + WSSS + 486980 + SINGAPORE/CHANG + + SR + 1.37 + 103.98 + 16 + 0 + + + + YBRF + 945780 + BRISBANE + QU + AU + -27.43 + 153.08 + 2 + 0 + + + + YBTL + 942940 + TOWNSVILLE(CIV/MIL) + QU + AU + -19.25 + 146.75 + 6 + 0 + + + + YMHF + 948640 + MELBOURNE + VC + AU + -37.73 + 144.90 + 81 + 0 + + + + YMMB + 948700 + MOORABBIN_AIRPORT + VC + AU + -37.98 + 145.10 + 13 + 0 + + + + YMMC + 948640 + MELBOURNE + VC + AU + -37.73 + 144.90 + 81 + 0 + + + + YMRF + 948640 + MELBOURNE + VC + AU + -37.73 + 144.90 + 81 + 0 + + + + YPDM + 948640 + MELBOURNE + VC + AU + -37.73 + 144.90 + 81 + 0 + + + + YPRF + 948640 + MELBOURNE + VC + AU + -37.73 + 144.90 + 81 + 0 + + + + YPRM + 948640 + MELBOURNE + VC + AU + -37.73 + 144.90 + 81 + 0 + + + + YSRF + 948640 + MELBOURNE + VC + AU + -37.73 + 144.90 + 81 + 0 + + + + ZPPP + 567780 + KUNMING/WUJIABA + CD + CI + 25.02 + 102.68 + 1892 + 0 + + + diff --git a/ncep/gov.noaa.nws.ncep.edex.plugin.mcidas/src/gov/noaa/nws/ncep/edex/plugin/mcidas/decoder/McidasDecoder.java b/ncep/gov.noaa.nws.ncep.edex.plugin.mcidas/src/gov/noaa/nws/ncep/edex/plugin/mcidas/decoder/McidasDecoder.java index b1091c6ede..74babfab6e 100644 --- a/ncep/gov.noaa.nws.ncep.edex.plugin.mcidas/src/gov/noaa/nws/ncep/edex/plugin/mcidas/decoder/McidasDecoder.java +++ b/ncep/gov.noaa.nws.ncep.edex.plugin.mcidas/src/gov/noaa/nws/ncep/edex/plugin/mcidas/decoder/McidasDecoder.java @@ -18,6 +18,7 @@ import com.raytheon.edex.plugin.AbstractDecoder; import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.PluginException; import com.raytheon.uf.common.time.DataTime; +import com.raytheon.uf.edex.decodertools.core.DecoderTools; import com.raytheon.uf.edex.decodertools.time.TimeTools; /** @@ -261,7 +262,10 @@ public class McidasDecoder extends AbstractDecoder { record.setAreaName(areaName); String fileName = ""; if (headers != null) { - fileName = (String) headers.get("traceId"); + // fileName = (String) headers.get("traceId"); + File ingestFile = new File( + (String) headers.get(DecoderTools.INGEST_FILE_NAME)); + fileName = ingestFile.getName(); } record.setInputFileName(fileName); diff --git a/ncep/gov.noaa.nws.ncep.edex.plugin.mosaic/utility/edex_static/base/distribution/mosaic.xml b/ncep/gov.noaa.nws.ncep.edex.plugin.mosaic/utility/edex_static/base/distribution/mosaic.xml index 9902240fa0..52b4707d23 100644 --- a/ncep/gov.noaa.nws.ncep.edex.plugin.mosaic/utility/edex_static/base/distribution/mosaic.xml +++ b/ncep/gov.noaa.nws.ncep.edex.plugin.mosaic/utility/edex_static/base/distribution/mosaic.xml @@ -1,4 +1,4 @@ - ^MANUAL INGEST.* + ^MOSAIC.* diff --git a/ncep/gov.noaa.nws.ncep.edex.plugin.ncgrib/utility/edex_static/base/grib/ncgrib/ncgribModelNameMap.xml b/ncep/gov.noaa.nws.ncep.edex.plugin.ncgrib/utility/edex_static/base/grib/ncgrib/ncgribModelNameMap.xml index 8eb3e0c393..ebda0cdf06 100644 --- a/ncep/gov.noaa.nws.ncep.edex.plugin.ncgrib/utility/edex_static/base/grib/ncgrib/ncgribModelNameMap.xml +++ b/ncep/gov.noaa.nws.ncep.edex.plugin.ncgrib/utility/edex_static/base/grib/ncgrib/ncgribModelNameMap.xml @@ -2,6 +2,10 @@ + + ecavg_.* + ecensDerv + gens_cmce.*_cmc_geavg.* cmceDerv @@ -219,4 +223,4 @@ sref40Derv - \ No newline at end of file + diff --git a/ncep/gov.noaa.nws.ncep.edex.plugin.ncscat/res/spring/ncscat-ingest.xml b/ncep/gov.noaa.nws.ncep.edex.plugin.ncscat/res/spring/ncscat-ingest.xml index a84ff1ac4c..70c0755d38 100644 --- a/ncep/gov.noaa.nws.ncep.edex.plugin.ncscat/res/spring/ncscat-ingest.xml +++ b/ncep/gov.noaa.nws.ncep.edex.plugin.ncscat/res/spring/ncscat-ingest.xml @@ -15,7 +15,7 @@ - + + ^NCSCAT.* diff --git a/ncep/gov.noaa.nws.ncep.edex.plugin.ncuair/src/gov/noaa/nws/ncep/edex/plugin/ncuair/util/NcUairParser.java b/ncep/gov.noaa.nws.ncep.edex.plugin.ncuair/src/gov/noaa/nws/ncep/edex/plugin/ncuair/util/NcUairParser.java index 1791515c59..4bd2c33a41 100644 --- a/ncep/gov.noaa.nws.ncep.edex.plugin.ncuair/src/gov/noaa/nws/ncep/edex/plugin/ncuair/util/NcUairParser.java +++ b/ncep/gov.noaa.nws.ncep.edex.plugin.ncuair/src/gov/noaa/nws/ncep/edex/plugin/ncuair/util/NcUairParser.java @@ -12,6 +12,7 @@ * 02/2010 210 T. Lee Fixed TTCC tropopause * 09/2011 Chin Chen add batch parsing methods for better performance * 09/2011 457 S. Gurung Renamed H5 to Nc and h5 to nc + * 12/2013 T. Lee Fixed TTCC Wmax pressure off by factor of 10 * * * @@ -25,1095 +26,1188 @@ package gov.noaa.nws.ncep.edex.plugin.ncuair.util; import gov.noaa.nws.ncep.common.dataplugin.ncuair.NcUairLiftedIndex; import gov.noaa.nws.ncep.common.dataplugin.ncuair.NcUairMaxWind; import gov.noaa.nws.ncep.common.dataplugin.ncuair.NcUairObsLevels; -import gov.noaa.nws.ncep.common.dataplugin.ncuair.NcUairTropopause; import gov.noaa.nws.ncep.common.dataplugin.ncuair.NcUairRecord; -import gov.noaa.nws.ncep.edex.plugin.ncuair.util.NcUairWindGroup; +import gov.noaa.nws.ncep.common.dataplugin.ncuair.NcUairTropopause; import gov.noaa.nws.ncep.common.tools.IDecoderConstantsN; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.*; - -import com.raytheon.edex.exception.DecoderException; public class NcUairParser { - //UU is data from ship; XX is data from mobile - public static final int TTAA=1; - public static final int TTBB=2; - public static final int TTCC=3; - public static final int TTDD=4; - public static final int PPAA=5; - public static final int PPBB=6; - public static final int PPCC=7; - public static final int PPDD=8; - public static final int UUAA=1; - public static final int UUBB=2; - public static final int UUCC=3; - public static final int UUDD=4; - public static final int XXAA=1; - public static final int XXBB=2; - public static final int XXCC=9; - public static final int XXDD=10; - - /** + // UU is data from ship; XX is data from mobile + public static final int TTAA = 1; + + public static final int TTBB = 2; + + public static final int TTCC = 3; + + public static final int TTDD = 4; + + public static final int PPAA = 5; + + public static final int PPBB = 6; + + public static final int PPCC = 7; + + public static final int PPDD = 8; + + public static final int UUAA = 1; + + public static final int UUBB = 2; + + public static final int UUCC = 3; + + public static final int UUDD = 4; + + public static final int XXAA = 1; + + public static final int XXBB = 2; + + public static final int XXCC = 9; + + public static final int XXDD = 10; + + /** * Constructor */ public NcUairParser() { } - + /** * Return the dataType with format "(TT|PP|XX|UU)(AA|BB|CC|DD)" * - * @param theReport The input upper air data report + * @param theReport + * The input upper air data report * @return */ public static String getDataType(String theReport) { - - /** Regular expression for dataType */ - final String DATA_TYPE = "((TT|PP|XX|UU)(AA|BB|CC|DD)) "; - Pattern datatypePattern = Pattern.compile(DATA_TYPE); - Matcher datatypeMatcher = datatypePattern.matcher(theReport); - String retType = null; - - if ( datatypeMatcher.find()) { - retType = datatypeMatcher.group(1); - } - return retType; + + /** Regular expression for dataType */ + final String DATA_TYPE = "((TT|PP|XX|UU)(AA|BB|CC|DD)) "; + Pattern datatypePattern = Pattern.compile(DATA_TYPE); + Matcher datatypeMatcher = datatypePattern.matcher(theReport); + String retType = null; + + if (datatypeMatcher.find()) { + retType = datatypeMatcher.group(1); + } + return retType; } - + /** * Return the station Number * - * @param theReport The input upper air data report + * @param theReport + * The input upper air data report * @return */ public static String getStationNumber(String theReport) { - /** Regular expression for stationNumber */ - final String STATIONNUMBER = "(TT|PP)(AA|BB|CC|DD) ( )?(\\d{2})(\\d{2})(\\d{1}|/) (\\d{5})"; - Pattern stationNumberPattern = Pattern.compile(STATIONNUMBER); - Matcher stationNumberMatcher = stationNumberPattern.matcher(theReport); - String retStationNumber = null; + /** Regular expression for stationNumber */ + final String STATIONNUMBER = "(TT|PP)(AA|BB|CC|DD) ( )?(\\d{2})(\\d{2})(\\d{1}|/) (\\d{5})"; + Pattern stationNumberPattern = Pattern.compile(STATIONNUMBER); + Matcher stationNumberMatcher = stationNumberPattern.matcher(theReport); + String retStationNumber = null; - if ( stationNumberMatcher.find()) { - retStationNumber = stationNumberMatcher.group(7); - } else { - /** Regular expression for stationNumber */ - final String STATIONNUMBER2 = "(TT|PP)(AA|BB|CC|DD) (\\d{5}) NIL"; - Pattern stationNumberPattern2 = Pattern.compile(STATIONNUMBER2); - Matcher stationNumberMatcher2 = stationNumberPattern2.matcher(theReport); - if ( stationNumberMatcher2.find()) { - retStationNumber = stationNumberMatcher2.group(3); - } else { - /** Regular expression for stationNumber */ - final String STATIONNUMBER3 = "(TT|PP)(AA|BB|CC|DD) (/////) (\\d{5}) NIL"; - Pattern stationNumberPattern3 = Pattern.compile(STATIONNUMBER3); - Matcher stationNumberMatcher3 = stationNumberPattern3.matcher(theReport); - if ( stationNumberMatcher3.find()) { - retStationNumber = stationNumberMatcher3.group(4); - } - } - } - return retStationNumber; + if (stationNumberMatcher.find()) { + retStationNumber = stationNumberMatcher.group(7); + } else { + /** Regular expression for stationNumber */ + final String STATIONNUMBER2 = "(TT|PP)(AA|BB|CC|DD) (\\d{5}) NIL"; + Pattern stationNumberPattern2 = Pattern.compile(STATIONNUMBER2); + Matcher stationNumberMatcher2 = stationNumberPattern2 + .matcher(theReport); + if (stationNumberMatcher2.find()) { + retStationNumber = stationNumberMatcher2.group(3); + } else { + /** Regular expression for stationNumber */ + final String STATIONNUMBER3 = "(TT|PP)(AA|BB|CC|DD) (/////) (\\d{5}) NIL"; + Pattern stationNumberPattern3 = Pattern.compile(STATIONNUMBER3); + Matcher stationNumberMatcher3 = stationNumberPattern3 + .matcher(theReport); + if (stationNumberMatcher3.find()) { + retStationNumber = stationNumberMatcher3.group(4); + } + } + } + return retStationNumber; } - - /** - * Get the correction indicator from WMO header. - * - * @param theReport The input upper air data report - * @return a String for corIndicator - */ - public static String findCorIndicator(String theReport) { - - String corIndicator = null; - - /** Regular expression for corIndicator */ - final String corpat = "[A-Z]{4}\\d{0,2} [A-Z]{4} \\d{6}( )?([A-Z]{3})?\\r\\r\\n"; - Pattern CORPattern = Pattern.compile(corpat); - Matcher corMatcher = CORPattern.matcher(theReport); - if ( corMatcher.find()) { - corIndicator = corMatcher.group(2); - } - - return corIndicator; - } - - /** - * From a given dataType returns an integer to represent - * that dataType. - * - * @param dataType The input dataType - * @return an integer for that dataType - */ - public static Integer getUairType(String dataType) { - HashMap uairhm = new HashMap(); - - uairhm.put("TTAA", new Integer(TTAA)); - uairhm.put("TTBB", new Integer(TTBB)); - uairhm.put("TTCC", new Integer(TTCC)); - uairhm.put("TTDD", new Integer(TTDD)); - - uairhm.put("PPAA", new Integer(PPAA)); - uairhm.put("PPBB", new Integer(PPBB)); - uairhm.put("PPCC", new Integer(PPCC)); - uairhm.put("PPDD", new Integer(PPDD)); - - uairhm.put("XXAA", new Integer(XXAA)); - uairhm.put("XXBB", new Integer(XXBB)); - uairhm.put("XXCC", new Integer(XXCC)); - uairhm.put("XXDD", new Integer(XXDD)); - - uairhm.put("UUAA", new Integer(UUAA)); - uairhm.put("UUBB", new Integer(UUBB)); - uairhm.put("UUCC", new Integer(UUCC)); - uairhm.put("UUDD", new Integer(UUDD)); - - return (Integer) uairhm.get(dataType); - } - - /** - * Parse the entire code message and interpret to - * observation level information according its data - * type. + /** + * Get the correction indicator from WMO header. * - * @param codeMessage The input upper air code groups - * @param record The in and out Uair record + * @param theReport + * The input upper air data report + * @return a String for corIndicator + */ + public static String findCorIndicator(String theReport) { + + String corIndicator = null; + + /** Regular expression for corIndicator */ + final String corpat = "[A-Z]{4}\\d{0,2} [A-Z]{4} \\d{6}( )?([A-Z]{3})?\\r\\r\\n"; + Pattern CORPattern = Pattern.compile(corpat); + Matcher corMatcher = CORPattern.matcher(theReport); + + if (corMatcher.find()) { + corIndicator = corMatcher.group(2); + } + + return corIndicator; + } + + /** + * From a given dataType returns an integer to represent that dataType. + * + * @param dataType + * The input dataType + * @return an integer for that dataType + */ + public static Integer getUairType(String dataType) { + HashMap uairhm = new HashMap(); + + uairhm.put("TTAA", new Integer(TTAA)); + uairhm.put("TTBB", new Integer(TTBB)); + uairhm.put("TTCC", new Integer(TTCC)); + uairhm.put("TTDD", new Integer(TTDD)); + + uairhm.put("PPAA", new Integer(PPAA)); + uairhm.put("PPBB", new Integer(PPBB)); + uairhm.put("PPCC", new Integer(PPCC)); + uairhm.put("PPDD", new Integer(PPDD)); + + uairhm.put("XXAA", new Integer(XXAA)); + uairhm.put("XXBB", new Integer(XXBB)); + uairhm.put("XXCC", new Integer(XXCC)); + uairhm.put("XXDD", new Integer(XXDD)); + + uairhm.put("UUAA", new Integer(UUAA)); + uairhm.put("UUBB", new Integer(UUBB)); + uairhm.put("UUCC", new Integer(UUCC)); + uairhm.put("UUDD", new Integer(UUDD)); + + return (Integer) uairhm.get(dataType); + } + + /** + * Parse the entire code message and interpret to observation level + * information according its data type. + * + * @param codeMessage + * The input upper air code groups + * @param record + * The in and out Uair record * @return */ - static int exceptionCount=0; - public static void getLevels(String codeMessage, NcUairRecord record) { + static int exceptionCount = 0; - Boolean windKnot = false; + public static void getLevels(String codeMessage, NcUairRecord record) { - String dataType = record.getDataType(); + Boolean windKnot = false; - int uairType = getUairType(dataType); - //System.out.println("getLEvel uair datatype="+dataType); - String[] codeGroupAr;//Chin, do not use fix array size, it will cause exception when size is over 500 = new String[500]; - List codeGpList = new ArrayList(); - //System.out.println("codeMessage...\n" + codeMessage); + String dataType = record.getDataType(); - if ( dataType.substring(0,2).equals("XX") || dataType.substring(0,2).equals("UU") ) { - windKnot = NcUairShipMobile.getWindKnot(); - } else { - windKnot = NcUairTimeGroup.getWindKnot(); - } - // Break the code message into segments by a " " - Scanner sc = new Scanner(codeMessage).useDelimiter(" "); - int cgSize = 0; - - while (sc.hasNext()) { - String codeGroup = sc.next(); - codeGpList.add(codeGroup); - //Chin codeGroupAr[cgSize] = codeGroup; - cgSize++; - } - codeGroupAr = new String[cgSize]; - codeGpList.toArray(codeGroupAr); - try{ - switch (uairType) { - case TTAA : { - processTTAACC(codeGroupAr, cgSize, windKnot, record); - break; - } - case TTBB : { - processTTBBDD(codeGroupAr, cgSize, windKnot, record); - break; - } - case TTCC : { - processTTAACC(codeGroupAr, cgSize, windKnot, record); - break; - } - case TTDD : { - processTTBBDD(codeGroupAr, cgSize, windKnot, record); - break; - } - case PPAA: { - processPPAACC(codeGroupAr, cgSize, windKnot, record); - break; - } - case PPBB : { - processPPBBDD(codeGroupAr, cgSize, windKnot, record); - break; - } - case PPCC : { - processPPAACC(codeGroupAr, cgSize, windKnot, record); - break; - } - case PPDD : { - processPPBBDD(codeGroupAr, cgSize, windKnot, record); - break; - } - default: { - System.out.println("\n Invalid datatype!"); - } - } - } catch ( Exception e){ - exceptionCount++; - System.out.println("NcUair parsing exception! #"+exceptionCount); - } - } + int uairType = getUairType(dataType); + // System.out.println("getLEvel uair datatype="+dataType); + String[] codeGroupAr;// Chin, do not use fix array size, it will cause + // exception when size is over 500 = new + // String[500]; + List codeGpList = new ArrayList(); + // System.out.println("codeMessage...\n" + codeMessage); - - /** - * Decodes a Pres/height, temperature, and wind fields in the - * forms PPhhh and TTTdd and DDDff for TTAA/CC.' - * - * @param codeGroupAr The input uppair code group array - * @param cgSize The input cgSize is the size of the code group array - * @param windKnot The input windKnot is flag to indicate wind in knot or not. - * @param record The in and out Uair record - * @return - */ - public static void processTTAACC(String[] codeGroupAr, int cgSize, - Boolean windKnot, NcUairRecord record) { - - Boolean above= false; - Boolean endrpt = false; - Boolean topwindFlag = false; - Boolean drop = false; - - int level = 0; - int topwind = IDecoderConstantsN.UAIR_INTEGER_MISSING; - - String dataType = record.getDataType(); - String stationNumber = record.getStnum(); + if (dataType.substring(0, 2).equals("XX") + || dataType.substring(0, 2).equals("UU")) { + windKnot = NcUairShipMobile.getWindKnot(); + } else { + windKnot = NcUairTimeGroup.getWindKnot(); + } + // Break the code message into segments by a " " + Scanner sc = new Scanner(codeMessage).useDelimiter(" "); + int cgSize = 0; - if ( dataType.substring(2,4).equals("CC") ) { - above = true; - } - if ( dataType.substring(0,2).equals("XX") || dataType.substring(0,2).equals("UU") ) { - topwind = NcUairShipMobile.getTopwind(); - if ( dataType.substring(0,2).equals("XX") ) { - drop = true; - } - } else { - topwind = NcUairTimeGroup.getTopwind(); - } - if ( topwind == IDecoderConstantsN.UAIR_INTEGER_MISSING ) { - topwindFlag = true; - } - int topWind = getTopWind( topwind, above); - - int i = 0; - while ( i < cgSize && ! endrpt ) { - - float pres = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float height = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float temp = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float dewpTemp = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float wdir = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float wspeed = IDecoderConstantsN.UAIR_FLOAT_MISSING; - - if ( codeGroupAr[i].length() < 3) { - break; - } - if ( codeGroupAr[i].equals("51515") ) { - endrpt = true; - i++; - // Decode lifted index and mean low level wind groups - if ( (i + 2) < cgSize ) { - processLiftedIndex(codeGroupAr, i, windKnot, record); - } - break; - } - - // This should be drop data - if ( codeGroupAr[i].equals("61616") ) { - endrpt = true; - if ( drop ) { - // process drop data - //System.out.println("got drop 61616 in TT AACC - need to process...\n"); - } - break; - } - - String pp = codeGroupAr[i].substring(0,2); - if ( pp.equals("^C") ) { - break; - } - - if ( pp.equals("88") || pp.equals("77") || pp.equals("66") ) { - // Decode supplemental data - String hhh = codeGroupAr[i].substring(2,5); - if ( pp.equals("88") ) { - // Decode tropopause information - if ( hhh.equals("999")) { - // NO tropopause data - i++; - } else { - processTropopause(codeGroupAr, i, topwindFlag, windKnot, record, above); - if ( topwindFlag ) { - i = i + 2; - } else { - i = i + 3; - } - } - } else if ( pp.equals("77") || pp.equals("66")) { - // Decode maximum wind group - if ( hhh.equals("999")) { - // NO maximum wind data - i++; - } else { - processMaximumWindShear(codeGroupAr, i, cgSize, windKnot, record); - i = i + 3; - } - } - } else if ( codeGroupAr[i].equals("31313") ) { - i = i + 3; - } else if ( codeGroupAr[i].equals("41414") ) { - i = i + 2; - } else { - int range = i + 2; - if ( range < cgSize ) { - // Decode TTAA normal report -pressure and height - NcUairPressureHeightGroup.PressureHeightField(codeGroupAr[i], above, level, stationNumber, dataType, record); - pres = NcUairPressureHeightGroup.getPressure(); - height = NcUairPressureHeightGroup.getHeight(); + while (sc.hasNext()) { + String codeGroup = sc.next(); + codeGpList.add(codeGroup); + // Chin codeGroupAr[cgSize] = codeGroup; + cgSize++; + } + codeGroupAr = new String[cgSize]; + codeGpList.toArray(codeGroupAr); + try { + switch (uairType) { + case TTAA: { + processTTAACC(codeGroupAr, cgSize, windKnot, record); + break; + } + case TTBB: { + processTTBBDD(codeGroupAr, cgSize, windKnot, record); + break; + } + case TTCC: { + processTTAACC(codeGroupAr, cgSize, windKnot, record); + break; + } + case TTDD: { + processTTBBDD(codeGroupAr, cgSize, windKnot, record); + break; + } + case PPAA: { + processPPAACC(codeGroupAr, cgSize, windKnot, record); + break; + } + case PPBB: { + processPPBBDD(codeGroupAr, cgSize, windKnot, record); + break; + } + case PPCC: { + processPPAACC(codeGroupAr, cgSize, windKnot, record); + break; + } + case PPDD: { + processPPBBDD(codeGroupAr, cgSize, windKnot, record); + break; + } + default: { + System.out.println("\n Invalid datatype!"); + } + } + } catch (Exception e) { + exceptionCount++; + System.out.println("NcUair parsing exception! #" + exceptionCount); + } + } - // Decode temperature group - NcUairTempGroup.TempField(codeGroupAr[i+1]); - temp = NcUairTempGroup.getTemperature(); - dewpTemp = NcUairTempGroup.getDewpointTemp(); + /** + * Decodes a Pres/height, temperature, and wind fields in the forms PPhhh + * and TTTdd and DDDff for TTAA/CC.' + * + * @param codeGroupAr + * The input uppair code group array + * @param cgSize + * The input cgSize is the size of the code group array + * @param windKnot + * The input windKnot is flag to indicate wind in knot or not. + * @param record + * The in and out Uair record + * @return + */ + public static void processTTAACC(String[] codeGroupAr, int cgSize, + Boolean windKnot, NcUairRecord record) { - if ( pres >= topWind ) { - // Decode wind group - NcUairWindGroup.WindField(codeGroupAr[i+2], windKnot); - wspeed = NcUairWindGroup.getSped(); - wdir = NcUairWindGroup.getDrct(); - if ( wdir > 360 ) { - wdir = IDecoderConstantsN.UAIR_FLOAT_MISSING; - endrpt = true; - break; - } - } else { - i--; - } - - // Add level - addLevels(record, pres, height, temp, dewpTemp, wdir, wspeed); - } - i = i + 3; - level++; - } - } - - } - - /** - * Decodes a pressure/height, temperature, and wind fields in the - * forms PPhhh and TTTdd and DDDff for TTBB/DD. - * - * @param codeGroupAr The input uppair code group array - * @param cgSize The input cgSize is the size of the code group array - * @param windKnot The input windKnot is flag to indicate wind in knot or not. - * @param record The in and out Uair record - * @return - */ - public static void processTTBBDD(String[] codeGroupAr, - int cgSize, Boolean windKnot, NcUairRecord record) { - - Boolean above=false; - Boolean endrpt = false; - Boolean wind = false; - Boolean drop = false; - - String dataType = record.getDataType(); - - if ( dataType.substring(2,4).equals("DD") ) { - above = true; - } - if ( dataType.substring(0,2).equals("XX") ) { - drop = true; - } + Boolean above = false; + Boolean endrpt = false; + Boolean topwindFlag = false; + Boolean drop = false; - int i = 0; - while ( i < cgSize && ! endrpt ) { - - float pres = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float height = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float temp = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float dewpTemp = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float wdir = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float wspeed = IDecoderConstantsN.UAIR_FLOAT_MISSING; - - if ( codeGroupAr[i].equals("51515") ) { - endrpt = true; - i++; - // Decode lifted index and mean low level wind groups - if ( (i + 2) < cgSize ) { - processLiftedIndex(codeGroupAr, i, windKnot, record); - } - break; - } - - if ( codeGroupAr[i].equals("61616") ) { - endrpt = true; - if ( drop ) { - //System.out.println("got drop 61616 in BBDD need to process.... \n"); - } - break; - } - - if ( codeGroupAr[i].equals("21212") ) { - wind = true; - i++; - //System.out.println("got 21212 significant wind group need to process...\n"); - break; - } - - if ( codeGroupAr[i].equals("31313")) { - i = i + 3; - } else if ( codeGroupAr[i].equals("41414") ) { - i = i + 2; - } else { - int range = i + 1; - if ( range < cgSize ) { - // Decode Pres group - pres = getPressureFromTTBBDD(codeGroupAr[i], above); - - if ( ! wind ) { - // Decode temperature group - NcUairTempGroup.TempField(codeGroupAr[i+1]); - temp = NcUairTempGroup.getTemperature(); - dewpTemp = NcUairTempGroup.getDewpointTemp(); - } else { - // Decode wind group - NcUairWindGroup.WindField(codeGroupAr[i+1], windKnot); - wspeed = NcUairWindGroup.getSped(); - wdir = NcUairWindGroup.getDrct(); - } - - // Add level - addLevels(record, pres, height, temp, dewpTemp, wdir, wspeed); - - } - i = i + 2; - } - } - } - - /** - * Decodes a pressure/height and temperature fields for PPAACC. - * These reports contain wind data at mandatory - * levels below 100 mb. - * - * @param codeGroupAr The input uppair code group array - * @param cgSize The input cgSize is the size of the code group array - * @param windKnot The input windKnot is flag to indicate wind in knot or not. - * @param record The in and out Uair record - * @return - */ - public static void processPPAACC(String[] codeGroupAr, int cgSize, - Boolean windKnot, NcUairRecord record) { + int level = 0; + int topwind = IDecoderConstantsN.UAIR_INTEGER_MISSING; - Boolean above=false; - Boolean endrpt = false; - float height = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float temp = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float dewpTemp = IDecoderConstantsN.UAIR_FLOAT_MISSING; - - float pold; - - String dataType = record.getDataType(); - - if ( dataType.substring(2,4).equals("CC") ) { - above = true; - pold = 100; - } else { - pold = 2000; - } + String dataType = record.getDataType(); + String stationNumber = record.getStnum(); - int i = 0; - while ( i < cgSize && ! endrpt ) { - - if ( codeGroupAr[i].equals("51515")) { - endrpt = true; - break; - } - - String ppIndicator = codeGroupAr[i].substring(0,2); - // Check that first two characters are 44 or 55. - if ( ppIndicator.equals("44") || ppIndicator.equals("55")) { - String skip = codeGroupAr[i].substring(2,5); - if ( skip.equals("///")) { - i++; - } else { - // Decode number of pressures which is the third character. - /* chin, fix bug, when a non-number char is decoded */ - int onetothree=0; - try{ - onetothree = Integer.parseInt(codeGroupAr[i].substring(2,3)); - } catch (NumberFormatException e) { - onetothree=0; - - } - if ( onetothree > 0 && onetothree <= 3) { - // Decode the pressure - float[] presArr = { IDecoderConstantsN.UAIR_FLOAT_MISSING, - IDecoderConstantsN.UAIR_FLOAT_MISSING, - IDecoderConstantsN.UAIR_FLOAT_MISSING, - }; - presArr = getPressureFromPPAACC(codeGroupAr[i], above); - - i++; - for (int index = 0; index < onetothree; index++) { - float wdir = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float wspeed = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float pres = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float ppp = presArr[index]; - if ( ppp < pold ) { - pres = presArr[index]; - pold = ppp; - } - - // Decode wind group - if ( i < cgSize ) { - NcUairWindGroup.WindField(codeGroupAr[i], windKnot); - wspeed = NcUairWindGroup.getSped(); - wdir = NcUairWindGroup.getDrct(); - } - - // Add level - addLevels(record, pres, height, temp, dewpTemp, wdir, wspeed); - - i++; - } - } - else { - // no pressure group - i++; - } - } - } else if ( ppIndicator.equals("77") || ppIndicator.equals("66")) { - // Decode maximum wind group - String hhh = codeGroupAr[i].substring(2,5); - if ( hhh.equals("999")) { - // NO maximum wind and wind shear data - i++; - } else { - processMaximumWindShear(codeGroupAr, i, cgSize, windKnot, record); - i = i + 3; - } - } else { - i++; - break; - } - } - } + if (dataType.substring(2, 4).equals("CC")) { + above = true; + } + if (dataType.substring(0, 2).equals("XX") + || dataType.substring(0, 2).equals("UU")) { + topwind = NcUairShipMobile.getTopwind(); + if (dataType.substring(0, 2).equals("XX")) { + drop = true; + } + } else { + topwind = NcUairTimeGroup.getTopwind(); + } + if (topwind == IDecoderConstantsN.UAIR_INTEGER_MISSING) { + topwindFlag = true; + } + int topWind = getTopWind(topwind, above); - /** - * Decodes a pressure/height and temperature fields for PPBBDD. - * These reports contain significant wind data above 100 mb. - * - * @param codeGroupAr The input uppair code group array - * @param cgSize The input cgSize is the size of the code group array - * @param windKnot The input windKnot is flag to indicate wind in knot or not. - * @param record The in and out Uair record - * @return - */ - public static void processPPBBDD(String[] codeGroupAr, int cgSize, - Boolean windKnot, NcUairRecord record) { - - Boolean endrpt = false; - Boolean pressflag = false; - Boolean above = false; - - String dataType = record.getDataType(); - - if ( dataType.substring(2,4).equals("DD") ) { - above = true; - } + int i = 0; + while (i < cgSize && !endrpt) { - int i = 0; - try{ - while ( i < cgSize && ! endrpt ) { - - float pres = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float height = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float temp = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float dewpTemp = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float wdir = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float wspeed = IDecoderConstantsN.UAIR_FLOAT_MISSING; - - - if ( codeGroupAr[i].equals("21212") ) { - pressflag = true; - i++; - if ( i >= cgSize ) { - break; - } - //System.out.println("got 21212 in PP BBDD - need to process...\n"); - break; - } - - if ( codeGroupAr[i].equals("51515") || codeGroupAr[i].equals("41414")) { - endrpt = true; - //System.out.println("got end group 51515 41414 in PP BBDD - BREAK \n"); - break; - } + float pres = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float height = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float temp = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float dewpTemp = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float wdir = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float wspeed = IDecoderConstantsN.UAIR_FLOAT_MISSING; - // Convert the unit digits to integers and compute height. - Boolean missing = false; - int noWind = 0; - if ( ! pressflag ) { - while ( ! missing && ( noWind < 3 ) ) { - int index = noWind + 3; - String unit="/"; - unit = codeGroupAr[i].substring(index-1,index); - - if ( unit.equals(("/")) ) { - missing = true; - break; - } + if (codeGroupAr[i].length() < 3) { + break; + } + if (codeGroupAr[i].equals("51515")) { + endrpt = true; + i++; + // Decode lifted index and mean low level wind groups + if ((i + 2) < cgSize) { + processLiftedIndex(codeGroupAr, i, windKnot, record); + } + break; + } - // Decode height; invalid height if returns FLOAT_MISSING. - height = getHeightFromPPBBDD(codeGroupAr[i], index); - if ( height == IDecoderConstantsN.UAIR_FLOAT_MISSING ) { - i++; - break; - } - int range = i+noWind+1; - if ( range < cgSize ) { - // Decode wind group. - NcUairWindGroup.WindField(codeGroupAr[i+noWind+1], windKnot); - wspeed = NcUairWindGroup.getSped(); - wdir = NcUairWindGroup.getDrct(); - } - - // Add level - addLevels(record, pres, height, temp, dewpTemp, wdir, wspeed); - - noWind ++; - } + // This should be drop data + if (codeGroupAr[i].equals("61616")) { + endrpt = true; + if (drop) { + // process drop data + // System.out.println("got drop 61616 in TT AACC - need to process...\n"); + } + break; + } - i = i + noWind + 1; - } else { - int range = i+1; - if ( range < cgSize ) { - // Decode pressure group - pres = getPressureFromTTBBDD(codeGroupAr[i], above); - NcUairWindGroup.WindField(codeGroupAr[i+1], windKnot); - wspeed = NcUairWindGroup.getSped(); - wdir = NcUairWindGroup.getDrct(); - } - i= i+2; - } - } - } - catch(Exception e) { - - } - } - - /** - * Decodes a pressure field for mandatory wind - * reports (PPAA or PPCC). The pressures reporting are returned. - * - * @param presGroup The input pressure code group - * @param above The input above is flag - * @return pressure - */ - public static float[] getPressureFromPPAACC(String presGroup, Boolean above) { + String pp = codeGroupAr[i].substring(0, 2); + if (pp.equals("^C")) { + break; + } - float pressure[] = { IDecoderConstantsN.UAIR_FLOAT_MISSING, - IDecoderConstantsN.UAIR_FLOAT_MISSING, - IDecoderConstantsN.UAIR_FLOAT_MISSING - }; + if (pp.equals("88") || pp.equals("77") || pp.equals("66")) { + // Decode supplemental data + String hhh = codeGroupAr[i].substring(2, 5); + if (pp.equals("88")) { + // Decode tropopause information + if (hhh.equals("999")) { + // NO tropopause data + i++; + } else { + processTropopause(codeGroupAr, i, topwindFlag, + windKnot, record, above); + if (topwindFlag) { + i = i + 2; + } else { + i = i + 3; + } + } + } else if (pp.equals("77") || pp.equals("66")) { + // Decode maximum wind group + if (hhh.equals("999")) { + // NO maximum wind data + i++; + } else { + processMaximumWindShear(codeGroupAr, i, cgSize, + windKnot, above, record); + i = i + 3; + } + } + } else if (codeGroupAr[i].equals("31313")) { + i = i + 3; + } else if (codeGroupAr[i].equals("41414")) { + i = i + 2; + } else { + int range = i + 2; + if (range < cgSize) { + // Decode TTAA normal report -pressure and height + NcUairPressureHeightGroup.PressureHeightField( + codeGroupAr[i], above, level, stationNumber, + dataType, record); + pres = NcUairPressureHeightGroup.getPressure(); + height = NcUairPressureHeightGroup.getHeight(); - String bpres[] = { "00", "92", "85", "70", "50", "40", - "30", "25", "20", "15", "10" }; + // Decode temperature group + NcUairTempGroup.TempField(codeGroupAr[i + 1]); + temp = NcUairTempGroup.getTemperature(); + dewpTemp = NcUairTempGroup.getDewpointTemp(); - String apres[] = { "70", "50", "30", "20", "10", - "07", "05", "03", "02", "01" }; + if (pres >= topWind) { + // Decode wind group + NcUairWindGroup.WindField(codeGroupAr[i + 2], windKnot); + wspeed = NcUairWindGroup.getSped(); + wdir = NcUairWindGroup.getDrct(); + if (wdir > 360) { + wdir = IDecoderConstantsN.UAIR_FLOAT_MISSING; + endrpt = true; + break; + } + } else { + i--; + } - int rbprs[] = { 1000, 925, 850, 700, 500, 400, - 300, 250, 200, 150, 100 }; + // Add level + addLevels(record, pres, height, temp, dewpTemp, wdir, + wspeed); + } + i = i + 3; + level++; + } + } - int raprs[] = { 70, 50, 30, 20, 10, 7, 5, 3, 2, 1 }; + } - int level = -1; + /** + * Decodes a pressure/height, temperature, and wind fields in the forms + * PPhhh and TTTdd and DDDff for TTBB/DD. + * + * @param codeGroupAr + * The input uppair code group array + * @param cgSize + * The input cgSize is the size of the code group array + * @param windKnot + * The input windKnot is flag to indicate wind in knot or not. + * @param record + * The in and out Uair record + * @return + */ + public static void processTTBBDD(String[] codeGroupAr, int cgSize, + Boolean windKnot, NcUairRecord record) { - String hh = presGroup.substring(3,5); - // Check first pressure against list. - int ifirst = -1; - if ( ! above ) { - for ( String plevel : bpres ) { - ifirst ++; - if ( hh.equals(plevel)) { - level = ifirst; - break; - } - } - } else { - for ( String plevel : apres ) { - ifirst ++; - if ( hh.equals(plevel)) { - level = ifirst; - break; - } - } - } + Boolean above = false; + Boolean endrpt = false; + Boolean wind = false; + Boolean drop = false; - if ( ! above ) { - if ( ifirst < 11 && level >= 0 ) { - pressure[0] = rbprs[level]; - if ( level+1 < 11 ) { - pressure[1] = rbprs[level+1]; - } - if ( level+2 < 11 ) { - pressure[2] = rbprs[level+2]; - } - } - } else { - if ( ifirst < 10 && level >= 0 ) { - pressure[0] = raprs[level]; - if ( level+1 < 10 ) { - pressure[1] = raprs[level+1]; - } - if ( level+2 < 10 ) { - pressure[2] = raprs[level+2]; - } - } - } + String dataType = record.getDataType(); - return pressure; - } + if (dataType.substring(2, 4).equals("DD")) { + above = true; + } + if (dataType.substring(0, 2).equals("XX")) { + drop = true; + } - /** - * Decodes the height from a significant wind field from reports (PPBB or PPDD). - * The field is of the form atuuu where a is 1 if the height is - * above 100000 feet and 9 or 8 otherwise. t is the ten-thousands - * digit of the height and the u's are up to three thousands-of-feet - * fields. The heights are converted from feet to meters. - * - * @param heightGroup The input heightGroup contains the height code group. - * @param index The input index is the current position in the code group. - * @return pressure - */ - public static float getHeightFromPPBBDD(String heightGroup, int index) { - float height = IDecoderConstantsN.UAIR_FLOAT_MISSING; - final double feetToMeter = 0.3048; - - String hhIndicator = heightGroup.substring(0,1); - int iadd = 0; - // Check that the first character of the field is '9' or '1'. - if ( hhIndicator.equals("9") || hhIndicator.equals("8")) { - iadd = 0; - } else { - return height; - } - - // Convert the tens digit to an integer. - int iten; - iten = Integer.parseInt(heightGroup.substring(1,2)) * 10; - int iunit = Integer.parseInt(heightGroup.substring(index-1,index)); - height = ( iten + iunit ) * 1000 + iadd; - height = (float) (height * feetToMeter); - return height; - } - - /** - * Decodes a pressure field from a group reports (TTBB or TTDD). - * The pressures reporting are returned. - * - * @param presGroup The input pressure code group - * @param above The input above is flag - * @return pressure - */ - public static float getPressureFromTTBBDD(String presGroup, Boolean above) { + int i = 0; + while (i < cgSize && !endrpt) { - float pressure = IDecoderConstantsN.UAIR_FLOAT_MISSING; - - String clev[] = { "00", "11", "22", "33", "44", - "55", "66", "77", "88", "99" }; - - if ( presGroup.length() == 5 ) { - String pp = presGroup.substring(0,2); - String hhh = presGroup.substring(2,5); - - int level = -1; - if ( ! pp.equals("//") && ! hhh.substring(2,3).equals("/")) { - for ( String plevel : clev ) { - level++; - if ( pp.equals(plevel)) { - break; - } - } - // If a level was found, decode the pressure. - if ( level != -1 && level < 10 ) { - int ihhh = Integer.parseInt(hhh); - if ( above ) { - pressure = (float) ihhh/ (float) 10; - } else { - if ( ihhh < 100 ) { - pressure = ihhh + 1000; - } else { - pressure = ihhh; - } - } - } - } - } - return pressure; - } + float pres = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float height = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float temp = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float dewpTemp = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float wdir = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float wspeed = IDecoderConstantsN.UAIR_FLOAT_MISSING; - /** - * Decodes data for the tropopause level from the TTAA reports. - * The output data are ordered PRES TEMP DWPT DRCT SPED. - * - * @param codeGroupAr The input uppair code group array - * @param index The input index is the current position of the code group array - * @param topwindFlag the input index is the flag to indicate top wind - * @param windKnot The input windKnot is flag to indicate wind in knot or not. - * @param record The in and out Uair record - * @return - */ - public static void processTropopause(String[] codeGroupAr, int index, - Boolean topwindFlag, Boolean windKnot, NcUairRecord record, Boolean above) { - - float pres = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float temp = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float dewpTemp = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float wdir = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float wspeed = IDecoderConstantsN.UAIR_FLOAT_MISSING; + if (codeGroupAr[i].equals("51515")) { + endrpt = true; + i++; + // Decode lifted index and mean low level wind groups + if ((i + 2) < cgSize) { + processLiftedIndex(codeGroupAr, i, windKnot, record); + } + break; + } - int i = index; + if (codeGroupAr[i].equals("61616")) { + endrpt = true; + if (drop) { + // System.out.println("got drop 61616 in BBDD need to process.... \n"); + } + break; + } - String pp = codeGroupAr[i].substring(0,2); - String hhh = codeGroupAr[i].substring(2,5); + if (codeGroupAr[i].equals("21212")) { + wind = true; + i++; + // System.out.println("got 21212 significant wind group need to process...\n"); + break; + } - if ( pp.equals("88") ) { - // Decode pressure and height - pres = Integer.parseInt(hhh); - if (above) { - pres = pres / 10.f; - } + if (codeGroupAr[i].equals("31313")) { + i = i + 3; + } else if (codeGroupAr[i].equals("41414")) { + i = i + 2; + } else { + int range = i + 1; + if (range < cgSize) { + // Decode Pres group + pres = getPressureFromTTBBDD(codeGroupAr[i], above); - // Decode temperature group - NcUairTempGroup.TempField(codeGroupAr[i+1]); - temp = NcUairTempGroup.getTemperature(); - dewpTemp = NcUairTempGroup.getDewpointTemp(); + if (!wind) { + // Decode temperature group + NcUairTempGroup.TempField(codeGroupAr[i + 1]); + temp = NcUairTempGroup.getTemperature(); + dewpTemp = NcUairTempGroup.getDewpointTemp(); + } else { + // Decode wind group + NcUairWindGroup.WindField(codeGroupAr[i + 1], windKnot); + wspeed = NcUairWindGroup.getSped(); + wdir = NcUairWindGroup.getDrct(); + } - if ( ! topwindFlag ) { - // Decode wind group - NcUairWindGroup.WindField(codeGroupAr[i+2], windKnot); - wspeed = NcUairWindGroup.getSped(); - wdir = NcUairWindGroup.getDrct(); - } - - addTrop(record, pres, temp, dewpTemp, wdir, wspeed); - } - } - - /** - * Decodes data for the maximum wind level(s) and wind shear from the TTAA reports. - * The output data are ordered PRES DRCT SPED. - * - * @param codeGroupAr The input uppair code group array - * @param index The input index is the current position of the code group array - * @param cgSize the input cgSize is the size of the codeGroupAr. - * @param windKnot The input windKnot is flag to indicate wind in knot or not. - * @param record The in and out Uair record - * @return - */ - public static void processMaximumWindShear(String[] codeGroupAr, - int index, int cgSize, Boolean windKnot, NcUairRecord record) { - - float pres = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float wdir = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float wspeed = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float loShear = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float hiShear = IDecoderConstantsN.UAIR_FLOAT_MISSING; + // Add level + addLevels(record, pres, height, temp, dewpTemp, wdir, + wspeed); - int i = index; + } + i = i + 2; + } + } + } - String ppIndicator = codeGroupAr[i].substring(0,2); - String hhh = codeGroupAr[i].substring(2,5); + /** + * Decodes a pressure/height and temperature fields for PPAACC. These + * reports contain wind data at mandatory levels below 100 mb. + * + * @param codeGroupAr + * The input uppair code group array + * @param cgSize + * The input cgSize is the size of the code group array + * @param windKnot + * The input windKnot is flag to indicate wind in knot or not. + * @param record + * The in and out Uair record + * @return + */ + public static void processPPAACC(String[] codeGroupAr, int cgSize, + Boolean windKnot, NcUairRecord record) { - if ( ppIndicator.equals("77") || ppIndicator.equals("66")) { - // Decode pressure and height - if ( ! hhh.substring(1,3).equals("//") ) { - pres = Integer.parseInt(hhh); - } - - // Decode wind group - NcUairWindGroup.WindField(codeGroupAr[i+1], windKnot); - wspeed = NcUairWindGroup.getSped(); - wdir = NcUairWindGroup.getDrct(); - - if ( i+2 < cgSize ) { - String windshearIndicator = codeGroupAr[i+2].substring(0,1); - if ( windshearIndicator.equals("4")) { - String below = codeGroupAr[i+2].substring(1,3); - String abov = codeGroupAr[i+2].substring(3,5); - if ( ! below.equals("//")) { - loShear = Integer.parseInt(below); - } - if ( ! abov.equals("//")) { - hiShear = Integer.parseInt(abov); - } - } - } - - NcUairMaxWind mwind = null; - mwind = new NcUairMaxWind(); - mwind.setPres(pres); - mwind.setDrct(wdir); - mwind.setSped(wspeed); - mwind.setLoShear(loShear); - mwind.setHiShear(hiShear); - - record.addMaxWind(mwind); - } - } - - /** - * Decodes data for the lifted index group from the TTAA reports. - * The output data are ordered liTemp, wdirSurface, wspeedSurface, - * wdirAbove, wspeedAbove - * - * @param codeGroupAr The input uppair code group array - * @param index The input index is the current position of the code group array - * @param windKnot The input windKnot is flag to indicate wind in knot or not. - * @param record The in and out Uair record - * @return - */ - public static void processLiftedIndex(String[] codeGroupAr, - int index, Boolean windKnot, NcUairRecord record) { - - float liTemp = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float wdirSurface = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float wspeedSurface = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float wdirAbove = IDecoderConstantsN.UAIR_FLOAT_MISSING; - float wspeedAbove = IDecoderConstantsN.UAIR_FLOAT_MISSING; + Boolean above = false; + Boolean endrpt = false; + float height = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float temp = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float dewpTemp = IDecoderConstantsN.UAIR_FLOAT_MISSING; - int i = index; - if ( codeGroupAr[i].equals("10164") ) { - int ittt = Integer.parseInt(codeGroupAr[i+1]); - if ( ittt > 50 ) { - // subtract 50 if lllll greater than 50 - ittt = ittt - 50; - } - int isign = ittt%2; - /* - * If the integer is even, the liTemp is positive. - * Otherwise, the liTemp is negative. - */ - if ( isign == 1 ) { - liTemp = - ittt; - } else { - liTemp = ittt; - } - liTemp = (float) (liTemp / 10.); - i = i + 2; - } - - if ( codeGroupAr[i].equals("10194") ) { - // Decode wind group from surface to 5000ft - NcUairWindGroup.WindField(codeGroupAr[i+1], windKnot); - wspeedSurface = NcUairWindGroup.getSped(); - wdirSurface = NcUairWindGroup.getDrct(); + float pold; + + String dataType = record.getDataType(); + + if (dataType.substring(2, 4).equals("CC")) { + above = true; + pold = 100; + } else { + pold = 2000; + } + + int i = 0; + while (i < cgSize && !endrpt) { + + if (codeGroupAr[i].equals("51515")) { + endrpt = true; + break; + } + + String ppIndicator = codeGroupAr[i].substring(0, 2); + // Check that first two characters are 44 or 55. + if (ppIndicator.equals("44") || ppIndicator.equals("55")) { + String skip = codeGroupAr[i].substring(2, 5); + if (skip.equals("///")) { + i++; + } else { + // Decode number of pressures which is the third character. + /* chin, fix bug, when a non-number char is decoded */ + int onetothree = 0; + try { + onetothree = Integer.parseInt(codeGroupAr[i].substring( + 2, 3)); + } catch (NumberFormatException e) { + onetothree = 0; + + } + if (onetothree > 0 && onetothree <= 3) { + // Decode the pressure + float[] presArr = { + IDecoderConstantsN.UAIR_FLOAT_MISSING, + IDecoderConstantsN.UAIR_FLOAT_MISSING, + IDecoderConstantsN.UAIR_FLOAT_MISSING, }; + presArr = getPressureFromPPAACC(codeGroupAr[i], above); + + i++; + for (int index = 0; index < onetothree; index++) { + float wdir = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float wspeed = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float pres = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float ppp = presArr[index]; + if (ppp < pold) { + pres = presArr[index]; + pold = ppp; + } + + // Decode wind group + if (i < cgSize) { + NcUairWindGroup.WindField(codeGroupAr[i], + windKnot); + wspeed = NcUairWindGroup.getSped(); + wdir = NcUairWindGroup.getDrct(); + } + + // Add level + addLevels(record, pres, height, temp, dewpTemp, + wdir, wspeed); + + i++; + } + } else { + // no pressure group + i++; + } + } + } else if (ppIndicator.equals("77") || ppIndicator.equals("66")) { + // Decode maximum wind group + String hhh = codeGroupAr[i].substring(2, 5); + if (hhh.equals("999")) { + // NO maximum wind and wind shear data + i++; + } else { + processMaximumWindShear(codeGroupAr, i, cgSize, windKnot, + above, record); + i = i + 3; + } + } else { + i++; + break; + } + } + } + + /** + * Decodes a pressure/height and temperature fields for PPBBDD. These + * reports contain significant wind data above 100 mb. + * + * @param codeGroupAr + * The input uppair code group array + * @param cgSize + * The input cgSize is the size of the code group array + * @param windKnot + * The input windKnot is flag to indicate wind in knot or not. + * @param record + * The in and out Uair record + * @return + */ + public static void processPPBBDD(String[] codeGroupAr, int cgSize, + Boolean windKnot, NcUairRecord record) { + + Boolean endrpt = false; + Boolean pressflag = false; + Boolean above = false; + + String dataType = record.getDataType(); + + if (dataType.substring(2, 4).equals("DD")) { + above = true; + } + + int i = 0; + try { + while (i < cgSize && !endrpt) { + + float pres = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float height = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float temp = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float dewpTemp = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float wdir = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float wspeed = IDecoderConstantsN.UAIR_FLOAT_MISSING; + + if (codeGroupAr[i].equals("21212")) { + pressflag = true; + i++; + if (i >= cgSize) { + break; + } + // System.out.println("got 21212 in PP BBDD - need to process...\n"); + break; + } + + if (codeGroupAr[i].equals("51515") + || codeGroupAr[i].equals("41414")) { + endrpt = true; + // System.out.println("got end group 51515 41414 in PP BBDD - BREAK \n"); + break; + } + + // Convert the unit digits to integers and compute height. + Boolean missing = false; + int noWind = 0; + if (!pressflag) { + while (!missing && (noWind < 3)) { + int index = noWind + 3; + String unit = "/"; + unit = codeGroupAr[i].substring(index - 1, index); + + if (unit.equals(("/"))) { + missing = true; + break; + } + + // Decode height; invalid height if returns + // FLOAT_MISSING. + height = getHeightFromPPBBDD(codeGroupAr[i], index); + if (height == IDecoderConstantsN.UAIR_FLOAT_MISSING) { + i++; + break; + } + int range = i + noWind + 1; + if (range < cgSize) { + // Decode wind group. + NcUairWindGroup.WindField(codeGroupAr[i + noWind + + 1], windKnot); + wspeed = NcUairWindGroup.getSped(); + wdir = NcUairWindGroup.getDrct(); + } + + // Add level + addLevels(record, pres, height, temp, dewpTemp, wdir, + wspeed); + + noWind++; + } + + i = i + noWind + 1; + } else { + int range = i + 1; + if (range < cgSize) { + // Decode pressure group + pres = getPressureFromTTBBDD(codeGroupAr[i], above); + NcUairWindGroup.WindField(codeGroupAr[i + 1], windKnot); + wspeed = NcUairWindGroup.getSped(); + wdir = NcUairWindGroup.getDrct(); + } + i = i + 2; + } + } + } catch (Exception e) { + + } + } + + /** + * Decodes a pressure field for mandatory wind reports (PPAA or PPCC). The + * pressures reporting are returned. + * + * @param presGroup + * The input pressure code group + * @param above + * The input above is flag + * @return pressure + */ + public static float[] getPressureFromPPAACC(String presGroup, Boolean above) { + + float pressure[] = { IDecoderConstantsN.UAIR_FLOAT_MISSING, + IDecoderConstantsN.UAIR_FLOAT_MISSING, + IDecoderConstantsN.UAIR_FLOAT_MISSING }; + + String bpres[] = { "00", "92", "85", "70", "50", "40", "30", "25", + "20", "15", "10" }; + + String apres[] = { "70", "50", "30", "20", "10", "07", "05", "03", + "02", "01" }; + + int rbprs[] = { 1000, 925, 850, 700, 500, 400, 300, 250, 200, 150, 100 }; + + int raprs[] = { 70, 50, 30, 20, 10, 7, 5, 3, 2, 1 }; + + int level = -1; + + String hh = presGroup.substring(3, 5); + // Check first pressure against list. + int ifirst = -1; + if (!above) { + for (String plevel : bpres) { + ifirst++; + if (hh.equals(plevel)) { + level = ifirst; + break; + } + } + } else { + for (String plevel : apres) { + ifirst++; + if (hh.equals(plevel)) { + level = ifirst; + break; + } + } + } + + if (!above) { + if (ifirst < 11 && level >= 0) { + pressure[0] = rbprs[level]; + if (level + 1 < 11) { + pressure[1] = rbprs[level + 1]; + } + if (level + 2 < 11) { + pressure[2] = rbprs[level + 2]; + } + } + } else { + if (ifirst < 10 && level >= 0) { + pressure[0] = raprs[level]; + if (level + 1 < 10) { + pressure[1] = raprs[level + 1]; + } + if (level + 2 < 10) { + pressure[2] = raprs[level + 2]; + } + } + } + + return pressure; + } + + /** + * Decodes the height from a significant wind field from reports (PPBB or + * PPDD). The field is of the form atuuu where a is 1 if the height is above + * 100000 feet and 9 or 8 otherwise. t is the ten-thousands digit of the + * height and the u's are up to three thousands-of-feet fields. The heights + * are converted from feet to meters. + * + * @param heightGroup + * The input heightGroup contains the height code group. + * @param index + * The input index is the current position in the code group. + * @return pressure + */ + public static float getHeightFromPPBBDD(String heightGroup, int index) { + float height = IDecoderConstantsN.UAIR_FLOAT_MISSING; + final double feetToMeter = 0.3048; + + String hhIndicator = heightGroup.substring(0, 1); + int iadd = 0; + // Check that the first character of the field is '9' or '1'. + if (hhIndicator.equals("9") || hhIndicator.equals("8")) { + iadd = 0; + } else { + return height; + } + + // Convert the tens digit to an integer. + int iten; + iten = Integer.parseInt(heightGroup.substring(1, 2)) * 10; + int iunit = Integer.parseInt(heightGroup.substring(index - 1, index)); + height = (iten + iunit) * 1000 + iadd; + height = (float) (height * feetToMeter); + return height; + } + + /** + * Decodes a pressure field from a group reports (TTBB or TTDD). The + * pressures reporting are returned. + * + * @param presGroup + * The input pressure code group + * @param above + * The input above is flag + * @return pressure + */ + public static float getPressureFromTTBBDD(String presGroup, Boolean above) { + + float pressure = IDecoderConstantsN.UAIR_FLOAT_MISSING; + + String clev[] = { "00", "11", "22", "33", "44", "55", "66", "77", "88", + "99" }; + + if (presGroup.length() == 5) { + String pp = presGroup.substring(0, 2); + String hhh = presGroup.substring(2, 5); + + int level = -1; + if (!pp.equals("//") && !hhh.substring(2, 3).equals("/")) { + for (String plevel : clev) { + level++; + if (pp.equals(plevel)) { + break; + } + } + // If a level was found, decode the pressure. + if (level != -1 && level < 10) { + int ihhh = Integer.parseInt(hhh); + if (above) { + pressure = (float) ihhh / (float) 10; + } else { + if (ihhh < 100) { + pressure = ihhh + 1000; + } else { + pressure = ihhh; + } + } + } + } + } + return pressure; + } + + /** + * Decodes data for the tropopause level from the TTAA reports. The output + * data are ordered PRES TEMP DWPT DRCT SPED. + * + * @param codeGroupAr + * The input uppair code group array + * @param index + * The input index is the current position of the code group + * array + * @param topwindFlag + * the input index is the flag to indicate top wind + * @param windKnot + * The input windKnot is flag to indicate wind in knot or not. + * @param record + * The in and out Uair record + * @return + */ + public static void processTropopause(String[] codeGroupAr, int index, + Boolean topwindFlag, Boolean windKnot, NcUairRecord record, + Boolean above) { + + float pres = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float temp = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float dewpTemp = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float wdir = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float wspeed = IDecoderConstantsN.UAIR_FLOAT_MISSING; + + int i = index; + + String pp = codeGroupAr[i].substring(0, 2); + String hhh = codeGroupAr[i].substring(2, 5); + + if (pp.equals("88")) { + // Decode pressure and height + pres = Integer.parseInt(hhh); + if (above) { + pres = pres / 10.f; + } + + // Decode temperature group + NcUairTempGroup.TempField(codeGroupAr[i + 1]); + temp = NcUairTempGroup.getTemperature(); + dewpTemp = NcUairTempGroup.getDewpointTemp(); + + if (!topwindFlag) { + // Decode wind group + NcUairWindGroup.WindField(codeGroupAr[i + 2], windKnot); + wspeed = NcUairWindGroup.getSped(); + wdir = NcUairWindGroup.getDrct(); + } + + addTrop(record, pres, temp, dewpTemp, wdir, wspeed); + } + } + + /** + * Decodes data for the maximum wind level(s) and wind shear from the TTAA + * reports. The output data are ordered PRES DRCT SPED. + * + * @param codeGroupAr + * The input uppair code group array + * @param index + * The input index is the current position of the code group + * array + * @param cgSize + * the input cgSize is the size of the codeGroupAr. + * @param windKnot + * The input windKnot is flag to indicate wind in knot or not. + * @param record + * The in and out Uair record + * @return + */ + public static void processMaximumWindShear(String[] codeGroupAr, int index, + int cgSize, Boolean windKnot, Boolean above, NcUairRecord record) { + + float pres = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float wdir = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float wspeed = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float loShear = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float hiShear = IDecoderConstantsN.UAIR_FLOAT_MISSING; + + int i = index; + + String ppIndicator = codeGroupAr[i].substring(0, 2); + String hhh = codeGroupAr[i].substring(2, 5); + + if (ppIndicator.equals("77") || ppIndicator.equals("66")) { + // Decode pressure and height + if (!hhh.substring(1, 3).equals("//")) { + if (above) { + pres = Integer.parseInt(hhh) / 10.f; + } else { + pres = Integer.parseInt(hhh); + } + } + + // Decode wind group + NcUairWindGroup.WindField(codeGroupAr[i + 1], windKnot); + wspeed = NcUairWindGroup.getSped(); + wdir = NcUairWindGroup.getDrct(); + + if (i + 2 < cgSize) { + String windshearIndicator = codeGroupAr[i + 2].substring(0, 1); + if (windshearIndicator.equals("4")) { + String below = codeGroupAr[i + 2].substring(1, 3); + String abov = codeGroupAr[i + 2].substring(3, 5); + if (!below.equals("//")) { + loShear = Integer.parseInt(below); + } + if (!abov.equals("//")) { + hiShear = Integer.parseInt(abov); + } + } + } + + NcUairMaxWind mwind = null; + mwind = new NcUairMaxWind(); + mwind.setPres(pres); + mwind.setDrct(wdir); + mwind.setSped(wspeed); + mwind.setLoShear(loShear); + mwind.setHiShear(hiShear); + + record.addMaxWind(mwind); + } + } + + /** + * Decodes data for the lifted index group from the TTAA reports. The output + * data are ordered liTemp, wdirSurface, wspeedSurface, wdirAbove, + * wspeedAbove + * + * @param codeGroupAr + * The input uppair code group array + * @param index + * The input index is the current position of the code group + * array + * @param windKnot + * The input windKnot is flag to indicate wind in knot or not. + * @param record + * The in and out Uair record + * @return + */ + public static void processLiftedIndex(String[] codeGroupAr, int index, + Boolean windKnot, NcUairRecord record) { + + float liTemp = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float wdirSurface = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float wspeedSurface = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float wdirAbove = IDecoderConstantsN.UAIR_FLOAT_MISSING; + float wspeedAbove = IDecoderConstantsN.UAIR_FLOAT_MISSING; + + int i = index; + if (codeGroupAr[i].equals("10164")) { + int ittt = Integer.parseInt(codeGroupAr[i + 1]); + if (ittt > 50) { + // subtract 50 if lllll greater than 50 + ittt = ittt - 50; + } + int isign = ittt % 2; + /* + * If the integer is even, the liTemp is positive. Otherwise, the + * liTemp is negative. + */ + if (isign == 1) { + liTemp = -ittt; + } else { + liTemp = ittt; + } + liTemp = (float) (liTemp / 10.); + i = i + 2; + } + + if (codeGroupAr[i].equals("10194")) { + // Decode wind group from surface to 5000ft + NcUairWindGroup.WindField(codeGroupAr[i + 1], windKnot); + wspeedSurface = NcUairWindGroup.getSped(); + wdirSurface = NcUairWindGroup.getDrct(); + + // Decode wind group from 5000ft to 10000ft + NcUairWindGroup.WindField(codeGroupAr[i + 2], windKnot); + wspeedAbove = NcUairWindGroup.getSped(); + wdirAbove = NcUairWindGroup.getDrct(); + + NcUairLiftedIndex li = null; + li = new NcUairLiftedIndex(); + li.setLiTemp(liTemp); + li.setLoDrct(wdirSurface); + li.setLoSped(wspeedSurface); + li.setHiDrct(wdirAbove); + li.setHiSped(wspeedAbove); + record.addLiftedIndex(li); + } + } + + /** + * Compute the top pressure reporting wind data. If topwind is missing, set + * return top wind to a large value so that all the winds will be assumed to + * be missing. + * + * @param topwind + * The input topwind + * @param above + * The input above is flag to indicate above 100mb. + * @return an int for topWind. + */ + public static int getTopWind(int topwind, Boolean above) { + + int retTopWind = 2000; + + if (topwind == IDecoderConstantsN.UAIR_INTEGER_MISSING) { + retTopWind = 2000; + } else if (topwind > 0) { + if (above) { + retTopWind = topwind * 10; + } else { + retTopWind = topwind * 100; + } + } else if (topwind == 0) { + if (!above) { + retTopWind = 1000; + } else { + retTopWind = 0; + } + } else { + retTopWind = 2000; + } + return retTopWind; + } + + /** + * Add levels to record. + * + * @param record + * The in and out Uair record + * @param pres + * The input pressure + * @param hght + * The input geopotential height + * @param temp + * The input temperature + * @param dwpt + * The input dew point temperature. + * @param drct + * The input wind direction + * @param sped + * The input wind speed + * @return + */ + public static void addLevels(NcUairRecord record, float pres, + float geoHeight, float temp, float dwpt, float drct, float sped) { + + NcUairObsLevels level = null; + level = new NcUairObsLevels(); + level.setPres(pres); + level.setHght(geoHeight); + level.setTemp(temp); + level.setDwpt(dwpt); + level.setDrct(drct); + level.setSped(sped); + + record.addObsLevels(level); + } + + /** + * Add tropopause to record. + * + * @param record + * The in and out Uair record + * @param pres + * The input pressure + * @param temp + * The input temperature + * @param dwpt + * The input dew point temperature. + * @param drct + * The input wind direction + * @param sped + * The input wind speed + * @return + */ + public static void addTrop(NcUairRecord record, float pres, float temp, + float dwpt, float drct, float sped) { + + NcUairTropopause trop = null; + trop = new NcUairTropopause(); + trop.setPres(pres); + trop.setTemp(temp); + trop.setDwpt(dwpt); + trop.setDrct(drct); + trop.setSped(sped); + + record.addTropopause(trop); + } - // Decode wind group from 5000ft to 10000ft - NcUairWindGroup.WindField(codeGroupAr[i+2], windKnot); - wspeedAbove = NcUairWindGroup.getSped(); - wdirAbove = NcUairWindGroup.getDrct(); - - NcUairLiftedIndex li = null; - li = new NcUairLiftedIndex(); - li.setLiTemp(liTemp); - li.setLoDrct(wdirSurface); - li.setLoSped(wspeedSurface); - li.setHiDrct(wdirAbove); - li.setHiSped(wspeedAbove); - record.addLiftedIndex(li); - } - } - - /** - * Compute the top pressure reporting wind data. - * If topwind is missing, set return top wind to a large value so that - * all the winds will be assumed to be missing. - * - * @param topwind The input topwind - * @param above The input above is flag to indicate above 100mb. - * @return an int for topWind. - */ - public static int getTopWind(int topwind, Boolean above) { - - int retTopWind = 2000; - - if ( topwind == IDecoderConstantsN.UAIR_INTEGER_MISSING ) { - retTopWind = 2000; - } else if ( topwind > 0 ) { - if ( above ) { - retTopWind = topwind * 10; - } else { - retTopWind = topwind * 100; - } - } else if ( topwind == 0 ) { - if ( ! above ) { - retTopWind = 1000; - } else { - retTopWind = 0; - } - } else { - retTopWind = 2000; - } - return retTopWind; - } - - /** - * Add levels to record. - * - * @param record The in and out Uair record - * @param pres The input pressure - * @param hght The input geopotential height - * @param temp The input temperature - * @param dwpt The input dew point temperature. - * @param drct The input wind direction - * @param sped The input wind speed - * @return - */ - public static void addLevels(NcUairRecord record, float pres, float geoHeight, - float temp, float dwpt, float drct, float sped) { - - NcUairObsLevels level = null; - level = new NcUairObsLevels(); - level.setPres(pres); - level.setHght(geoHeight); - level.setTemp(temp); - level.setDwpt(dwpt); - level.setDrct(drct); - level.setSped(sped); - - record.addObsLevels(level); - } - - /** - * Add tropopause to record. - * - * @param record The in and out Uair record - * @param pres The input pressure - * @param temp The input temperature - * @param dwpt The input dew point temperature. - * @param drct The input wind direction - * @param sped The input wind speed - * @return - */ - public static void addTrop(NcUairRecord record, float pres, - float temp, float dwpt, float drct, float sped) { - - NcUairTropopause trop = null; - trop = new NcUairTropopause(); - trop.setPres(pres); - trop.setTemp(temp); - trop.setDwpt(dwpt); - trop.setDrct(drct); - trop.setSped(sped); - - record.addTropopause(trop); - } - } diff --git a/ncep/gov.noaa.nws.ncep.edex.plugin.ntrans/res/spring/ntrans-ingest.xml b/ncep/gov.noaa.nws.ncep.edex.plugin.ntrans/res/spring/ntrans-ingest.xml index 3be95f7491..b5f934cf88 100644 --- a/ncep/gov.noaa.nws.ncep.edex.plugin.ntrans/res/spring/ntrans-ingest.xml +++ b/ncep/gov.noaa.nws.ncep.edex.plugin.ntrans/res/spring/ntrans-ingest.xml @@ -13,7 +13,7 @@ - + + ^NTRANS.* diff --git a/ncep/gov.noaa.nws.ncep.edex.plugin.solarimage/utility/edex_static/base/distribution/solarimage.xml b/ncep/gov.noaa.nws.ncep.edex.plugin.solarimage/utility/edex_static/base/distribution/solarimage.xml index ed85754402..cdba2b0bcb 100644 --- a/ncep/gov.noaa.nws.ncep.edex.plugin.solarimage/utility/edex_static/base/distribution/solarimage.xml +++ b/ncep/gov.noaa.nws.ncep.edex.plugin.solarimage/utility/edex_static/base/distribution/solarimage.xml @@ -1,4 +1,4 @@ - ^SXI_* + ^SIMPLE* diff --git a/ncep/gov.noaa.nws.ncep.edex.uengine/gemglb.nts b/ncep/gov.noaa.nws.ncep.edex.uengine/gemglb.nts deleted file mode 100644 index 6ae69f473a..0000000000 --- a/ncep/gov.noaa.nws.ncep.edex.uengine/gemglb.nts +++ /dev/null @@ -1,191 +0,0 @@ -ADDSTN YES -AFOSFL -AIRM -ANOTLN -ANOTYP -AWPSFL -ANLYSS 4/2;2;2;2 -AREA @dca;iad;bwi -ATCF -BORDER 1 -BOXLIN -BUFRFIL -CENTER -CINT 0 -CLEAR YES -CLRBAR -CNTRFL -COLORS 1 -COLUMN 1 -CONTUR 0 -CPYFIL -CSIG -CTLFLG YES -CTYPE C -CURVE 2 -CXSTNS -DATTIM 18-20 -DELTAN -DELTAX -DELTAY -DEVICE XW -DTAAREA -EDGEOPTS -ENCY -EXTEND 2;2;2;2 -FHOUR -FILTER YES -FINT 0 -FLINE 10-20 -FXYTBL -GAMMA 0.3 -GAREA WV -IJSKIP -GBDIAG -GBFILE -GBTBLS -GDATTIM LAST -GDEFIL GDLIST.FIL -GDFILE $GEMDATA/HRCBOB.GRD -GDNUM LIST -GDOUTF -GDPFUN TMPC -GFUNC TMPC -GGLIMS -GGVGF -GLEVEL 500 -GPACK -GPOINT IAD -GRDAREA -GRDHDR -GRDLBL 0 -GRDNAM -GRDTYP S -GSKIP -GUESS -GUESFUN -GVCORD PRES -GVECT WND -G2DIAG -G2DRT -G2IDS -G2IS -G2PDT -G2TBLS -HILO -HISTGRD NO -HLSYM -HRCN -IDNTYP STID -IMCBAR -INDXFL -INFO -ISIG -KXKY 10;10 -LAT -LATLON -LEVELS 500 -LINE 3 -LOCI -LON -LSTALL YES -LSTPRM -LTNG -LUTFIL -MAP 1 -$MAPFIL HIPOWO.CIA -MARKER 0 -MAXGRD 200 -MIXRLN 0 -MSCALE 0 -MRGDAT YES -NCON -NPASS 2 -NTRACE 5 -OUTFIL -OUTPUT t -OVERWR NO -PANEL 0 -PDSEXT NO -PIXRES 1 -PLUS -POSN 0 -PRBTYP -PROJ MER -PTYPE LOG -QCNTL -QSCT -RADFIL -REGION VIEW -REFVEC -$RESPONDYES -SATFIL -FAXFIL -SAVFIL -SCALE 999 -SEARCH 20 -SFEFIL SFLIST.FIL -SFFILE /export-2/cdbbkp/ldmcdb/data/decoders/hrly/20110530.hrly -SFFSRC -SFOUTF -SFPARM dset -SFPRMF METAR.PACK -SHAPE -SHIPFL NO -SHRTTL -SKIP 0 -SKPMIS y -SNBUFR -SNEFIL SNLIST.FIL -SNFILE $GEMDATA/HRCBOB.SND -SNOUTF -SNPARM ;TMPC;;HGHT;DWPC;BRBM -SNPRMF SNMERG.PACK -SOURCE SF -STATION BWI -STNCOL 1 -STNDEX SHOW -STNFIL SFSTNS.TBL -STNPLT -STNTYP A -STREAM -STRMID -SVRL -TAXIS -TCMG -TEXT 1 -THTALN 0 -THTELN 0 -TIMSTN 1/0 -TITLE 1 -TRACE1 TMPF;DWPF:3/2;3 -TRACE2 PMSL/4 -TRACE3 SKNT;GUST;DARR/1 -TRACE4 VSBY/7 -TRACE5 CLDS;;WSYM/6 -TRAK1 -TRAK2 -TRAKE -TXTCOL -TXTFIL -TXTLOC -TXTYPE -TYPE C -UKAFIL -VCOORD PRES -VGFILE -WARN -WATCH -WIND BM1 -WINPOS 1 -WSTM -XAXIS -YAXIS -WOU -WCN -WCP -WSAT -FHR -TAG -STAT -ASCT diff --git a/ncep/gov.noaa.nws.ncep.edex.uengine/last.nts b/ncep/gov.noaa.nws.ncep.edex.uengine/last.nts deleted file mode 100644 index 6b9be5e181..0000000000 --- a/ncep/gov.noaa.nws.ncep.edex.uengine/last.nts +++ /dev/null @@ -1,7 +0,0 @@ -SFFILE /export-2/cdbbkp/ldmcdb/data/decoders/hrly/20110530.hrly -AREA @dca;iad;bwi -DATTIM 18-20 -OUTPUT t -SKPMIS y -IDNTYP STID -SFPARM dset diff --git a/ncep/gov.noaa.nws.ncep.gempak.parameters/src/gov/noaa/nws/ncep/gempak/parameters/infill/FINT.java b/ncep/gov.noaa.nws.ncep.gempak.parameters/src/gov/noaa/nws/ncep/gempak/parameters/infill/FINT.java index a5a1a332be..7220e69ff3 100644 --- a/ncep/gov.noaa.nws.ncep.gempak.parameters/src/gov/noaa/nws/ncep/gempak/parameters/infill/FINT.java +++ b/ncep/gov.noaa.nws.ncep.gempak.parameters/src/gov/noaa/nws/ncep/gempak/parameters/infill/FINT.java @@ -259,6 +259,9 @@ public class FINT { public static List parseFINT(String fint, int zoomLevelIndex, float minValue, float maxValue) { + if (fint.equals("0")) + fint = ""; + List fvalues = null; Double fmin = new Double(minValue); Double fmax = new Double(maxValue); diff --git a/ncep/gov.noaa.nws.ncep.gempak.parameters/src/gov/noaa/nws/ncep/gempak/parameters/infill/FLine.java b/ncep/gov.noaa.nws.ncep.gempak.parameters/src/gov/noaa/nws/ncep/gempak/parameters/infill/FLine.java index 994b67861f..9832f69c05 100644 --- a/ncep/gov.noaa.nws.ncep.gempak.parameters/src/gov/noaa/nws/ncep/gempak/parameters/infill/FLine.java +++ b/ncep/gov.noaa.nws.ncep.gempak.parameters/src/gov/noaa/nws/ncep/gempak/parameters/infill/FLine.java @@ -5,19 +5,20 @@ import gov.noaa.nws.ncep.gempak.parameters.core.util.StringUtil; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; + /** *
  * SOFTWARE HISTORY
  * Date          Ticket#     Engineer     Description
  * ------------ ---------- ----------- --------------------------
  * 04-Nov-2009    185        Archana.S   Initial Creation
-*  07-Jun-2010    185        Archana.S   Updated the method call to 
-*                                        the private method removeBlanksWithinString()
-*                                        to use the static method from the StringUtilities
-*                                        class and deleted the private method
-*                                        removeBlanksWithinString() from this class.
-*                                        Renamed the package as
-*                                        gov.noaa.nws.ncep.gempak.parameters.infill    
+ *  07-Jun-2010    185        Archana.S   Updated the method call to 
+ *                                        the private method removeBlanksWithinString()
+ *                                        to use the static method from the StringUtilities
+ *                                        class and deleted the private method
+ *                                        removeBlanksWithinString() from this class.
+ *                                        Renamed the package as
+ *                                        gov.noaa.nws.ncep.gempak.parameters.infill    
  * 
* @author Archana.S * @version 1 @@ -30,580 +31,671 @@ import java.util.regex.Pattern; * a list of Color objects instead of integers. */ /** - * FLine supplies the color and pattern information for filling a contour. - * A string containing the color and/or pattern information is entered as an input - * to the constructor. - * The input can be given in either one of the formats listed below:

- * color1;color2;...;colorn/type1;...typen

- * color1-colorn

- * (Note: The second format is used to generate a list of colors from color1 to colorn).

- * The status of the parse operation can be tested using the method isFLineStringParsed(). - * The colors are stored as a list of Integers and can be retrieved using the method - * getFillColorList(). - * The patterns are also stored as a list of Integers and can be retrieved using the method - * getFillTypeList(). + * FLine supplies the color and pattern information for filling a + * contour. A string containing the color and/or pattern information is entered + * as an input to the constructor. The input can be given in either one of the + * formats listed below: + *

+ * color1;color2;...;colorn/type1;...typen + *

+ * color1-colorn + *

+ * (Note: The second format is used to generate a list of colors from color1 to + * colorn). + *

+ * The status of the parse operation can be tested using the method + * isFLineStringParsed(). The colors are stored as a list of + * Integers and can be retrieved using the method + * getFillColorList(). The patterns are also stored as a list of + * Integers and can be retrieved using the method getFillTypeList(). */ public class FLine { - - /**A boolean flag to indicate if the input string was parsed*/ - private boolean isFLineStringParsed; - - /**The input string that contains the color and pattern information for filling the contour*/ - private String fLineString; - - /**The Error Message*/ - private String errorMessage; - - /**The starting value for the color range*/ - private Integer startColorRange; - - /**The ending value for the color range*/ - private Integer endColorRange; - - /**The list of integers representing the parsed color values*/ - private List fillColorList; - /**The list of integers representing the parsed color values*/ - private List fillTypeList; - - /**The default color*/ - private Integer defaultFillColor; - - /**The default fill pattern*/ - private Integer defaultFillType; - - /**A regular expression to represent repeating groups in a list of color/pattern values*/ - private String LIST_OF_INTEGERS = "(-?;?\\d;*)*"; - - - /**The default constructor generates 2 lists: - * The list of fill colors contains 1 element set to 0, to indicate no color.

- * Currently, the color list is a list of integers. - */ - - public FLine(){ - setIsFLineStringParsed(false); - fillColorList = new ArrayList(); - fillTypeList = new ArrayList(); - defaultFillColor = 1; /*Default fill color is no color*/ - defaultFillType = 1; /*Default fill pattern is set to solid */ + /** A boolean flag to indicate if the input string was parsed */ + private boolean isFLineStringParsed; + + /** + * The input string that contains the color and pattern information for + * filling the contour + */ + private String fLineString; + + /** The Error Message */ + private String errorMessage; + + /** The starting value for the color range */ + private Integer startColorRange; + + /** The ending value for the color range */ + private Integer endColorRange; + + /** The list of integers representing the parsed color values */ + private List fillColorList; + + /** The list of integers representing the parsed color values */ + private List fillTypeList; + + /** The default color */ + private Integer defaultFillColor; + + /** The default fill pattern */ + private Integer defaultFillType; + + /** + * A regular expression to represent repeating groups in a list of + * color/pattern values + */ + private String LIST_OF_INTEGERS = "(-?;?\\d;*)*"; + + /** + * The default constructor generates 2 lists: The list of fill colors + * contains 1 element set to 0, to indicate no color. + *

+ * Currently, the color list is a list of integers. + */ + + public FLine() { + setIsFLineStringParsed(false); + fillColorList = new ArrayList(); + fillTypeList = new ArrayList(); + defaultFillColor = 1; /* Default fill color is no color */ + defaultFillType = 1; /* Default fill pattern is set to solid */ fillTypeList.add(defaultFillType); - fillColorList.add(defaultFillColor); - setStartColorRange(defaultFillColor); - setEndColorRange(defaultFillColor); - - - } - - /** - * @param String fLineStringInput - *

- * The input string containing the color and/or pattern information - * is parsed when the constructor invokes the private method - * parseFLineString(). - */ - - public FLine(String fLineStringInput){ - - // process '-' - String newFline = null; - String[] tmpstr = fLineStringInput.trim().split(";"); - for (int i = 0; i < tmpstr.length; i++) { - if (tmpstr[i].contains("-")) { - String[] twoends = tmpstr[i].split("-", 2); - int start = Integer.parseInt(twoends[0]); - int end = Integer.parseInt(twoends[1]); - String newstr = twoends[0] + ";"; - - if (start < end) { - for (int j = start + 1; j <= end; j++) { - newstr = newstr.concat(String.valueOf(j)); - if (j != end) newstr = newstr + ";"; - } - } else { - for (int j = start - 1; j >= end; j--) { - newstr = newstr.concat(String.valueOf(j)); - if (j != end) newstr = newstr + ";"; - } - } - - tmpstr[i] = newstr; - } - - if ( i == 0 ) - newFline = tmpstr[i]; - else - newFline = newFline.concat(tmpstr[i]); - - if ( i != (tmpstr.length - 1) ) newFline = newFline + ";"; - } - fLineStringInput = newFline; - - - - /*Set default values and initialize instance variables*/ - - setIsFLineStringParsed(false); - - fillColorList = new ArrayList(); - fillTypeList = new ArrayList(); - - /*The actual color represented by the integer 1,is based on user input*/ - defaultFillColor = 1; - - /*Default fill pattern is set to solid */ - defaultFillType = 1; - + fillColorList.add(defaultFillColor); setStartColorRange(defaultFillColor); - setEndColorRange(defaultFillColor); - - /* - * If the input string is not empty or null, the method parseFLineString() - * is invoked to parse it. - * The boolean value returned by this method is used to set the boolean - * state variable isFLineStringParsed. - */ - if(((fLineStringInput != null)) && (!fLineStringInput.trim().isEmpty())){ + setEndColorRange(defaultFillColor); - this.setFLineString(fLineStringInput); - if(fLineStringInput.contains(" ")){ - String inputStringWithoutBlanks = StringUtil.removeBlanksWithinString(fLineStringInput); - setIsFLineStringParsed(this.parseFLineString(inputStringWithoutBlanks)); - }else{ - setIsFLineStringParsed(this.parseFLineString(fLineStringInput)); - } + } - /*If both the colors and the patterns have been parsed, update the list of - *patterns to matcht the number of colors*/ - if(this.getFillTypeList().size() > 0 && this.getFillColorList().size() > 0){ - this.setMissingAttributes(this.getFillColorList(),this.getFillTypeList()); - } - /*Else, if only the colors were entered as input and parsed, set the default pattern to - *SOLID (i.e the Integer 1) and repeat it to match the number of colors*/ - else if(this.getFillTypeList().size() == 0 && this.getFillColorList().size() > 0){ - this.getFillTypeList().add(defaultFillType); - this.setMissingAttributes(this.getFillColorList(),this.getFillTypeList()); - } - }else{ - /* - * If the input string is empty or null, then the color list is created with - * a single element - the default color (integer object set to 1) - */ + /** + * @param String + * fLineStringInput + *

+ * The input string containing the color and/or pattern + * information is parsed when the constructor invokes the private + * method parseFLineString(). + */ - fillColorList.add(defaultFillColor); - /* - *Set the default pattern variable to SOLID and add it to the list of patterns - **/ - - fillTypeList.add(defaultFillType); - + public FLine(String fLineStringInput) { - } - } - /** - * @return String fLineString - */ - public String getFLineString() { - return fLineString; - } - - /** - * @return String errorMessage - */ - public String getErrorMessage() { - return errorMessage; - } - - /** - * @return List (of Integer) fillColorList - */ - public List getFillColorList() { - return fillColorList; - } -/** - * - * @return List of Integer fillTypeList - */ - public List getFillTypeList() { - return fillTypeList; - } - - - /** - * @return Integer startColorRange - */ - - public Integer getStartColorRange() { - return startColorRange; - } - - /** - * @return Integer endColorRange - */ - public Integer getEndColorRange() { - return endColorRange; - } - /** - * @param boolean isFLineStringParsed - */ - public void setIsFLineStringParsed(boolean isFLineStringParsed) { - this.isFLineStringParsed = isFLineStringParsed; - } - /** - * @return boolean isFLineStringParsed - */ - public boolean isFLineStringParsed() { - return isFLineStringParsed; - } - - /** - * @param String lineString - */ - private void setFLineString(String lineString) { - fLineString = lineString; - } - - /** - * @param String errorMessage - */ - private void setErrorMessage(String errorMessage) { - this.errorMessage = errorMessage; - } - /** - * @param List (of Integer) lineColorList - */ - private void setFillColorList(List lineColorList) { - fillColorList = lineColorList; - } - /** - * @param List of Integer fillPatternsList - */ - private void setFillTypeList(List fillPatternsList) { - fillTypeList = fillPatternsList; - } - /** - * @param Integer startColorRange - */ - private void setStartColorRange(Integer startColorRange) { - this.startColorRange = startColorRange; - } - /** - * @param Integer endColorRange - */ - private void setEndColorRange(Integer endColorRange) { - this.endColorRange = endColorRange; - } - /** - * - * @param String fLineStringInput - * @return boolean isFLineStringParsedCorrectly - */ - private boolean parseFLineString(String fLineStringInput){ - boolean isFLineStringParsedCorrectly = false; - boolean isColorToken = false; - String[] fLineTokens; - - /*It is checked if both the colors and the patterns are entered*/ - if(fLineStringInput.contains("/")){ - - /*If yes, then the colors and patterns are parsed into tokens using the delimiter character "/" */ - fLineTokens = fLineStringInput.split("/"); - - /*If the token contains only 1 element, it is checked if a list of colors have been - * entered*/ - if(fLineTokens.length >= 1) { - - /*If the token matches the regular expression for a list of integers - *it is construed to be a list of color values. - *The integer values for the colors are then extracted and stored in the list of colors.*/ - - if(Pattern.matches(LIST_OF_INTEGERS,fLineTokens[0])){ - isColorToken = true; - isFLineStringParsedCorrectly = this.parseColorOrPatternTokens(fLineTokens[0], isColorToken); - } - } - /*If the token contains two elements, the second element is - * processed as the list of patterns - **/ - isColorToken = false; - if(fLineTokens.length == 2){ - if(Pattern.matches(LIST_OF_INTEGERS,fLineTokens[1])){ - isFLineStringParsedCorrectly = this.parseColorOrPatternTokens - (fLineTokens[1], isColorToken); - } - } - } - /* - * Else it is checked if a range of colors have been entered. - * If so, the method parseRangeOfColors() is invoked to process - * the string tokens generated by splitting the input - * string into tokens using the character '-' as a delimiter. - */ - else if(fLineStringInput.contains("-")){ - fLineTokens = fLineStringInput.split("-"); - isFLineStringParsedCorrectly = this.parseRangeOfColors(fLineTokens); - } - else{ - /*It is checked if only a list of color values (colr1;..;colrn) have been entered. - *If so, then the method parseColorOrPatternTokens() is invoked to - *process the color tokens generated by splitting the input string using - *the '-' character as a delimiter.s - * */ - if(Pattern.matches(LIST_OF_INTEGERS,fLineStringInput.trim())){ - isColorToken = true; - - isFLineStringParsedCorrectly = this.parseColorOrPatternTokens - (fLineStringInput, isColorToken); - } - } - return isFLineStringParsedCorrectly; - } -/** - *@param String inputToken - *@param boolean isColorToken - *@return boolean isTokenParsed - *

- *The method parseColorOrPatternTokens() can be used to process the string tokens - *containing either the list of colors or the list of patterns. - *It returns true if the parse operation was successful. - */ - private boolean parseColorOrPatternTokens(String inputToken, boolean isColorToken){ - boolean isTokenParsed = false; - boolean multipleTokensFound = false; - String[] tokenStringArray; - List integerTokenList = new ArrayList(); - /* - * If the input string contains a ';', it is split using this character - * as a delimiter. - */ - if(inputToken.contains(";")){ - tokenStringArray = inputToken.split(";"); - /* - * If more than one token is generated as a result of the split operation - * a boolean flag multipleTokensFound is set to true. - */ - if(tokenStringArray.length > 1){ - multipleTokensFound = true; - }else{ - /* - * Else it is assumed that a single token containing a single integer - * was generated. - */ - try{ - /* - * An attempt is made to extract the integer from the string and - * store it. - */ - integerTokenList.add(Integer.parseInt(tokenStringArray[0])); - isTokenParsed = true; - /* - * If the input boolean isColorToken is set to true, then the - * extracted integer is stored in the color list. - */ - if(isColorToken){ - //TODO: check the single Integer in the list for valid color values? - this.setFillColorList(integerTokenList); - } - else{ - this.setFillTypeList(integerTokenList); - } - }catch(Exception e){ - integerTokenList.add(0);/*A blank input string token represents no color or no pattern */ - this.setErrorMessage("INVALID STRING FORMAT"); - } - } - /* - * If several tokens are generated, then using a for-loop,, - * an attempt is made to extract an integer from each string token. - * If it is successful, then integers are added one by one to a list of integers. - */ - if(multipleTokensFound){ - for(int currentIndex=0;currentIndex < tokenStringArray.length; currentIndex++){ - try{ - integerTokenList.add(Integer.parseInt(tokenStringArray[currentIndex])); - isTokenParsed = true; - }catch(Exception e){ - integerTokenList.add(0); - this.setErrorMessage("INVALID STRING FORMAT"); - } - } - - } - - /*If it is a color token, the list of integers extracted is stored as a list of colors. - **/ - if(isColorToken){ - //TODO: check each Integer in the list for valid color values? - this.setFillColorList(integerTokenList); - } - else{ - //TODO - /*It is a list of patterns - - *check if each integer in the list belongs to one of the valid pattern - *values and if so, add it to the list of patterns. - * */ - this.setFillTypeList(integerTokenList); - } - } - /* - * Else, if the input string token does not contain the ';' delimiter, - * it is assumed that it contains a single integer and an attempt is made to - * extract this integer. - * Of the attempt is successful, then the integer is stored as a single member - * of the list of colors. - */ - else{ - try{ - integerTokenList.add(Integer.parseInt(inputToken)); - isTokenParsed = true; - - if(isColorToken){ - //TODO: check the single Integer for valid color values? - this.setFillColorList(integerTokenList); - } - else{ - this.setFillTypeList(integerTokenList); - } - }catch(NumberFormatException e){ - this.setErrorMessage("INVALID STRING FORMAT"); - } - } - return isTokenParsed; - } - - /** - * @param String[] colorRangeStringTokens - * @return boolean isColorRangeStringParsed - *

- * The method parseRangeOfColors accepts as input a string array containing - * two tokens - the starting and ending values of the color range, in that order. - * If the two integer values are successfully parsed from the string tokens, - * the method generateColorRange() is invoked to populate the list with - * all the color values in the range. - */ - private boolean parseRangeOfColors(String[] colorRangeStringTokens){ - - boolean isColorRangeStringParsed = false; - Integer colorValue = 0; - for(int currentIndex=0;currentIndex <= 1;currentIndex ++){ - - try{ - colorValue = Integer.parseInt(colorRangeStringTokens[currentIndex]); - if(currentIndex == 0){ - /*TODO: Check if colorValue lies in the permissible range - *for color values - */ - this.setStartColorRange(colorValue); - } else { - this.setEndColorRange(colorValue); - } - isColorRangeStringParsed = true; - }catch(Exception e){ - this.setErrorMessage("INVALID STRING FORMAT"); - } - - } - - if(isColorRangeStringParsed){ - this.generateColorRange(this.getStartColorRange(), - this.getEndColorRange()); - } - return isColorRangeStringParsed; - } - - /** - * @param Integer startColorValue - * @param Integer endColorValue - * The method generateColorRange() accepts as input, two integers that represent - * the starting and ending values of the color range. - * A loop is used to generate every integer (representing a color value) in between the range. - */ - private void generateColorRange(Integer startColorValue, Integer endColorValue){ - int currentIndex = 0; - - /*If the starting and ending color values in the range are equal - *only a single element - the starting color value of the range is added to the list. - **/ - if(startColorValue == endColorValue){ - this.getFillColorList().add(startColorValue); - } - /*Else if the starting color value in the range is less than ending color value, - *a loop is used to generate all the intermediate color values from the starting value - *to the ending value by incrementing the loop counter - */ - else if(startColorValue < endColorValue){ - for(currentIndex = startColorValue; currentIndex <= endColorValue; currentIndex++){ - this.getFillColorList().add(currentIndex); - } - } - /*Else if the starting color value in the range is greater than ending color value, - *a loop is used to generate all the intermediate color values from the starting value - *to the ending value by decrementing the loop counter - */ - else{ - for(currentIndex = startColorValue;currentIndex >= endColorValue; currentIndex--){ - this.getFillColorList().add(currentIndex); - } - } - } - - /** - * The method setMissingAttributeschecks if the list of the list of patterns is - * less than that of the colors. If so, it invokes the method setMissingPatterns - * to repeat the patterns in the list till both the lists have the same number of elements - * @param List of Integer - colorsList - * @param List of Integer - patternsList - */ - private void setMissingAttributes(List colorsList,List patternsList){ - int colorsListSize = colorsList.size(); - int patternsListSize = patternsList.size(); - int numElementsToAdd = 0; - - - if(patternsListSize < colorsListSize){ - numElementsToAdd = colorsListSize - patternsListSize; - this.setMissingPatterns(patternsList,numElementsToAdd); + // if the input string contains "-" as well as "/", ignore the fill type + // list after "/" + // e.g.: 0;20-32/1;2;3 => parse 0-20-32 and ignore the rest + String[] fLineTmpstr = { fLineStringInput }; + if (fLineStringInput.trim().contains("-") + && fLineStringInput.trim().contains("/")) { + fLineTmpstr = fLineStringInput.trim().split("/"); + fLineStringInput = fLineTmpstr[0]; } - } - /** - *The method setMissingPatterns uses the input integer numElementsToAdd - *to decide how many elements to add, so as to repeat the patterns in the input list of patterns. - * @param List of Integer - patternsList - * @param int numElementsToAdd - */ - private void setMissingPatterns(List patternsList,int numElementsToAdd){ - int currentIndex = 0; - int count = 1; - while(count <= numElementsToAdd){ - patternsList.add(patternsList.get(currentIndex)); - currentIndex++; - count++; - } - this.setFillTypeList(patternsList); - } - + // process '-' + String newFline = null; + String[] tmpstr = fLineStringInput.trim().split(";"); + for (int i = 0; i < tmpstr.length; i++) { + if (tmpstr[i].contains("-")) { + String[] twoends = tmpstr[i].split("-", 2); + int start = Integer.parseInt(twoends[0]); + int end = Integer.parseInt(twoends[1]); + String newstr = twoends[0] + ";"; + + if (start < end) { + for (int j = start + 1; j <= end; j++) { + newstr = newstr.concat(String.valueOf(j)); + if (j != end) + newstr = newstr + ";"; + } + } else { + for (int j = start - 1; j >= end; j--) { + newstr = newstr.concat(String.valueOf(j)); + if (j != end) + newstr = newstr + ";"; + } + } + + tmpstr[i] = newstr; + } + + if (i == 0) + newFline = tmpstr[i]; + else + newFline = newFline.concat(tmpstr[i]); + + if (i != (tmpstr.length - 1)) + newFline = newFline + ";"; + } + fLineStringInput = newFline; + + /* Set default values and initialize instance variables */ + + setIsFLineStringParsed(false); + + fillColorList = new ArrayList(); + fillTypeList = new ArrayList(); + + /* The actual color represented by the integer 1,is based on user input */ + defaultFillColor = 1; + + /* Default fill pattern is set to solid */ + defaultFillType = 1; + + setStartColorRange(defaultFillColor); + setEndColorRange(defaultFillColor); + + /* + * If the input string is not empty or null, the method + * parseFLineString() is invoked to parse it. The boolean value returned + * by this method is used to set the boolean state variable + * isFLineStringParsed. + */ + if (((fLineStringInput != null)) + && (!fLineStringInput.trim().isEmpty())) { + + this.setFLineString(fLineStringInput); + if (fLineStringInput.contains(" ")) { + String inputStringWithoutBlanks = StringUtil + .removeBlanksWithinString(fLineStringInput); + setIsFLineStringParsed(this + .parseFLineString(inputStringWithoutBlanks)); + } else { + setIsFLineStringParsed(this.parseFLineString(fLineStringInput)); + } + + /* + * If both the colors and the patterns have been parsed, update the + * list ofpatterns to matcht the number of colors + */ + if (this.getFillTypeList().size() > 0 + && this.getFillColorList().size() > 0) { + this.setMissingAttributes(this.getFillColorList(), + this.getFillTypeList()); + } + /* + * Else, if only the colors were entered as input and parsed, set + * the default pattern toSOLID (i.e the Integer 1) and repeat it to + * match the number of colors + */ + else if (this.getFillTypeList().size() == 0 + && this.getFillColorList().size() > 0) { + this.getFillTypeList().add(defaultFillType); + this.setMissingAttributes(this.getFillColorList(), + this.getFillTypeList()); + } + } else { + /* + * If the input string is empty or null, then the color list is + * created with a single element - the default color (integer object + * set to 1) + */ + + fillColorList.add(defaultFillColor); + /* + * Set the default pattern variable to SOLID and add it to the list + * of patterns + */ + + fillTypeList.add(defaultFillType); + + } + } + + /** + * @return String fLineString + */ + public String getFLineString() { + return fLineString; + } + + /** + * @return String errorMessage + */ + public String getErrorMessage() { + return errorMessage; + } + + /** + * @return List (of Integer) fillColorList + */ + public List getFillColorList() { + return fillColorList; + } + + /** + * + * @return List of Integer fillTypeList + */ + public List getFillTypeList() { + return fillTypeList; + } + + /** + * @return Integer startColorRange + */ + + public Integer getStartColorRange() { + return startColorRange; + } + + /** + * @return Integer endColorRange + */ + public Integer getEndColorRange() { + return endColorRange; + } + + /** + * @param boolean isFLineStringParsed + */ + public void setIsFLineStringParsed(boolean isFLineStringParsed) { + this.isFLineStringParsed = isFLineStringParsed; + } + + /** + * @return boolean isFLineStringParsed + */ + public boolean isFLineStringParsed() { + return isFLineStringParsed; + } + + /** + * @param String + * lineString + */ + private void setFLineString(String lineString) { + fLineString = lineString; + } + + /** + * @param String + * errorMessage + */ + private void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + /** + * @param List + * (of Integer) lineColorList + */ + private void setFillColorList(List lineColorList) { + fillColorList = lineColorList; + } + + /** + * @param List + * of Integer fillPatternsList + */ + private void setFillTypeList(List fillPatternsList) { + fillTypeList = fillPatternsList; + } + + /** + * @param Integer + * startColorRange + */ + private void setStartColorRange(Integer startColorRange) { + this.startColorRange = startColorRange; + } + + /** + * @param Integer + * endColorRange + */ + private void setEndColorRange(Integer endColorRange) { + this.endColorRange = endColorRange; + } + + /** + * + * @param String + * fLineStringInput + * @return boolean isFLineStringParsedCorrectly + */ + private boolean parseFLineString(String fLineStringInput) { + boolean isFLineStringParsedCorrectly = false; + boolean isColorToken = false; + String[] fLineTokens; + + /* It is checked if both the colors and the patterns are entered */ + if (fLineStringInput.contains("/")) { + + /* + * If yes, then the colors and patterns are parsed into tokens using + * the delimiter character "/" + */ + fLineTokens = fLineStringInput.split("/"); + + /* + * If the token contains only 1 element, it is checked if a list of + * colors have been entered + */ + if (fLineTokens.length >= 1) { + + /* + * If the token matches the regular expression for a list of + * integersit is construed to be a list of color values.The + * integer values for the colors are then extracted and stored + * in the list of colors. + */ + + if (Pattern.matches(LIST_OF_INTEGERS, fLineTokens[0])) { + isColorToken = true; + isFLineStringParsedCorrectly = this + .parseColorOrPatternTokens(fLineTokens[0], + isColorToken); + } + } + /* + * If the token contains two elements, the second element is + * processed as the list of patterns + */ + isColorToken = false; + if (fLineTokens.length == 2) { + if (Pattern.matches(LIST_OF_INTEGERS, fLineTokens[1])) { + isFLineStringParsedCorrectly = this + .parseColorOrPatternTokens(fLineTokens[1], + isColorToken); + } + } + } + /* + * Else it is checked if a range of colors have been entered. If so, the + * method parseRangeOfColors() is invoked to process the string tokens + * generated by splitting the input string into tokens using the + * character '-' as a delimiter. + */ + else if (fLineStringInput.contains("-")) { + fLineTokens = fLineStringInput.split("-"); + isFLineStringParsedCorrectly = this.parseRangeOfColors(fLineTokens); + } else { + /* + * It is checked if only a list of color values (colr1;..;colrn) + * have been entered.If so, then the method + * parseColorOrPatternTokens() is invoked toprocess the color tokens + * generated by splitting the input string usingthe '-' character as + * a delimiter.s + */ + if (Pattern.matches(LIST_OF_INTEGERS, fLineStringInput.trim())) { + isColorToken = true; + + isFLineStringParsedCorrectly = this.parseColorOrPatternTokens( + fLineStringInput, isColorToken); + } + } + return isFLineStringParsedCorrectly; + } + + /** + * @param String + * inputToken + * @param boolean isColorToken + * @return boolean isTokenParsed + *

+ * The method parseColorOrPatternTokens() can be used + * to process the string tokens containing either the list of colors + * or the list of patterns. It returns true if the parse operation + * was successful. + */ + private boolean parseColorOrPatternTokens(String inputToken, + boolean isColorToken) { + boolean isTokenParsed = false; + boolean multipleTokensFound = false; + String[] tokenStringArray; + List integerTokenList = new ArrayList(); + /* + * If the input string contains a ';', it is split using this character + * as a delimiter. + */ + if (inputToken.contains(";")) { + tokenStringArray = inputToken.split(";"); + /* + * If more than one token is generated as a result of the split + * operation a boolean flag multipleTokensFound is set to true. + */ + if (tokenStringArray.length > 1) { + multipleTokensFound = true; + } else { + /* + * Else it is assumed that a single token containing a single + * integer was generated. + */ + try { + /* + * An attempt is made to extract the integer from the string + * and store it. + */ + + integerTokenList.add(Integer.parseInt(tokenStringArray[0])); + isTokenParsed = true; + /* + * If the input boolean isColorToken is set to true, then + * the extracted integer is stored in the color list. + */ + if (isColorToken) { + // TODO: check the single Integer in the list for valid + // color values? + this.setFillColorList(removeInvalidColors(integerTokenList)); + } else { + this.setFillTypeList(integerTokenList); + } + } catch (Exception e) { + integerTokenList.add(0);/* + * A blank input string token + * represents no color or no pattern + */ + this.setErrorMessage("INVALID STRING FORMAT"); + } + } + /* + * If several tokens are generated, then using a for-loop,, an + * attempt is made to extract an integer from each string token. If + * it is successful, then integers are added one by one to a list of + * integers. + */ + if (multipleTokensFound) { + for (int currentIndex = 0; currentIndex < tokenStringArray.length; currentIndex++) { + try { + integerTokenList.add(Integer + .parseInt(tokenStringArray[currentIndex])); + isTokenParsed = true; + } catch (Exception e) { + integerTokenList.add(0); + this.setErrorMessage("INVALID STRING FORMAT"); + } + } + + } + + /* + * If it is a color token, the list of integers extracted is stored + * as a list of colors. + */ + if (isColorToken) { + // TODO: check each Integer in the list for valid color values? + this.setFillColorList(removeInvalidColors(integerTokenList)); + } else { + // TODO + /* + * It is a list of patterns -check if each integer in the list + * belongs to one of the valid patternvalues and if so, add it + * to the list of patterns. + */ + this.setFillTypeList(integerTokenList); + } + } + /* + * Else, if the input string token does not contain the ';' delimiter, + * it is assumed that it contains a single integer and an attempt is + * made to extract this integer. Of the attempt is successful, then the + * integer is stored as a single member of the list of colors. + */ + else { + try { + integerTokenList.add(Integer.parseInt(inputToken)); + isTokenParsed = true; + + if (isColorToken) { + // TODO: check the single Integer for valid color values? + this.setFillColorList(integerTokenList); + } else { + this.setFillTypeList(integerTokenList); + } + } catch (NumberFormatException e) { + this.setErrorMessage("INVALID STRING FORMAT"); + } + } + return isTokenParsed; + } + + /** + * @param String + * [] colorRangeStringTokens + * @return boolean isColorRangeStringParsed + *

+ * The method parseRangeOfColors accepts as input a + * string array containing two tokens - the starting and ending + * values of the color range, in that order. If the two integer + * values are successfully parsed from the string tokens, the method + * generateColorRange() is invoked to populate the list + * with all the color values in the range. + */ + private boolean parseRangeOfColors(String[] colorRangeStringTokens) { + + boolean isColorRangeStringParsed = false; + Integer colorValue = 0; + for (int currentIndex = 0; currentIndex <= 1; currentIndex++) { + + try { + colorValue = Integer + .parseInt(colorRangeStringTokens[currentIndex]); + if (currentIndex == 0) { + /* + * TODO: Check if colorValue lies in the permissible range + * for color values + */ + this.setStartColorRange(colorValue); + } else { + this.setEndColorRange(colorValue); + } + isColorRangeStringParsed = true; + } catch (Exception e) { + this.setErrorMessage("INVALID STRING FORMAT"); + } + + } + + if (isColorRangeStringParsed) { + this.generateColorRange(this.getStartColorRange(), + this.getEndColorRange()); + } + return isColorRangeStringParsed; + } + + /** + * @param Integer + * startColorValue + * @param Integer + * endColorValue The method generateColorRange() + * accepts as input, two integers that represent the starting and + * ending values of the color range. A loop is used to generate + * every integer (representing a color value) in between the + * range. + */ + private void generateColorRange(Integer startColorValue, + Integer endColorValue) { + int currentIndex = 0; + + /* + * If the starting and ending color values in the range are equalonly a + * single element - the starting color value of the range is added to + * the list. + */ + if (startColorValue == endColorValue) { + this.getFillColorList().add(startColorValue); + } + /* + * Else if the starting color value in the range is less than ending + * color value,a loop is used to generate all the intermediate color + * values from the starting valueto the ending value by incrementing the + * loop counter + */ + else if (startColorValue < endColorValue) { + for (currentIndex = startColorValue; currentIndex <= endColorValue; currentIndex++) { + this.getFillColorList().add(currentIndex); + } + } + /* + * Else if the starting color value in the range is greater than ending + * color value,a loop is used to generate all the intermediate color + * values from the starting valueto the ending value by decrementing the + * loop counter + */ + else { + for (currentIndex = startColorValue; currentIndex >= endColorValue; currentIndex--) { + this.getFillColorList().add(currentIndex); + } + } + } + + /** + * The method setMissingAttributeschecks if the list of the + * list of patterns is less than that of the colors. If so, it invokes the + * method setMissingPatterns to repeat the patterns in the list + * till both the lists have the same number of elements + * + * @param List + * of Integer - colorsList + * @param List + * of Integer - patternsList + */ + private void setMissingAttributes(List colorsList, + List patternsList) { + int colorsListSize = colorsList.size(); + int patternsListSize = patternsList.size(); + int numElementsToAdd = 0; + + if (patternsListSize < colorsListSize) { + numElementsToAdd = colorsListSize - patternsListSize; + this.setMissingPatterns(patternsList, numElementsToAdd); + } + + } + + /** + * The method setMissingPatterns uses the input integer + * numElementsToAdd to decide how many elements to add, so as + * to repeat the patterns in the input list of patterns. + * + * @param List + * of Integer - patternsList + * @param int numElementsToAdd + */ + private void setMissingPatterns(List patternsList, + int numElementsToAdd) { + int currentIndex = 0; + int count = 1; + while (count <= numElementsToAdd) { + patternsList.add(patternsList.get(currentIndex)); + currentIndex++; + count++; + } + this.setFillTypeList(patternsList); + } + + private List removeInvalidColors(List integerList) { + + // Only allow integers 0 through 32 so that it does not exceed + // the number of colors available (refer to class GempakColor) + + List newIntegerList = new ArrayList(); + + int size = (integerList != null) ? integerList.size() : 0; + for (int i = 0; i < size; i++) { + int tmp = integerList.get(i); + if (tmp >= 0 && tmp <= 32) + newIntegerList.add(tmp); + } + + return newIntegerList; + } } - - - - - - - - - - - - - - - - - - - - - - diff --git a/ncep/gov.noaa.nws.ncep.gempak.parameters/src/gov/noaa/nws/ncep/gempak/parameters/intext/TextStringParser.java b/ncep/gov.noaa.nws.ncep.gempak.parameters/src/gov/noaa/nws/ncep/gempak/parameters/intext/TextStringParser.java index 0ab816679a..371dd73a48 100644 --- a/ncep/gov.noaa.nws.ncep.gempak.parameters/src/gov/noaa/nws/ncep/gempak/parameters/intext/TextStringParser.java +++ b/ncep/gov.noaa.nws.ncep.gempak.parameters/src/gov/noaa/nws/ncep/gempak/parameters/intext/TextStringParser.java @@ -8,7 +8,7 @@ package gov.noaa.nws.ncep.gempak.parameters.intext; * TEXT is the size, font, text width and hardware/software flag for * graphics text separated with slashes: * - * text size / font / width / hw flag + * text size / font / width/ border / rotation / justification / / hw flag * * The size may be a real number multiplier for the default text * size. If the size is zero or unspecified, the current size @@ -107,11 +107,12 @@ package gov.noaa.nws.ncep.gempak.parameters.intext; * ------------ ---------- ----------- -------------------------- * Nov 30,2010 363 X. Guo Initial Creation * Dec 06,2010 X. Guo Add symbol size + * Sep 09, 2013 1036 S. Gurung Added border, justification, rotation and textStyle * * * @author xguo * @version 1 - * @see $GEMPAK/help/hlx/txt.hl2 */ + * @see $GEMPAK/help/hlx/text.hl2 */ public class TextStringParser { @@ -131,7 +132,19 @@ public class TextStringParser { private int width; //Text HW flag - private String hwflg; + private String hwflg; + + //Text border + private int border; + + //Text justification + private char justification; + + //Text rotation + private char rotation; + + //Text style (normal/bold/italic) + private int textStyle; //Parse Flag private boolean isTextStringParsed; @@ -139,6 +152,18 @@ public class TextStringParser { //expression private String textExpre = "((-|\\+)?[0-9]+(\\.[0-9]+)?)+"; + //font expression + private String fontExpre = "[1-3]+"; + + //border expression + private String borderExpre = "[1-2][1-3][1]"; + + //rotation expression + private String rotExpre = "s|n|S|N"; + + //justification expression + private String justExpre = "c|C|r|R|l|L"; + /** * The default constructor HILOStringParser generates a single **/ @@ -184,7 +209,7 @@ public class TextStringParser { String textStr = txtStr + "/"; /* - * check and see if the input string with 4 strings separated by slashes + * check and see if the input string with 4 or 7 strings separated by slashes */ while (( pos = textStr.indexOf("/", start)) >= 0 ) { if ( pos != start ) { @@ -198,8 +223,14 @@ public class TextStringParser { } } else if ( cnt == 1 ) { //parse font - if ( tmp.matches(textExpre) ) { - setTextFont (checkFontSize(Integer.valueOf(tmp))); + if ( tmp.matches(fontExpre) ) { + if (tmp.length()==1){ + setTextFont (checkFontSize(Integer.valueOf(tmp))); + } + else { + setTextFont (checkFontSize(Integer.valueOf(tmp.substring(1,2)))); + setTextStyle(Integer.valueOf(tmp.substring(0,1))); + } } else { setTextFont (1); @@ -207,13 +238,31 @@ public class TextStringParser { } else if ( cnt == 2 ) { //parse width if ( tmp.matches(textExpre) ) { - setTextWidth (Integer.valueOf(tmp)); + setTextWidth (Math.round(Float.valueOf(tmp))); } else { setTextWidth (2); } } - else if ( cnt == 3 ) { // parse hw flag + else if (cnt == 3 && (tmp.equalsIgnoreCase("HW") || tmp.equalsIgnoreCase("SW"))) { // parse hw flag for HLSYM + setTextHWFlag (tmp); + } + else if ( cnt == 3 ) { // parse border + if ( tmp.matches(borderExpre) && tmp.length() == 3) { + setTextBorder (Integer.valueOf(tmp)); + } + } + else if ( cnt == 4 ) { // parse rotation + if ( tmp.matches(rotExpre) && tmp.length() == 1) { + setTextRotation (tmp.toUpperCase().charAt(0)); + } + } + else if ( cnt == 5 ) { // parse justification + if ( tmp.matches(justExpre) && tmp.length() == 1) { + setTextJustification (tmp.toUpperCase().charAt(0)); + } + } + else if ( cnt == 6 ) { // parse hw flag setTextHWFlag (tmp); } else { @@ -236,6 +285,10 @@ public class TextStringParser { font = 1; width = 2; hwflg = "HW"; + border = 000; + rotation = 'S'; + justification = 'C'; + textStyle = 0; } /** @@ -307,6 +360,51 @@ public class TextStringParser { public String getTextHWFlag () { return hwflg; } + + + /** + * Set Text border + */ + private void setTextBorder ( int border ) { + this.border = border; + } + + /** + * Get Text border + */ + public int getTextBorder () { + return border; + } + + /** + * Set Text justification + */ + private void setTextJustification ( char justification ) { + this.justification = justification; + } + + /** + * Get Text justification + */ + public char getTextJustification () { + return justification; + } + + + /** + * Set Text rotation + */ + private void setTextRotation ( char rotation ) { + this.rotation = rotation; + } + + /** + * Get Text rotation + */ + public char getTextRotation () { + return rotation; + } + /** * Get parse status */ @@ -319,7 +417,27 @@ public class TextStringParser { */ public String getInputTextString () { return inputTxtStr; + } + + /** + * Get textStyle + * + * 0 Normal + * 1 Italic + * 2 Bold + * 3 Italic-Bold + */ + public int getTextStyle() { + return textStyle; } + + /** + * Set textStyle + */ + public void setTextStyle(int textStyle) { + this.textStyle = textStyle; + } + /** * Convert size name to CAVE number * Name GEMPAK Size CAVE Size @@ -338,8 +456,7 @@ public class TextStringParser { float [] range = {0.714f, 0.857f, 1.000f, 1.286f, 1.714f, 2.429f }; String [] name = {"TINY","SMALL","MEDIUM","LARGE","HUGE","GIANT"}; - - for ( int i = 0; i < fontsize.length-1; i ++ ) { + for ( int i = 0; i <= fontsize.length-1; i ++ ) { String txtName1 = textName.substring(0, 1); String name1 = name[i].substring(0, 1); if ( textName.toUpperCase().compareTo(name[i]) == 0 || @@ -369,9 +486,33 @@ public class TextStringParser { int sizev = 14; int [] fontsize = {10, 12, 14, 18, 24, 34 }; float [] range = {0.714f, 0.857f, 1.000f, 1.286f, 1.714f, 2.429f }; - int len = range.length; + int len = range.length; - if ( value <= range[len-1] ) { + for ( int i = 0; i < len-1; i ++ ) { + + if ( value <= range[len-1] ) { + if ( ( range[i] <= value ) && ( value <= range[i+1]) ) { + if ( ( value - range[i] ) <= ( range[i+1] - value ) ) { + sizev = fontsize[i] ; + sizes = range[i] ; + } + else { + sizev = fontsize[i+1] ; + sizes = range[i+1] ; + } + break; + } + } else if (value == fontsize[i]) { + sizev = fontsize[i]; + sizes = range[i]; + break; + } else { + sizev = fontsize[len-1] ; + sizes = range[len-1] ; + } + } + + /*if ( value <= range[len-1] ) { for ( int i = 0; i < len-1; i ++ ) { if ( ( range[i] <= value ) && ( value <= range[i+1]) ) { if ( ( value - range[i] ) <= ( range[i+1] - value ) ) { @@ -389,7 +530,7 @@ public class TextStringParser { else { sizev = fontsize[len-1] ; sizes = range[len-1] ; - } + }*/ setTextSize (sizev ); setSymbolMarkerSize (sizes); } diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/BigNsharp/Sndglib/winds.c b/ncep/gov.noaa.nws.ncep.ui.nsharp/BigNsharp/Sndglib/winds.c index 6200d977fc..bc9afae291 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/BigNsharp/Sndglib/winds.c +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/BigNsharp/Sndglib/winds.c @@ -126,9 +126,8 @@ void mean_wind(float pbot, float ptop, float *mnu, float *mnv, /* mnv - V-Component of mean wind (kt) */ /*************************************************************/ { - float pinc, usum, vsum, wgt, w1, num, p, ix1; + float pinc, usum, vsum, wgt, w1, num, i, ix1, p; float sfctemp, sfcdwpt, sfcpres, lower, upper; - int i; Parcel pcl; *wdir = RMISSD; @@ -169,7 +168,7 @@ void mean_wind(float pbot, float ptop, float *mnu, float *mnv, else { num = wgt = usum = vsum = 0; p = pbot; - for (i = 0; i <= 20; i++) { + for (i=0;i<=20;i++) { w1 = p; usum = usum + (i_wndu(p, I_PRES) * w1); vsum = vsum + (i_wndv(p, I_PRES) * w1); @@ -204,9 +203,8 @@ void mean_wind_npw(float pbot, float ptop, float *mnu, float *mnv, /* mnv - V-Component of mean wind (kt) */ /*************************************************************/ { - float pinc, usum, vsum, wgt, w1, num, p, ix1; + float pinc, usum, vsum, wgt, w1, num, i, ix1; float sfctemp, sfcdwpt, sfcpres, lower, upper; - int i; Parcel pcl; *wdir = RMISSD; @@ -246,19 +244,17 @@ void mean_wind_npw(float pbot, float ptop, float *mnu, float *mnv, } else { num = wgt = usum = vsum = 0; - p = pbot; - for (i = 0; i <= 20; i++) { - w1 = p; - usum = usum + i_wndu(p, I_PRES); - vsum = vsum + i_wndv(p, I_PRES); - p -= pinc; - wgt = wgt + w1; + for (i = pbot; i >= ptop; i -= pinc) { + w1 = 1; + usum = usum + i_wndu(i, I_PRES); + vsum = vsum + i_wndv(i, I_PRES); + //wgt = wgt + w1; num++; } } - *mnu = (usum / wgt); - *mnv = (vsum / wgt); + *mnu = (usum / num); + *mnv = (vsum / num); if (qc(*mnu) && qc(*mnv)) { *wdir = angle(*mnu, *mnv); @@ -283,9 +279,8 @@ void sr_wind(float pbot, float ptop, float stdir, float stspd, /* mnv - V-Component of mean wind (kt) */ /*************************************************************/ { - float pinc, usum, vsum, wgt, w1, num, ix1, stu, stv, p; + float pinc, usum, vsum, wgt, w1, num, i, ix1, stu, stv; short idx; - int i; /* ----- Calculate Storm motion vectors ----- */ stu = ucomp(stdir, stspd); @@ -312,16 +307,20 @@ void sr_wind(float pbot, float ptop, float stdir, float stspd, ((i_wndu(ptop, I_PRES) - stu) * ptop); vsum = ((i_wndv(pbot, I_PRES) - stv) * pbot) + ((i_wndv(ptop, I_PRES) - stv) * ptop); + /*usum = ((ucomp(i_wdir(pbot, I_PRES), i_wspd(pbot, I_PRES)) - stu) * pbot) + + ((ucomp(i_wdir(ptop, I_PRES), i_wspd(ptop, I_PRES)) - stu) * ptop); + vsum = ((vcomp(i_wdir(pbot, I_PRES), i_wspd(pbot, I_PRES)) - stv) * pbot) + + ((vcomp(i_wdir(ptop, I_PRES), i_wspd(ptop, I_PRES)) - stv) * ptop);*/ wgt = pbot + ptop; } else { num = wgt = usum = vsum = 0; - p = pbot; - for (i = 0; i <= 20 ; i++) { - w1 = p; - usum = usum + ((i_wndu(p, I_PRES) - stu) * w1); - vsum = vsum + ((i_wndv(p, I_PRES) - stv) * w1); - p -= pinc; + for (i = pbot; i >= ptop; i -= pinc) { + w1 = i; + usum = usum + ((i_wndu(i, I_PRES) - stu) * w1); + vsum = vsum + ((i_wndv(i, I_PRES) - stv) * w1); + /*usum = usum + ((ucomp(i_wdir(i, I_PRES), i_wspd(i, I_PRES)) - stu) * w1); + vsum = vsum + ((vcomp(i_wdir(i, I_PRES), i_wspd(i, I_PRES)) - stv) * w1);*/ wgt = wgt + w1; num++; } @@ -377,6 +376,10 @@ void wind_shear(float pbot, float ptop, float *shu, float *shv, /* 10/9/07 RLT edit */ ubot = i_wndu(pbot, I_PRES); vbot = i_wndv(pbot, I_PRES); + /*ubot = ucomp((i_wdir(pbot, I_PRES)), (i_wspd(pbot, I_PRES))); + vbot = vcomp((i_wdir(pbot, I_PRES)), (i_wspd(pbot, I_PRES))); + printf("\n ubot = %7.1f vbot = %7.1f\n", ubot, vbot);*/ + } if (ptop == -1) { ptop = i_pres(agl(3000.0)); } @@ -387,6 +390,15 @@ void wind_shear(float pbot, float ptop, float *shu, float *shv, /* ----- Calculate Vector Difference ----- */ *shu = i_wndu(ptop, I_PRES) - ubot; *shv = i_wndv(ptop, I_PRES) - vbot; + /* *shu = ucomp((i_wdir(ptop, I_PRES)), (i_wspd(ptop, I_PRES))) - ubot; + *shv = vcomp((i_wdir(ptop, I_PRES)), (i_wspd(ptop, I_PRES))) - vbot; */ + + /*printf( "TOP: %7.1f %7.1f %7.1f %7.1f %7.1f\nBOT: %7.1f %7.1f %7.1f %7.1f %7.1f\nANS: %7.1f %7.1f %7.1f %7.1f\n", + ptop, i_wdir(ptop, I_PRES), i_wspd(ptop, I_PRES), i_wndu(ptop, I_PRES), i_wndv(ptop, I_PRES), pbot, + angle(ubot, vbot), speed(ubot, vbot), i_wndu(pbot, I_PRES), i_wndv(pbot, I_PRES), angle(*shu, *shv), + speed(*shu, *shv), *shu, *shv);*/ + + if (qc(*shu) && qc(*shv)) { *sdir = angle(*shu, *shv); *smag = speed(*shu, *shv); @@ -503,12 +515,10 @@ float helicity(float lower, float upper, float sdir, float sspd, srv2 = kt_to_mps(vcomp(sndg[i][idxd], sndg[i][idxs]) - cy); lyrh = (sru2 * srv1) - (sru1 * srv2); - if (lyrh > 0.0) { + if (lyrh > 0.0) *phel += lyrh; - } - else { + else *nhel += lyrh; - } sru1 = sru2; srv1 = srv2; } @@ -517,14 +527,17 @@ float helicity(float lower, float upper, float sdir, float sspd, /* ----- Finish with interpolated top layer ----- */ sru2 = kt_to_mps(i_wndu(i_pres(msl(upper)), I_PRES) - cx); srv2 = kt_to_mps(i_wndv(i_pres(msl(upper)), I_PRES) - cy); - + lyrh = (sru2 * srv1) - (sru1 * srv2); - if (lyrh > 0.0) { + if (lyrh > 0.0) *phel += lyrh; - } - else { + else *nhel += lyrh; - } + +/* +fprintf(stderr, "helicity: layer: %.1f:%.1f phel: %.1f nhel: %.1f\n", +lower, upper, *phel, *nhel); +*/ return (*phel + *nhel); } diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/NsharpWxMath.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/NsharpWxMath.java index 2ebec15ce9..59e761cf12 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/NsharpWxMath.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/NsharpWxMath.java @@ -72,6 +72,7 @@ public class NsharpWxMath { */ public static double getPressureYFromTemp(double temp, double tempX) { double pressureY; + temp -= tempOffset; //TT605593 pressureY = (tempX - (temp * 0.54))/0.90692; return pressureY; } diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/background/NsharpSkewTPaneBackground.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/background/NsharpSkewTPaneBackground.java index 68118c68d2..fd6a24fc68 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/background/NsharpSkewTPaneBackground.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/background/NsharpSkewTPaneBackground.java @@ -291,7 +291,7 @@ public class NsharpSkewTPaneBackground extends NsharpGenericPaneBackground { presslinesNumbersShape.addLineSegment(lines); //System.out.println("lines="+ lines[0] + "; "+ lines[1]); //System.out.println("x1="+world.mapX(NsharpConstants.left)+"y1=" +world.mapY(coor.y)+"x2="+world.mapX(NsharpConstants.right)+"y2="+ - // world.mapY(coor.y)); + // world.mapY(coor.y)); } IExtent ext = desc.getRenderableDisplay().getExtent(); double xmin = ext.getMinX(); //Extent's viewable envelope min x and y @@ -540,6 +540,7 @@ public class NsharpSkewTPaneBackground extends NsharpGenericPaneBackground { double xmax = ext.getMaxX(); //Extent's viewable envelope min x and y double ymax = ext.getMaxY(); double ymin = ext.getMinY(); + //System.out.println(" xmin="+xmin+ " xmax="+ xmax+ " ymax="+ymax+" ymin="+ymin); double dispX = xmin + 20 * currentZoomLevel; double dispY = ymax - 20 * currentZoomLevel; //We are getting Y (pressure) level for plotting Temp number, therefore dispX here is not important for the @@ -567,10 +568,9 @@ public class NsharpSkewTPaneBackground extends NsharpGenericPaneBackground { tempGap= 5; else if(currentZoomLevel <=0.75) tempGap= 8; - /*tempGap = (int) ((currentZoomLevel * 10) /1); - if((currentZoomLevel * 10) %1 != 0) - tempGap++;*/ - for (int i = /*70*/(int)lowTempMax+tempOffset; i >= /*-70+*/(int)lowTempMin+tempOffset; i -= tempGap) { + //TT605593 assume temp range is from -100 to 100 at ground level + for (int i = 100; i >= -100; i -= tempGap) { + // for (int i = /*70*/(int)lowTempMax+tempOffset; i >= /*-70+*/(int)lowTempMin+tempOffset; i -= tempGap) { Coordinate coorS = NsharpWxMath.getSkewTXY(dispPressure, i); double startX1 = world.mapX(coorS.x); double startY1 = world.mapY(coorS.y); @@ -591,8 +591,12 @@ public class NsharpSkewTPaneBackground extends NsharpGenericPaneBackground { if((dispPressure -NsharpConstants.MIN_PRESSURE) <10) dispPressure = NsharpConstants.MIN_PRESSURE+5*currentZoomLevel; - // top temp number - for (int i = (int)topTempMax+tempOffset; i >= (int)topTempMin+tempOffset; i -= tempGap) { + // top temp number.TT605593 + //Chin: without zooming, highest level temp is assume around 70 degree lower than ground + // Also, to make sure top temp number is in sync with lower temp number, when consider tempGap + int topTMax = 100- (( 70 / tempGap ) +1) * tempGap; + for (int i = topTMax; i >= topTMax - 200; i -= tempGap) { + //for (int i = (int)topTempMax+tempOffset; i >= (int)topTempMin+tempOffset; i -= tempGap) { Coordinate coorEnd1 = NsharpWxMath.getSkewTXY(dispPressure, i); double endX1 = world.mapX(coorEnd1.x); double endY1 = world.mapY(coorEnd1.y); @@ -613,24 +617,25 @@ public class NsharpSkewTPaneBackground extends NsharpGenericPaneBackground { Coordinate coorEnd = NsharpWxMath.getSkewTXY(100, i); dispX=world.mapX(coorEnd.x); dispY=world.mapY(coorEnd.y); - //System.out.println("temp x="+dispX+" y="+dispY); if(dispX>xmax){ // when temp line's top point's x coordinate is greater than view xman, the line will not be plotted. + // Can not find a solution for that now. // therefore, we have to find this temp line's top point's Y coordinate at xman position. // In other words, find the intersection point of temp line with skewT rectangle's right side line. - dispX = xmax-5; - coorEnd = world.unMap(dispX, 0); + dispX = xmax-20; // need to minus some number. Otherwise, it wont be plotted. + //TT605593 + coorEnd = world.unMap(xmax, 0); double py= NsharpWxMath.getPressureYFromTemp(i, coorEnd.x); dispY = world.mapY(py); } double [][] tlines = {{world.mapX(coorStart.x), world.mapY(coorStart.y)}, {dispX, dispY}}; - //System.out.println("temp="+i+" "+world.mapX(coorStart.x)+ "," +world.mapY(coorStart.y)+ " ;" - // +dispX+ "," + dispY); + //System.out.println("temp="+i+" wLx="+world.mapX(coorStart.x)+" sLx="+coorStart.x+ ",wLy=" +world.mapY(coorStart.y)+ " ;wHx=" + // +dispX+" sHx="+coorEnd.x+",wHy=" + dispY); temperatureLineShape.addLineSegment(tlines); } temperatureLineShape.compile(); - + //System.out.println("lower min"+ lowTempMin+ " lower nax "+ lowTempMax+ " upper min "+ topTempMin + " topTempMax "+ topTempMax); } //@SuppressWarnings("deprecation") @@ -666,6 +671,7 @@ public class NsharpSkewTPaneBackground extends NsharpGenericPaneBackground { target.drawWireframeShape(tempNumbersShape, NsharpConstants.color_white, 1, LineStyle.DEFAULT, smallFont); drawPressureLineNumber(target); target.clearClippingPlane(); + } //this function is used for printing public void paintForPrint( WGraphics world, GC gc){ diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpResourceHandler.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpResourceHandler.java index 8b1f4444f1..0c45432560 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpResourceHandler.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpResourceHandler.java @@ -11,6 +11,7 @@ * Date Ticket# Engineer Description * ------- ------- -------- ----------- * 04/30/2012 229 Chin Chen Initial coding + * 01/13/2014 Chin Chen TTR829- when interpolation, edit graph is allowed * 08/20/2013 2259 bsteffen Delete old skewt plugin. * * @@ -74,2518 +75,2929 @@ import com.raytheon.viz.core.graphing.WGraphics; import com.raytheon.viz.core.graphing.WindBarbFactory; import com.sun.jna.ptr.FloatByReference; import com.vividsolutions.jts.geom.Coordinate; + @SuppressWarnings("deprecation") public class NsharpResourceHandler { - private IRenderableDisplay[] displayArray=null; - private NsharpPartListener.PartEvent editorPartStatus =NsharpPartListener.PartEvent.partClosed; - private NsharpSkewTPaneResource skewtPaneRsc; - private NsharpWitoPaneResource witoPaneRsc; - private NsharpHodoPaneResource hodoPaneRsc; - private NsharpTimeStnPaneResource timeStnPaneRsc; - private NsharpInsetPaneResource insetPaneRsc; - private NsharpDataPaneResource dataPaneRsc; - private NsharpSpcGraphsPaneResource spcGraphsPaneRsc; - private NsharpAbstractPaneResource futurePaneRsc; - private String[] defaultDays; - NsharpNative nsharpNative=null; - private int displayDataPageMax; - private static final int INSETPAGEMAX =2; - private int currentTextChapter= 1; - private int currentInsetPage= 1; - private int cnYOrig = NsharpConstants.COLOR_NOTATION_Y_ORIG; - private int dtNextPageEnd = NsharpConstants.DATA_TIMELINE_NEXT_PAGE_END_; - private int charHeight = NsharpConstants.CHAR_HEIGHT_; - private int dtXOrig = NsharpConstants.DATA_TIMELINE_X_ORIG; - private int dtYOrig = NsharpConstants.DATA_TIMELINE_Y_ORIG; - private int dtWidth = NsharpConstants.DATA_TIMELINE_WIDTH; - private String paneConfigurationName; - private int numTimeLinePerPage=1; - /* Hodograph Modes - definition is based on definitions in globals_xw.h of BigNsharp */ - private static final int HODO_NORMAL = 0; - //private static int HODO_EFFECTIVE= 1; not used in BigNsharp source code - private static final int HODO_STORMRELATIVE= 2; - @SuppressWarnings("unused") - private static final int HODO_BNDRY= 3; - private static final int HODO_MEANWIND= 4; - @SuppressWarnings("unused") - private int currentHodoWindMode = HODO_MEANWIND; - private NsharpConfigManager configMgr; - private NsharpConfigStore configStore; - private NsharpGraphProperty graphConfigProperty; - private HashMap linePropertyMap; - private NsharpDataPageProperty dataPageProperty; - private int[] pageDisplayOrderNumberArray = new int[NsharpConstants.PAGE_MAX_NUMBER+1]; //index is the real page defined in NsharpConstants to be shown, value is the order number of this page. index 0 point to a dummy. - private boolean overlayIsOn = false; - private boolean interpolateIsOn = false; - private boolean compareSndIsOn = false; - private boolean compareStnIsOn = false; - private boolean compareTmIsOn = false; - private boolean editGraphOn=false; - private boolean getTimeMatcher=false; - public int TEMP_TYPE = 1; - public int DEWPOINT_TYPE = 2; - private int currentTempCurveType; - private int currentSoundingLayerIndex =0; - private int hodoEditingSoundingLayerIndex =0; - private boolean plotInteractiveTemp= false; - private Coordinate interactiveTempPointCoordinate; - public static final float INVALID_DATA = NsharpNativeConstants.NSHARP_NATIVE_INVALID_DATA; + private IRenderableDisplay[] displayArray = null; + + private NsharpPartListener.PartEvent editorPartStatus = NsharpPartListener.PartEvent.partClosed; + + private NsharpSkewTPaneResource skewtPaneRsc; + + private NsharpWitoPaneResource witoPaneRsc; + + private NsharpHodoPaneResource hodoPaneRsc; + + private NsharpTimeStnPaneResource timeStnPaneRsc; + + private NsharpInsetPaneResource insetPaneRsc; + + private NsharpDataPaneResource dataPaneRsc; + + private NsharpSpcGraphsPaneResource spcGraphsPaneRsc; + + private NsharpAbstractPaneResource futurePaneRsc; + + private String[] defaultDays; + + NsharpNative nsharpNative = null; + + private int displayDataPageMax; + + private static final int INSETPAGEMAX = 2; + + private int currentTextChapter = 1; + + private int currentInsetPage = 1; + + private int cnYOrig = NsharpConstants.COLOR_NOTATION_Y_ORIG; + + private int dtNextPageEnd = NsharpConstants.DATA_TIMELINE_NEXT_PAGE_END_; + + private int charHeight = NsharpConstants.CHAR_HEIGHT_; + + private int dtXOrig = NsharpConstants.DATA_TIMELINE_X_ORIG; + + private int dtYOrig = NsharpConstants.DATA_TIMELINE_Y_ORIG; + + private int dtWidth = NsharpConstants.DATA_TIMELINE_WIDTH; + + private String paneConfigurationName; + + private int numTimeLinePerPage = 1; + + /* + * Hodograph Modes - definition is based on definitions in globals_xw.h of + * BigNsharp + */ + private static final int HODO_NORMAL = 0; + + // private static int HODO_EFFECTIVE= 1; not used in BigNsharp source code + private static final int HODO_STORMRELATIVE = 2; + + @SuppressWarnings("unused") + private static final int HODO_BNDRY = 3; + + private static final int HODO_MEANWIND = 4; + + @SuppressWarnings("unused") + private int currentHodoWindMode = HODO_MEANWIND; + + private NsharpConfigManager configMgr; + + private NsharpConfigStore configStore; + + private NsharpGraphProperty graphConfigProperty; + + private HashMap linePropertyMap; + + private NsharpDataPageProperty dataPageProperty; + + private int[] pageDisplayOrderNumberArray = new int[NsharpConstants.PAGE_MAX_NUMBER + 1]; // index + // is + // the + // real + // page + // defined + // in + // NsharpConstants + // to + // be + // shown, + // value + // is + // the + // order + // number + // of + // this + // page. + // index + // 0 + // point + // to + // a + // dummy. + + private boolean overlayIsOn = false; + + private boolean interpolateIsOn = false; + + private boolean compareSndIsOn = false; + + private boolean compareStnIsOn = false; + + private boolean compareTmIsOn = false; + + private boolean editGraphOn = false; + + private boolean getTimeMatcher = false; + + public int TEMP_TYPE = 1; + + public int DEWPOINT_TYPE = 2; + + private int currentTempCurveType; + + private int currentSoundingLayerIndex = 0; + + private int hodoEditingSoundingLayerIndex = 0; + + private boolean plotInteractiveTemp = false; + + private Coordinate interactiveTempPointCoordinate; + + public static final float INVALID_DATA = NsharpNativeConstants.NSHARP_NATIVE_INVALID_DATA; + protected static final double BARB_LENGTH = 3.5; - private String soundingType= null; + + private String soundingType = null; protected DataTime displayedSounding; - - private int currentGraphMode= NsharpConstants.GRAPH_SKEWT; - + + private int currentGraphMode = NsharpConstants.GRAPH_SKEWT; + protected ListenerList listenerList = new ListenerList(); - - //current active sounding layer list - private List soundingLys = null; - private List previousSoundingLys = null; - private String pickedStnInfoStr; // current picked stn info with time line, e.g. "ATLH 101209/03(Thu)V003" - private NsharpStationInfo pickedStnInfo = null; - private IFrameCoordinator.FrameChangeOperation currentOpDirection = IFrameCoordinator.FrameChangeOperation.NEXT; // next =forward - private HashMap stormSlinkyColorMap = new HashMap(); - - private List>>stnTimeSndTable = new ArrayList< List>>(); - // stnTimeSndTable: - // Store all sounding profiles property for GUI display control - // 1st index refer to stnId, 2nd index refer to time line and 3rd point to sndType. - // It is same as [][][] 3d array. - // We dynamically expand this 3D array based on newly added stnid/timeline/sndType When a new sounding data is loaded, - // All unloaded element is null. Only when user load new sounding with this stnId/this time line/this sndType, then - // the element allocated. - // - // stn3-> T1--->T2--->T3->... - // ^ - // / - // stn2-> T1--->T2--->T3->... - // ^ - // / - //stn1-> T1--->T2--->T3->... - // | | | - // V V V - // snd1 snd1 snd1 - // | | | - // V V V - // snd2 snd2 snd2 - // | | | - // V V V - // stnTimeSndTable first dimension (station id) should be in sync with stnElementList, - // 2nd dimension (time line) should be in sync with timeElementList, and - // 3rd dimension (sounding type) should be in sync with sndTypeElementList - // NULL element in stnTimeSndTable indicates that sounding data is not loaded yet. - + + // current active sounding layer list + private List soundingLys = null; + + private List previousSoundingLys = null; + + private String pickedStnInfoStr; // current picked stn info with time line, + // e.g. "ATLH 101209/03(Thu)V003" + + private NsharpStationInfo pickedStnInfo = null; + + private IFrameCoordinator.FrameChangeOperation currentOpDirection = IFrameCoordinator.FrameChangeOperation.NEXT; // next + // =forward + + private HashMap stormSlinkyColorMap = new HashMap(); + + private List>> stnTimeSndTable = new ArrayList>>(); + + // stnTimeSndTable: + // Store all sounding profiles property for GUI display control + // 1st index refer to stnId, 2nd index refer to time line and 3rd point to + // sndType. + // It is same as [][][] 3d array. + // We dynamically expand this 3D array based on newly added + // stnid/timeline/sndType When a new sounding data is loaded, + // All unloaded element is null. Only when user load new sounding with this + // stnId/this time line/this sndType, then + // the element allocated. + // + // stn3-> T1--->T2--->T3->... + // ^ + // / + // stn2-> T1--->T2--->T3->... + // ^ + // / + // stn1-> T1--->T2--->T3->... + // | | | + // V V V + // snd1 snd1 snd1 + // | | | + // V V V + // snd2 snd2 snd2 + // | | | + // V V V + // stnTimeSndTable first dimension (station id) should be in sync with + // stnElementList, + // 2nd dimension (time line) should be in sync with timeElementList, and + // 3rd dimension (sounding type) should be in sync with sndTypeElementList + // NULL element in stnTimeSndTable indicates that sounding data is not + // loaded yet. + private List stnElementList = new ArrayList(); - private List timeElementList = new ArrayList(); - private List sndElementList = new ArrayList(); - private NsharpSoundingElementStateProperty curSndProfileProp = null; - private NsharpSoundingElementStateProperty preSndProfileProp = null; - private int curTimeLinePage=1; - private int totalTimeLinePage=1; - private int curStnIdPage=1; - private int totalStnIdPage=1; - private int curSndPage=1; - private int totalSndPage=1; - private int previousTimeLineStateListIndex; - - private int currentStnElementListIndex=-1; //index to first dim of stnTimeSndTable and index to stnElementList - private int currentTimeElementListIndex=-1;//index to 2nd dim of stnTimeSndTable and index to timeElementList - private int currentSndElementListIndex=-1;//index to 3rd dim of stnTimeSndTable and index to sndElementList - - //use element state, NsharpConstants.LoadState or NsharpConstants.ActState, as key to set color for drawing - private HashMap elementColorMap = new HashMap(); - private short currentParcel = NsharpNativeConstants.PARCELTYPE_MOST_UNSTABLE; - private float currentParcelLayerPressure = NsharpNativeConstants.MU_LAYER; - private float smWindDir, smWindSpd; - public List>> getStnTimeSndTable() { - return stnTimeSndTable; - } - public List getAllLoadedSndDesciptionList(){ - List strLst = new ArrayList(); - for(List> tlListList: stnTimeSndTable){ - // add a new element for the new sndType to each existing sndlist of each existing time of each existing stnId - for(List sndtyList: tlListList){ - for (NsharpSoundingElementStateProperty elem: sndtyList){ - if(elem!=null) - strLst.add(elem.getElementDescription()); - } - } - } - return strLst; - } + private List timeElementList = new ArrayList(); - public List getStnElementList() { - return stnElementList; - } + private List sndElementList = new ArrayList(); + private NsharpSoundingElementStateProperty curSndProfileProp = null; - public List getTimeElementList() { - return timeElementList; - } + private NsharpSoundingElementStateProperty preSndProfileProp = null; + private int curTimeLinePage = 1; - public List getSndElementList() { - return sndElementList; - } + private int totalTimeLinePage = 1; + private int curStnIdPage = 1; - public int getCurrentStnElementListIndex() { - return currentStnElementListIndex; - } + private int totalStnIdPage = 1; + private int curSndPage = 1; - public int getCurrentTimeElementListIndex() { - return currentTimeElementListIndex; - } + private int totalSndPage = 1; - public int getTimeElementListSize(){ - return timeElementList.size(); - } + private int previousTimeLineStateListIndex; - public int getCurrentSndElementListIndex() { - return currentSndElementListIndex; - } - + private int currentStnElementListIndex = -1; // index to first dim of + // stnTimeSndTable and index to + // stnElementList - //shape and color storage - public class ShapeAndLineProperty { - IWireframeShape shape; - NsharpLineProperty lp; - public ShapeAndLineProperty() { - super(); - lp = new NsharpLineProperty(); - } - - } - public HashMap getLinePropertyMap() { - return linePropertyMap; - } + private int currentTimeElementListIndex = -1;// index to 2nd dim of + // stnTimeSndTable and index to + // timeElementList - + private int currentSndElementListIndex = -1;// index to 3rd dim of + // stnTimeSndTable and index to + // sndElementList - public boolean isCompareStnIsOn() { - return compareStnIsOn; - } - public boolean isCompareTmIsOn() { - return compareTmIsOn; - } - - public boolean isCompareSndIsOn() { - return compareSndIsOn; - } + // use element state, NsharpConstants.LoadState or NsharpConstants.ActState, + // as key to set color for drawing + private HashMap elementColorMap = new HashMap(); + private short currentParcel = NsharpNativeConstants.PARCELTYPE_MOST_UNSTABLE; - public boolean isOverlayIsOn() { - return overlayIsOn; - } + private float currentParcelLayerPressure = NsharpNativeConstants.MU_LAYER; - - public NsharpNative getNsharpNative() { - return nsharpNative; - } - - + private float smWindDir, smWindSpd; - public void setNextTextChapter(){ - if(currentTextChapter == displayDataPageMax){ - currentTextChapter = 1; - } - else - currentTextChapter++; - } - public void setNextInsetPage(){ - if(currentInsetPage == INSETPAGEMAX){ - currentInsetPage = 1; - } - else - currentInsetPage++; - } - - - public void setOverlayIsOn(boolean overlay) { - previousSoundingLys=null; - previousTimeLineStateListIndex=-1; - preSndProfileProp = null; - this.overlayIsOn = overlay; - - if(hodoPaneRsc!=null) - hodoPaneRsc.createRscHodoWindShapeAll(); - if(skewtPaneRsc!=null) - skewtPaneRsc.handleResize(); - } + public List>> getStnTimeSndTable() { + return stnTimeSndTable; + } - public boolean isInterpolateIsOn() { - return interpolateIsOn; - } - - /* - * When compareStnIsOn is changed, - */ - public void setCompareStnIsOn(boolean compareIsOn) { - this.compareStnIsOn = compareIsOn; - - //This is the case when sounding data is not available at currentTimeElementListIndex/currentSndElementListIndex/currentStnElementListIndex and user set - // compare stn on. - if(compareStnIsOn){ - if(soundingLys==null && currentTimeElementListIndex>=0 && currentSndElementListIndex>=0){ - //find a new available stn for current time and sndType - boolean found = false; - for(int i =0; i< stnElementList.size(); i++){ - if(stnElementList.get(i).getActionState() == NsharpConstants.ActState.ACTIVE - && stnTimeSndTable.get(i).get(currentTimeElementListIndex).get(currentSndElementListIndex)!=null){ - found = true; - currentStnElementListIndex = i; - } - - if(found) - break; - } - if(!found) - return; - } + public List getAllLoadedSndDesciptionList() { + List strLst = new ArrayList(); + for (List> tlListList : stnTimeSndTable) { + // add a new element for the new sndType to each existing sndlist of + // each existing time of each existing stnId + for (List sndtyList : tlListList) { + for (NsharpSoundingElementStateProperty elem : sndtyList) { + if (elem != null) + strLst.add(elem.getElementDescription()); + } + } + } + return strLst; + } - int colorIndex = NsharpConstants.LINE_COMP1; - for(NsharpOperationElement elm: stnElementList) { - int stnIndex = stnElementList.indexOf(elm); - NsharpSoundingElementStateProperty stnTmElm = stnTimeSndTable.get(stnIndex).get(currentTimeElementListIndex).get(currentSndElementListIndex); - if(stnTmElm!=null){ - stnTmElm.setCompColorIndex(colorIndex); - //if(colorIndex > NsharpConstants.LINE_COMP10) - // colorIndex = NsharpConstants.LINE_COMP1; - } - colorIndex++; - if(colorIndex > NsharpConstants.LINE_COMP10) - colorIndex = NsharpConstants.LINE_COMP1; - } - } - setCurSndProfileProp(); - setCurrentSoundingLayerInfo(); - resetData(); - } - - public void setCompareSndIsOn(boolean compareSndIsOn) { - this.compareSndIsOn = compareSndIsOn; - //This is the case when sounding data is not available at currentTimeElementListIndex/currentSndElementListIndex/currentStnElementListIndex and user set - // compSnd on - if(compareSndIsOn){ - if(soundingLys==null && currentStnElementListIndex >=0 && currentTimeElementListIndex >=0){ - //find a new available snd type for current time and stn - boolean found = false; - for(int i =0; i< sndElementList.size(); i++){ - if(sndElementList.get(i).getActionState() == NsharpConstants.ActState.ACTIVE - && stnTimeSndTable.get(currentStnElementListIndex).get(currentTimeElementListIndex).get(i)!=null){ - found = true; - currentSndElementListIndex = i; - } - if(found) - break; - } - if(!found) - return; - } - int colorIndex = NsharpConstants.LINE_COMP1; - for(NsharpOperationElement elm: sndElementList) { - int sndIndex = sndElementList.indexOf(elm); - NsharpSoundingElementStateProperty stnTmElm = stnTimeSndTable.get(currentStnElementListIndex).get(currentTimeElementListIndex).get(sndIndex); - if(stnTmElm!=null){ - stnTmElm.setCompColorIndex(colorIndex); - //if(colorIndex > NsharpConstants.LINE_COMP10) - // colorIndex = NsharpConstants.LINE_COMP1; - } - colorIndex++; - if(colorIndex > NsharpConstants.LINE_COMP10) - colorIndex = NsharpConstants.LINE_COMP1; - } - } - setCurSndProfileProp(); - setCurrentSoundingLayerInfo(); - resetData(); + public List getStnElementList() { + return stnElementList; + } - } + public List getTimeElementList() { + return timeElementList; + } + public List getSndElementList() { + return sndElementList; + } - public void setCompareTmIsOn(boolean compareIsOn) { - this.compareTmIsOn = compareIsOn; - //This is the case when sounding data is not available at currentTimeElementListIndex/currentSndElementListIndex/currentStnElementListIndex and user set - // compTm on - if(compareIsOn){ - if(soundingLys==null && currentStnElementListIndex >=0 && currentSndElementListIndex >=0){ - //find a new available time line for current snd type and stn - boolean found = false; - for(int i =0; i< timeElementList.size(); i++){ - if(timeElementList.get(i).getActionState() == NsharpConstants.ActState.ACTIVE - && stnTimeSndTable.get(currentStnElementListIndex).get(i).get(currentSndElementListIndex)!=null){ - found = true; - currentTimeElementListIndex = i; - } - if(found) - break; - } - if(!found) - return; - } - int colorIndex = NsharpConstants.LINE_COMP1; - for(NsharpOperationElement elm: timeElementList) { - int tmIndex = timeElementList.indexOf(elm); - NsharpSoundingElementStateProperty stnTmElm = stnTimeSndTable.get(currentStnElementListIndex).get(tmIndex).get(currentSndElementListIndex); - if(stnTmElm!=null){ - stnTmElm.setCompColorIndex(colorIndex); - //if(colorIndex > NsharpConstants.LINE_COMP10) - // colorIndex = NsharpConstants.LINE_COMP1; - } - colorIndex++; - if(colorIndex > NsharpConstants.LINE_COMP10) - colorIndex = NsharpConstants.LINE_COMP1; - } - } - setCurSndProfileProp(); - setCurrentSoundingLayerInfo(); - resetData(); - } + public int getCurrentStnElementListIndex() { + return currentStnElementListIndex; + } - public void setEditGraphOn(boolean editGraphOn) { - this.editGraphOn = editGraphOn; - } + public int getCurrentTimeElementListIndex() { + return currentTimeElementListIndex; + } - public boolean isEditGraphOn() { - return editGraphOn; - } + public int getTimeElementListSize() { + return timeElementList.size(); + } + + public int getCurrentSndElementListIndex() { + return currentSndElementListIndex; + } + + // shape and color storage + public class ShapeAndLineProperty { + IWireframeShape shape; + + NsharpLineProperty lp; + + public ShapeAndLineProperty() { + super(); + lp = new NsharpLineProperty(); + } + + } + + public HashMap getLinePropertyMap() { + return linePropertyMap; + } + + public boolean isCompareStnIsOn() { + return compareStnIsOn; + } + + public boolean isCompareTmIsOn() { + return compareTmIsOn; + } + + public boolean isCompareSndIsOn() { + return compareSndIsOn; + } + + public boolean isOverlayIsOn() { + return overlayIsOn; + } + + public NsharpNative getNsharpNative() { + return nsharpNative; + } + + public void setNextTextChapter() { + if (currentTextChapter == displayDataPageMax) { + currentTextChapter = 1; + } else + currentTextChapter++; + } + + public void setNextInsetPage() { + if (currentInsetPage == INSETPAGEMAX) { + currentInsetPage = 1; + } else + currentInsetPage++; + } + + public void setOverlayIsOn(boolean overlay) { + previousSoundingLys = null; + previousTimeLineStateListIndex = -1; + preSndProfileProp = null; + this.overlayIsOn = overlay; + + if (hodoPaneRsc != null) + hodoPaneRsc.createRscHodoWindShapeAll(); + if (skewtPaneRsc != null) + skewtPaneRsc.handleResize(); + } + + public boolean isInterpolateIsOn() { + return interpolateIsOn; + } + + /* + * When compareStnIsOn is changed, + */ + public void setCompareStnIsOn(boolean compareIsOn) { + this.compareStnIsOn = compareIsOn; + + // This is the case when sounding data is not available at + // currentTimeElementListIndex/currentSndElementListIndex/currentStnElementListIndex + // and user set + // compare stn on. + if (compareStnIsOn) { + if (soundingLys == null && currentTimeElementListIndex >= 0 + && currentSndElementListIndex >= 0) { + // find a new available stn for current time and sndType + boolean found = false; + for (int i = 0; i < stnElementList.size(); i++) { + if (stnElementList.get(i).getActionState() == NsharpConstants.ActState.ACTIVE + && stnTimeSndTable.get(i) + .get(currentTimeElementListIndex) + .get(currentSndElementListIndex) != null) { + found = true; + currentStnElementListIndex = i; + } + + if (found) + break; + } + if (!found) + return; + } + + int colorIndex = NsharpConstants.LINE_COMP1; + for (NsharpOperationElement elm : stnElementList) { + int stnIndex = stnElementList.indexOf(elm); + NsharpSoundingElementStateProperty stnTmElm = stnTimeSndTable + .get(stnIndex).get(currentTimeElementListIndex) + .get(currentSndElementListIndex); + if (stnTmElm != null) { + stnTmElm.setCompColorIndex(colorIndex); + // if(colorIndex > NsharpConstants.LINE_COMP10) + // colorIndex = NsharpConstants.LINE_COMP1; + } + colorIndex++; + if (colorIndex > NsharpConstants.LINE_COMP10) + colorIndex = NsharpConstants.LINE_COMP1; + } + } + setCurSndProfileProp(); + setCurrentSoundingLayerInfo(); + resetData(); + } + + public void setCompareSndIsOn(boolean compareSndIsOn) { + this.compareSndIsOn = compareSndIsOn; + // This is the case when sounding data is not available at + // currentTimeElementListIndex/currentSndElementListIndex/currentStnElementListIndex + // and user set + // compSnd on + if (compareSndIsOn) { + if (soundingLys == null && currentStnElementListIndex >= 0 + && currentTimeElementListIndex >= 0) { + // find a new available snd type for current time and stn + boolean found = false; + for (int i = 0; i < sndElementList.size(); i++) { + if (sndElementList.get(i).getActionState() == NsharpConstants.ActState.ACTIVE + && stnTimeSndTable.get(currentStnElementListIndex) + .get(currentTimeElementListIndex).get(i) != null) { + found = true; + currentSndElementListIndex = i; + } + if (found) + break; + } + if (!found) + return; + } + int colorIndex = NsharpConstants.LINE_COMP1; + for (NsharpOperationElement elm : sndElementList) { + int sndIndex = sndElementList.indexOf(elm); + NsharpSoundingElementStateProperty stnTmElm = stnTimeSndTable + .get(currentStnElementListIndex) + .get(currentTimeElementListIndex).get(sndIndex); + if (stnTmElm != null) { + stnTmElm.setCompColorIndex(colorIndex); + // if(colorIndex > NsharpConstants.LINE_COMP10) + // colorIndex = NsharpConstants.LINE_COMP1; + } + colorIndex++; + if (colorIndex > NsharpConstants.LINE_COMP10) + colorIndex = NsharpConstants.LINE_COMP1; + } + } + setCurSndProfileProp(); + setCurrentSoundingLayerInfo(); + resetData(); + + } + + public void setCompareTmIsOn(boolean compareIsOn) { + this.compareTmIsOn = compareIsOn; + // This is the case when sounding data is not available at + // currentTimeElementListIndex/currentSndElementListIndex/currentStnElementListIndex + // and user set + // compTm on + if (compareIsOn) { + if (soundingLys == null && currentStnElementListIndex >= 0 + && currentSndElementListIndex >= 0) { + // find a new available time line for current snd type and stn + boolean found = false; + for (int i = 0; i < timeElementList.size(); i++) { + if (timeElementList.get(i).getActionState() == NsharpConstants.ActState.ACTIVE + && stnTimeSndTable.get(currentStnElementListIndex) + .get(i).get(currentSndElementListIndex) != null) { + found = true; + currentTimeElementListIndex = i; + } + if (found) + break; + } + if (!found) + return; + } + int colorIndex = NsharpConstants.LINE_COMP1; + for (NsharpOperationElement elm : timeElementList) { + int tmIndex = timeElementList.indexOf(elm); + NsharpSoundingElementStateProperty stnTmElm = stnTimeSndTable + .get(currentStnElementListIndex).get(tmIndex) + .get(currentSndElementListIndex); + if (stnTmElm != null) { + stnTmElm.setCompColorIndex(colorIndex); + // if(colorIndex > NsharpConstants.LINE_COMP10) + // colorIndex = NsharpConstants.LINE_COMP1; + } + colorIndex++; + if (colorIndex > NsharpConstants.LINE_COMP10) + colorIndex = NsharpConstants.LINE_COMP1; + } + } + setCurSndProfileProp(); + setCurrentSoundingLayerInfo(); + resetData(); + } + + public void setEditGraphOn(boolean editGraphOn) { + this.editGraphOn = editGraphOn; + } + + public boolean isEditGraphOn() { + return editGraphOn; + } - public int getCurrentGraphMode() { - return currentGraphMode; - } + return currentGraphMode; + } - public void setCurrentGraphMode(int currentGraphMode) { - this.currentGraphMode = currentGraphMode; - if(skewtPaneRsc!=null) - skewtPaneRsc.setCurrentGraphMode(currentGraphMode); - refreshPane(); - } + public void setCurrentGraphMode(int currentGraphMode) { + this.currentGraphMode = currentGraphMode; + if (skewtPaneRsc != null) + skewtPaneRsc.setCurrentGraphMode(currentGraphMode); + refreshPane(); + } + public short getCurrentParcel() { + return currentParcel; + } - public short getCurrentParcel() { - return currentParcel; - } + // native nsharp c/fortran lib + // NsharpNative is native nsharp lib awips/lib/libnsharp.so wrapper class - //native nsharp c/fortran lib - //NsharpNative is native nsharp lib awips/lib/libnsharp.so wrapper class - - public float getSmWindDir() { - return smWindDir; - } - public float getSmWindSpd() { - return smWindSpd; - } + public float getSmWindDir() { + return smWindDir; + } - public void setCurrentHodoWindMode(int cursorPositionIndex) { - switch(cursorPositionIndex){ - case 0: - this.currentHodoWindMode = HODO_NORMAL; - break; - case 1: - this.currentHodoWindMode = HODO_STORMRELATIVE; - break; - case 2: - default: - this.currentHodoWindMode = HODO_MEANWIND; - break; - } - } + public float getSmWindSpd() { + return smWindSpd; + } + + public void setCurrentHodoWindMode(int cursorPositionIndex) { + switch (cursorPositionIndex) { + case 0: + this.currentHodoWindMode = HODO_NORMAL; + break; + case 1: + this.currentHodoWindMode = HODO_STORMRELATIVE; + break; + case 2: + default: + this.currentHodoWindMode = HODO_MEANWIND; + break; + } + } + + public NsharpStationInfo getPickedStnInfo() { + return pickedStnInfo; + } - public NsharpStationInfo getPickedStnInfo() { - return pickedStnInfo; - } public String getSoundingType() { - return soundingType; - } + return soundingType; + } + public void setSoundingType(String soundingType) { + this.soundingType = soundingType; + } - public void setSoundingType(String soundingType) { - this.soundingType = soundingType; - } - public void setCurrentParcel(short currentParcel) { - this.currentParcel = currentParcel; - currentParcelLayerPressure=NsharpNativeConstants.parcelToLayerMap.get(currentParcel); - //inform data/skewT panel as well - if(dataPaneRsc!=null){ - dataPaneRsc.setCurrentParcel(currentParcel); - } - if(skewtPaneRsc!=null){ - if(currentParcel == NsharpNativeConstants.PARCELTYPE_USER_DEFINED) - currentParcelLayerPressure = NsharpParcelDialog.getUserDefdParcelMb(); - skewtPaneRsc.createRscParcelTraceShapes(currentParcel,currentParcelLayerPressure); - skewtPaneRsc.createRscParcelRtTraceShapesList(currentParcel,currentParcelLayerPressure); - skewtPaneRsc.createLCLEtcLinesShape(); - } - } - - public void updateParcelFromPanel(short currentParcel){ - this.currentParcel = currentParcel; - currentParcelLayerPressure=NsharpNativeConstants.parcelToLayerMap.get(currentParcel); - if(skewtPaneRsc!=null){ - skewtPaneRsc.createRscParcelTraceShapes(currentParcel,currentParcelLayerPressure); - skewtPaneRsc.createRscParcelRtTraceShapesList(currentParcel,currentParcelLayerPressure); - skewtPaneRsc.createLCLEtcLinesShape(); - } - } - - public void setHodoStmCenter(Coordinate hodoHouseC) { - if(hodoPaneRsc==null) - return; - //hodoPaneRsc.setHodoHouseC(hodoHouseC); - Coordinate c = hodoPaneRsc.getHodoBackground().getWorld().unMap(hodoHouseC.x, hodoHouseC.y); - c = WxMath.speedDir((float) c.x, (float) c.y); - smWindDir = (float) c.y; - smWindSpd = (float)c.x; - nsharpNative.nsharpLib.set_storm(smWindSpd, smWindDir); - if(insetPaneRsc!=null){ - WGraphics WGc = insetPaneRsc.getPsblWatchTypeBackground().getWorld(); - insetPaneRsc.createBkgPsblWatchShape(WGc); - - //Sr wind vs Height graph shape need to recreate - WGc= insetPaneRsc.getSrWindsBackground().getWorld(); - insetPaneRsc.createRscSrWindShape(WGc); - } - if(skewtPaneRsc!=null){ - skewtPaneRsc.createEffectiveLayerLinesShape(); - skewtPaneRsc.updatePsblWatchColor(); - } - } - - //This function is called only when interpolation "on/off" is changed by user - public void resetInfoOnInterpolate(boolean interpolateIsOn) throws CloneNotSupportedException{ - //We dont want to assume previous interpolation on/off state. So, reset soundingLys any how. - this.interpolateIsOn = interpolateIsOn; - NsharpSoundingElementStateProperty elem = getCurSoundingElementStateProperty(); - if(elem!=null){ - if(interpolateIsOn==false){ - soundingLys = elem.getSndLyLst(); - - } - else{ - //interpolation is on - //we dont want to change original raw data, so use a deep copy - List intpSndLst = new ArrayList(); - for(NcSoundingLayer layer: elem.getSndLyLst() ) { - intpSndLst.add((NcSoundingLayer) layer.clone()); - } - - // interpolation - intpSndLst = performInterpolation(intpSndLst); - - soundingLys = intpSndLst; - - } - - - nsharpNative.populateSndgData(soundingLys); - if(skewtPaneRsc!=null) - skewtPaneRsc.resetData(soundingLys,previousSoundingLys); - if(hodoPaneRsc!=null) - hodoPaneRsc.resetData(soundingLys,previousSoundingLys); - if(witoPaneRsc!=null) - witoPaneRsc.resetData(soundingLys, previousSoundingLys); - if(dataPaneRsc!=null) - dataPaneRsc.resetData(soundingLys, previousSoundingLys); - if(insetPaneRsc!=null) - insetPaneRsc.resetData(soundingLys, previousSoundingLys); - - //re-create shape - if(skewtPaneRsc!=null) - skewtPaneRsc.handleResize(); - if(hodoPaneRsc!=null) - hodoPaneRsc.createRscHodoWindShapeAll(); - if(insetPaneRsc!=null) - insetPaneRsc.createInsetWireFrameShapes(); - if(witoPaneRsc!=null) - witoPaneRsc.createRscWireFrameShapes(); - - } - - } - - - public void handleNsharpEditorPartEvent(NsharpPartListener.PartEvent pStatus){ - switch(pStatus){ - case partActivated: - if(editorPartStatus != NsharpPartListener.PartEvent.partDeactivated){ - //repopulateSndgData(); - //resetRsc(); - resetData(); - } - - break; - default: - break; - } - editorPartStatus = pStatus; - } - public void resetRsc() { - restoreAllSoundingData(); - NsharpSoundingElementStateProperty elem = getCurSoundingElementStateProperty(); - if(elem!=null){ - this.soundingLys = elem.getSndLyLst(); - //Set default parcel trace data - currentParcel = NsharpNativeConstants.PARCELTYPE_MOST_UNSTABLE; - currentParcelLayerPressure = NsharpNativeConstants.MU_LAYER; - setSoundingInfo(this.soundingLys); - currentTextChapter = 1; - overlayIsOn = false; - interpolateIsOn = false; - compareStnIsOn = false; - compareSndIsOn = false; - compareTmIsOn = false; - editGraphOn = false; - if(skewtPaneRsc!=null) - skewtPaneRsc.setCurrentSkewTEditMode(NsharpConstants.SKEWT_EDIT_MODE_EDITPOINT); - resetData(); - } - - } - public synchronized void resetData(){ - //System.out.println("resetData called, rscHdr="+this.toString() + " pickedStnInfoStr="+pickedStnInfoStr+ " nsharpNative="+nsharpNative.toString()); - - //update active sounding layer and picked stn info - //re-populate snd data to nsharp native code lib for later calculating - nsharpNative.populateSndgData(soundingLys); - if(skewtPaneRsc!=null) - skewtPaneRsc.resetData(soundingLys,previousSoundingLys); - if(hodoPaneRsc!=null) - hodoPaneRsc.resetData(soundingLys,previousSoundingLys); - if(insetPaneRsc!=null) - insetPaneRsc.resetData(soundingLys, previousSoundingLys); - if(dataPaneRsc!=null) - dataPaneRsc.resetData(soundingLys, previousSoundingLys); - if(witoPaneRsc!=null) - witoPaneRsc.resetData(soundingLys, previousSoundingLys); - - NsharpShowTextDialog textarea = NsharpShowTextDialog.getAccess(); - if(textarea != null){ - textarea.refreshTextData(); - } - //if soundingLys is null, then we stop here, after reset data. - if(soundingLys == null) - return; - if(soundingLys.size() >0){ - //set initial hodohouseC - - // ----- set hodo circle at Bunkers Right, Chin according to TTR6065 or RaytheonTicket#10438 - FloatByReference dummy1= new FloatByReference(-999); - FloatByReference dummy2= new FloatByReference(-999); - FloatByReference bwdir= new FloatByReference(-999); - FloatByReference bwspd= new FloatByReference(-999); - nsharpNative.nsharpLib.bunkers_storm_motion(dummy1, dummy2, bwdir, bwspd); - //System.out.println("resetData windspd="+ bwspd.getValue()+ " dir="+bwdir.getValue()); - smWindSpd = bwspd.getValue(); - smWindDir = bwdir.getValue(); - nsharpNative.nsharpLib.set_storm(smWindSpd, smWindDir); - - //reset parcel - currentParcel = NsharpNativeConstants.PARCELTYPE_MOST_UNSTABLE; - currentParcelLayerPressure = NsharpNativeConstants.MU_LAYER; - //reset parcel dialog as well - if(NsharpParcelDialog.getAccess()!=null){ - NsharpParcelDialog.getAccess().resetUserDefParcel(); - } - /* Chin::: - * This api is called in many scenarios. - * User may want to keep his previous picked parcel type. - * Therefore, thdataPaneRsc.resetCurrentParcel should be called from - * other area that really meant to reset parcel type. - */ - } - //Chin: TBD remove handle resize here to fix sizing issue when swapped nsharp from side pane back to main pane - // but, may cause other problem? - //if(skewtPaneRsc!=null) - //skewtPaneRsc.handleResize(); - if(skewtPaneRsc!=null) - skewtPaneRsc.createRscWireFrameShapes(); - if(hodoPaneRsc!=null) - hodoPaneRsc.createRscHodoWindShapeAll(); - if(insetPaneRsc!=null) - insetPaneRsc.createInsetWireFrameShapes(); - if(witoPaneRsc!=null) - witoPaneRsc.createAllWireFrameShapes(); - } - private class NsharpOperationElementComparator implements Comparator{ - @Override - public int compare(NsharpOperationElement o1, NsharpOperationElement o2) { - - String s1tok1="";//, s1tok2=""; - String s2tok1="";//, s2tok2=""; - StringTokenizer st1 = new StringTokenizer(o1.getElementDescription()); - int tkCount1 = st1.countTokens(); - //System.out.println("ElementComparatorTimeLine o1="+o1.elementDescription+"c1 = "+tkCount1); - if(tkCount1 >= 1) - { - s1tok1 = st1.nextToken(); - } - else{ - return 0; - - } - //System.out.println("t1="+s1tok1+" t2="+s2tok1); - StringTokenizer st2 = new StringTokenizer(o2.getElementDescription()); - int tkCount2 = st2.countTokens(); - //System.out.println("ElementComparatorTimeLine o2="+o2.elementDescription+"c2 = "+tkCount2); - if(tkCount2 >= 1) - { - s2tok1 = st2.nextToken(); - } - else{ - return 0; - - } - //System.out.println("t1="+s2tok1+" t2="+s2tok2); - if(s1tok1.compareTo(s2tok1) == 0){ - return 0; - }else if (s1tok1.compareTo(s2tok1) < 0){ - return 1; - } else if (s1tok1.compareTo(s2tok1) > 0) { - return -1; - } - return 0; - } - } - - private int getIndexFromElementList(String targetDescription, List elemLst){ - for(NsharpOperationElement sndProp: elemLst){ - if(sndProp.getElementDescription().equals(targetDescription) ) - return elemLst.indexOf(sndProp); - - } - return -1; - } - - private void restoreAllSoundingData(){ - for(List> tlListList: stnTimeSndTable){ - // add a new element for the new sndType to each existing sndlist of each existing time of each existing stnId - for(List sndtyList: tlListList){ - for (NsharpSoundingElementStateProperty elem: sndtyList){ - if(elem!=null) - elem.restoreSndLyLstFromBackup(); - } - } - } - } - private int addElemToElemList(String elemDesc,List elemList){ - NsharpOperationElement elem = new NsharpOperationElement(elemDesc,NsharpConstants.ActState.ACTIVE); - elemList.add(elem); - Collections.sort(elemList, new NsharpOperationElementComparator()); - return elemList.indexOf(elem); - } - private void addNewSndToStnTimeSndTable(int sndIndex){ - for(List> tlListList: stnTimeSndTable){ - // add a new element for the new sndType to each existing sndlist of each existing time of each existing stnId - for(List sndtyList: tlListList){ - sndtyList.add(sndIndex,null); - } - } - } - private void addNewStnToStnTimeSndTable(int stnIndex){ - // Add new stnid to outer list of stnTimeSndTable - List> listListForNewStn = new ArrayList>(); - // based on new stn id, add list for each existing time line - for(int i=0; i sndListForTm = new ArrayList(); - for(int j=0; j< sndElementList.size(); j++ ){ - sndListForTm.add(null); - } - listListForNewStn.add(sndListForTm); - } - stnTimeSndTable.add(stnIndex, listListForNewStn); - } - private void addNewTimeToStnTimeSndTable(int timeIndex){ - for(List> tlListList: stnTimeSndTable){ - // based on sndTypeElementList - //create sndlist for the new time line for each existing stnid - List newSndList = new ArrayList(); - for(int i=0; i< sndElementList.size();i++ ){ - newSndList.add(null); - } - //add sndlist for the new time line to stn list - tlListList.add(timeIndex,newSndList); - } - } - private void addElementToTableAndLists(String stnId_timeLine_sndType,String stnId, String tmLine, String sndType, NsharpStationInfo stnInfo, List sndLyLst){ - //System.out.println("stn to be added "+ stnId + " timeline "+tmLine); - NsharpSoundingElementStateProperty newSndPropElem=null; - int tmIndex = getIndexFromElementList(tmLine, timeElementList); - int stnIndex = getIndexFromElementList(stnId, stnElementList); - int sndTpyeIndex = getIndexFromElementList(sndType, sndElementList); - currentTimeElementListIndex = tmIndex; - currentStnElementListIndex = stnIndex; - currentSndElementListIndex = sndTpyeIndex; - //based on these 3 indexes, we have 8 cases to handle. - if(tmIndex>=0 && stnIndex>=0 && sndTpyeIndex>=0){ - //CASE1: All 3 index are good (>=0) - if(stnTimeSndTable.get(stnIndex).get(tmIndex).get(sndTpyeIndex) != null) - // this sounding element is already loaded - return; - else { - //replace previously added "null" object with real NsharpSoundingElementStateProperty object - newSndPropElem = - new NsharpSoundingElementStateProperty(stnId_timeLine_sndType,stnId, tmLine, stnInfo, sndLyLst); - stnTimeSndTable.get(stnIndex).get(tmIndex).set(sndTpyeIndex, newSndPropElem); - } - } - else if (tmIndex >=0 ){ - if(stnIndex >=0 ){ - //CASE2 : tmIndex/stnIndex are good (>=0), sndTpyeIndex is bad (<0), a new snd type - //add new sndType to sndTypeElementList - currentSndElementListIndex = addElemToElemList(sndType,sndElementList ); - //Add new snd type to each snd type list of stnTimeSndTable - addNewSndToStnTimeSndTable(currentSndElementListIndex); - //replace previously added "null" object with real NsharpSoundingElementStateProperty object - newSndPropElem = - new NsharpSoundingElementStateProperty(stnId_timeLine_sndType, stnId, tmLine, stnInfo, sndLyLst); - stnTimeSndTable.get(currentStnElementListIndex).get(currentTimeElementListIndex).set(currentSndElementListIndex, newSndPropElem); - } - else{ - if(sndTpyeIndex >=0){ - //CASE3 : tmIndex/sndTpyeIndex are good, stnIndex is bad (<0), a new stnId - //add new stn to stnElementList - currentStnElementListIndex = addElemToElemList(stnId,stnElementList ); - // Add new stnid to outer list of stnTimeSndTable - addNewStnToStnTimeSndTable(currentStnElementListIndex); - //replace previously added "null" object with real NsharpSoundingElementStateProperty object - newSndPropElem = - new NsharpSoundingElementStateProperty(stnId_timeLine_sndType, stnId, tmLine, stnInfo, sndLyLst); - stnTimeSndTable.get(currentStnElementListIndex).get(currentTimeElementListIndex).set(currentSndElementListIndex, newSndPropElem); - - } - else{ - //CASE4 : tmIndex is good, stnIndex/sndTpyeIndex are bad (<0), new stnId and new snd type - //add new stn to stnElementList - currentStnElementListIndex = addElemToElemList(stnId,stnElementList ); - //add new sndType to sndTypeElementList - currentSndElementListIndex = addElemToElemList(sndType,sndElementList ); - //Add new snd type to each snd type list of stnTimeSndTable - addNewSndToStnTimeSndTable(currentSndElementListIndex); - // Add new stnid to outer list of stnTimeSndTable - addNewStnToStnTimeSndTable(currentStnElementListIndex); - //replace previously added "null" object with real NsharpSoundingElementStateProperty object - newSndPropElem = - new NsharpSoundingElementStateProperty(stnId_timeLine_sndType, stnId, tmLine, stnInfo, sndLyLst); - stnTimeSndTable.get(currentStnElementListIndex).get(currentTimeElementListIndex).set(currentSndElementListIndex, newSndPropElem); - - } - } - } - else{ - if(stnIndex >=0 ){ - if(sndTpyeIndex >=0){ - //CASE5 : stnIndex/sndTpyeIndex are good, tmIndex is bad (<0) - //add new time line to timeElementList - currentTimeElementListIndex = addElemToElemList(tmLine,timeElementList ); - //add new time line to StnTimeSndTable - addNewTimeToStnTimeSndTable(currentTimeElementListIndex); - //replace previously added "null" object with real NsharpSoundingElementStateProperty object - newSndPropElem = - new NsharpSoundingElementStateProperty(stnId_timeLine_sndType, stnId, tmLine, stnInfo, sndLyLst); - stnTimeSndTable.get(currentStnElementListIndex).get(currentTimeElementListIndex).set(currentSndElementListIndex, newSndPropElem); - - } - else{ - //CASE6 : stnIndex is good, tmIndex/sndTpyeIndex are bad (<0) - //add new time line to timeElementList - currentTimeElementListIndex = addElemToElemList(tmLine,timeElementList ); - //add new sndType to sndTypeElementList - currentSndElementListIndex = addElemToElemList(sndType,sndElementList ); - //Add new snd type to each snd type list of stnTimeSndTable - addNewSndToStnTimeSndTable(currentSndElementListIndex); - //add new time line to StnTimeSndTable - addNewTimeToStnTimeSndTable(currentTimeElementListIndex); - //replace previously added "null" object with real NsharpSoundingElementStateProperty object - newSndPropElem = - new NsharpSoundingElementStateProperty(stnId_timeLine_sndType, stnId, tmLine, stnInfo, sndLyLst); - stnTimeSndTable.get(currentStnElementListIndex).get(currentTimeElementListIndex).set(currentSndElementListIndex, newSndPropElem); - - } - - } - else{ - if(sndTpyeIndex >=0){ - //CASE7 : sndTpyeIndex is good, tmIndex/stnIndex are bad (<0) - //add new time line to timeElementList - currentTimeElementListIndex = addElemToElemList(tmLine,timeElementList ); - //add new stn to stnElementList - currentStnElementListIndex = addElemToElemList(stnId,stnElementList ); - //add new time line to StnTimeSndTable - addNewTimeToStnTimeSndTable(currentTimeElementListIndex); - // Add new stnid to outer list of stnTimeSndTable - addNewStnToStnTimeSndTable(currentStnElementListIndex); - //replace previously added "null" object with real NsharpSoundingElementStateProperty object - newSndPropElem = - new NsharpSoundingElementStateProperty(stnId_timeLine_sndType, stnId, tmLine, stnInfo, sndLyLst); - stnTimeSndTable.get(currentStnElementListIndex).get(currentTimeElementListIndex).set(currentSndElementListIndex, newSndPropElem); - - } - else{ - //CASE8 : All are bad (<0) - // an element with new time line, new stnId and new sndType - //add new time line to timeElementList - currentTimeElementListIndex = addElemToElemList(tmLine,timeElementList ); - //add new stn to stnElementList - currentStnElementListIndex = addElemToElemList(stnId,stnElementList ); - //add new sndType to sndTypeElementList - currentSndElementListIndex = addElemToElemList(sndType,sndElementList ); - - //Construct stnTimeSndTable - if(stnTimeSndTable.size()>0){ - List> listListForNewStn = new ArrayList>(); - // based on new stn id, add list for each existing time line - for(NsharpOperationElement tmElem: timeElementList){ - // based on each time line, add element for each existing sndType - List sndlistForTm = new ArrayList(); - for(NsharpOperationElement sndElem: sndElementList ){ - if(tmLine.equals(tmElem.getElementDescription()) && sndType.equals(sndElem.getElementDescription()) ){ - //only one case falls in this route as only one new loaded sounding data - newSndPropElem = - new NsharpSoundingElementStateProperty(stnId_timeLine_sndType, stnId, tmLine, stnInfo, sndLyLst); - - sndlistForTm.add(newSndPropElem); - } - else{ - //create for not avail sounding profiles - sndlistForTm.add(null); - } - } - listListForNewStn.add(sndlistForTm); - } - - //Now update stnTimeSndTable by adding "dummy" NsharpSoundingElementStateProperty to all exiting stn listList and time list - //Note that we have NOT added "listListForNewStn" to stnTimeSndTable yet. - //we have to update current table now - for(List> tlListList: stnTimeSndTable){ - // add a new element for the new sndType to each existing sndlist of each existing time of each existing stnId - for(List sndtyList: tlListList){ - sndtyList.add(currentSndElementListIndex,null); - } - // based on sndTypeElementList - //add a new sndlist for the new time line for each existing stnid - List newSndList = new ArrayList(); - for(int i=0;i< sndElementList.size();i++ ){ - { - newSndList.add(null); - } - } - tlListList.add(currentTimeElementListIndex,newSndList); - } - //finally, add this new stn list to table - stnTimeSndTable.add(currentStnElementListIndex, listListForNewStn); - } - else{ - //this is the case, we are adding first element to stnTimeSndTable - // need a new stn time line list to stnTimeSndTable - List newList = new ArrayList(); - List> newListList = new ArrayList>(); - - newSndPropElem = - new NsharpSoundingElementStateProperty(stnId_timeLine_sndType, stnId, tmLine,stnInfo, sndLyLst); - newList.add(newSndPropElem); - newListList.add(newList); - stnTimeSndTable.add(newListList); - curSndProfileProp=newSndPropElem; - return; - } - - } - } - } - setCurSndProfileProp(); - - } - private void setCurSndProfileProp() { - if(currentTimeElementListIndex <0 || currentTimeElementListIndex >= timeElementList.size()|| - currentStnElementListIndex < 0 || currentStnElementListIndex >= stnElementList.size() - || currentSndElementListIndex<0 || currentSndElementListIndex>= sndElementList.size()){ - curSndProfileProp = null; - preSndProfileProp = null; - } - else { - preSndProfileProp = curSndProfileProp; - curSndProfileProp = stnTimeSndTable.get(currentStnElementListIndex).get(currentTimeElementListIndex).get(currentSndElementListIndex); - } - } - private void cleanUpStnTimeSndTable(int stni, int tmi, int sndi){ - boolean found = false; - //find if this station is no longer in use - List> tlListList = stnTimeSndTable.get(stni); - for(List sndtyList: tlListList){ - for (NsharpSoundingElementStateProperty elem: sndtyList){ - if(elem!=null) { - found = true; - break; - } - } - if(found) - break; - } - if(!found){ - //This stn is no longer in use...delete it from stnTimeSndTable and stnElementList - stnElementList.remove(stni); - tlListList= stnTimeSndTable.remove(stni); - tlListList.clear(); - } - //find if this time line is no longer in use - found = false; - for (List> tmListListForStn: stnTimeSndTable){ - List sndtyListForTm = tmListListForStn.get(tmi); - for (NsharpSoundingElementStateProperty elem: sndtyListForTm){ - if(elem!=null) { - found = true; - break; - } - } - if(found) - break; - } - if(!found){ - //This time line is no longer in use...delete it from stnTimeSndTable and timeElementList - timeElementList.remove(tmi); - for (List> tmListListForStn: stnTimeSndTable){ - List sndtyListForTm = tmListListForStn.remove(tmi); - sndtyListForTm.clear(); - } - } - //find if this sounding type is no longer in use - found = false; - for (List> tmListListForStn: stnTimeSndTable){ - for(List sndtyListForTm : tmListListForStn){ - NsharpSoundingElementStateProperty elem= sndtyListForTm.get(sndi); - if(elem!=null) { - found = true; - break; - } - } - if(found) - break; - } - if(!found){ - //This sounding type is no longer in use...delete it from stnTimeSndTable and sndElementList - sndElementList.remove(sndi); - for (List> tmListListForStn: stnTimeSndTable){ - for(List sndtyListForTm : tmListListForStn){ - sndtyListForTm.remove(sndi); - } - } - } - - } - public boolean deleteRsc(List deletingDataTimeList){ - boolean curSndDeleted = false; - for(String dataTmLine: deletingDataTimeList){ - if(curSndProfileProp!=null && curSndProfileProp.getElementDescription().equals(dataTmLine)){ - curSndDeleted = true; - } - //find deleting element from stnTimeSndTable and null it - boolean setdone = false; - for(List> tlListList: stnTimeSndTable){ - for(List sndtyList: tlListList){ - for (NsharpSoundingElementStateProperty elem: sndtyList){ - if(elem!=null && dataTmLine.equals(elem.getElementDescription())){ - int sndi = sndtyList.indexOf(elem); - int tmi = tlListList.indexOf(sndtyList); - int stni = stnTimeSndTable.indexOf(tlListList); - sndtyList.set(sndtyList.indexOf(elem),null); - setdone = true; - // clean up stnTimeSndTable if a stn/timeline/snd is no longer in use - cleanUpStnTimeSndTable(stni,tmi,sndi); - break; - } - } - if(setdone) - break; - } - if(setdone) - break; - } - } - - if(curSndDeleted || soundingLys == null){ - //this is the case that we are deleting current snd, so, a new current snd should be selected - curSndProfileProp = null; - //find CurrentElementIndexes After Delete current snding - boolean found = false; - int stni=0; - for(List> tlListList: stnTimeSndTable){ - int timei=0; - for(List sndtyList: tlListList){ - int sndi=0; - for (NsharpSoundingElementStateProperty elem: sndtyList){ - if(elem!=null && stnElementList.get(stni).getActionState()== NsharpConstants.ActState.ACTIVE && - timeElementList.get(timei).getActionState()== NsharpConstants.ActState.ACTIVE && - sndElementList.get(sndi).getActionState()== NsharpConstants.ActState.ACTIVE){ - currentStnElementListIndex = stni; - currentSndElementListIndex = sndi; - currentTimeElementListIndex = timei; - found = true; - break; - } - sndi++; - } - if(found) - break; - timei++; - } - if(found) - break; - stni++; - } - if(!found){ - currentStnElementListIndex = -1; - currentSndElementListIndex = -1; - currentTimeElementListIndex = -1; - } - setCurSndProfileProp(); - } - else{ - // currentStnElementListIndex, currentSndElementListIndex and currentTimeElementListIndex may not point to right element - //after some elements are deleted. - currentStnElementListIndex = -1; - currentTimeElementListIndex = -1; - currentSndElementListIndex = -1; - if(curSndProfileProp!= null){ - boolean found = false; - for (List> tmListListForStn: stnTimeSndTable){ - for(List sndtyListForTm : tmListListForStn){ - for (NsharpSoundingElementStateProperty elem: sndtyListForTm){ - if(elem!=null && curSndProfileProp.getElementDescription().equals(elem.getElementDescription())){ - currentSndElementListIndex = sndtyListForTm.indexOf(elem); - currentTimeElementListIndex = tmListListForStn.indexOf(sndtyListForTm); - currentStnElementListIndex = stnTimeSndTable.indexOf(tmListListForStn); - found= true; - break; - } - } - if(found) - break; - } - if(found) - break; - } - } - } - setCurrentSoundingLayerInfo(); - resetData(); - System.out.println("num="+getFrameCount()); - return curSndDeleted; - // anything more to do? - } - public void deleteRscAll(){ - NsharpMapResource nsharpMapResource = NsharpMapResource.getOrCreateNsharpMapResource(); - nsharpMapResource.setPoints(null); - if(soundingLys!=null){ - soundingLys.clear(); - soundingLys=null; - } - if(previousSoundingLys!=null){ - previousSoundingLys.clear(); - previousSoundingLys = null; - } - if(stnTimeSndTable != null){ - for(List> stnListList: stnTimeSndTable){ - for(List timeList: stnListList){ - timeList.clear(); - } - stnListList.clear(); - } - stnTimeSndTable.clear(); - } - if(timeElementList != null) - timeElementList.clear(); - if(stnElementList != null) - stnElementList.clear(); - if(sndElementList != null) - sndElementList.clear(); - curSndProfileProp = null; - preSndProfileProp = null; - currentTextChapter = 1; - currentInsetPage = 1; - currentParcel = NsharpNativeConstants.PARCELTYPE_MOST_UNSTABLE; - currentParcelLayerPressure = NsharpNativeConstants.MU_LAYER; - currentTimeElementListIndex = -1; - currentStnElementListIndex = -1; - currentSndElementListIndex = -1; - resetData(); - } - - - private NsharpSoundingElementStateProperty getCurSoundingElementStateProperty(){ - if(currentTimeElementListIndex >=0 && currentStnElementListIndex>=0 && currentSndElementListIndex>=0 && - stnTimeSndTable.get( currentStnElementListIndex).get( currentTimeElementListIndex).get(currentSndElementListIndex)!=null){ - return stnTimeSndTable.get( currentStnElementListIndex).get( currentTimeElementListIndex).get(currentSndElementListIndex); - } - return null; - } - private void setCurrentSoundingLayerInfo() { - NsharpSoundingElementStateProperty elem = getCurSoundingElementStateProperty(); - if(elem!=null){ - pickedStnInfoStr = elem.getElementDescription(); - pickedStnInfo = elem.getStnInfo(); - - if(overlayIsOn){ - previousSoundingLys = soundingLys; - } - else { - previousSoundingLys = null; - } - - if(interpolateIsOn == true){ - //we dont want to change original raw data, so use a new copy - NcSoundingLayer newLayer; - List mySndLst = new ArrayList(); - for(NcSoundingLayer layer:elem.getSndLyLst()){ - newLayer = new NcSoundingLayer(); - try { - newLayer = (NcSoundingLayer) layer.clone(); - - } catch (CloneNotSupportedException e) { - e.printStackTrace(); - } //here a shallowCopy is enough - mySndLst.add(newLayer); - } - // interpolation - mySndLst = performInterpolation(mySndLst); - - soundingLys = mySndLst; - } - else { - soundingLys = elem.getSndLyLst(); - } - } - else{ - previousSoundingLys = null; - soundingLys = null; - } - - } - public void addRsc(Map> soundMap, NsharpStationInfo stnInfo, boolean fromNCP){ - if(fromNCP){ - //this is from NCP do nothing now - this.addRsc(true, soundMap, stnInfo); - //NCP case: - //Key String format will be like this for NCUAIR - // KGRI 100616/03(Wed)-NCUAIR - // and for PFC/Grid sounding will be like this - //KGRI 100616/03(Wed)V001-GFSSND - } - else{ - //D2D case:::: - //this is from D2D, edit display and time line string to add short day-of-week and - //also add sounding type to string to solve an issue that data with same stn, same time line but different - //sounding type will not be loaded. - //D2D's key string is like this: "KGRI 2010-06-16 03:00:00" - // will change it to "KGRI 100616/03(Wed)-GFSSND" - Set dataTimelineSet = soundMap.keySet(); - SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - //DateFormatSymbols dfs= new DateFormatSymbols(); - //String[] defaultDays = dfs.getShortWeekdays(); - Calendar cal =Calendar.getInstance(); - Date date; - Map> newmap = new HashMap> (); - String sndType = stnInfo.getSndType(); - for(String timeline: dataTimelineSet){ - System.out.println("D2D sending timeline Str:"+ timeline); - String dateStr = timeline.substring(timeline.indexOf(' ')+1); - String stnId= timeline.substring(0, timeline.indexOf(' ')); - try { - date = df.parse(dateStr); - cal.setTime(date); - String dayOfWeek = defaultDays[cal.get(Calendar.DAY_OF_WEEK)]; - //dateStr = timeline.substring(0, timeline.indexOf(':'))+dayOfWeek+stnInfo.getSndType(); - //System.out.println("New Str:"+ dateStr); - String finalTimeStr = String.format("%4$s %1$ty%1$tm%1$td/%1$tH(%2$s) %3$s", cal, dayOfWeek,sndType,stnId); - System.out.println("D2D (modified) timeline Str:"+ finalTimeStr); - //put newTimeStr to new map with original value - newmap.put(finalTimeStr, soundMap.get(timeline)); - } catch (ParseException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - continue; - } - } - //this is from D2D, and it does not want to display new data right away. - this.addRsc(false, newmap, stnInfo); - } - } - /* - public void loadSoundingData( boolean displayNewData, List soundDataLst, String stnId, String sndType, - Timestamp rangeStartTime,double latitude,double longitude){ - //* testing code - //stnInfo.setStnId("KFSD"); - { - Set keyset= new HashSet(soundMap.keySet()); - for(String key: keyset) { - List sndLy = soundMap.remove(key); - String newkey= key.replace("NAMS", "yahoo"); - //String newkey= key.replace("GFSS", "NAMS"); - //newkey = newkey.replace("KSLN", "KFSD"); - soundMap.put(newkey, sndLy); - } - stnInfo.setSndType(stnInfo.getSndType().replace("NAMS", "yahoo")); - //stnInfo.setSndType(stnInfo.getSndType().replace("GFSS", "NAMS")); - }// - - //need to format reftime to GMT time string. Timestamp.toString produce a local time Not GMT time - Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); - cal.setTimeInMillis(rangeStartTime.getTime()); - String dayOfWeek = defaultDays[cal.get(Calendar.DAY_OF_WEEK)]; - String timeLine = String.format("%1$ty%1$tm%1$td/%1$tH(%2$s)", cal, dayOfWeek); - if(stnId.indexOf(" ")>=0){ - //take care stnId with SPACE case. - stnId = stnId.replace(" ", "_"); - } - if(timeElementList.isEmpty() || stnElementList.isEmpty() || - currentSndElementListIndex < 0 ||sndElementList.isEmpty() || - currentTimeElementListIndex < 0 || currentStnElementListIndex < 0){ - //if no data was loaded since, then display this data any way - displayNewData = true; - } - //save current timeline and stn state properties if we are NOT loading new data - NsharpOperationElement currentTL=null; - NsharpOperationElement currentStn=null; - NsharpOperationElement currentSnd=null; - NsharpSoundingElementStateProperty currentPreSndProfileProp=null; - if(!displayNewData){ - currentTL = timeElementList.get(currentTimeElementListIndex); - currentStn = stnElementList.get(currentStnElementListIndex); - currentSnd = sndElementList.get(currentSndElementListIndex); - currentPreSndProfileProp = preSndProfileProp; - } - //add new data to table - //add time line to stnTimeTable and set its index - addElementToTableAndLists((stnId+" "+timeLine+" "+sndType),stnId,timeLine,sndType,stnInfo, soundDataLst); - - if(displayNewData){ - //Set default parcel trace data - currentParcel = NsharpNativeConstants.PARCELTYPE_MOST_UNSTABLE; - currentParcelLayerPressure = NsharpNativeConstants.MU_LAYER; - setCurrentSoundingLayerInfo(); - resetData(); - } - else { - //Not display new data. Reset current "parameter"s after adding data to map/lists - currentStnElementListIndex= stnElementList.indexOf(currentStn); - currentTimeElementListIndex = timeElementList.indexOf(currentTL); - currentSndElementListIndex = sndElementList.indexOf(currentSnd); - preSndProfileProp = currentPreSndProfileProp; - curSndProfileProp = stnTimeSndTable.get(currentStnElementListIndex).get(currentTimeElementListIndex).get(currentSndElementListIndex); - } - - //set total time line group and stn id list page number - calculateTimeStnBoxData(); - - //set data time to descriptor - //this is necessary for looping - // starting 13.2.1, this line is changed by Raytheon - if (( skewtPaneRsc.getDescriptor().getFramesInfo().getFrameCount() == 0)&& !getTimeMatcher) { - //was this line before 13.2.1 if (( skewtPaneRsc.getDescriptor().getTimeMatcher() == null || skewtPaneRsc.getDescriptor().getTimeMatcher().getTimeMatchBasis() == null)&& !getTimeMatcher) { - //DataTime[] dataTimes = new DataTime[dataTimelineList.size()]; - //Chin Note: we just have to do this once and set dataTimes size bigger than 1. - //Nsharp handles changing frame itself. It just need system to send change frame notice. - //That is happened at NsharpSkewTDescriptor.checkDrawTime(). - DataTime[] dataTimes = new DataTime[2]; - Date now = new Date(); - for(int k =0; k < 2 ; k++){ - dataTimes[k]= new DataTime(now, k); - } - //no need to get a descriptor from a renderableDispaly since we have a descriptor - skewtPaneRsc.getDescriptor().setDataTimes(dataTimes); - getTimeMatcher=true; + this.currentParcel = currentParcel; + currentParcelLayerPressure = NsharpNativeConstants.parcelToLayerMap + .get(currentParcel); + // inform data/skewT panel as well + if (dataPaneRsc != null) { + dataPaneRsc.setCurrentParcel(currentParcel); } - - NsharpShowTextDialog textarea = NsharpShowTextDialog.getAccess(); - if(textarea != null){ - textarea.refreshTextData(); - } - NsharpPaletteWindow win = NsharpPaletteWindow.getInstance() ; - if(win!=null) - currentGraphMode=win.getCurrentGraphMode(); - - refreshPane(); - - } - */ - - private void addRsc( boolean displayNewData,Map> soundMap, NsharpStationInfo stnInfo){ - /* testing code - //stnInfo.setStnId("KFSD"); - { - Set keyset= new HashSet(soundMap.keySet()); - for(String key: keyset) { - List sndLy = soundMap.remove(key); - String newkey= key.replace("NCUAIR", "gpduair"); - //String newkey= key.replace("GFSS", "NAMS"); - //String newkey = key.replace("OAK", "KFSD"); - soundMap.put(newkey, sndLy); - } - stnInfo.setSndType(stnInfo.getSndType().replace("NCUAIR", "gpduair")); - //stnInfo.setSndType(stnInfo.getSndType().replace("GFSS", "NAMS")); - }//*/ - - - if(stnInfo.getStnId() != null && stnInfo.getStnId().indexOf(" ")>=0){ - //take care stnId with SPACE case. - String stnId= stnInfo.getStnId(); - String newStnId = stnId.replace(" ", "_"); - stnInfo.setStnId(newStnId); - String dspInfo= stnInfo.getStnDisplayInfo(); - stnInfo.setStnDisplayInfo(dspInfo.replace(stnId, newStnId)); - Set keyset= new HashSet(soundMap.keySet()); - for(String key: keyset) { - List sndLy = soundMap.remove(key); - String newkey= key.replace(stnId, newStnId); - soundMap.put(newkey, sndLy); - } - - } - - if(soundMap.size() <=0 || (skewtPaneRsc==null)){ - return; - } - if(timeElementList.isEmpty() || stnElementList.isEmpty() || - currentSndElementListIndex < 0 ||sndElementList.isEmpty() || - currentTimeElementListIndex < 0 || currentStnElementListIndex < 0){ - //if no data was loaded since, then display this data any way - displayNewData = true; - } - //save current timeline and stn state properties if we are NOT loading new data - NsharpOperationElement currentTL=null; - NsharpOperationElement currentStn=null; - NsharpOperationElement currentSnd=null; - NsharpSoundingElementStateProperty currentPreSndProfileProp=null; - if(!displayNewData){ - currentTL = timeElementList.get(currentTimeElementListIndex); - currentStn = stnElementList.get(currentStnElementListIndex); - currentSnd = sndElementList.get(currentSndElementListIndex); - currentPreSndProfileProp = preSndProfileProp; - } - //add new data to table - Set dataTimelineSet = soundMap.keySet(); - String[] tempTimeLineArr = dataTimelineSet.toArray(new String[dataTimelineSet.size()]); - Arrays.sort(tempTimeLineArr); - for (int i=0; i< tempTimeLineArr.length; i++){ - // based on this KEY string format "KGRI 100616/03(Wed) GFSSND" - String stnId_timeLine_sndType = tempTimeLineArr[i].toString(); - String stnId = stnId_timeLine_sndType.substring(0,stnId_timeLine_sndType.indexOf(" ")); - String timeLine_sndType= stnId_timeLine_sndType.substring(stnId_timeLine_sndType.indexOf(" ")+1); - String timeLine= timeLine_sndType.substring(0,timeLine_sndType.indexOf(" ")); - String sndType= timeLine_sndType.substring(timeLine_sndType.indexOf(" ")+1); - //No more needed? timeLine = timeLine.replace(" ", "-"); //fixed DR15325 - sorting time line issue in D2D - //add time line to stnTimeTable and set its index - addElementToTableAndLists(stnId_timeLine_sndType,stnId,timeLine,sndType,stnInfo, soundMap.get(stnId_timeLine_sndType)); - } - if(displayNewData){ - //Set default parcel trace data - currentParcel = NsharpNativeConstants.PARCELTYPE_MOST_UNSTABLE; - currentParcelLayerPressure = NsharpNativeConstants.MU_LAYER; - setCurrentSoundingLayerInfo(); - resetData(); - } - else { - //Not display new data. Reset current "parameter"s after adding data to map/lists - currentStnElementListIndex= stnElementList.indexOf(currentStn); - currentTimeElementListIndex = timeElementList.indexOf(currentTL); - currentSndElementListIndex = sndElementList.indexOf(currentSnd); - preSndProfileProp = currentPreSndProfileProp; - curSndProfileProp = stnTimeSndTable.get(currentStnElementListIndex).get(currentTimeElementListIndex).get(currentSndElementListIndex); - } - - //set total time line group and stn id list page number - calculateTimeStnBoxData(); - - //set data time to descriptor - //this is necessary for looping - // starting 13.2.1, this line is changed by Raytheon - if (( skewtPaneRsc.getDescriptor().getFramesInfo().getFrameCount() == 0)&& !getTimeMatcher) { - //was this line before 13.2.1 if (( skewtPaneRsc.getDescriptor().getTimeMatcher() == null || skewtPaneRsc.getDescriptor().getTimeMatcher().getTimeMatchBasis() == null)&& !getTimeMatcher) { - //DataTime[] dataTimes = new DataTime[dataTimelineList.size()]; - //Chin Note: we just have to do this once and set dataTimes size bigger than 1. - //Nsharp handles changing frame itself. It just need system to send change frame notice. - //That is happened at NsharpSkewTDescriptor.checkDrawTime(). - DataTime[] dataTimes = new DataTime[2/*stnTimeTable.size()*/]; - Date now = new Date(); - for(int k =0; k < 2/*stnTimeTable.size()*/ ; k++){ - dataTimes[k]= new DataTime(now, k); - } - //no need to get a descriptor from a renderableDispaly since we have a descriptor - skewtPaneRsc.getDescriptor().setDataTimes(dataTimes); - getTimeMatcher=true; + if (skewtPaneRsc != null) { + if (currentParcel == NsharpNativeConstants.PARCELTYPE_USER_DEFINED) + currentParcelLayerPressure = NsharpParcelDialog + .getUserDefdParcelMb(); + skewtPaneRsc.createRscParcelTraceShapes(currentParcel, + currentParcelLayerPressure); + skewtPaneRsc.createRscParcelRtTraceShapesList(currentParcel, + currentParcelLayerPressure); + skewtPaneRsc.createLCLEtcLinesShape(); } - - NsharpShowTextDialog textarea = NsharpShowTextDialog.getAccess(); - if(textarea != null){ - textarea.refreshTextData(); - } - NsharpPaletteWindow win = NsharpPaletteWindow.getInstance() ; - if(win!=null) - currentGraphMode=win.getCurrentGraphMode(); - - refreshPane(); - - } + } - public void addRsc(Map> soundMap, NsharpStationInfo stnInfo){ - //by default, display new data - //NCP always call from this route. - this.addRsc(true, soundMap, stnInfo); - return; - } - public String getPickedStnInfoStr() { - return pickedStnInfoStr; - } + public void updateParcelFromPanel(short currentParcel) { + this.currentParcel = currentParcel; + currentParcelLayerPressure = NsharpNativeConstants.parcelToLayerMap + .get(currentParcel); + if (skewtPaneRsc != null) { + skewtPaneRsc.createRscParcelTraceShapes(currentParcel, + currentParcelLayerPressure); + skewtPaneRsc.createRscParcelRtTraceShapesList(currentParcel, + currentParcelLayerPressure); + skewtPaneRsc.createLCLEtcLinesShape(); + } + } + public void setHodoStmCenter(Coordinate hodoHouseC) { + if (hodoPaneRsc == null) + return; + // hodoPaneRsc.setHodoHouseC(hodoHouseC); + Coordinate c = hodoPaneRsc.getHodoBackground().getWorld() + .unMap(hodoHouseC.x, hodoHouseC.y); + c = WxMath.speedDir((float) c.x, (float) c.y); + smWindDir = (float) c.y; + smWindSpd = (float) c.x; + nsharpNative.nsharpLib.set_storm(smWindSpd, smWindDir); + if (insetPaneRsc != null) { + WGraphics WGc = insetPaneRsc.getPsblWatchTypeBackground() + .getWorld(); + insetPaneRsc.createBkgPsblWatchShape(WGc); - public void handleUserClickOnStationId(Coordinate c) { - - //first to find if it is for change to next page, or change sorting - //System.out.println("numTimeLinePerPage="+numTimeLinePerPage+"gap="+(cnYOrig-dtNextPageEnd)); - int index =((int)(c.y - dtYOrig))/ charHeight; - - if(index == 0 ){ - //change to next/previous page - if( totalStnIdPage == 1) - return; - if((c.x - (dtXOrig+dtWidth)) < (dtWidth/2)){ - curStnIdPage++; - if(curStnIdPage>totalStnIdPage) - curStnIdPage=1; - } else { - curStnIdPage--; - if(curStnIdPage <=0) - curStnIdPage = totalStnIdPage; - } - return; - } - // recalculate index for time line - index =((int)(c.y - dtNextPageEnd))/ charHeight + - (curStnIdPage-1)* numTimeLinePerPage ; - - if( index < this.stnElementList.size() ){ - switch(stnElementList.get(index).getActionState()){ - - case INACTIVE: - stnElementList.get(index).setActionState( NsharpConstants.ActState.ACTIVE); - break; - case ACTIVE: - //do not allow deactivate current stn - if(index == currentStnElementListIndex) - return; - stnElementList.get(index).setActionState( NsharpConstants.ActState.INACTIVE); - break; - default: - return; - } - //findCurrentElementIndexesAfterConfig(); - //setCurSndProfileProp(); - //setCurrentSoundingLayerInfo(); - //resetData(); try these - if(skewtPaneRsc!=null) - skewtPaneRsc.createRscWireFrameShapes(); - if(hodoPaneRsc!=null) - hodoPaneRsc.createRscHodoWindShapeAll(); + // Sr wind vs Height graph shape need to recreate + WGc = insetPaneRsc.getSrWindsBackground().getWorld(); + insetPaneRsc.createRscSrWindShape(WGc); + } + if (skewtPaneRsc != null) { + skewtPaneRsc.createEffectiveLayerLinesShape(); + skewtPaneRsc.updatePsblWatchColor(); + } + } - } - } - - public void handleUserClickOnTimeLine(Coordinate c) { - - //first to find if it is for change to next/prev page - //System.out.println("numTimeLinePerPage="+numTimeLinePerPage+"gap="+(cnYOrig-dtNextPageEnd)); - int index =((int)(c.y - dtYOrig))/ charHeight; - if(index == 0 ){ - //change to next/previous page - if( totalTimeLinePage == 1) - return; - if((c.x - dtXOrig) < (dtWidth /2)){ - curTimeLinePage++; - if(curTimeLinePage>totalTimeLinePage) - curTimeLinePage=1; - } else { - curTimeLinePage--; - if(curTimeLinePage <=0) - curTimeLinePage = totalTimeLinePage; - } - return; - } - // recalculate index for time line - index =((int)(c.y - dtNextPageEnd))/ charHeight + - (curTimeLinePage-1)* numTimeLinePerPage ; - - if( index < timeElementList.size() && index >=0 ){ - switch(timeElementList.get(index).getActionState()){ - case INACTIVE: - timeElementList.get(index).setActionState( NsharpConstants.ActState.ACTIVE); - break; - case ACTIVE: - if(index == currentTimeElementListIndex) - //dont allow to deactive current time line - return; - timeElementList.get(index).setActionState( NsharpConstants.ActState.INACTIVE); - break; - - default: - return; + // This function is called only when interpolation "on/off" is changed by + // user + public void resetInfoOnInterpolate(boolean interpolateIsOn) + throws CloneNotSupportedException { + // We dont want to assume previous interpolation on/off state. So, reset + // soundingLys any how. + this.interpolateIsOn = interpolateIsOn; + NsharpSoundingElementStateProperty elem = getCurSoundingElementStateProperty(); + if (elem != null) { + if (interpolateIsOn == false) { + soundingLys = elem.getSndLyLst(); - } + } else { + /* + * //TTR829 //interpolation is on //we dont want to change + * original raw data, so use a deep copy List + * intpSndLst = new ArrayList(); + * for(NcSoundingLayer layer: elem.getSndLyLst() ) { + * intpSndLst.add((NcSoundingLayer) layer.clone()); } + * + * // interpolation intpSndLst = + * performInterpolation(intpSndLst); + * + * soundingLys = intpSndLst; + */ + // end TTR829 + soundingLys = performInterpolation(soundingLys); + } - //findCurrentElementIndexesAfterConfig(); - //setCurSndProfileProp(); - //setCurrentSoundingLayerInfo(); - //resetData(); try these - if(skewtPaneRsc!=null) - skewtPaneRsc.createRscWireFrameShapes(); - if(hodoPaneRsc!=null) - hodoPaneRsc.createRscHodoWindShapeAll(); - - } - } - public void handleUserClickOnSndLine(Coordinate c) { - - //first to find if it is for change to next/prev page - //System.out.println("numTimeLinePerPage="+numTimeLinePerPage+"gap="+(cnYOrig-dtNextPageEnd)); - int index =((int)(c.y - dtYOrig))/ charHeight; - if(index == 0 ){ - //change to next/previous page - if( totalSndPage == 1) - return; - if((c.x - dtXOrig) < (dtWidth/2)){ - curSndPage++; - if(curSndPage>totalSndPage) - curSndPage=1; - } else { - curSndPage--; - if(curSndPage <=0) - curSndPage = totalSndPage; - } - return; - } - // recalculate index for time line - index =((int)(c.y - dtNextPageEnd))/ charHeight + - (curSndPage-1)* numTimeLinePerPage ; - - if( index < sndElementList.size() && index >=0 ){ - switch(sndElementList.get(index).getActionState()){ - case INACTIVE: - sndElementList.get(index).setActionState( NsharpConstants.ActState.ACTIVE); - break; - case ACTIVE: - if(index == currentSndElementListIndex) - //dont allow to deactive current time line - return; - sndElementList.get(index).setActionState( NsharpConstants.ActState.INACTIVE); - break; - - default: - return; + nsharpNative.populateSndgData(soundingLys); + if (skewtPaneRsc != null) + skewtPaneRsc.resetData(soundingLys, previousSoundingLys); + if (hodoPaneRsc != null) + hodoPaneRsc.resetData(soundingLys, previousSoundingLys); + if (witoPaneRsc != null) + witoPaneRsc.resetData(soundingLys, previousSoundingLys); + if (dataPaneRsc != null) + dataPaneRsc.resetData(soundingLys, previousSoundingLys); + if (insetPaneRsc != null) + insetPaneRsc.resetData(soundingLys, previousSoundingLys); - } - if(skewtPaneRsc!=null) - skewtPaneRsc.createRscWireFrameShapes(); - if(hodoPaneRsc!=null) - hodoPaneRsc.createRscHodoWindShapeAll(); - - } - } - private void moveTimeLineIndexBackward(){ - previousTimeLineStateListIndex = currentTimeElementListIndex; - int counter=0; - while(true){ - currentTimeElementListIndex++; - currentTimeElementListIndex = currentTimeElementListIndex % this.timeElementList.size(); - counter++; - if(counter > timeElementList.size()) - break; - if( timeElementList.get(currentTimeElementListIndex).getActionState() == NsharpConstants.ActState.ACTIVE - && stnTimeSndTable.get(currentStnElementListIndex).get(currentTimeElementListIndex).get(currentSndElementListIndex)!=null){ - break;//out of while loop - } - - } - } - private void moveTimeLineIndexForward (){ - previousTimeLineStateListIndex = currentTimeElementListIndex; - int counter=0; - while(true){ - currentTimeElementListIndex= currentTimeElementListIndex + this.timeElementList.size();// so, we wont get a negative number - currentTimeElementListIndex--; - currentTimeElementListIndex = currentTimeElementListIndex % this.timeElementList.size(); - counter++; - if(counter > timeElementList.size()) - break; - if( timeElementList.get(currentTimeElementListIndex).getActionState() == NsharpConstants.ActState.ACTIVE - && stnTimeSndTable.get(currentStnElementListIndex).get(currentTimeElementListIndex).get(currentSndElementListIndex)!=null){ - break;//out of while loop - } - } - //System.out.println("timeline="+timeLineStateList.get(pickedTimeGroupIndex).getElementDescription()); - } - private void moveTimeLineIndexCycle (){ - previousTimeLineStateListIndex = currentTimeElementListIndex; - //Note: direction should only be NEXT or PREVIOUS - int counter=0; - while(true){ - counter++; - if(counter > timeElementList.size()){ - currentTimeElementListIndex = previousTimeLineStateListIndex; - break; - } - if(currentOpDirection == IFrameCoordinator.FrameChangeOperation.NEXT ){ - currentTimeElementListIndex--; - if(currentTimeElementListIndex <= 0){ - //the end of forward direction, change direction to backward - currentOpDirection = IFrameCoordinator.FrameChangeOperation.PREVIOUS; - currentTimeElementListIndex=0; - } + // re-create shape + if (skewtPaneRsc != null) + skewtPaneRsc.handleResize(); + if (hodoPaneRsc != null) + hodoPaneRsc.createRscHodoWindShapeAll(); + if (insetPaneRsc != null) + insetPaneRsc.createInsetWireFrameShapes(); + if (witoPaneRsc != null) + witoPaneRsc.createRscWireFrameShapes(); - } - else{ // direction is FrameChangeOperation.PREVIOUS - currentTimeElementListIndex++; - if(currentTimeElementListIndex >= timeElementList.size()-1){ - //the end of backward direction, change direction to forward - currentOpDirection = IFrameCoordinator.FrameChangeOperation.NEXT; - currentTimeElementListIndex = timeElementList.size()-1; - } - } - if( timeElementList.get(currentTimeElementListIndex).getActionState() == NsharpConstants.ActState.ACTIVE - && stnTimeSndTable.get(currentStnElementListIndex).get(currentTimeElementListIndex).get(currentSndElementListIndex)!=null){ - break;//out of while loop - } - } + } - } - /* - * Note: looping only apply to curAggregateTimeLineList NOT stationIdList - */ - public void setLoopingDataTimeLine(LoopProperties loopProperties) { - //System.out.println("setLoopingDataTimeLine loopmode ="+loopProperties.getMode().toString()); - if( this.timeElementList.size()>0) { - switch(loopProperties.getMode()){ - case Forward: - moveTimeLineIndexForward(); - break; - case Backward: - moveTimeLineIndexBackward(); - break; - case Cycle: - moveTimeLineIndexCycle(); - - break; - } - - curTimeLinePage = currentTimeElementListIndex/numTimeLinePerPage + 1; - setCurSndProfileProp(); - setCurrentSoundingLayerInfo(); - resetData(); - refreshPane(); - } - - } - public enum LoopMode { + } + + public void handleNsharpEditorPartEvent(NsharpPartListener.PartEvent pStatus) { + switch (pStatus) { + case partActivated: + if (editorPartStatus != NsharpPartListener.PartEvent.partDeactivated) { + // repopulateSndgData(); + // resetRsc(); + resetData(); + } + + break; + default: + break; + } + editorPartStatus = pStatus; + } + + public void resetRsc() { + restoreAllSoundingData(); + NsharpSoundingElementStateProperty elem = getCurSoundingElementStateProperty(); + if (elem != null) { + this.soundingLys = elem.getSndLyLst(); + // Set default parcel trace data + currentParcel = NsharpNativeConstants.PARCELTYPE_MOST_UNSTABLE; + currentParcelLayerPressure = NsharpNativeConstants.MU_LAYER; + setSoundingInfo(this.soundingLys); + currentTextChapter = 1; + overlayIsOn = false; + interpolateIsOn = false; + compareStnIsOn = false; + compareSndIsOn = false; + compareTmIsOn = false; + editGraphOn = false; + if (skewtPaneRsc != null) + skewtPaneRsc + .setCurrentSkewTEditMode(NsharpConstants.SKEWT_EDIT_MODE_EDITPOINT); + resetData(); + } + + } + + public synchronized void resetData() { + // System.out.println("resetData called, rscHdr="+this.toString() + + // " pickedStnInfoStr="+pickedStnInfoStr+ + // " nsharpNative="+nsharpNative.toString()); + + // update active sounding layer and picked stn info + // re-populate snd data to nsharp native code lib for later calculating + nsharpNative.populateSndgData(soundingLys); + if (skewtPaneRsc != null) + skewtPaneRsc.resetData(soundingLys, previousSoundingLys); + if (hodoPaneRsc != null) + hodoPaneRsc.resetData(soundingLys, previousSoundingLys); + if (insetPaneRsc != null) + insetPaneRsc.resetData(soundingLys, previousSoundingLys); + if (dataPaneRsc != null) + dataPaneRsc.resetData(soundingLys, previousSoundingLys); + if (witoPaneRsc != null) + witoPaneRsc.resetData(soundingLys, previousSoundingLys); + + NsharpShowTextDialog textarea = NsharpShowTextDialog.getAccess(); + if (textarea != null) { + textarea.refreshTextData(); + } + // if soundingLys is null, then we stop here, after reset data. + if (soundingLys == null) + return; + if (soundingLys.size() > 0) { + // set initial hodohouseC + + // ----- set hodo circle at Bunkers Right, Chin according to TTR6065 + // or RaytheonTicket#10438 + FloatByReference dummy1 = new FloatByReference(-999); + FloatByReference dummy2 = new FloatByReference(-999); + FloatByReference bwdir = new FloatByReference(-999); + FloatByReference bwspd = new FloatByReference(-999); + nsharpNative.nsharpLib.bunkers_storm_motion(dummy1, dummy2, bwdir, + bwspd); + // System.out.println("resetData windspd="+ bwspd.getValue()+ + // " dir="+bwdir.getValue()); + smWindSpd = bwspd.getValue(); + smWindDir = bwdir.getValue(); + nsharpNative.nsharpLib.set_storm(smWindSpd, smWindDir); + + // reset parcel + currentParcel = NsharpNativeConstants.PARCELTYPE_MOST_UNSTABLE; + currentParcelLayerPressure = NsharpNativeConstants.MU_LAYER; + // reset parcel dialog as well + if (NsharpParcelDialog.getAccess() != null) { + NsharpParcelDialog.getAccess().resetUserDefParcel(); + } + /* + * Chin::: This api is called in many scenarios. User may want to + * keep his previous picked parcel type. Therefore, + * thdataPaneRsc.resetCurrentParcel should be called from other area + * that really meant to reset parcel type. + */ + } + // Chin: TBD remove handle resize here to fix sizing issue when swapped + // nsharp from side pane back to main pane + // but, may cause other problem? + // if(skewtPaneRsc!=null) + // skewtPaneRsc.handleResize(); + if (skewtPaneRsc != null) + skewtPaneRsc.createRscWireFrameShapes(); + if (hodoPaneRsc != null) + hodoPaneRsc.createRscHodoWindShapeAll(); + if (insetPaneRsc != null) + insetPaneRsc.createInsetWireFrameShapes(); + if (witoPaneRsc != null) + witoPaneRsc.createAllWireFrameShapes(); + } + + private class NsharpOperationElementComparator implements + Comparator { + @Override + public int compare(NsharpOperationElement o1, NsharpOperationElement o2) { + + String s1tok1 = "";// , s1tok2=""; + String s2tok1 = "";// , s2tok2=""; + StringTokenizer st1 = new StringTokenizer( + o1.getElementDescription()); + int tkCount1 = st1.countTokens(); + // System.out.println("ElementComparatorTimeLine o1="+o1.elementDescription+"c1 = "+tkCount1); + if (tkCount1 >= 1) { + s1tok1 = st1.nextToken(); + } else { + return 0; + + } + // System.out.println("t1="+s1tok1+" t2="+s2tok1); + StringTokenizer st2 = new StringTokenizer( + o2.getElementDescription()); + int tkCount2 = st2.countTokens(); + // System.out.println("ElementComparatorTimeLine o2="+o2.elementDescription+"c2 = "+tkCount2); + if (tkCount2 >= 1) { + s2tok1 = st2.nextToken(); + } else { + return 0; + + } + // System.out.println("t1="+s2tok1+" t2="+s2tok2); + if (s1tok1.compareTo(s2tok1) == 0) { + return 0; + } else if (s1tok1.compareTo(s2tok1) < 0) { + return 1; + } else if (s1tok1.compareTo(s2tok1) > 0) { + return -1; + } + return 0; + } + } + + private int getIndexFromElementList(String targetDescription, + List elemLst) { + for (NsharpOperationElement sndProp : elemLst) { + if (sndProp.getElementDescription().equals(targetDescription)) + return elemLst.indexOf(sndProp); + + } + return -1; + } + + private void restoreAllSoundingData() { + for (List> tlListList : stnTimeSndTable) { + // add a new element for the new sndType to each existing sndlist of + // each existing time of each existing stnId + for (List sndtyList : tlListList) { + for (NsharpSoundingElementStateProperty elem : sndtyList) { + if (elem != null) + elem.restoreSndLyLstFromBackup(); + } + } + } + } + + private int addElemToElemList(String elemDesc, + List elemList) { + NsharpOperationElement elem = new NsharpOperationElement(elemDesc, + NsharpConstants.ActState.ACTIVE); + elemList.add(elem); + Collections.sort(elemList, new NsharpOperationElementComparator()); + return elemList.indexOf(elem); + } + + private void addNewSndToStnTimeSndTable(int sndIndex) { + for (List> tlListList : stnTimeSndTable) { + // add a new element for the new sndType to each existing sndlist of + // each existing time of each existing stnId + for (List sndtyList : tlListList) { + sndtyList.add(sndIndex, null); + } + } + } + + private void addNewStnToStnTimeSndTable(int stnIndex) { + // Add new stnid to outer list of stnTimeSndTable + List> listListForNewStn = new ArrayList>(); + // based on new stn id, add list for each existing time line + for (int i = 0; i < timeElementList.size(); i++) { + // based on each time line, add element for each existing sndType + List sndListForTm = new ArrayList(); + for (int j = 0; j < sndElementList.size(); j++) { + sndListForTm.add(null); + } + listListForNewStn.add(sndListForTm); + } + stnTimeSndTable.add(stnIndex, listListForNewStn); + } + + private void addNewTimeToStnTimeSndTable(int timeIndex) { + for (List> tlListList : stnTimeSndTable) { + // based on sndTypeElementList + // create sndlist for the new time line for each existing stnid + List newSndList = new ArrayList(); + for (int i = 0; i < sndElementList.size(); i++) { + newSndList.add(null); + } + // add sndlist for the new time line to stn list + tlListList.add(timeIndex, newSndList); + } + } + + private void addElementToTableAndLists(String stnId_timeLine_sndType, + String stnId, String tmLine, String sndType, + NsharpStationInfo stnInfo, List sndLyLst) { + // System.out.println("stn to be added "+ stnId + " timeline "+tmLine); + NsharpSoundingElementStateProperty newSndPropElem = null; + int tmIndex = getIndexFromElementList(tmLine, timeElementList); + int stnIndex = getIndexFromElementList(stnId, stnElementList); + int sndTpyeIndex = getIndexFromElementList(sndType, sndElementList); + currentTimeElementListIndex = tmIndex; + currentStnElementListIndex = stnIndex; + currentSndElementListIndex = sndTpyeIndex; + // based on these 3 indexes, we have 8 cases to handle. + if (tmIndex >= 0 && stnIndex >= 0 && sndTpyeIndex >= 0) { + // CASE1: All 3 index are good (>=0) + if (stnTimeSndTable.get(stnIndex).get(tmIndex).get(sndTpyeIndex) != null) + // this sounding element is already loaded + return; + else { + // replace previously added "null" object with real + // NsharpSoundingElementStateProperty object + newSndPropElem = new NsharpSoundingElementStateProperty( + stnId_timeLine_sndType, stnId, tmLine, stnInfo, + sndLyLst); + stnTimeSndTable.get(stnIndex).get(tmIndex) + .set(sndTpyeIndex, newSndPropElem); + } + } else if (tmIndex >= 0) { + if (stnIndex >= 0) { + // CASE2 : tmIndex/stnIndex are good (>=0), sndTpyeIndex is bad + // (<0), a new snd type + // add new sndType to sndTypeElementList + currentSndElementListIndex = addElemToElemList(sndType, + sndElementList); + // Add new snd type to each snd type list of stnTimeSndTable + addNewSndToStnTimeSndTable(currentSndElementListIndex); + // replace previously added "null" object with real + // NsharpSoundingElementStateProperty object + newSndPropElem = new NsharpSoundingElementStateProperty( + stnId_timeLine_sndType, stnId, tmLine, stnInfo, + sndLyLst); + stnTimeSndTable.get(currentStnElementListIndex) + .get(currentTimeElementListIndex) + .set(currentSndElementListIndex, newSndPropElem); + } else { + if (sndTpyeIndex >= 0) { + // CASE3 : tmIndex/sndTpyeIndex are good, stnIndex is bad + // (<0), a new stnId + // add new stn to stnElementList + currentStnElementListIndex = addElemToElemList(stnId, + stnElementList); + // Add new stnid to outer list of stnTimeSndTable + addNewStnToStnTimeSndTable(currentStnElementListIndex); + // replace previously added "null" object with real + // NsharpSoundingElementStateProperty object + newSndPropElem = new NsharpSoundingElementStateProperty( + stnId_timeLine_sndType, stnId, tmLine, stnInfo, + sndLyLst); + stnTimeSndTable.get(currentStnElementListIndex) + .get(currentTimeElementListIndex) + .set(currentSndElementListIndex, newSndPropElem); + + } else { + // CASE4 : tmIndex is good, stnIndex/sndTpyeIndex are bad + // (<0), new stnId and new snd type + // add new stn to stnElementList + currentStnElementListIndex = addElemToElemList(stnId, + stnElementList); + // add new sndType to sndTypeElementList + currentSndElementListIndex = addElemToElemList(sndType, + sndElementList); + // Add new snd type to each snd type list of stnTimeSndTable + addNewSndToStnTimeSndTable(currentSndElementListIndex); + // Add new stnid to outer list of stnTimeSndTable + addNewStnToStnTimeSndTable(currentStnElementListIndex); + // replace previously added "null" object with real + // NsharpSoundingElementStateProperty object + newSndPropElem = new NsharpSoundingElementStateProperty( + stnId_timeLine_sndType, stnId, tmLine, stnInfo, + sndLyLst); + stnTimeSndTable.get(currentStnElementListIndex) + .get(currentTimeElementListIndex) + .set(currentSndElementListIndex, newSndPropElem); + + } + } + } else { + if (stnIndex >= 0) { + if (sndTpyeIndex >= 0) { + // CASE5 : stnIndex/sndTpyeIndex are good, tmIndex is bad + // (<0) + // add new time line to timeElementList + currentTimeElementListIndex = addElemToElemList(tmLine, + timeElementList); + // add new time line to StnTimeSndTable + addNewTimeToStnTimeSndTable(currentTimeElementListIndex); + // replace previously added "null" object with real + // NsharpSoundingElementStateProperty object + newSndPropElem = new NsharpSoundingElementStateProperty( + stnId_timeLine_sndType, stnId, tmLine, stnInfo, + sndLyLst); + stnTimeSndTable.get(currentStnElementListIndex) + .get(currentTimeElementListIndex) + .set(currentSndElementListIndex, newSndPropElem); + + } else { + // CASE6 : stnIndex is good, tmIndex/sndTpyeIndex are bad + // (<0) + // add new time line to timeElementList + currentTimeElementListIndex = addElemToElemList(tmLine, + timeElementList); + // add new sndType to sndTypeElementList + currentSndElementListIndex = addElemToElemList(sndType, + sndElementList); + // Add new snd type to each snd type list of stnTimeSndTable + addNewSndToStnTimeSndTable(currentSndElementListIndex); + // add new time line to StnTimeSndTable + addNewTimeToStnTimeSndTable(currentTimeElementListIndex); + // replace previously added "null" object with real + // NsharpSoundingElementStateProperty object + newSndPropElem = new NsharpSoundingElementStateProperty( + stnId_timeLine_sndType, stnId, tmLine, stnInfo, + sndLyLst); + stnTimeSndTable.get(currentStnElementListIndex) + .get(currentTimeElementListIndex) + .set(currentSndElementListIndex, newSndPropElem); + + } + + } else { + if (sndTpyeIndex >= 0) { + // CASE7 : sndTpyeIndex is good, tmIndex/stnIndex are bad + // (<0) + // add new time line to timeElementList + currentTimeElementListIndex = addElemToElemList(tmLine, + timeElementList); + // add new stn to stnElementList + currentStnElementListIndex = addElemToElemList(stnId, + stnElementList); + // add new time line to StnTimeSndTable + addNewTimeToStnTimeSndTable(currentTimeElementListIndex); + // Add new stnid to outer list of stnTimeSndTable + addNewStnToStnTimeSndTable(currentStnElementListIndex); + // replace previously added "null" object with real + // NsharpSoundingElementStateProperty object + newSndPropElem = new NsharpSoundingElementStateProperty( + stnId_timeLine_sndType, stnId, tmLine, stnInfo, + sndLyLst); + stnTimeSndTable.get(currentStnElementListIndex) + .get(currentTimeElementListIndex) + .set(currentSndElementListIndex, newSndPropElem); + + } else { + // CASE8 : All are bad (<0) + // an element with new time line, new stnId and new sndType + // add new time line to timeElementList + currentTimeElementListIndex = addElemToElemList(tmLine, + timeElementList); + // add new stn to stnElementList + currentStnElementListIndex = addElemToElemList(stnId, + stnElementList); + // add new sndType to sndTypeElementList + currentSndElementListIndex = addElemToElemList(sndType, + sndElementList); + + // Construct stnTimeSndTable + if (stnTimeSndTable.size() > 0) { + List> listListForNewStn = new ArrayList>(); + // based on new stn id, add list for each existing time + // line + for (NsharpOperationElement tmElem : timeElementList) { + // based on each time line, add element for each + // existing sndType + List sndlistForTm = new ArrayList(); + for (NsharpOperationElement sndElem : sndElementList) { + if (tmLine.equals(tmElem + .getElementDescription()) + && sndType.equals(sndElem + .getElementDescription())) { + // only one case falls in this route as only + // one new loaded sounding data + newSndPropElem = new NsharpSoundingElementStateProperty( + stnId_timeLine_sndType, stnId, + tmLine, stnInfo, sndLyLst); + + sndlistForTm.add(newSndPropElem); + } else { + // create for not avail sounding profiles + sndlistForTm.add(null); + } + } + listListForNewStn.add(sndlistForTm); + } + + // Now update stnTimeSndTable by adding "dummy" + // NsharpSoundingElementStateProperty to all exiting stn + // listList and time list + // Note that we have NOT added "listListForNewStn" to + // stnTimeSndTable yet. + // we have to update current table now + for (List> tlListList : stnTimeSndTable) { + // add a new element for the new sndType to each + // existing sndlist of each existing time of each + // existing stnId + for (List sndtyList : tlListList) { + sndtyList.add(currentSndElementListIndex, null); + } + // based on sndTypeElementList + // add a new sndlist for the new time line for each + // existing stnid + List newSndList = new ArrayList(); + for (int i = 0; i < sndElementList.size(); i++) { + { + newSndList.add(null); + } + } + tlListList.add(currentTimeElementListIndex, + newSndList); + } + // finally, add this new stn list to table + stnTimeSndTable.add(currentStnElementListIndex, + listListForNewStn); + } else { + // this is the case, we are adding first element to + // stnTimeSndTable + // need a new stn time line list to stnTimeSndTable + List newList = new ArrayList(); + List> newListList = new ArrayList>(); + + newSndPropElem = new NsharpSoundingElementStateProperty( + stnId_timeLine_sndType, stnId, tmLine, stnInfo, + sndLyLst); + newList.add(newSndPropElem); + newListList.add(newList); + stnTimeSndTable.add(newListList); + curSndProfileProp = newSndPropElem; + return; + } + + } + } + } + setCurSndProfileProp(); + + } + + private void setCurSndProfileProp() { + if (currentTimeElementListIndex < 0 + || currentTimeElementListIndex >= timeElementList.size() + || currentStnElementListIndex < 0 + || currentStnElementListIndex >= stnElementList.size() + || currentSndElementListIndex < 0 + || currentSndElementListIndex >= sndElementList.size()) { + curSndProfileProp = null; + preSndProfileProp = null; + } else { + preSndProfileProp = curSndProfileProp; + curSndProfileProp = stnTimeSndTable.get(currentStnElementListIndex) + .get(currentTimeElementListIndex) + .get(currentSndElementListIndex); + } + } + + private void cleanUpStnTimeSndTable(int stni, int tmi, int sndi) { + boolean found = false; + // find if this station is no longer in use + List> tlListList = stnTimeSndTable + .get(stni); + for (List sndtyList : tlListList) { + for (NsharpSoundingElementStateProperty elem : sndtyList) { + if (elem != null) { + found = true; + break; + } + } + if (found) + break; + } + if (!found) { + // This stn is no longer in use...delete it from stnTimeSndTable and + // stnElementList + stnElementList.remove(stni); + tlListList = stnTimeSndTable.remove(stni); + tlListList.clear(); + } + // find if this time line is no longer in use + found = false; + for (List> tmListListForStn : stnTimeSndTable) { + List sndtyListForTm = tmListListForStn + .get(tmi); + for (NsharpSoundingElementStateProperty elem : sndtyListForTm) { + if (elem != null) { + found = true; + break; + } + } + if (found) + break; + } + if (!found) { + // This time line is no longer in use...delete it from + // stnTimeSndTable and timeElementList + timeElementList.remove(tmi); + for (List> tmListListForStn : stnTimeSndTable) { + List sndtyListForTm = tmListListForStn + .remove(tmi); + sndtyListForTm.clear(); + } + } + // find if this sounding type is no longer in use + found = false; + for (List> tmListListForStn : stnTimeSndTable) { + for (List sndtyListForTm : tmListListForStn) { + NsharpSoundingElementStateProperty elem = sndtyListForTm + .get(sndi); + if (elem != null) { + found = true; + break; + } + } + if (found) + break; + } + if (!found) { + // This sounding type is no longer in use...delete it from + // stnTimeSndTable and sndElementList + sndElementList.remove(sndi); + for (List> tmListListForStn : stnTimeSndTable) { + for (List sndtyListForTm : tmListListForStn) { + sndtyListForTm.remove(sndi); + } + } + } + + } + + public boolean deleteRsc(List deletingDataTimeList) { + boolean curSndDeleted = false; + for (String dataTmLine : deletingDataTimeList) { + if (curSndProfileProp != null + && curSndProfileProp.getElementDescription().equals( + dataTmLine)) { + curSndDeleted = true; + } + // find deleting element from stnTimeSndTable and null it + boolean setdone = false; + for (List> tlListList : stnTimeSndTable) { + for (List sndtyList : tlListList) { + for (NsharpSoundingElementStateProperty elem : sndtyList) { + if (elem != null + && dataTmLine.equals(elem + .getElementDescription())) { + int sndi = sndtyList.indexOf(elem); + int tmi = tlListList.indexOf(sndtyList); + int stni = stnTimeSndTable.indexOf(tlListList); + sndtyList.set(sndtyList.indexOf(elem), null); + setdone = true; + // clean up stnTimeSndTable if a stn/timeline/snd is + // no longer in use + cleanUpStnTimeSndTable(stni, tmi, sndi); + break; + } + } + if (setdone) + break; + } + if (setdone) + break; + } + } + + if (curSndDeleted || soundingLys == null) { + // this is the case that we are deleting current snd, so, a new + // current snd should be selected + curSndProfileProp = null; + // find CurrentElementIndexes After Delete current snding + boolean found = false; + int stni = 0; + for (List> tlListList : stnTimeSndTable) { + int timei = 0; + for (List sndtyList : tlListList) { + int sndi = 0; + for (NsharpSoundingElementStateProperty elem : sndtyList) { + if (elem != null + && stnElementList.get(stni).getActionState() == NsharpConstants.ActState.ACTIVE + && timeElementList.get(timei).getActionState() == NsharpConstants.ActState.ACTIVE + && sndElementList.get(sndi).getActionState() == NsharpConstants.ActState.ACTIVE) { + currentStnElementListIndex = stni; + currentSndElementListIndex = sndi; + currentTimeElementListIndex = timei; + found = true; + break; + } + sndi++; + } + if (found) + break; + timei++; + } + if (found) + break; + stni++; + } + if (!found) { + currentStnElementListIndex = -1; + currentSndElementListIndex = -1; + currentTimeElementListIndex = -1; + } + setCurSndProfileProp(); + } else { + // currentStnElementListIndex, currentSndElementListIndex and + // currentTimeElementListIndex may not point to right element + // after some elements are deleted. + currentStnElementListIndex = -1; + currentTimeElementListIndex = -1; + currentSndElementListIndex = -1; + if (curSndProfileProp != null) { + boolean found = false; + for (List> tmListListForStn : stnTimeSndTable) { + for (List sndtyListForTm : tmListListForStn) { + for (NsharpSoundingElementStateProperty elem : sndtyListForTm) { + if (elem != null + && curSndProfileProp + .getElementDescription() + .equals(elem + .getElementDescription())) { + currentSndElementListIndex = sndtyListForTm + .indexOf(elem); + currentTimeElementListIndex = tmListListForStn + .indexOf(sndtyListForTm); + currentStnElementListIndex = stnTimeSndTable + .indexOf(tmListListForStn); + found = true; + break; + } + } + if (found) + break; + } + if (found) + break; + } + } + } + setCurrentSoundingLayerInfo(); + resetData(); + System.out.println("num=" + getFrameCount()); + return curSndDeleted; + // anything more to do? + } + + public void deleteRscAll() { + NsharpMapResource nsharpMapResource = NsharpMapResource + .getOrCreateNsharpMapResource(); + nsharpMapResource.setPoints(null); + if (soundingLys != null) { + soundingLys.clear(); + soundingLys = null; + } + if (previousSoundingLys != null) { + previousSoundingLys.clear(); + previousSoundingLys = null; + } + if (stnTimeSndTable != null) { + for (List> stnListList : stnTimeSndTable) { + for (List timeList : stnListList) { + timeList.clear(); + } + stnListList.clear(); + } + stnTimeSndTable.clear(); + } + if (timeElementList != null) + timeElementList.clear(); + if (stnElementList != null) + stnElementList.clear(); + if (sndElementList != null) + sndElementList.clear(); + curSndProfileProp = null; + preSndProfileProp = null; + currentTextChapter = 1; + currentInsetPage = 1; + currentParcel = NsharpNativeConstants.PARCELTYPE_MOST_UNSTABLE; + currentParcelLayerPressure = NsharpNativeConstants.MU_LAYER; + currentTimeElementListIndex = -1; + currentStnElementListIndex = -1; + currentSndElementListIndex = -1; + resetData(); + } + + private NsharpSoundingElementStateProperty getCurSoundingElementStateProperty() { + if (currentTimeElementListIndex >= 0 + && currentStnElementListIndex >= 0 + && currentSndElementListIndex >= 0 + && stnTimeSndTable.get(currentStnElementListIndex) + .get(currentTimeElementListIndex) + .get(currentSndElementListIndex) != null) { + return stnTimeSndTable.get(currentStnElementListIndex) + .get(currentTimeElementListIndex) + .get(currentSndElementListIndex); + } + return null; + } + + private void setCurrentSoundingLayerInfo() { + NsharpSoundingElementStateProperty elem = getCurSoundingElementStateProperty(); + if (elem != null) { + pickedStnInfoStr = elem.getElementDescription(); + pickedStnInfo = elem.getStnInfo(); + + if (overlayIsOn) { + previousSoundingLys = soundingLys; + } else { + previousSoundingLys = null; + } + + if (interpolateIsOn == true) { + /* + * TTR829 deep copy is not necessary as performInterpolation() + * will re-allocate new layer for each layer //we dont want to + * change original raw data, so use a new copy NcSoundingLayer + * newLayer; List mySndLst = new + * ArrayList(); for(NcSoundingLayer + * layer:elem.getSndLyLst()){ newLayer = new NcSoundingLayer(); + * try { newLayer = (NcSoundingLayer) layer.clone(); + * + * } catch (CloneNotSupportedException e) { e.printStackTrace(); + * } //here a shallowCopy is enough mySndLst.add(newLayer); } // + * interpolation mySndLst = performInterpolation(mySndLst); + * + * soundingLys = mySndLst; + */ + + soundingLys = performInterpolation(elem.getSndLyLst()); + } else { + soundingLys = elem.getSndLyLst(); + } + } else { + previousSoundingLys = null; + soundingLys = null; + } + + } + + public void addRsc(Map> soundMap, + NsharpStationInfo stnInfo, boolean fromNCP) { + if (fromNCP) { + // this is from NCP do nothing now + this.addRsc(true, soundMap, stnInfo); + // NCP case: + // Key String format will be like this for NCUAIR + // KGRI 100616/03(Wed)-NCUAIR + // and for PFC/Grid sounding will be like this + // KGRI 100616/03(Wed)V001-GFSSND + } else { + // D2D case:::: + // this is from D2D, edit display and time line string to add short + // day-of-week and + // also add sounding type to string to solve an issue that data with + // same stn, same time line but different + // sounding type will not be loaded. + // D2D's key string is like this: "KGRI 2010-06-16 03:00:00" + // will change it to "KGRI 100616/03(Wed)-GFSSND" + Set dataTimelineSet = soundMap.keySet(); + SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + // DateFormatSymbols dfs= new DateFormatSymbols(); + // String[] defaultDays = dfs.getShortWeekdays(); + Calendar cal = Calendar.getInstance(); + Date date; + Map> newmap = new HashMap>(); + String sndType = stnInfo.getSndType(); + for (String timeline : dataTimelineSet) { + System.out.println("D2D sending timeline Str:" + timeline); + String dateStr = timeline.substring(timeline.indexOf(' ') + 1); + String stnId = timeline.substring(0, timeline.indexOf(' ')); + try { + date = df.parse(dateStr); + cal.setTime(date); + String dayOfWeek = defaultDays[cal + .get(Calendar.DAY_OF_WEEK)]; + // dateStr = timeline.substring(0, + // timeline.indexOf(':'))+dayOfWeek+stnInfo.getSndType(); + // System.out.println("New Str:"+ dateStr); + String finalTimeStr = String.format( + "%4$s %1$ty%1$tm%1$td/%1$tH(%2$s) %3$s", cal, + dayOfWeek, sndType, stnId); + System.out.println("D2D (modified) timeline Str:" + + finalTimeStr); + // put newTimeStr to new map with original value + newmap.put(finalTimeStr, soundMap.get(timeline)); + } catch (ParseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + continue; + } + } + // this is from D2D, and it does not want to display new data right + // away. + this.addRsc(false, newmap, stnInfo); + } + } + + /* + * public void loadSoundingData( boolean displayNewData, + * List soundDataLst, String stnId, String sndType, + * Timestamp rangeStartTime,double latitude,double longitude){ //* testing + * code //stnInfo.setStnId("KFSD"); { Set keyset= new + * HashSet(soundMap.keySet()); for(String key: keyset) { + * List sndLy = soundMap.remove(key); String newkey= + * key.replace("NAMS", "yahoo"); //String newkey= key.replace("GFSS", + * "NAMS"); //newkey = newkey.replace("KSLN", "KFSD"); soundMap.put(newkey, + * sndLy); } stnInfo.setSndType(stnInfo.getSndType().replace("NAMS", + * "yahoo")); //stnInfo.setSndType(stnInfo.getSndType().replace("GFSS", + * "NAMS")); }// + * + * //need to format reftime to GMT time string. Timestamp.toString produce a + * local time Not GMT time Calendar cal = + * Calendar.getInstance(TimeZone.getTimeZone("GMT")); + * cal.setTimeInMillis(rangeStartTime.getTime()); String dayOfWeek = + * defaultDays[cal.get(Calendar.DAY_OF_WEEK)]; String timeLine = + * String.format("%1$ty%1$tm%1$td/%1$tH(%2$s)", cal, dayOfWeek); + * if(stnId.indexOf(" ")>=0){ //take care stnId with SPACE case. stnId = + * stnId.replace(" ", "_"); } if(timeElementList.isEmpty() || + * stnElementList.isEmpty() || currentSndElementListIndex < 0 + * ||sndElementList.isEmpty() || currentTimeElementListIndex < 0 || + * currentStnElementListIndex < 0){ //if no data was loaded since, then + * display this data any way displayNewData = true; } //save current + * timeline and stn state properties if we are NOT loading new data + * NsharpOperationElement currentTL=null; NsharpOperationElement + * currentStn=null; NsharpOperationElement currentSnd=null; + * NsharpSoundingElementStateProperty currentPreSndProfileProp=null; + * if(!displayNewData){ currentTL = + * timeElementList.get(currentTimeElementListIndex); currentStn = + * stnElementList.get(currentStnElementListIndex); currentSnd = + * sndElementList.get(currentSndElementListIndex); currentPreSndProfileProp + * = preSndProfileProp; } //add new data to table //add time line to + * stnTimeTable and set its index + * addElementToTableAndLists((stnId+" "+timeLine + * +" "+sndType),stnId,timeLine,sndType,stnInfo, soundDataLst); + * + * if(displayNewData){ //Set default parcel trace data currentParcel = + * NsharpNativeConstants.PARCELTYPE_MOST_UNSTABLE; + * currentParcelLayerPressure = NsharpNativeConstants.MU_LAYER; + * setCurrentSoundingLayerInfo(); resetData(); } else { //Not display new + * data. Reset current "parameter"s after adding data to map/lists + * currentStnElementListIndex= stnElementList.indexOf(currentStn); + * currentTimeElementListIndex = timeElementList.indexOf(currentTL); + * currentSndElementListIndex = sndElementList.indexOf(currentSnd); + * preSndProfileProp = currentPreSndProfileProp; curSndProfileProp = + * stnTimeSndTable + * .get(currentStnElementListIndex).get(currentTimeElementListIndex + * ).get(currentSndElementListIndex); } + * + * //set total time line group and stn id list page number + * calculateTimeStnBoxData(); + * + * //set data time to descriptor //this is necessary for looping // starting + * 13.2.1, this line is changed by Raytheon if (( + * skewtPaneRsc.getDescriptor().getFramesInfo().getFrameCount() == 0)&& + * !getTimeMatcher) { //was this line before 13.2.1 if (( + * skewtPaneRsc.getDescriptor().getTimeMatcher() == null || + * skewtPaneRsc.getDescriptor().getTimeMatcher().getTimeMatchBasis() == + * null)&& !getTimeMatcher) { //DataTime[] dataTimes = new + * DataTime[dataTimelineList.size()]; //Chin Note: we just have to do this + * once and set dataTimes size bigger than 1. //Nsharp handles changing + * frame itself. It just need system to send change frame notice. //That is + * happened at NsharpSkewTDescriptor.checkDrawTime(). DataTime[] dataTimes = + * new DataTime[2]; Date now = new Date(); for(int k =0; k < 2 ; k++){ + * dataTimes[k]= new DataTime(now, k); } //no need to get a descriptor from + * a renderableDispaly since we have a descriptor + * skewtPaneRsc.getDescriptor().setDataTimes(dataTimes); + * getTimeMatcher=true; } + * + * NsharpShowTextDialog textarea = NsharpShowTextDialog.getAccess(); + * if(textarea != null){ textarea.refreshTextData(); } NsharpPaletteWindow + * win = NsharpPaletteWindow.getInstance() ; if(win!=null) + * currentGraphMode=win.getCurrentGraphMode(); + * + * refreshPane(); + * + * } + */ + + private void addRsc(boolean displayNewData, + Map> soundMap, + NsharpStationInfo stnInfo) { + /* + * testing code //stnInfo.setStnId("KFSD"); { Set keyset= new + * HashSet(soundMap.keySet()); for(String key: keyset) { + * List sndLy = soundMap.remove(key); String newkey= + * key.replace("NCUAIR", "gpduair"); //String newkey= + * key.replace("GFSS", "NAMS"); //String newkey = key.replace("OAK", + * "KFSD"); soundMap.put(newkey, sndLy); } + * stnInfo.setSndType(stnInfo.getSndType().replace("NCUAIR", + * "gpduair")); + * //stnInfo.setSndType(stnInfo.getSndType().replace("GFSS", "NAMS")); + * }// + */ + + if (stnInfo.getStnId() != null && stnInfo.getStnId().indexOf(" ") >= 0) { + // take care stnId with SPACE case. + String stnId = stnInfo.getStnId(); + String newStnId = stnId.replace(" ", "_"); + stnInfo.setStnId(newStnId); + String dspInfo = stnInfo.getStnDisplayInfo(); + stnInfo.setStnDisplayInfo(dspInfo.replace(stnId, newStnId)); + Set keyset = new HashSet(soundMap.keySet()); + for (String key : keyset) { + List sndLy = soundMap.remove(key); + String newkey = key.replace(stnId, newStnId); + soundMap.put(newkey, sndLy); + } + + } + + if (soundMap.size() <= 0 || (skewtPaneRsc == null)) { + return; + } + if (timeElementList.isEmpty() || stnElementList.isEmpty() + || currentSndElementListIndex < 0 || sndElementList.isEmpty() + || currentTimeElementListIndex < 0 + || currentStnElementListIndex < 0) { + // if no data was loaded since, then display this data any way + displayNewData = true; + } + // save current timeline and stn state properties if we are NOT loading + // new data + NsharpOperationElement currentTL = null; + NsharpOperationElement currentStn = null; + NsharpOperationElement currentSnd = null; + NsharpSoundingElementStateProperty currentPreSndProfileProp = null; + if (!displayNewData) { + currentTL = timeElementList.get(currentTimeElementListIndex); + currentStn = stnElementList.get(currentStnElementListIndex); + currentSnd = sndElementList.get(currentSndElementListIndex); + currentPreSndProfileProp = preSndProfileProp; + } + // add new data to table + Set dataTimelineSet = soundMap.keySet(); + String[] tempTimeLineArr = dataTimelineSet + .toArray(new String[dataTimelineSet.size()]); + Arrays.sort(tempTimeLineArr); + for (int i = 0; i < tempTimeLineArr.length; i++) { + // based on this KEY string format "KGRI 100616/03(Wed) GFSSND" + String stnId_timeLine_sndType = tempTimeLineArr[i].toString(); + String stnId = stnId_timeLine_sndType.substring(0, + stnId_timeLine_sndType.indexOf(" ")); + String timeLine_sndType = stnId_timeLine_sndType + .substring(stnId_timeLine_sndType.indexOf(" ") + 1); + String timeLine = timeLine_sndType.substring(0, + timeLine_sndType.indexOf(" ")); + String sndType = timeLine_sndType.substring(timeLine_sndType + .indexOf(" ") + 1); + // No more needed? timeLine = timeLine.replace(" ", "-"); //fixed + // DR15325 - sorting time line issue in D2D + // add time line to stnTimeTable and set its index + addElementToTableAndLists(stnId_timeLine_sndType, stnId, timeLine, + sndType, stnInfo, soundMap.get(stnId_timeLine_sndType)); + } + if (displayNewData) { + // Set default parcel trace data + currentParcel = NsharpNativeConstants.PARCELTYPE_MOST_UNSTABLE; + currentParcelLayerPressure = NsharpNativeConstants.MU_LAYER; + setCurrentSoundingLayerInfo(); + resetData(); + } else { + // Not display new data. Reset current "parameter"s after adding + // data to map/lists + currentStnElementListIndex = stnElementList.indexOf(currentStn); + currentTimeElementListIndex = timeElementList.indexOf(currentTL); + currentSndElementListIndex = sndElementList.indexOf(currentSnd); + preSndProfileProp = currentPreSndProfileProp; + curSndProfileProp = stnTimeSndTable.get(currentStnElementListIndex) + .get(currentTimeElementListIndex) + .get(currentSndElementListIndex); + } + + // set total time line group and stn id list page number + calculateTimeStnBoxData(); + + // set data time to descriptor + // this is necessary for looping + // starting 13.2.1, this line is changed by Raytheon + if ((skewtPaneRsc.getDescriptor().getFramesInfo().getFrameCount() == 0) + && !getTimeMatcher) { + // was this line before 13.2.1 if (( + // skewtPaneRsc.getDescriptor().getTimeMatcher() == null || + // skewtPaneRsc.getDescriptor().getTimeMatcher().getTimeMatchBasis() + // == null)&& !getTimeMatcher) { + // DataTime[] dataTimes = new DataTime[dataTimelineList.size()]; + // Chin Note: we just have to do this once and set dataTimes size + // bigger than 1. + // Nsharp handles changing frame itself. It just need system to send + // change frame notice. + // That is happened at NsharpSkewTDescriptor.checkDrawTime(). + DataTime[] dataTimes = new DataTime[2/* stnTimeTable.size() */]; + Date now = new Date(); + for (int k = 0; k < 2/* stnTimeTable.size() */; k++) { + dataTimes[k] = new DataTime(now, k); + } + // no need to get a descriptor from a renderableDispaly since we + // have a descriptor + skewtPaneRsc.getDescriptor().setDataTimes(dataTimes); + getTimeMatcher = true; + } + + NsharpShowTextDialog textarea = NsharpShowTextDialog.getAccess(); + if (textarea != null) { + textarea.refreshTextData(); + } + NsharpPaletteWindow win = NsharpPaletteWindow.getInstance(); + if (win != null) + currentGraphMode = win.getCurrentGraphMode(); + + refreshPane(); + + } + + public void addRsc(Map> soundMap, + NsharpStationInfo stnInfo) { + // by default, display new data + // NCP always call from this route. + this.addRsc(true, soundMap, stnInfo); + return; + } + + public String getPickedStnInfoStr() { + return pickedStnInfoStr; + } + + public void handleUserClickOnStationId(Coordinate c) { + + // first to find if it is for change to next page, or change sorting + // System.out.println("numTimeLinePerPage="+numTimeLinePerPage+"gap="+(cnYOrig-dtNextPageEnd)); + int index = ((int) (c.y - dtYOrig)) / charHeight; + + if (index == 0) { + // change to next/previous page + if (totalStnIdPage == 1) + return; + if ((c.x - (dtXOrig + dtWidth)) < (dtWidth / 2)) { + curStnIdPage++; + if (curStnIdPage > totalStnIdPage) + curStnIdPage = 1; + } else { + curStnIdPage--; + if (curStnIdPage <= 0) + curStnIdPage = totalStnIdPage; + } + return; + } + // recalculate index for time line + index = ((int) (c.y - dtNextPageEnd)) / charHeight + (curStnIdPage - 1) + * numTimeLinePerPage; + + if (index < this.stnElementList.size()) { + switch (stnElementList.get(index).getActionState()) { + + case INACTIVE: + stnElementList.get(index).setActionState( + NsharpConstants.ActState.ACTIVE); + break; + case ACTIVE: + // do not allow deactivate current stn + if (index == currentStnElementListIndex) + return; + stnElementList.get(index).setActionState( + NsharpConstants.ActState.INACTIVE); + break; + default: + return; + } + // findCurrentElementIndexesAfterConfig(); + // setCurSndProfileProp(); + // setCurrentSoundingLayerInfo(); + // resetData(); try these + if (skewtPaneRsc != null) + skewtPaneRsc.createRscWireFrameShapes(); + if (hodoPaneRsc != null) + hodoPaneRsc.createRscHodoWindShapeAll(); + + } + } + + public void handleUserClickOnTimeLine(Coordinate c) { + + // first to find if it is for change to next/prev page + // System.out.println("numTimeLinePerPage="+numTimeLinePerPage+"gap="+(cnYOrig-dtNextPageEnd)); + int index = ((int) (c.y - dtYOrig)) / charHeight; + if (index == 0) { + // change to next/previous page + if (totalTimeLinePage == 1) + return; + if ((c.x - dtXOrig) < (dtWidth / 2)) { + curTimeLinePage++; + if (curTimeLinePage > totalTimeLinePage) + curTimeLinePage = 1; + } else { + curTimeLinePage--; + if (curTimeLinePage <= 0) + curTimeLinePage = totalTimeLinePage; + } + return; + } + // recalculate index for time line + index = ((int) (c.y - dtNextPageEnd)) / charHeight + + (curTimeLinePage - 1) * numTimeLinePerPage; + + if (index < timeElementList.size() && index >= 0) { + switch (timeElementList.get(index).getActionState()) { + case INACTIVE: + timeElementList.get(index).setActionState( + NsharpConstants.ActState.ACTIVE); + break; + case ACTIVE: + if (index == currentTimeElementListIndex) + // dont allow to deactive current time line + return; + timeElementList.get(index).setActionState( + NsharpConstants.ActState.INACTIVE); + break; + + default: + return; + + } + + // findCurrentElementIndexesAfterConfig(); + // setCurSndProfileProp(); + // setCurrentSoundingLayerInfo(); + // resetData(); try these + if (skewtPaneRsc != null) + skewtPaneRsc.createRscWireFrameShapes(); + if (hodoPaneRsc != null) + hodoPaneRsc.createRscHodoWindShapeAll(); + + } + } + + public void handleUserClickOnSndLine(Coordinate c) { + + // first to find if it is for change to next/prev page + // System.out.println("numTimeLinePerPage="+numTimeLinePerPage+"gap="+(cnYOrig-dtNextPageEnd)); + int index = ((int) (c.y - dtYOrig)) / charHeight; + if (index == 0) { + // change to next/previous page + if (totalSndPage == 1) + return; + if ((c.x - dtXOrig) < (dtWidth / 2)) { + curSndPage++; + if (curSndPage > totalSndPage) + curSndPage = 1; + } else { + curSndPage--; + if (curSndPage <= 0) + curSndPage = totalSndPage; + } + return; + } + // recalculate index for time line + index = ((int) (c.y - dtNextPageEnd)) / charHeight + (curSndPage - 1) + * numTimeLinePerPage; + + if (index < sndElementList.size() && index >= 0) { + switch (sndElementList.get(index).getActionState()) { + case INACTIVE: + sndElementList.get(index).setActionState( + NsharpConstants.ActState.ACTIVE); + break; + case ACTIVE: + if (index == currentSndElementListIndex) + // dont allow to deactive current time line + return; + sndElementList.get(index).setActionState( + NsharpConstants.ActState.INACTIVE); + break; + + default: + return; + + } + if (skewtPaneRsc != null) + skewtPaneRsc.createRscWireFrameShapes(); + if (hodoPaneRsc != null) + hodoPaneRsc.createRscHodoWindShapeAll(); + + } + } + + private void moveTimeLineIndexBackward() { + previousTimeLineStateListIndex = currentTimeElementListIndex; + int counter = 0; + while (true) { + currentTimeElementListIndex++; + currentTimeElementListIndex = currentTimeElementListIndex + % this.timeElementList.size(); + counter++; + if (counter > timeElementList.size()) + break; + if (timeElementList.get(currentTimeElementListIndex) + .getActionState() == NsharpConstants.ActState.ACTIVE + && stnTimeSndTable.get(currentStnElementListIndex) + .get(currentTimeElementListIndex) + .get(currentSndElementListIndex) != null) { + break;// out of while loop + } + + } + } + + private void moveTimeLineIndexForward() { + previousTimeLineStateListIndex = currentTimeElementListIndex; + int counter = 0; + while (true) { + currentTimeElementListIndex = currentTimeElementListIndex + + this.timeElementList.size();// so, we wont get a negative + // number + currentTimeElementListIndex--; + currentTimeElementListIndex = currentTimeElementListIndex + % this.timeElementList.size(); + counter++; + if (counter > timeElementList.size()) + break; + if (timeElementList.get(currentTimeElementListIndex) + .getActionState() == NsharpConstants.ActState.ACTIVE + && stnTimeSndTable.get(currentStnElementListIndex) + .get(currentTimeElementListIndex) + .get(currentSndElementListIndex) != null) { + break;// out of while loop + } + } + // System.out.println("timeline="+timeLineStateList.get(pickedTimeGroupIndex).getElementDescription()); + } + + private void moveTimeLineIndexCycle() { + previousTimeLineStateListIndex = currentTimeElementListIndex; + // Note: direction should only be NEXT or PREVIOUS + int counter = 0; + while (true) { + counter++; + if (counter > timeElementList.size()) { + currentTimeElementListIndex = previousTimeLineStateListIndex; + break; + } + if (currentOpDirection == IFrameCoordinator.FrameChangeOperation.NEXT) { + currentTimeElementListIndex--; + if (currentTimeElementListIndex <= 0) { + // the end of forward direction, change direction to + // backward + currentOpDirection = IFrameCoordinator.FrameChangeOperation.PREVIOUS; + currentTimeElementListIndex = 0; + } + + } else { // direction is FrameChangeOperation.PREVIOUS + currentTimeElementListIndex++; + if (currentTimeElementListIndex >= timeElementList.size() - 1) { + // the end of backward direction, change direction to + // forward + currentOpDirection = IFrameCoordinator.FrameChangeOperation.NEXT; + currentTimeElementListIndex = timeElementList.size() - 1; + } + } + if (timeElementList.get(currentTimeElementListIndex) + .getActionState() == NsharpConstants.ActState.ACTIVE + && stnTimeSndTable.get(currentStnElementListIndex) + .get(currentTimeElementListIndex) + .get(currentSndElementListIndex) != null) { + break;// out of while loop + } + } + + } + + /* + * Note: looping only apply to curAggregateTimeLineList NOT stationIdList + */ + public void setLoopingDataTimeLine(LoopProperties loopProperties) { + // System.out.println("setLoopingDataTimeLine loopmode ="+loopProperties.getMode().toString()); + if (this.timeElementList.size() > 0) { + switch (loopProperties.getMode()) { + case Forward: + moveTimeLineIndexForward(); + break; + case Backward: + moveTimeLineIndexBackward(); + break; + case Cycle: + moveTimeLineIndexCycle(); + + break; + } + + curTimeLinePage = currentTimeElementListIndex / numTimeLinePerPage + + 1; + setCurSndProfileProp(); + setCurrentSoundingLayerInfo(); + resetData(); + refreshPane(); + } + + } + + public enum LoopMode { Forward, Backward, Cycle }; - - private int getElemlistActiveNumber(List elemlist){ - int n=0; - for (NsharpOperationElement elem: elemlist){ - if(elem.getActionState() == NsharpConstants.ActState.ACTIVE){ - n++; - } - } - return n; - } - - public void setSteppingTimeLine(IFrameCoordinator.FrameChangeOperation operation, IFrameCoordinator.FrameChangeMode mode) { - if( this.timeElementList.size() > 0 && getElemlistActiveNumber(timeElementList)>1/* && getAvailTimeLineNumber(currentStnStateListIndex)>1*/) { - int targetIndex = currentTimeElementListIndex; - //previousTimeLineStateListIndex = currentTimeLineStateListIndex; - //preset index for LAST and FIRST operation - switch(operation){ - case LAST: //the future-est time, at top of time line shown. set to -1, so in while loop, it starts from 0 - targetIndex=-1;// - break; - case FIRST: //the oldest time, set to dataTimelineList.length, so in while loop, it starts from dataTimelineList.length-1 - targetIndex = timeElementList.size(); - break; - default: - break; - - } - - int counter=0; - while(true){ - switch(operation){ - case LAST: //the future-est time, at top of time line shown - targetIndex++; - break; - case FIRST: //the oldest time - targetIndex--; - break; - case PREVIOUS: - targetIndex++; - targetIndex = targetIndex % this.timeElementList.size(); - break; - case NEXT: - // so, we wont get a negative number - targetIndex= targetIndex + this.timeElementList.size(); - targetIndex--; - targetIndex = targetIndex % this.timeElementList.size(); - break; - default: - break; - } - counter++; - if(counter >= timeElementList.size()) - return; // looped through whole list already, and index back to original - - if(timeElementList.get(targetIndex).getActionState() == NsharpConstants.ActState.ACTIVE){ - if(compareTmIsOn && currentStnElementListIndex >=0 && currentSndElementListIndex >=0 && - stnTimeSndTable.get(currentStnElementListIndex).get(targetIndex).get(currentSndElementListIndex)== null){ - continue; - } - else if(compareStnIsOn){ - boolean found = false; - if(currentStnElementListIndex >=0 && currentSndElementListIndex >=0 && - stnTimeSndTable.get(currentStnElementListIndex).get(targetIndex).get(currentSndElementListIndex)!=null){ - found = true; - } - else{ - //find an active and available stn for this timeline and set is as current - for (int i=0; i < stnElementList.size(); i++){ - if(stnElementList.get(i).getActionState()==NsharpConstants.ActState.ACTIVE && - stnTimeSndTable.get(i).get(targetIndex).get(currentSndElementListIndex) !=null){ - currentStnElementListIndex = i; - found = true; - break; - } - } - } - if(!found){ - currentStnElementListIndex = -1; - } - else{ - int colorIndex = NsharpConstants.LINE_COMP1; - for(NsharpOperationElement elm: stnElementList) { - int stnIndex = stnElementList.indexOf(elm); - NsharpSoundingElementStateProperty stnTmElm = stnTimeSndTable.get(stnIndex).get(targetIndex).get(currentSndElementListIndex); - if(stnTmElm != null){ - stnTmElm.setCompColorIndex(colorIndex); - //if(colorIndex > NsharpConstants.LINE_COMP10) - // colorIndex = NsharpConstants.LINE_COMP1; - } - colorIndex++; - if(colorIndex > NsharpConstants.LINE_COMP10) - colorIndex = NsharpConstants.LINE_COMP1; - } - } - //no matter we find current stn or not - //we should get out of here - break; - } - else if(compareSndIsOn){ - boolean found = false; - if(currentStnElementListIndex >=0 && currentSndElementListIndex >=0 && - stnTimeSndTable.get(currentStnElementListIndex).get(targetIndex).get(currentSndElementListIndex)!=null){ - found = true; - } - else { - //find an active and available snd for this stn and set is as current - for (int i=0; i < sndElementList.size(); i++){ - if(sndElementList.get(i).getActionState()== NsharpConstants.ActState.ACTIVE && - stnTimeSndTable.get(currentStnElementListIndex).get(targetIndex).get(i)!=null){ - currentSndElementListIndex = i; - found = true; - break; - } - } - } - if(!found){ - currentSndElementListIndex = -1; - } - else{ - int colorIndex = NsharpConstants.LINE_COMP1; - for(NsharpOperationElement elm: sndElementList) { - if(elm.getActionState() == NsharpConstants.ActState.INACTIVE) - continue; - int sndIndex = sndElementList.indexOf(elm); - NsharpSoundingElementStateProperty stnTmElm = stnTimeSndTable.get(currentStnElementListIndex).get(targetIndex).get(sndIndex); - if(stnTmElm!=null){ - stnTmElm.setCompColorIndex(colorIndex); - } - colorIndex++; - if(colorIndex > NsharpConstants.LINE_COMP10) - colorIndex = NsharpConstants.LINE_COMP1; - } - } - //no matter we find current snd type for this stn or not - //we should get out of here - break; - } - else{ - break; - } - } - } - previousTimeLineStateListIndex = currentTimeElementListIndex; - currentTimeElementListIndex = targetIndex; - curTimeLinePage = currentTimeElementListIndex/numTimeLinePerPage + 1; - setCurSndProfileProp(); - setCurrentSoundingLayerInfo(); - resetData(); - refreshPane(); - } - } - - /* - * Stn index stepping is only controlled by up/down arrow keys, down key = PREVIOUS operation, up key = NEXT operation - */ - public void setSteppingStnIdList(IFrameCoordinator.FrameChangeOperation operation) { - if( this.stnElementList.size() > 0 && getElemlistActiveNumber(stnElementList)>1){ - - int counter=0; - while(true){ - switch(operation){ - case NEXT: - currentStnElementListIndex= currentStnElementListIndex + this.stnElementList.size(); - currentStnElementListIndex--; - currentStnElementListIndex = currentStnElementListIndex % this.stnElementList.size(); - break; - case PREVIOUS: - // so, we wont get a negative number - currentStnElementListIndex++; - currentStnElementListIndex = currentStnElementListIndex % this.stnElementList.size(); - break; - default: - break; - - } - counter++; - //System.out.println("counter = "+ counter); - if(counter >= stnElementList.size()) - return; // looped through whole list already, and index back to original - if(stnElementList.get(currentStnElementListIndex).getActionState() == NsharpConstants.ActState.ACTIVE){ - if (compareStnIsOn && currentTimeElementListIndex>=0 && currentSndElementListIndex>=0 - && stnTimeSndTable.get(currentStnElementListIndex).get(currentTimeElementListIndex).get(currentSndElementListIndex)== null){//.getElementState() == NsharpConstants.LoadState.NOTAVAIL){ - continue; - } - else if(compareTmIsOn){ - boolean found = false; - if( currentTimeElementListIndex>=0 && currentSndElementListIndex>=0 && - stnTimeSndTable.get(currentStnElementListIndex).get(currentTimeElementListIndex).get(currentSndElementListIndex)!=null){ - // use currentTimeLineStateListIndex - found = true; - } - else { - //find an active and available timeline for this stn and set is as current - for (int i=0; i < timeElementList.size(); i++){ - if(timeElementList.get(i).getActionState()== NsharpConstants.ActState.ACTIVE && - stnTimeSndTable.get(currentStnElementListIndex).get(i).get(currentSndElementListIndex)!=null){ - currentTimeElementListIndex = i; - found = true; - break; - } - } - } - if(!found){ - currentTimeElementListIndex = -1; - } - else{ - int colorIndex = NsharpConstants.LINE_COMP1; - for(NsharpOperationElement elm: timeElementList) { - if(elm.getActionState() == NsharpConstants.ActState.INACTIVE) - continue; - int tmIndex = timeElementList.indexOf(elm); - NsharpSoundingElementStateProperty stnTmElm = stnTimeSndTable.get(currentStnElementListIndex).get(tmIndex).get(currentSndElementListIndex); - if(stnTmElm!=null){ - stnTmElm.setCompColorIndex(colorIndex); - } - colorIndex++; - if(colorIndex > NsharpConstants.LINE_COMP10) - colorIndex = NsharpConstants.LINE_COMP1; - - } - } - //no matter we find current time line for this stn or not - //we should get out of here - break; - } - else if(compareSndIsOn){ - boolean found = false; - if( currentTimeElementListIndex>=0 && currentSndElementListIndex>=0 && - stnTimeSndTable.get(currentStnElementListIndex).get(currentTimeElementListIndex).get(currentSndElementListIndex)!=null){ - found = true; - } - else { - //find an active and available snd for this stn and set is as current - for (int i=0; i < sndElementList.size(); i++){ - if(sndElementList.get(i).getActionState()== NsharpConstants.ActState.ACTIVE && - stnTimeSndTable.get(currentStnElementListIndex).get(currentTimeElementListIndex).get(i)!=null){ - currentSndElementListIndex = i; - found = true; - break; - } - } - } - if(!found){ - currentSndElementListIndex = -1; - } - else{ - int colorIndex = NsharpConstants.LINE_COMP1; - for(NsharpOperationElement elm: sndElementList) { - if(elm.getActionState() == NsharpConstants.ActState.INACTIVE) - continue; - int sndIndex = sndElementList.indexOf(elm); - NsharpSoundingElementStateProperty stnTmElm = stnTimeSndTable.get(currentStnElementListIndex).get(currentTimeElementListIndex).get(sndIndex); - if(stnTmElm!=null){ - stnTmElm.setCompColorIndex(colorIndex); - } - colorIndex++; - if(colorIndex > NsharpConstants.LINE_COMP10) - colorIndex = NsharpConstants.LINE_COMP1; - } - } - //no matter we find current snd type for this stn or not - //we should get out of here - break; - } - else - break; - } - } - curStnIdPage = currentStnElementListIndex/numTimeLinePerPage + 1; - - setCurSndProfileProp(); - setCurrentSoundingLayerInfo(); - resetData(); - - refreshPane(); - } - - } - /* - * Snd Type index stepping is only controlled by shift + up/down arrow keys, shift+down key = PREVIOUS operation, shift+up key = NEXT operation - */ - public void setSteppingSndTypeList(IFrameCoordinator.FrameChangeOperation operation) { - if( this.sndElementList.size() > 0 && getElemlistActiveNumber(sndElementList)>1){ - - int counter=0; - while(true){ - switch(operation){ - case NEXT: - currentSndElementListIndex= currentSndElementListIndex + this.sndElementList.size(); - currentSndElementListIndex--; - currentSndElementListIndex = currentSndElementListIndex % this.sndElementList.size(); - break; - case PREVIOUS: - // so, we wont get a negative number - currentSndElementListIndex++; - currentSndElementListIndex = currentSndElementListIndex % this.sndElementList.size(); - break; - default: - break; - - } - counter++; - //System.out.println("counter = "+ counter); - if(counter >= sndElementList.size()) - return; // looped through whole list already, and index back to original - if(sndElementList.get(currentSndElementListIndex).getActionState() == NsharpConstants.ActState.ACTIVE){ - if (compareSndIsOn && currentTimeElementListIndex>=0 && currentStnElementListIndex>=0 - && stnTimeSndTable.get(currentStnElementListIndex).get(currentTimeElementListIndex).get(currentSndElementListIndex)== null){ - continue; - } - else if(compareTmIsOn){ - boolean found = false; - if(currentTimeElementListIndex>=0 && currentStnElementListIndex>=0 && - stnTimeSndTable.get(currentStnElementListIndex).get(currentTimeElementListIndex).get(currentSndElementListIndex)!=null){ - // use currentTimeLineStateListIndex - found = true; - } - else { - //find an active and available timeline for this stn and set is as current - for (int i=0; i < timeElementList.size(); i++){ - if(timeElementList.get(i).getActionState()== NsharpConstants.ActState.ACTIVE && - stnTimeSndTable.get(currentStnElementListIndex).get(i).get(currentSndElementListIndex)!=null){ - currentTimeElementListIndex = i; - found = true; - break; - } - } - } - if(!found){ - currentTimeElementListIndex = -1; - } - else{ - int colorIndex = NsharpConstants.LINE_COMP1; - for(NsharpOperationElement elm: timeElementList) { - if(elm.getActionState() == NsharpConstants.ActState.INACTIVE) - continue; - int tmIndex = timeElementList.indexOf(elm); - NsharpSoundingElementStateProperty stnTmElm = stnTimeSndTable.get(currentStnElementListIndex).get(tmIndex).get(currentSndElementListIndex); - if(stnTmElm!=null){ - stnTmElm.setCompColorIndex(colorIndex); - } - colorIndex++; - if(colorIndex > NsharpConstants.LINE_COMP10) - colorIndex = NsharpConstants.LINE_COMP1; - } - } - //no matter we find current time line for this stn or not - //we should get out of here - break; - } - else if(compareStnIsOn){ - boolean found = false; - //find an active and available stn for this timeline and set is as current - if(currentTimeElementListIndex>=0 && currentStnElementListIndex>=0 && - stnTimeSndTable.get(currentStnElementListIndex).get(currentTimeElementListIndex).get(currentSndElementListIndex)!=null){ - found = true; - } - else { - for (int i=0; i < stnElementList.size(); i++){ - if(stnElementList.get(i).getActionState()==NsharpConstants.ActState.ACTIVE && - stnTimeSndTable.get(i).get(currentTimeElementListIndex).get(currentSndElementListIndex) !=null){ - currentStnElementListIndex = i; - found = true; - break; - } - } - } - if(!found){ - currentStnElementListIndex = -1; - } - else{ - int colorIndex = NsharpConstants.LINE_COMP1; - for(NsharpOperationElement elm: stnElementList) { - int stnIndex = stnElementList.indexOf(elm); - NsharpSoundingElementStateProperty stnTmElm = stnTimeSndTable.get(stnIndex).get(currentTimeElementListIndex).get(currentSndElementListIndex); - if(stnTmElm!=null){ - stnTmElm.setCompColorIndex(colorIndex); - } - colorIndex++; - if(colorIndex > NsharpConstants.LINE_COMP10) - colorIndex = NsharpConstants.LINE_COMP1; - - } - } - //no matter we find current stn or not - //we should get out of here - break; - } - else - break; - } - } - curStnIdPage = currentSndElementListIndex/numTimeLinePerPage + 1; - - setCurSndProfileProp(); - setCurrentSoundingLayerInfo(); - resetData(); - - refreshPane(); - } - - } - //used for sorting - public class tempPoint implements Comparable{ - double diff; - double temp; - double pressure; - int type; //1= temp, 2 = dewpoint - tempPoint(double diff,double temp,double pressure, int type){ - this.diff = diff; - this.temp = temp; - this.pressure = pressure; - this.type = type; - } - - @Override - public int compareTo(tempPoint o) { - if(this.diff >= o.diff) - return 1; - else - return 0; - } - } - /* - * Return the closest point to the input point on Hodo graph - * - */ - public Coordinate getClosestHodoPoint(Coordinate inputC){ - //System.out.println("picked pt CX "+ inputC.x + " CY "+ inputC.y); - Coordinate closeptC = new Coordinate(0,0); - if(hodoPaneRsc==null) - return closeptC; - - double curSmallestDist=10000; // picked a impossible big number to start with - double distance; - boolean ptFound = false; - NcSoundingLayer layer; - // - // Note: soundingLys list sorted with highest pressure as first element - // - for (int i=0; i< this.soundingLys.size(); i++) { - layer = this.soundingLys.get(i); - double curS, curD; - curS = layer.getWindSpeed(); - curD = layer.getWindDirection(); - closeptC = WxMath.uvComp((float)curS, (float)curD); - closeptC = hodoPaneRsc.getHodoBackground().getWorld().map(closeptC); - //System.out.println("closeptCx " + closeptC.x+ " closeptCy "+ closeptC.y); - distance = inputC.distance(closeptC); - //System.out.println("closeptCx " + closeptC.x+ " closeptCy "+ closeptC.y+" distance "+ distance + " curSmallestDist " +curSmallestDist); - if(distance < curSmallestDist){ - curSmallestDist = distance; - hodoEditingSoundingLayerIndex = i; - ptFound = true; - } - } - if(ptFound == false){ - closeptC.x=closeptC.y=0; - } else{ - layer = this.soundingLys.get(hodoEditingSoundingLayerIndex); - closeptC = WxMath.uvComp((float)layer.getWindSpeed(), (float)layer.getWindDirection()); - closeptC = hodoPaneRsc.getHodoBackground().getWorld().map(closeptC); - } - - //System.out.println("picked closeptCx " + closeptC.x+ " closeptCy "+ closeptC.y); - return closeptC; - } - - public List getSoundingLys() { - return soundingLys; - } - - public List getPreviousSoundingLys() { - return previousSoundingLys; - } - - - /* - * This interpolation is to smooth data out with a pressure gap of 25 mb per layer and also keep - * original lowest and highest layers. - */ - private List performInterpolation(List rawSndLysLst){ - NcSoundingLayer newLayer= new NcSoundingLayer(); - //System.out.println(" performInterpolation"); - nsharpNative.populateSndgData(rawSndLysLst); - - List mySndLst = new ArrayList(); - // add top layer - try { - //here a shallowCopy is enough - newLayer = (NcSoundingLayer) rawSndLysLst.get(0).clone(); - mySndLst.add(newLayer); - } catch (CloneNotSupportedException e) { - e.printStackTrace(); - } - // The first layer has highest pressure - // get a pressure value below first layer and can be divided by 25 exactly - int p =(int) (rawSndLysLst.get(0).getPressure()/25) * 25; - float interpolatedValue; - if ( p == (int)rawSndLysLst.get(0).getPressure()) - { // if p is same as first layer, then this layer is added already, start from 2nd layer - p = p-25; - } - for (; p >= 50 ; p = p-25){ - newLayer= new NcSoundingLayer(); - newLayer.setPressure(p); - interpolatedValue = nsharpNative.nsharpLib.itemp(p); - if(interpolatedValue ==NsharpNativeConstants.NSHARP_LEGACY_LIB_INVALID_DATA) - //this is not good layer data, usually happened when lowest layer pressure is - // more than 50, then when interpolate layer for pressure 50, will return unvalid value - continue; - newLayer.setTemperature(interpolatedValue); - interpolatedValue = nsharpNative.nsharpLib.idwpt(p); - newLayer.setDewpoint(interpolatedValue); - interpolatedValue = nsharpNative.nsharpLib.iwdir(p); - newLayer.setWindDirection(interpolatedValue); - interpolatedValue = nsharpNative.nsharpLib.iwspd(p); - newLayer.setWindSpeed(interpolatedValue); - interpolatedValue = nsharpNative.nsharpLib.ihght(p); - newLayer.setGeoHeight(interpolatedValue); - interpolatedValue = nsharpNative.nsharpLib.iomeg(p); - newLayer.setOmega(interpolatedValue); - - mySndLst.add(newLayer); - } - return mySndLst; - } - - - private void setSoundingInfo(List sndLys) { - if(overlayIsOn){ - previousSoundingLys = soundingLys; - } - else { - previousSoundingLys = null; - } - - if(interpolateIsOn == true){ - - //interpolation is on - //we dont want to change original raw data, so use a deep copy - List intpSndLst = new ArrayList(); - for(NcSoundingLayer layer: sndLys ) { - try { - intpSndLst.add((NcSoundingLayer) layer.clone()); - } catch (CloneNotSupportedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - // interpolation - intpSndLst = performInterpolation(intpSndLst); - - soundingLys = intpSndLst; - } - else { - soundingLys = sndLys; - - } - } - public void updateDisplay(IRenderableDisplay[] displayArray, String paneConfigurationName) { - skewtPaneRsc = null; - witoPaneRsc = null; - hodoPaneRsc = null; - timeStnPaneRsc = null; - insetPaneRsc = null; - dataPaneRsc = null; - spcGraphsPaneRsc = null; - futurePaneRsc = null; - for(IRenderableDisplay disp: displayArray) { - ResourcePair rscP = disp.getDescriptor().getResourceList().get(0); - NsharpAbstractPaneResource absPaneRsc = (NsharpAbstractPaneResource)rscP.getResource(); - if (absPaneRsc instanceof NsharpSkewTPaneResource){ - skewtPaneRsc = (NsharpSkewTPaneResource)absPaneRsc ; - skewtPaneRsc.setLinePropertyMap(linePropertyMap); - skewtPaneRsc.setGraphConfigProperty(graphConfigProperty); - skewtPaneRsc.setNsharpNative(nsharpNative); - } - else if (absPaneRsc instanceof NsharpDataPaneResource){ - dataPaneRsc = (NsharpDataPaneResource)absPaneRsc; - dataPaneRsc.setLinePropertyMap(linePropertyMap); - dataPaneRsc.setGraphConfigProperty(graphConfigProperty); - dataPaneRsc.setNsharpNative(nsharpNative); - dataPaneRsc.setPageDisplayOrderNumberArray(pageDisplayOrderNumberArray, dataPageProperty.getNumberPagePerDisplay()); - } - else if (absPaneRsc instanceof NsharpHodoPaneResource){ - hodoPaneRsc = (NsharpHodoPaneResource)absPaneRsc; - hodoPaneRsc.setLinePropertyMap(linePropertyMap); - hodoPaneRsc.setGraphConfigProperty(graphConfigProperty); - hodoPaneRsc.setNsharpNative(nsharpNative); - } - else if (absPaneRsc instanceof NsharpWitoPaneResource && - (paneConfigurationName.equals(NsharpConstants.PANE_SPCWS_CFG_STR)|| - paneConfigurationName.equals(NsharpConstants.PANE_DEF_CFG_1_STR)|| - paneConfigurationName.equals(NsharpConstants.PANE_DEF_CFG_2_STR))){ - - witoPaneRsc = (NsharpWitoPaneResource)absPaneRsc; - witoPaneRsc.setLinePropertyMap(linePropertyMap); - witoPaneRsc.setGraphConfigProperty(graphConfigProperty); - witoPaneRsc.setNsharpNative(nsharpNative); - - } - else if (absPaneRsc instanceof NsharpInsetPaneResource && - (paneConfigurationName.equals(NsharpConstants.PANE_SPCWS_CFG_STR)|| - paneConfigurationName.equals(NsharpConstants.PANE_DEF_CFG_1_STR)|| - paneConfigurationName.equals(NsharpConstants.PANE_DEF_CFG_2_STR))){ - - insetPaneRsc = (NsharpInsetPaneResource)absPaneRsc; - insetPaneRsc.setLinePropertyMap(linePropertyMap); - insetPaneRsc.setGraphConfigProperty(graphConfigProperty); - insetPaneRsc.setNsharpNative(nsharpNative); - - } - else if (absPaneRsc instanceof NsharpSpcGraphsPaneResource && paneConfigurationName.equals(NsharpConstants.PANE_SPCWS_CFG_STR)){ - spcGraphsPaneRsc = (NsharpSpcGraphsPaneResource)absPaneRsc; - spcGraphsPaneRsc.setLinePropertyMap(linePropertyMap); - spcGraphsPaneRsc.setGraphConfigProperty(graphConfigProperty); - spcGraphsPaneRsc.setNsharpNative(nsharpNative); - } - else if(absPaneRsc instanceof NsharpAbstractPaneResource && paneConfigurationName.equals(NsharpConstants.PANE_SIMPLE_D2D_CFG_STR)){ - futurePaneRsc = (NsharpAbstractPaneResource)absPaneRsc; - futurePaneRsc.setLinePropertyMap(linePropertyMap); - futurePaneRsc.setGraphConfigProperty(graphConfigProperty); - futurePaneRsc.setNsharpNative(nsharpNative); - - } - else if (absPaneRsc instanceof NsharpTimeStnPaneResource && - (paneConfigurationName.equals(NsharpConstants.PANE_SIMPLE_D2D_CFG_STR)|| - paneConfigurationName.equals(NsharpConstants.PANE_DEF_CFG_1_STR)|| - paneConfigurationName.equals(NsharpConstants.PANE_DEF_CFG_2_STR))){ - timeStnPaneRsc = (NsharpTimeStnPaneResource)absPaneRsc ; - timeStnPaneRsc.setLinePropertyMap(linePropertyMap); - timeStnPaneRsc.setGraphConfigProperty(graphConfigProperty); - timeStnPaneRsc.setNsharpNative(nsharpNative); - } - } - this.displayArray = displayArray; - } - public void resetRscSoundingData(){ - if(skewtPaneRsc!=null) - skewtPaneRsc.resetData(soundingLys,previousSoundingLys); - if(hodoPaneRsc!=null) - hodoPaneRsc.resetData(soundingLys,previousSoundingLys); - if(witoPaneRsc!=null) - witoPaneRsc.resetData(soundingLys, previousSoundingLys); - if(dataPaneRsc!=null) - dataPaneRsc.resetData(soundingLys, previousSoundingLys); - if(insetPaneRsc!=null) - insetPaneRsc.resetData(soundingLys, previousSoundingLys); - if(spcGraphsPaneRsc!=null) - spcGraphsPaneRsc.resetData(soundingLys, previousSoundingLys); - } - - - public NsharpResourceHandler(IRenderableDisplay[] displayArray, NsharpEditor editor) { - //System.out.println("NsharpResourceHandler constructed"); - //myNsharpEditor = editor; - elementColorMap.put(NsharpConstants.ActState.CURRENT.name(),NsharpConstants.color_green); - elementColorMap.put(NsharpConstants.ActState.ACTIVE.name(),NsharpConstants.color_yellow); - elementColorMap.put(NsharpConstants.ActState.INACTIVE.name(),NsharpConstants.color_white); - //elementColorMap.put(NsharpConstants.LoadState.NOTAVAIL.name(),NsharpConstants.color_red); - //elementColorMap.put(NsharpConstants.ActState.OVERLAY,NsharpConstants.color_red); - //elementColorMap.put(NsharpConstants.LoadState.AVAIL.name(),NsharpConstants.color_yellow); - nsharpNative = new NsharpNative(); - //System.out.println("NsharpResourceHandler constructed"+this.toString() + " nsharpNative="+nsharpNative.toString()); - //based on BigNsharp storm slinky color used and gempak color definition - stormSlinkyColorMap.put(new Integer(3),NsharpConstants.color_green); //green - stormSlinkyColorMap.put(new Integer(7),NsharpConstants.color_magenta); - stormSlinkyColorMap.put(new Integer(6),NsharpConstants.color_cyan); - stormSlinkyColorMap.put(new Integer(13),NsharpConstants.color_violet_md); - stormSlinkyColorMap.put(new Integer(20),NsharpConstants.color_yellow_DK); - stormSlinkyColorMap.put(new Integer(27),NsharpConstants.color_cyan_md); - NsharpPaletteWindow win = NsharpPaletteWindow.getInstance() ; - if(win!=null) - currentGraphMode=win.getCurrentGraphMode(); - - - // new for configMgr - configMgr = NsharpConfigManager.getInstance(); - configStore = configMgr.retrieveNsharpConfigStoreFromFs(); - graphConfigProperty = configStore.getGraphProperty(); - paneConfigurationName = graphConfigProperty.getPaneConfigurationName(); - - int tempOffset = graphConfigProperty.getTempOffset(); - NsharpWxMath.setTempOffset(tempOffset); - linePropertyMap = configStore.getLinePropertyMap(); - dataPageProperty = configStore.getDataPageProperty(); - updatePageOrderArray(); - updateDisplay(displayArray,paneConfigurationName); - displayDataPageMax = NsharpConstants.PAGE_MAX_NUMBER / dataPageProperty.getNumberPagePerDisplay(); - - DateFormatSymbols dfs= new DateFormatSymbols(); - defaultDays = dfs.getShortWeekdays(); + private int getElemlistActiveNumber(List elemlist) { + int n = 0; + for (NsharpOperationElement elem : elemlist) { + if (elem.getActionState() == NsharpConstants.ActState.ACTIVE) { + n++; + } + } + return n; } - public void disposeInternal() { - //System.out.println("NsharpResourceHandler disposeInternal called"); - listenerList=null; - soundingLys = null; - previousSoundingLys = null; - stormSlinkyColorMap = null; - elementColorMap= null; - - if(NsharpParcelDialog.getAccess()!= null){ - NsharpParcelDialog.getAccess().reset(); - } - - nsharpNative = null; - } - - + public void setSteppingTimeLine( + IFrameCoordinator.FrameChangeOperation operation, + IFrameCoordinator.FrameChangeMode mode) { + if (this.timeElementList.size() > 0 + && getElemlistActiveNumber(timeElementList) > 1/* + * && + * getAvailTimeLineNumber + * ( + * currentStnStateListIndex + * )>1 + */) { + int targetIndex = currentTimeElementListIndex; + // previousTimeLineStateListIndex = currentTimeLineStateListIndex; + // preset index for LAST and FIRST operation + switch (operation) { + case LAST: // the future-est time, at top of time line shown. set to + // -1, so in while loop, it starts from 0 + targetIndex = -1;// + break; + case FIRST: // the oldest time, set to dataTimelineList.length, so + // in while loop, it starts from + // dataTimelineList.length-1 + targetIndex = timeElementList.size(); + break; + default: + break; - public void printHeightMark(WGraphics world, GC gc) throws VizException{ - //print feet scales... - double vyMax = world.getViewYmax(); - double vyMin = world.getViewYmin(); - double vxMax = world.getViewXmax(); - for (int j = 0; j < NsharpConstants.HEIGHT_LEVEL_FEET.length; j++) { - float meters = (float)NsharpConstants.feetToMeters.convert(NsharpConstants.HEIGHT_LEVEL_FEET[j]); - - double pressure = nsharpNative.nsharpLib.ipres(meters); - double y = world.mapY(NsharpWxMath.getSkewTXY(pressure, -50).y); + } - gc.drawString( Integer.toString(NsharpConstants.HEIGHT_LEVEL_FEET[j]/1000), (int)vxMax + 40, - (int)y,false); - + int counter = 0; + while (true) { + switch (operation) { + case LAST: // the future-est time, at top of time line shown + targetIndex++; + break; + case FIRST: // the oldest time + targetIndex--; + break; + case PREVIOUS: + targetIndex++; + targetIndex = targetIndex % this.timeElementList.size(); + break; + case NEXT: + // so, we wont get a negative number + targetIndex = targetIndex + this.timeElementList.size(); + targetIndex--; + targetIndex = targetIndex % this.timeElementList.size(); + break; + default: + break; + } + counter++; + if (counter >= timeElementList.size()) + return; // looped through whole list already, and index back + // to original - gc.drawLine( (int)vxMax + 50,(int) y, (int) vxMax + 45,(int) y); - } - //print meter scales... + if (timeElementList.get(targetIndex).getActionState() == NsharpConstants.ActState.ACTIVE) { + if (compareTmIsOn + && currentStnElementListIndex >= 0 + && currentSndElementListIndex >= 0 + && stnTimeSndTable.get(currentStnElementListIndex) + .get(targetIndex) + .get(currentSndElementListIndex) == null) { + continue; + } else if (compareStnIsOn) { + boolean found = false; + if (currentStnElementListIndex >= 0 + && currentSndElementListIndex >= 0 + && stnTimeSndTable + .get(currentStnElementListIndex) + .get(targetIndex) + .get(currentSndElementListIndex) != null) { + found = true; + } else { + // find an active and available stn for this + // timeline and set is as current + for (int i = 0; i < stnElementList.size(); i++) { + if (stnElementList.get(i).getActionState() == NsharpConstants.ActState.ACTIVE + && stnTimeSndTable + .get(i) + .get(targetIndex) + .get(currentSndElementListIndex) != null) { + currentStnElementListIndex = i; + found = true; + break; + } + } + } + if (!found) { + currentStnElementListIndex = -1; + } else { + int colorIndex = NsharpConstants.LINE_COMP1; + for (NsharpOperationElement elm : stnElementList) { + int stnIndex = stnElementList.indexOf(elm); + NsharpSoundingElementStateProperty stnTmElm = stnTimeSndTable + .get(stnIndex).get(targetIndex) + .get(currentSndElementListIndex); + if (stnTmElm != null) { + stnTmElm.setCompColorIndex(colorIndex); + // if(colorIndex > + // NsharpConstants.LINE_COMP10) + // colorIndex = NsharpConstants.LINE_COMP1; + } + colorIndex++; + if (colorIndex > NsharpConstants.LINE_COMP10) + colorIndex = NsharpConstants.LINE_COMP1; + } + } + // no matter we find current stn or not + // we should get out of here + break; + } else if (compareSndIsOn) { + boolean found = false; + if (currentStnElementListIndex >= 0 + && currentSndElementListIndex >= 0 + && stnTimeSndTable + .get(currentStnElementListIndex) + .get(targetIndex) + .get(currentSndElementListIndex) != null) { + found = true; + } else { + // find an active and available snd for this stn and + // set is as current + for (int i = 0; i < sndElementList.size(); i++) { + if (sndElementList.get(i).getActionState() == NsharpConstants.ActState.ACTIVE + && stnTimeSndTable + .get(currentStnElementListIndex) + .get(targetIndex).get(i) != null) { + currentSndElementListIndex = i; + found = true; + break; + } + } + } + if (!found) { + currentSndElementListIndex = -1; + } else { + int colorIndex = NsharpConstants.LINE_COMP1; + for (NsharpOperationElement elm : sndElementList) { + if (elm.getActionState() == NsharpConstants.ActState.INACTIVE) + continue; + int sndIndex = sndElementList.indexOf(elm); + NsharpSoundingElementStateProperty stnTmElm = stnTimeSndTable + .get(currentStnElementListIndex) + .get(targetIndex).get(sndIndex); + if (stnTmElm != null) { + stnTmElm.setCompColorIndex(colorIndex); + } + colorIndex++; + if (colorIndex > NsharpConstants.LINE_COMP10) + colorIndex = NsharpConstants.LINE_COMP1; + } + } + // no matter we find current snd type for this stn or + // not + // we should get out of here + break; + } else { + break; + } + } + } + previousTimeLineStateListIndex = currentTimeElementListIndex; + currentTimeElementListIndex = targetIndex; + curTimeLinePage = currentTimeElementListIndex / numTimeLinePerPage + + 1; + setCurSndProfileProp(); + setCurrentSoundingLayerInfo(); + resetData(); + refreshPane(); + } + } + + /* + * Stn index stepping is only controlled by up/down arrow keys, down key = + * PREVIOUS operation, up key = NEXT operation + */ + public void setSteppingStnIdList( + IFrameCoordinator.FrameChangeOperation operation) { + if (this.stnElementList.size() > 0 + && getElemlistActiveNumber(stnElementList) > 1) { + + int counter = 0; + while (true) { + switch (operation) { + case NEXT: + currentStnElementListIndex = currentStnElementListIndex + + this.stnElementList.size(); + currentStnElementListIndex--; + currentStnElementListIndex = currentStnElementListIndex + % this.stnElementList.size(); + break; + case PREVIOUS: + // so, we wont get a negative number + currentStnElementListIndex++; + currentStnElementListIndex = currentStnElementListIndex + % this.stnElementList.size(); + break; + default: + break; + + } + counter++; + // System.out.println("counter = "+ counter); + if (counter >= stnElementList.size()) + return; // looped through whole list already, and index back + // to original + if (stnElementList.get(currentStnElementListIndex) + .getActionState() == NsharpConstants.ActState.ACTIVE) { + if (compareStnIsOn + && currentTimeElementListIndex >= 0 + && currentSndElementListIndex >= 0 + && stnTimeSndTable.get(currentStnElementListIndex) + .get(currentTimeElementListIndex) + .get(currentSndElementListIndex) == null) {// .getElementState() + // == + // NsharpConstants.LoadState.NOTAVAIL){ + continue; + } else if (compareTmIsOn) { + boolean found = false; + if (currentTimeElementListIndex >= 0 + && currentSndElementListIndex >= 0 + && stnTimeSndTable + .get(currentStnElementListIndex) + .get(currentTimeElementListIndex) + .get(currentSndElementListIndex) != null) { + // use currentTimeLineStateListIndex + found = true; + } else { + // find an active and available timeline for this + // stn and set is as current + for (int i = 0; i < timeElementList.size(); i++) { + if (timeElementList.get(i).getActionState() == NsharpConstants.ActState.ACTIVE + && stnTimeSndTable + .get(currentStnElementListIndex) + .get(i) + .get(currentSndElementListIndex) != null) { + currentTimeElementListIndex = i; + found = true; + break; + } + } + } + if (!found) { + currentTimeElementListIndex = -1; + } else { + int colorIndex = NsharpConstants.LINE_COMP1; + for (NsharpOperationElement elm : timeElementList) { + if (elm.getActionState() == NsharpConstants.ActState.INACTIVE) + continue; + int tmIndex = timeElementList.indexOf(elm); + NsharpSoundingElementStateProperty stnTmElm = stnTimeSndTable + .get(currentStnElementListIndex) + .get(tmIndex) + .get(currentSndElementListIndex); + if (stnTmElm != null) { + stnTmElm.setCompColorIndex(colorIndex); + } + colorIndex++; + if (colorIndex > NsharpConstants.LINE_COMP10) + colorIndex = NsharpConstants.LINE_COMP1; + + } + } + // no matter we find current time line for this stn or + // not + // we should get out of here + break; + } else if (compareSndIsOn) { + boolean found = false; + if (currentTimeElementListIndex >= 0 + && currentSndElementListIndex >= 0 + && stnTimeSndTable + .get(currentStnElementListIndex) + .get(currentTimeElementListIndex) + .get(currentSndElementListIndex) != null) { + found = true; + } else { + // find an active and available snd for this stn and + // set is as current + for (int i = 0; i < sndElementList.size(); i++) { + if (sndElementList.get(i).getActionState() == NsharpConstants.ActState.ACTIVE + && stnTimeSndTable + .get(currentStnElementListIndex) + .get(currentTimeElementListIndex) + .get(i) != null) { + currentSndElementListIndex = i; + found = true; + break; + } + } + } + if (!found) { + currentSndElementListIndex = -1; + } else { + int colorIndex = NsharpConstants.LINE_COMP1; + for (NsharpOperationElement elm : sndElementList) { + if (elm.getActionState() == NsharpConstants.ActState.INACTIVE) + continue; + int sndIndex = sndElementList.indexOf(elm); + NsharpSoundingElementStateProperty stnTmElm = stnTimeSndTable + .get(currentStnElementListIndex) + .get(currentTimeElementListIndex) + .get(sndIndex); + if (stnTmElm != null) { + stnTmElm.setCompColorIndex(colorIndex); + } + colorIndex++; + if (colorIndex > NsharpConstants.LINE_COMP10) + colorIndex = NsharpConstants.LINE_COMP1; + } + } + // no matter we find current snd type for this stn or + // not + // we should get out of here + break; + } else + break; + } + } + curStnIdPage = currentStnElementListIndex / numTimeLinePerPage + 1; + + setCurSndProfileProp(); + setCurrentSoundingLayerInfo(); + resetData(); + + refreshPane(); + } + + } + + /* + * Snd Type index stepping is only controlled by shift + up/down arrow keys, + * shift+down key = PREVIOUS operation, shift+up key = NEXT operation + */ + public void setSteppingSndTypeList( + IFrameCoordinator.FrameChangeOperation operation) { + if (this.sndElementList.size() > 0 + && getElemlistActiveNumber(sndElementList) > 1) { + + int counter = 0; + while (true) { + switch (operation) { + case NEXT: + currentSndElementListIndex = currentSndElementListIndex + + this.sndElementList.size(); + currentSndElementListIndex--; + currentSndElementListIndex = currentSndElementListIndex + % this.sndElementList.size(); + break; + case PREVIOUS: + // so, we wont get a negative number + currentSndElementListIndex++; + currentSndElementListIndex = currentSndElementListIndex + % this.sndElementList.size(); + break; + default: + break; + + } + counter++; + // System.out.println("counter = "+ counter); + if (counter >= sndElementList.size()) + return; // looped through whole list already, and index back + // to original + if (sndElementList.get(currentSndElementListIndex) + .getActionState() == NsharpConstants.ActState.ACTIVE) { + if (compareSndIsOn + && currentTimeElementListIndex >= 0 + && currentStnElementListIndex >= 0 + && stnTimeSndTable.get(currentStnElementListIndex) + .get(currentTimeElementListIndex) + .get(currentSndElementListIndex) == null) { + continue; + } else if (compareTmIsOn) { + boolean found = false; + if (currentTimeElementListIndex >= 0 + && currentStnElementListIndex >= 0 + && stnTimeSndTable + .get(currentStnElementListIndex) + .get(currentTimeElementListIndex) + .get(currentSndElementListIndex) != null) { + // use currentTimeLineStateListIndex + found = true; + } else { + // find an active and available timeline for this + // stn and set is as current + for (int i = 0; i < timeElementList.size(); i++) { + if (timeElementList.get(i).getActionState() == NsharpConstants.ActState.ACTIVE + && stnTimeSndTable + .get(currentStnElementListIndex) + .get(i) + .get(currentSndElementListIndex) != null) { + currentTimeElementListIndex = i; + found = true; + break; + } + } + } + if (!found) { + currentTimeElementListIndex = -1; + } else { + int colorIndex = NsharpConstants.LINE_COMP1; + for (NsharpOperationElement elm : timeElementList) { + if (elm.getActionState() == NsharpConstants.ActState.INACTIVE) + continue; + int tmIndex = timeElementList.indexOf(elm); + NsharpSoundingElementStateProperty stnTmElm = stnTimeSndTable + .get(currentStnElementListIndex) + .get(tmIndex) + .get(currentSndElementListIndex); + if (stnTmElm != null) { + stnTmElm.setCompColorIndex(colorIndex); + } + colorIndex++; + if (colorIndex > NsharpConstants.LINE_COMP10) + colorIndex = NsharpConstants.LINE_COMP1; + } + } + // no matter we find current time line for this stn or + // not + // we should get out of here + break; + } else if (compareStnIsOn) { + boolean found = false; + // find an active and available stn for this timeline + // and set is as current + if (currentTimeElementListIndex >= 0 + && currentStnElementListIndex >= 0 + && stnTimeSndTable + .get(currentStnElementListIndex) + .get(currentTimeElementListIndex) + .get(currentSndElementListIndex) != null) { + found = true; + } else { + for (int i = 0; i < stnElementList.size(); i++) { + if (stnElementList.get(i).getActionState() == NsharpConstants.ActState.ACTIVE + && stnTimeSndTable + .get(i) + .get(currentTimeElementListIndex) + .get(currentSndElementListIndex) != null) { + currentStnElementListIndex = i; + found = true; + break; + } + } + } + if (!found) { + currentStnElementListIndex = -1; + } else { + int colorIndex = NsharpConstants.LINE_COMP1; + for (NsharpOperationElement elm : stnElementList) { + int stnIndex = stnElementList.indexOf(elm); + NsharpSoundingElementStateProperty stnTmElm = stnTimeSndTable + .get(stnIndex) + .get(currentTimeElementListIndex) + .get(currentSndElementListIndex); + if (stnTmElm != null) { + stnTmElm.setCompColorIndex(colorIndex); + } + colorIndex++; + if (colorIndex > NsharpConstants.LINE_COMP10) + colorIndex = NsharpConstants.LINE_COMP1; + + } + } + // no matter we find current stn or not + // we should get out of here + break; + } else + break; + } + } + curStnIdPage = currentSndElementListIndex / numTimeLinePerPage + 1; + + setCurSndProfileProp(); + setCurrentSoundingLayerInfo(); + resetData(); + + refreshPane(); + } + + } + + // used for sorting + public class tempPoint implements Comparable { + double diff; + + double temp; + + double pressure; + + int type; // 1= temp, 2 = dewpoint + + tempPoint(double diff, double temp, double pressure, int type) { + this.diff = diff; + this.temp = temp; + this.pressure = pressure; + this.type = type; + } + + @Override + public int compareTo(tempPoint o) { + if (this.diff >= o.diff) + return 1; + else + return 0; + } + } + + /* + * Return the closest point to the input point on Hodo graph + */ + public Coordinate getClosestHodoPoint(Coordinate inputC) { + // System.out.println("picked pt CX "+ inputC.x + " CY "+ inputC.y); + Coordinate closeptC = new Coordinate(0, 0); + if (hodoPaneRsc == null) + return closeptC; + + double curSmallestDist = 10000; // picked a impossible big number to + // start with + double distance; + boolean ptFound = false; + NcSoundingLayer layer; + // + // Note: soundingLys list sorted with highest pressure as first element + // + for (int i = 0; i < this.soundingLys.size(); i++) { + layer = this.soundingLys.get(i); + double curS, curD; + curS = layer.getWindSpeed(); + curD = layer.getWindDirection(); + closeptC = WxMath.uvComp((float) curS, (float) curD); + closeptC = hodoPaneRsc.getHodoBackground().getWorld().map(closeptC); + // System.out.println("closeptCx " + closeptC.x+ " closeptCy "+ + // closeptC.y); + distance = inputC.distance(closeptC); + // System.out.println("closeptCx " + closeptC.x+ " closeptCy "+ + // closeptC.y+" distance "+ distance + " curSmallestDist " + // +curSmallestDist); + if (distance < curSmallestDist) { + curSmallestDist = distance; + hodoEditingSoundingLayerIndex = i; + ptFound = true; + } + } + if (ptFound == false) { + closeptC.x = closeptC.y = 0; + } else { + layer = this.soundingLys.get(hodoEditingSoundingLayerIndex); + closeptC = WxMath.uvComp((float) layer.getWindSpeed(), + (float) layer.getWindDirection()); + closeptC = hodoPaneRsc.getHodoBackground().getWorld().map(closeptC); + } + + // System.out.println("picked closeptCx " + closeptC.x+ " closeptCy "+ + // closeptC.y); + return closeptC; + } + + public List getSoundingLys() { + return soundingLys; + } + + public List getPreviousSoundingLys() { + return previousSoundingLys; + } + + /* + * This interpolation is to smooth data out with a pressure gap of 25 mb per + * layer and also keep original lowest and highest layers. + */ + private List performInterpolation( + List rawSndLysLst) { + NcSoundingLayer newLayer = new NcSoundingLayer(); + // System.out.println(" performInterpolation"); + nsharpNative.populateSndgData(rawSndLysLst); + + List mySndLst = new ArrayList(); + // add top layer + try { + // here a shallowCopy is enough + newLayer = (NcSoundingLayer) rawSndLysLst.get(0).clone(); + mySndLst.add(newLayer); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + // The first layer has highest pressure + // get a pressure value below first layer and can be divided by 25 + // exactly + int p = (int) (rawSndLysLst.get(0).getPressure() / 25) * 25; + float interpolatedValue; + if (p == (int) rawSndLysLst.get(0).getPressure()) { // if p is same as + // first layer, then + // this layer is + // added already, + // start from 2nd + // layer + p = p - 25; + } + for (; p >= 50; p = p - 25) { + newLayer = new NcSoundingLayer(); + newLayer.setPressure(p); + interpolatedValue = nsharpNative.nsharpLib.itemp(p); + if (interpolatedValue == NsharpNativeConstants.NSHARP_LEGACY_LIB_INVALID_DATA) + // this is not good layer data, usually happened when lowest + // layer pressure is + // more than 50, then when interpolate layer for pressure 50, + // will return unvalid value + continue; + newLayer.setTemperature(interpolatedValue); + interpolatedValue = nsharpNative.nsharpLib.idwpt(p); + newLayer.setDewpoint(interpolatedValue); + interpolatedValue = nsharpNative.nsharpLib.iwdir(p); + newLayer.setWindDirection(interpolatedValue); + interpolatedValue = nsharpNative.nsharpLib.iwspd(p); + newLayer.setWindSpeed(interpolatedValue); + interpolatedValue = nsharpNative.nsharpLib.ihght(p); + newLayer.setGeoHeight(interpolatedValue); + interpolatedValue = nsharpNative.nsharpLib.iomeg(p); + newLayer.setOmega(interpolatedValue); + + mySndLst.add(newLayer); + } + return mySndLst; + } + + private void setSoundingInfo(List sndLys) { + if (overlayIsOn) { + previousSoundingLys = soundingLys; + } else { + previousSoundingLys = null; + } + + if (interpolateIsOn == true) { + /* + * TTR829 deep copy is not necessary as performInterpolation() will + * re-allocate new layer for each layer //interpolation is on //we + * dont want to change original raw data, so use a deep copy + * List intpSndLst = new + * ArrayList(); for(NcSoundingLayer layer: sndLys ) + * { try { intpSndLst.add((NcSoundingLayer) layer.clone()); } catch + * (CloneNotSupportedException e) { // TODO Auto-generated catch + * block e.printStackTrace(); } } + * + * // interpolation intpSndLst = performInterpolation(intpSndLst); + * + * soundingLys = intpSndLst; + */ + + soundingLys = performInterpolation(sndLys); + } else { + soundingLys = sndLys; + + } + } + + public void updateDisplay(IRenderableDisplay[] displayArray, + String paneConfigurationName) { + skewtPaneRsc = null; + witoPaneRsc = null; + hodoPaneRsc = null; + timeStnPaneRsc = null; + insetPaneRsc = null; + dataPaneRsc = null; + spcGraphsPaneRsc = null; + futurePaneRsc = null; + for (IRenderableDisplay disp : displayArray) { + ResourcePair rscP = disp.getDescriptor().getResourceList().get(0); + NsharpAbstractPaneResource absPaneRsc = (NsharpAbstractPaneResource) rscP + .getResource(); + if (absPaneRsc instanceof NsharpSkewTPaneResource) { + skewtPaneRsc = (NsharpSkewTPaneResource) absPaneRsc; + skewtPaneRsc.setLinePropertyMap(linePropertyMap); + skewtPaneRsc.setGraphConfigProperty(graphConfigProperty); + skewtPaneRsc.setNsharpNative(nsharpNative); + } else if (absPaneRsc instanceof NsharpDataPaneResource) { + dataPaneRsc = (NsharpDataPaneResource) absPaneRsc; + dataPaneRsc.setLinePropertyMap(linePropertyMap); + dataPaneRsc.setGraphConfigProperty(graphConfigProperty); + dataPaneRsc.setNsharpNative(nsharpNative); + dataPaneRsc.setPageDisplayOrderNumberArray( + pageDisplayOrderNumberArray, + dataPageProperty.getNumberPagePerDisplay()); + } else if (absPaneRsc instanceof NsharpHodoPaneResource) { + hodoPaneRsc = (NsharpHodoPaneResource) absPaneRsc; + hodoPaneRsc.setLinePropertyMap(linePropertyMap); + hodoPaneRsc.setGraphConfigProperty(graphConfigProperty); + hodoPaneRsc.setNsharpNative(nsharpNative); + } else if (absPaneRsc instanceof NsharpWitoPaneResource + && (paneConfigurationName + .equals(NsharpConstants.PANE_SPCWS_CFG_STR) + || paneConfigurationName + .equals(NsharpConstants.PANE_DEF_CFG_1_STR) || paneConfigurationName + .equals(NsharpConstants.PANE_DEF_CFG_2_STR))) { + + witoPaneRsc = (NsharpWitoPaneResource) absPaneRsc; + witoPaneRsc.setLinePropertyMap(linePropertyMap); + witoPaneRsc.setGraphConfigProperty(graphConfigProperty); + witoPaneRsc.setNsharpNative(nsharpNative); + + } else if (absPaneRsc instanceof NsharpInsetPaneResource + && (paneConfigurationName + .equals(NsharpConstants.PANE_SPCWS_CFG_STR) + || paneConfigurationName + .equals(NsharpConstants.PANE_DEF_CFG_1_STR) || paneConfigurationName + .equals(NsharpConstants.PANE_DEF_CFG_2_STR))) { + + insetPaneRsc = (NsharpInsetPaneResource) absPaneRsc; + insetPaneRsc.setLinePropertyMap(linePropertyMap); + insetPaneRsc.setGraphConfigProperty(graphConfigProperty); + insetPaneRsc.setNsharpNative(nsharpNative); + + } else if (absPaneRsc instanceof NsharpSpcGraphsPaneResource + && paneConfigurationName + .equals(NsharpConstants.PANE_SPCWS_CFG_STR)) { + spcGraphsPaneRsc = (NsharpSpcGraphsPaneResource) absPaneRsc; + spcGraphsPaneRsc.setLinePropertyMap(linePropertyMap); + spcGraphsPaneRsc.setGraphConfigProperty(graphConfigProperty); + spcGraphsPaneRsc.setNsharpNative(nsharpNative); + } else if (absPaneRsc instanceof NsharpAbstractPaneResource + && paneConfigurationName + .equals(NsharpConstants.PANE_SIMPLE_D2D_CFG_STR)) { + futurePaneRsc = (NsharpAbstractPaneResource) absPaneRsc; + futurePaneRsc.setLinePropertyMap(linePropertyMap); + futurePaneRsc.setGraphConfigProperty(graphConfigProperty); + futurePaneRsc.setNsharpNative(nsharpNative); + + } else if (absPaneRsc instanceof NsharpTimeStnPaneResource + && (paneConfigurationName + .equals(NsharpConstants.PANE_SIMPLE_D2D_CFG_STR) + || paneConfigurationName + .equals(NsharpConstants.PANE_DEF_CFG_1_STR) || paneConfigurationName + .equals(NsharpConstants.PANE_DEF_CFG_2_STR))) { + timeStnPaneRsc = (NsharpTimeStnPaneResource) absPaneRsc; + timeStnPaneRsc.setLinePropertyMap(linePropertyMap); + timeStnPaneRsc.setGraphConfigProperty(graphConfigProperty); + timeStnPaneRsc.setNsharpNative(nsharpNative); + } + } + this.displayArray = displayArray; + } + + public void resetRscSoundingData() { + if (skewtPaneRsc != null) + skewtPaneRsc.resetData(soundingLys, previousSoundingLys); + if (hodoPaneRsc != null) + hodoPaneRsc.resetData(soundingLys, previousSoundingLys); + if (witoPaneRsc != null) + witoPaneRsc.resetData(soundingLys, previousSoundingLys); + if (dataPaneRsc != null) + dataPaneRsc.resetData(soundingLys, previousSoundingLys); + if (insetPaneRsc != null) + insetPaneRsc.resetData(soundingLys, previousSoundingLys); + if (spcGraphsPaneRsc != null) + spcGraphsPaneRsc.resetData(soundingLys, previousSoundingLys); + } + + public NsharpResourceHandler(IRenderableDisplay[] displayArray, + NsharpEditor editor) { + // System.out.println("NsharpResourceHandler constructed"); + // myNsharpEditor = editor; + elementColorMap.put(NsharpConstants.ActState.CURRENT.name(), + NsharpConstants.color_green); + elementColorMap.put(NsharpConstants.ActState.ACTIVE.name(), + NsharpConstants.color_yellow); + elementColorMap.put(NsharpConstants.ActState.INACTIVE.name(), + NsharpConstants.color_white); + // elementColorMap.put(NsharpConstants.LoadState.NOTAVAIL.name(),NsharpConstants.color_red); + // elementColorMap.put(NsharpConstants.ActState.OVERLAY,NsharpConstants.color_red); + // elementColorMap.put(NsharpConstants.LoadState.AVAIL.name(),NsharpConstants.color_yellow); + nsharpNative = new NsharpNative(); + // System.out.println("NsharpResourceHandler constructed"+this.toString() + // + " nsharpNative="+nsharpNative.toString()); + // based on BigNsharp storm slinky color used and gempak color + // definition + stormSlinkyColorMap.put(new Integer(3), NsharpConstants.color_green); // green + stormSlinkyColorMap.put(new Integer(7), NsharpConstants.color_magenta); + stormSlinkyColorMap.put(new Integer(6), NsharpConstants.color_cyan); + stormSlinkyColorMap.put(new Integer(13), + NsharpConstants.color_violet_md); + stormSlinkyColorMap.put(new Integer(20), + NsharpConstants.color_yellow_DK); + stormSlinkyColorMap.put(new Integer(27), NsharpConstants.color_cyan_md); + NsharpPaletteWindow win = NsharpPaletteWindow.getInstance(); + if (win != null) + currentGraphMode = win.getCurrentGraphMode(); + + // new for configMgr + configMgr = NsharpConfigManager.getInstance(); + configStore = configMgr.retrieveNsharpConfigStoreFromFs(); + graphConfigProperty = configStore.getGraphProperty(); + paneConfigurationName = graphConfigProperty.getPaneConfigurationName(); + + int tempOffset = graphConfigProperty.getTempOffset(); + NsharpWxMath.setTempOffset(tempOffset); + linePropertyMap = configStore.getLinePropertyMap(); + dataPageProperty = configStore.getDataPageProperty(); + updatePageOrderArray(); + updateDisplay(displayArray, paneConfigurationName); + displayDataPageMax = NsharpConstants.PAGE_MAX_NUMBER + / dataPageProperty.getNumberPagePerDisplay(); + + DateFormatSymbols dfs = new DateFormatSymbols(); + defaultDays = dfs.getShortWeekdays(); + } + + public void disposeInternal() { + // System.out.println("NsharpResourceHandler disposeInternal called"); + listenerList = null; + soundingLys = null; + previousSoundingLys = null; + stormSlinkyColorMap = null; + elementColorMap = null; + + if (NsharpParcelDialog.getAccess() != null) { + NsharpParcelDialog.getAccess().reset(); + } + + nsharpNative = null; + } + + public void printHeightMark(WGraphics world, GC gc) throws VizException { + // print feet scales... + double vyMax = world.getViewYmax(); + double vyMin = world.getViewYmin(); + double vxMax = world.getViewXmax(); + for (int j = 0; j < NsharpConstants.HEIGHT_LEVEL_FEET.length; j++) { + float meters = (float) NsharpConstants.feetToMeters + .convert(NsharpConstants.HEIGHT_LEVEL_FEET[j]); + + double pressure = nsharpNative.nsharpLib.ipres(meters); + double y = world.mapY(NsharpWxMath.getSkewTXY(pressure, -50).y); + + gc.drawString(Integer + .toString(NsharpConstants.HEIGHT_LEVEL_FEET[j] / 1000), + (int) vxMax + 40, (int) y, false); + + gc.drawLine((int) vxMax + 50, (int) y, (int) vxMax + 45, (int) y); + } + // print meter scales... for (int j = 0; j < NsharpConstants.HEIGHT_LEVEL_METERS.length; j++) { - int meters = NsharpConstants.HEIGHT_LEVEL_METERS[j]; - - double pressure = nsharpNative.nsharpLib.ipres(meters); - double y = world.mapY(NsharpWxMath.getSkewTXY(pressure, -50).y); + int meters = NsharpConstants.HEIGHT_LEVEL_METERS[j]; - gc.drawString( Integer.toString(meters/1000), (int)vxMax + 52, - (int)y,false); - + double pressure = nsharpNative.nsharpLib.ipres(meters); + double y = world.mapY(NsharpWxMath.getSkewTXY(pressure, -50).y); - gc.drawLine( (int)vxMax + 50,(int) y, (int) vxMax + 55,(int) y); - } + gc.drawString(Integer.toString(meters / 1000), (int) vxMax + 52, + (int) y, false); + + gc.drawLine((int) vxMax + 50, (int) y, (int) vxMax + 55, (int) y); + } // print surface level mark - double y = world.mapY(NsharpWxMath.getSkewTXY(soundingLys.get(0).getPressure(), -50).y); - gc.drawString("SFC("+Integer.toString((int)(soundingLys.get(0).getGeoHeight()))+"m)", (int)vxMax+ 50, - (int)y, false); - gc.drawLine((int) vxMax+ 50, (int)y, (int) vxMax + 55,(int) y); - // top level mark at 100 mbar + double y = world.mapY(NsharpWxMath.getSkewTXY(soundingLys.get(0) + .getPressure(), -50).y); + gc.drawString( + "SFC(" + + Integer.toString((int) (soundingLys.get(0) + .getGeoHeight())) + "m)", (int) vxMax + 50, + (int) y, false); + gc.drawLine((int) vxMax + 50, (int) y, (int) vxMax + 55, (int) y); + // top level mark at 100 mbar y = world.mapY(NsharpWxMath.getSkewTXY(100, -50).y); float hgt = nsharpNative.nsharpLib.ihght(100); - gc.drawString(Float.toString(hgt/1000F), (int)vxMax+ 50,(int)y, false); - gc.drawString("Kft Km", (int) vxMax+35, (int)y -8); - gc.drawString("MSL", (int) vxMax+45, (int)y -15); - gc.drawLine((int) vxMax+40, (int)y, (int) vxMax + 60,(int) y); - - gc.drawLine((int) vxMax+50, (int)vyMin, (int) vxMax + 50,(int)vyMax); + gc.drawString(Float.toString(hgt / 1000F), (int) vxMax + 50, (int) y, + false); + gc.drawString("Kft Km", (int) vxMax + 35, (int) y - 8); + gc.drawString("MSL", (int) vxMax + 45, (int) y - 15); + gc.drawLine((int) vxMax + 40, (int) y, (int) vxMax + 60, (int) y); + + gc.drawLine((int) vxMax + 50, (int) vyMin, (int) vxMax + 50, + (int) vyMax); } - + /** - * Prints the pressure lines number at left side out of skewT bkgd for printing job + * Prints the pressure lines number at left side out of skewT bkgd for + * printing job * * @throws VizException */ - public void printNsharpPressureLinesNumber(WGraphics world, GC gc) throws VizException { + public void printNsharpPressureLinesNumber(WGraphics world, GC gc) + throws VizException { String s = null; double vxMax = world.getViewXmax(); - double vxMin = world.getViewXmin(); + double vxMin = world.getViewXmin(); for (int i = 0; i < NsharpConstants.PRESSURE_MAIN_LEVELS.length; i++) { - //we only care about pressure for this case, temp is no important when calling getSkewTXY - Coordinate coor = NsharpWxMath.getSkewTXY(NsharpConstants.PRESSURE_MAIN_LEVELS[i],0); + // we only care about pressure for this case, temp is no important + // when calling getSkewTXY + Coordinate coor = NsharpWxMath.getSkewTXY( + NsharpConstants.PRESSURE_MAIN_LEVELS[i], 0); - gc.drawLine((int)vxMin, (int)world.mapY(coor.y), - (int)vxMax, - (int)world.mapY(coor.y)); + gc.drawLine((int) vxMin, (int) world.mapY(coor.y), (int) vxMax, + (int) world.mapY(coor.y)); } for (int i = 0; i < NsharpConstants.PRESSURE_MARK_LEVELS.length; i++) { - //we only care about pressure for this case, temp is no important when calling getSkewTXY - Coordinate coor = NsharpWxMath.getSkewTXY(NsharpConstants.PRESSURE_MARK_LEVELS[i],0); + // we only care about pressure for this case, temp is no important + // when calling getSkewTXY + Coordinate coor = NsharpWxMath.getSkewTXY( + NsharpConstants.PRESSURE_MARK_LEVELS[i], 0); - gc.drawLine((int)vxMin, (int)world.mapY(coor.y), - (int)vxMin+10, - (int)world.mapY(coor.y)); + gc.drawLine((int) vxMin, (int) world.mapY(coor.y), + (int) vxMin + 10, (int) world.mapY(coor.y)); } for (int i = 0; i < NsharpConstants.PRESSURE_NUMBERING_LEVELS.length; i++) { - s = NsharpConstants.pressFormat.format(NsharpConstants.PRESSURE_NUMBERING_LEVELS[i]); - //we only care about pressure for this case, temp is no important when calling getSkewTXY - Coordinate coor = NsharpWxMath.getSkewTXY(NsharpConstants.PRESSURE_NUMBERING_LEVELS[i],0); + s = NsharpConstants.pressFormat + .format(NsharpConstants.PRESSURE_NUMBERING_LEVELS[i]); + // we only care about pressure for this case, temp is no important + // when calling getSkewTXY + Coordinate coor = NsharpWxMath.getSkewTXY( + NsharpConstants.PRESSURE_NUMBERING_LEVELS[i], 0); - gc.drawString( s, (int)vxMin-20, - (int)world.mapY(coor.y), false); + gc.drawString(s, (int) vxMin - 20, (int) world.mapY(coor.y), false); } } @@ -2594,89 +3006,96 @@ public class NsharpResourceHandler { * * @throws VizException */ - public void printNsharpTempNumber(WGraphics world, GC gc) throws VizException { + public void printNsharpTempNumber(WGraphics world, GC gc) + throws VizException { for (int i = 40; i > -50; i -= 10) { Coordinate coorStart = NsharpWxMath.getSkewTXY(1050, i); double startX = world.mapX(coorStart.x); double startY = world.mapY(coorStart.y); - gc.drawString( Integer.toString(i), (int)startX,(int)startY+5,false); + gc.drawString(Integer.toString(i), (int) startX, (int) startY + 5, + false); } for (int i = -60; i > -120; i -= 10) { Coordinate coorEnd = NsharpWxMath.getSkewTXY(100, i); - //System.out.println("X = "+ startX + " Y = "+ startY); + // System.out.println("X = "+ startX + " Y = "+ startY); double endX = world.mapX(coorEnd.x); double endY = world.mapY(coorEnd.y); - - gc.drawString( Integer.toString(i),(int) endX,(int)endY-10,false); + gc.drawString(Integer.toString(i), (int) endX, (int) endY - 10, + false); } } + /** * - * Print Wind barb for printing job - * This function followed algorithm in plot_barbs (void) at xwvid1.c - * to choose wind bulb for drawing around every 400m + * Print Wind barb for printing job This function followed algorithm in + * plot_barbs (void) at xwvid1.c to choose wind bulb for drawing around + * every 400m * */ - public void printNsharpWind(WGraphics world, GC gc)throws VizException { + public void printNsharpWind(WGraphics world, GC gc) throws VizException { ArrayList> windList = new ArrayList>(); - double windX = world.getViewXmax() + 6*BARB_LENGTH; - //System.out.println("windX="+windX); + double windX = world.getViewXmax() + 6 * BARB_LENGTH; + // System.out.println("windX="+windX); float lastHeight = -999; double windY; for (NcSoundingLayer layer : soundingLys) { float pressure = layer.getPressure(); float spd = layer.getWindSpeed(); float dir = layer.getWindDirection(); - - if ( pressure < 100) { + if (pressure < 100) { continue; } - - if ((layer.getGeoHeight() - lastHeight) < 400){ - - continue; + + if ((layer.getGeoHeight() - lastHeight) < 400) { + + continue; } // Get the vertical ordinate. - windY = world.mapY(NsharpWxMath.getSkewTXY(pressure, 0).y); - + windY = world.mapY(NsharpWxMath.getSkewTXY(pressure, 0).y); + List barb = WindBarbFactory.getWindGraphics( - /*metersPerSecondToKnots.convert*/(double) (spd), (double) dir); + /* metersPerSecondToKnots.convert */(double) (spd), (double) dir); if (barb != null) { WindBarbFactory.scaleBarb(barb, -7); WindBarbFactory.translateBarb(barb, windX, windY); windList.add(barb); } - + lastHeight = layer.getGeoHeight(); } - Coordinate pt1=new Coordinate(0,0), pt2; + Coordinate pt1 = new Coordinate(0, 0), pt2; for (List barb : windList) { for (LineStroke stroke : barb) { - //stroke render: rewrite stroke.render() for our printing purpose - if(stroke.getType()=="M") { - pt1 = stroke.getPoint(); - //change X coordinate by mirroring x coordinate at windX axis. AS we scaleBarb with -5 time. - // It is easier to mirror at x-axis for this case. - pt1.x = windX - (pt1.x-windX); - //System.out.print("Myp1x="+(int)pt1.x+" p1y="+(int)pt1.y); - - } - else if(stroke.getType()=="D"){ + // stroke render: rewrite stroke.render() for our printing + // purpose + if (stroke.getType() == "M") { + pt1 = stroke.getPoint(); + // change X coordinate by mirroring x coordinate at windX + // axis. AS we scaleBarb with -5 time. + // It is easier to mirror at x-axis for this case. + pt1.x = windX - (pt1.x - windX); + // System.out.print("Myp1x="+(int)pt1.x+" p1y="+(int)pt1.y); + + } else if (stroke.getType() == "D") { pt2 = stroke.getPoint(); - pt2.x = windX - (pt2.x-windX); - //System.out.println( " p2x="+(int)pt2.x+" p2y="+ (int)pt2.y); - gc.drawLine((int)pt1.x, (int)pt1.y, (int)pt2.x, (int)pt2.y); + pt2.x = windX - (pt2.x - windX); + // System.out.println( " p2x="+(int)pt2.x+" p2y="+ + // (int)pt2.y); + gc.drawLine((int) pt1.x, (int) pt1.y, (int) pt2.x, + (int) pt2.y); } } } - gc.drawLine((int)windX,(int)world.mapY(NsharpWxMath.getSkewTXY(100, 0).y), - (int)windX,(int)world.mapY(NsharpWxMath.getSkewTXY(1000, 0).y)); + gc.drawLine((int) windX, + (int) world.mapY(NsharpWxMath.getSkewTXY(100, 0).y), + (int) windX, + (int) world.mapY(NsharpWxMath.getSkewTXY(1000, 0).y)); } /** @@ -2685,714 +3104,731 @@ public class NsharpResourceHandler { * * @throws VizException */ - public void printNsharpWetbulbTraceCurve( - WGraphics world, GC gc) throws VizException { - if((soundingLys == null) || (soundingLys.size()==0)) - return; - float t1; - - Coordinate c2 = null; + public void printNsharpWetbulbTraceCurve(WGraphics world, GC gc) + throws VizException { + if ((soundingLys == null) || (soundingLys.size() == 0)) + return; + float t1; + + Coordinate c2 = null; Coordinate c1; // print trace for (NcSoundingLayer layer : this.soundingLys) { - if (layer.getDewpoint() > -200){ - t1 = nsharpNative.nsharpLib.wetbulb(layer.getPressure(), layer.getTemperature(), - layer.getDewpoint()); + if (layer.getDewpoint() > -200) { + t1 = nsharpNative.nsharpLib.wetbulb(layer.getPressure(), + layer.getTemperature(), layer.getDewpoint()); - c1 = NsharpWxMath.getSkewTXY(layer.getPressure(), t1); - c1.x = world.mapX(c1.x); - c1.y = world.mapY(c1.y); - if(c2!= null){ - gc.drawLine((int)c1.x, (int)c1.y, (int)c2.x, (int)c2.y); - } - c2 = c1; - } + c1 = NsharpWxMath.getSkewTXY(layer.getPressure(), t1); + c1.x = world.mapX(c1.x); + c1.y = world.mapY(c1.y); + if (c2 != null) { + gc.drawLine((int) c1.x, (int) c1.y, (int) c2.x, (int) c2.y); + } + c2 = c1; + } } - - } - - public void printNsharpParcelTraceCurve(WGraphics world, GC gc) throws VizException{ - if(soundingLys.size() > 0){ - //for (ParcelData parData: parcelList){ - //plotNsharpParcelTraceCurve(null, 0, world, NsharpConstants.color_white,parData.parcelType, parData.userPressure, gc, true); - //nsharpNative.nsharpLib.define_parcel(parData.parcelType, parData.parcelLayerPressure); - nsharpNative.nsharpLib.define_parcel(currentParcel,currentParcelLayerPressure); - _lplvalues lpvls = new _lplvalues(); - nsharpNative.nsharpLib.get_lpvaluesData(lpvls); - float sfctemp, sfcdwpt, sfcpres; - sfctemp = lpvls.temp; - sfcdwpt = lpvls.dwpt; - sfcpres = lpvls.pres; - - float vtemp = nsharpNative.nsharpLib.virtemp (sfcpres, sfctemp, sfcdwpt); - Coordinate c1 = NsharpWxMath.getSkewTXY(sfcpres, vtemp); - c1.x = world.mapX(c1.x); - c1.y = world.mapY(c1.y); - FloatByReference p2 = new FloatByReference(0), t2 = new FloatByReference(0);; - nsharpNative.nsharpLib.drylift (sfcpres, sfctemp, sfcdwpt, p2, t2); - vtemp = nsharpNative.nsharpLib.virtemp (p2.getValue(), t2.getValue(), t2.getValue()); - Coordinate c2 = NsharpWxMath.getSkewTXY(p2.getValue(), vtemp); - c2.x = world.mapX(c2.x); - c2.y = world.mapY(c2.y); - - gc.drawLine((int)c1.x, (int)c1.y, (int)c2.x, (int)c2.y); - c1 = c2; - - - float t3; - for (float i = p2.getValue() - 50; i >= 100; i = i - 50) - { - t3 = nsharpNative.nsharpLib.wetlift (p2.getValue(), t2.getValue(), i); - vtemp = nsharpNative.nsharpLib.virtemp (i, t3, t3); - c2 = NsharpWxMath.getSkewTXY(i, vtemp); - c2.x = world.mapX(c2.x); - c2.y = world.mapY(c2.y); - - gc.drawLine((int)c1.x, (int)c1.y, (int)c2.x, (int)c2.y); - c1 = c2; - } - - t3 = nsharpNative.nsharpLib.wetlift (p2.getValue(), t2.getValue(), 100); - vtemp = nsharpNative.nsharpLib.virtemp (100, t3, t3); - c2 = NsharpWxMath.getSkewTXY(100, vtemp); - c2.x = world.mapX(c2.x); - c2.y = world.mapY(c2.y); - - gc.drawLine((int)c1.x, (int)c1.y, (int)c2.x, (int)c2.y); - //} - } } + + public void printNsharpParcelTraceCurve(WGraphics world, GC gc) + throws VizException { + if (soundingLys.size() > 0) { + // for (ParcelData parData: parcelList){ + // plotNsharpParcelTraceCurve(null, 0, world, + // NsharpConstants.color_white,parData.parcelType, + // parData.userPressure, gc, true); + // nsharpNative.nsharpLib.define_parcel(parData.parcelType, + // parData.parcelLayerPressure); + nsharpNative.nsharpLib.define_parcel(currentParcel, + currentParcelLayerPressure); + _lplvalues lpvls = new _lplvalues(); + nsharpNative.nsharpLib.get_lpvaluesData(lpvls); + + float sfctemp, sfcdwpt, sfcpres; + sfctemp = lpvls.temp; + sfcdwpt = lpvls.dwpt; + sfcpres = lpvls.pres; + + float vtemp = nsharpNative.nsharpLib.virtemp(sfcpres, sfctemp, + sfcdwpt); + Coordinate c1 = NsharpWxMath.getSkewTXY(sfcpres, vtemp); + c1.x = world.mapX(c1.x); + c1.y = world.mapY(c1.y); + FloatByReference p2 = new FloatByReference(0), t2 = new FloatByReference( + 0); + ; + nsharpNative.nsharpLib.drylift(sfcpres, sfctemp, sfcdwpt, p2, t2); + vtemp = nsharpNative.nsharpLib.virtemp(p2.getValue(), + t2.getValue(), t2.getValue()); + Coordinate c2 = NsharpWxMath.getSkewTXY(p2.getValue(), vtemp); + c2.x = world.mapX(c2.x); + c2.y = world.mapY(c2.y); + + gc.drawLine((int) c1.x, (int) c1.y, (int) c2.x, (int) c2.y); + c1 = c2; + + float t3; + for (float i = p2.getValue() - 50; i >= 100; i = i - 50) { + t3 = nsharpNative.nsharpLib.wetlift(p2.getValue(), + t2.getValue(), i); + vtemp = nsharpNative.nsharpLib.virtemp(i, t3, t3); + c2 = NsharpWxMath.getSkewTXY(i, vtemp); + c2.x = world.mapX(c2.x); + c2.y = world.mapY(c2.y); + + gc.drawLine((int) c1.x, (int) c1.y, (int) c2.x, (int) c2.y); + c1 = c2; + } + + t3 = nsharpNative.nsharpLib.wetlift(p2.getValue(), t2.getValue(), + 100); + vtemp = nsharpNative.nsharpLib.virtemp(100, t3, t3); + c2 = NsharpWxMath.getSkewTXY(100, vtemp); + c2.x = world.mapX(c2.x); + c2.y = world.mapY(c2.y); + + gc.drawLine((int) c1.x, (int) c1.y, (int) c2.x, (int) c2.y); + // } + } + } + /** * * Print the temperature curve when during overlap or compare mode * * @throws VizException */ - - public void printNsharpPressureTempCurve(WGraphics world, int type, GC gc,List soundingLys) throws VizException { - if((soundingLys == null) || (soundingLys.size()==0)) - return; - double maxPressure = NsharpWxMath.reverseSkewTXY(new Coordinate(0, world - .getWorldYmax())).y; - double minPressure = NsharpWxMath.reverseSkewTXY(new Coordinate(0, world - .getWorldYmin())).y; + public void printNsharpPressureTempCurve(WGraphics world, int type, GC gc, + List soundingLys) throws VizException { + if ((soundingLys == null) || (soundingLys.size() == 0)) + return; + + double maxPressure = NsharpWxMath.reverseSkewTXY(new Coordinate(0, + world.getWorldYmax())).y; + double minPressure = NsharpWxMath.reverseSkewTXY(new Coordinate(0, + world.getWorldYmin())).y; Coordinate c0 = null; - for (NcSoundingLayer layer : soundingLys) { - double t; - if(type == TEMP_TYPE) - t = layer.getTemperature(); - else if (type == DEWPOINT_TYPE) - t = layer.getDewpoint(); - else - break; + for (NcSoundingLayer layer : soundingLys) { + double t; + if (type == TEMP_TYPE) + t = layer.getTemperature(); + else if (type == DEWPOINT_TYPE) + t = layer.getDewpoint(); + else + break; double pressure = layer.getPressure(); - if (t != INVALID_DATA && pressure >= minPressure + if (t != INVALID_DATA && pressure >= minPressure && pressure <= maxPressure) { Coordinate c1 = NsharpWxMath.getSkewTXY(pressure, t); - + c1.x = world.mapX(c1.x); c1.y = world.mapY(c1.y); - //System.out.println("C.x "+ c1.x + " C.y "+ c1.y); + // System.out.println("C.x "+ c1.x + " C.y "+ c1.y); if (c0 != null) { - gc.drawLine((int)c0.x, (int)c0.y, (int)c1.x, (int)c1.y); - } + gc.drawLine((int) c0.x, (int) c0.y, (int) c1.x, (int) c1.y); + } c0 = c1; } } - + } - - - /** + + /** * * Print the HODO * - * + * * @throws VizException */ - public void printNsharpHodoWind(WGraphics world, GC gc, List soundingLays) throws VizException { + public void printNsharpHodoWind(WGraphics world, GC gc, + List soundingLays) throws VizException { Coordinate c0 = null; Coordinate c1; - for (NcSoundingLayer layer : soundingLays){ - if(layer.getPressure() < 100 || layer.getWindSpeed() <0) - continue; + for (NcSoundingLayer layer : soundingLays) { + if (layer.getPressure() < 100 || layer.getWindSpeed() < 0) + continue; float wspd = layer.getWindSpeed(); float wdir = layer.getWindDirection(); - c1 = WxMath.uvComp(wspd, wdir); + c1 = WxMath.uvComp(wspd, wdir); if (c0 != null) { - gc.setLineWidth(1); - gc.drawLine((int)world.mapX(c0.x),(int) world.mapY(c0.y),(int) world - .mapX(c1.x),(int) world.mapY(c1.y)); + gc.setLineWidth(1); + gc.drawLine((int) world.mapX(c0.x), (int) world.mapY(c0.y), + (int) world.mapX(c1.x), (int) world.mapY(c1.y)); } c0 = c1; } - } - - public boolean isPlotInteractiveTemp() { - return plotInteractiveTemp; - } + public boolean isPlotInteractiveTemp() { + return plotInteractiveTemp; + } + public void setPlotInteractiveTemp(boolean plotInteractiveTemp) { + this.plotInteractiveTemp = plotInteractiveTemp; + if (skewtPaneRsc != null) + skewtPaneRsc.setPlotInteractiveTemp(plotInteractiveTemp); + } - public void setPlotInteractiveTemp(boolean plotInteractiveTemp) { - this.plotInteractiveTemp = plotInteractiveTemp; - if(skewtPaneRsc!=null) - skewtPaneRsc.setPlotInteractiveTemp(plotInteractiveTemp); - } - public void setInteractiveTempPointCoordinate( - Coordinate interactiveTempPointCoordinate) { - //System.out.println("setInteractiveTempPointCoordinate called"); - this.interactiveTempPointCoordinate = interactiveTempPointCoordinate; - plotInteractiveTemp = true; - if(skewtPaneRsc!=null){ - skewtPaneRsc.setPlotInteractiveTemp(plotInteractiveTemp); - skewtPaneRsc.setInteractiveTempPointCoordinate(interactiveTempPointCoordinate); - } - } - public void setInteractiveHodoPointCoordinate(Coordinate c){ - if(hodoPaneRsc == null) - return; - try { - NcSoundingLayer hodoLayer = soundingLys.get(hodoEditingSoundingLayerIndex); - if(hodoLayer != null){ - //TTR575 - nsharpNative.populateSndgData(soundingLys); - //end TTR575 - Coordinate c1 = hodoPaneRsc.getHodoBackground().getWorld().unMap(c.x, c.y); - //System.out.println("picked pt after unmap CX "+ c1.x + " CY "+ c1.y); - c1 = WxMath.speedDir((float) c1.x, (float) c1.y); - hodoLayer.setWindSpeed((float)c1.x); - hodoLayer.setWindDirection((float)c1.y); - hodoPaneRsc.createRscHodoWindShapeAll(); - if(witoPaneRsc!=null) - witoPaneRsc.createAllWireFrameShapes(); - if(insetPaneRsc!=null) - insetPaneRsc.createInsetWireFrameShapes(); - if(skewtPaneRsc!=null) - //CHIN:::fix edit zoom issue skewtPaneRsc.handleResize(); - skewtPaneRsc.createRscWireFrameShapes(); - } - } - catch(Exception e) { - - } - } - public void applyMovingTempLine(){ - if(skewtPaneRsc==null) - return; - Coordinate inC = NsharpWxMath.reverseSkewTXY(skewtPaneRsc.getWorld().unMap(interactiveTempPointCoordinate)); - float inTemp = (float) inC.x; - currentSoundingLayerIndex = skewtPaneRsc.getCurrentSoundingLayerIndex(); - currentTempCurveType = skewtPaneRsc.getCurrentTempCurveType(); - float currentLayerTemp, currentLayerDewP; - float smallestGap = skewtPaneRsc.getTempDewPtSmallestGap(); - float tempShiftedDist; - currentLayerTemp = soundingLys.get(currentSoundingLayerIndex).getTemperature(); - currentLayerDewP = soundingLys.get(currentSoundingLayerIndex).getDewpoint(); - if(currentTempCurveType == TEMP_TYPE){ - if(inTemp < currentLayerTemp){ - // shift to left, tempShiftedDist should be a negative number - if((currentLayerTemp - inTemp)> smallestGap){ - tempShiftedDist = -smallestGap; - } - else { - tempShiftedDist = inTemp - currentLayerTemp; - } - } - else { - // shift to right, tempShiftedDist should be a positive number - tempShiftedDist = inTemp - currentLayerTemp; - } - } - else { - if(inTemp < currentLayerDewP){ - // shift to left, tempShiftedDist should be a negative number - tempShiftedDist = inTemp - currentLayerDewP; - } - else { - // shift to right, tempShiftedDist should be a positive number - if((inTemp - currentLayerDewP)> smallestGap){ - tempShiftedDist = smallestGap; - } - else { - tempShiftedDist = inTemp - currentLayerDewP; - } - } - } - for (NcSoundingLayer layer : soundingLys) { - float t; - if(currentTempCurveType == TEMP_TYPE){ - t = layer.getTemperature(); - if (t != NsharpNativeConstants.NSHARP_NATIVE_INVALID_DATA ) { - layer.setTemperature(t+tempShiftedDist); - } - } - else{ - t = layer.getDewpoint(); - if (t != NsharpNativeConstants.NSHARP_NATIVE_INVALID_DATA ) { - layer.setDewpoint(t+tempShiftedDist); - } - } - } - //re-populate snd data to nsharp native code lib for later calculating - nsharpNative.populateSndgData(soundingLys); - //get storm motion wind data after populate sounding from NsharpLib - skewtPaneRsc.setSoundingLys(soundingLys); - //CHIN:::fix edit zoom issue skewtPaneRsc.handleResize(); - skewtPaneRsc.createRscWireFrameShapes(); - if(hodoPaneRsc!=null){ - hodoPaneRsc.setSoundingLys(soundingLys); - hodoPaneRsc.createRscHodoWindShapeAll(); - } - } - public void applyInteractiveTempPoint(){ - if(skewtPaneRsc==null) - return; - Coordinate inC = NsharpWxMath.reverseSkewTXY(skewtPaneRsc.getWorld().unMap(interactiveTempPointCoordinate)); - double inTemp = inC.x; - currentSoundingLayerIndex = skewtPaneRsc.getCurrentSoundingLayerIndex(); - NcSoundingLayer layer = this.soundingLys.get(currentSoundingLayerIndex); - currentTempCurveType = skewtPaneRsc.getCurrentTempCurveType(); - //System.out.println("applyInteractiveTempPoint called pressure " + inC.y + " temp "+ inTemp + - // " currentTempCurveType " + currentTempCurveType ); - - if(currentTempCurveType == TEMP_TYPE){ - if(inTemp < layer.getDewpoint()) - // temp can not be lower than dew point - layer.setTemperature(layer.getDewpoint()); - else - layer.setTemperature((float)inTemp); - } - else{ - if(inTemp > layer.getTemperature()) - // dew point can not be higher than temp - layer.setDewpoint(layer.getTemperature()); - else - layer.setDewpoint((float)inTemp); - } + public void setInteractiveTempPointCoordinate( + Coordinate interactiveTempPointCoordinate) { + // System.out.println("setInteractiveTempPointCoordinate called"); + this.interactiveTempPointCoordinate = interactiveTempPointCoordinate; + plotInteractiveTemp = true; + if (skewtPaneRsc != null) { + skewtPaneRsc.setPlotInteractiveTemp(plotInteractiveTemp); + skewtPaneRsc + .setInteractiveTempPointCoordinate(interactiveTempPointCoordinate); + } + } + public void setInteractiveHodoPointCoordinate(Coordinate c) { + if (hodoPaneRsc == null) + return; + try { + NcSoundingLayer hodoLayer = soundingLys + .get(hodoEditingSoundingLayerIndex); + if (hodoLayer != null) { + // TTR575 + nsharpNative.populateSndgData(soundingLys); + // end TTR575 + Coordinate c1 = hodoPaneRsc.getHodoBackground().getWorld() + .unMap(c.x, c.y); + // System.out.println("picked pt after unmap CX "+ c1.x + + // " CY "+ c1.y); + c1 = WxMath.speedDir((float) c1.x, (float) c1.y); + hodoLayer.setWindSpeed((float) c1.x); + hodoLayer.setWindDirection((float) c1.y); + hodoPaneRsc.createRscHodoWindShapeAll(); + if (witoPaneRsc != null) + witoPaneRsc.createAllWireFrameShapes(); + if (insetPaneRsc != null) + insetPaneRsc.createInsetWireFrameShapes(); + if (skewtPaneRsc != null) + // CHIN:::fix edit zoom issue skewtPaneRsc.handleResize(); + skewtPaneRsc.createRscWireFrameShapes(); + } + } catch (Exception e) { - //re-populate snd data to nsharp native code lib for later calculating - nsharpNative.populateSndgData(soundingLys); - //get storm motion wind data after populate sounding from NsharpLib - skewtPaneRsc.setSoundingLys(soundingLys); - //CHIN:::fix edit zoom issue skewtPaneRsc.handleResize(); - skewtPaneRsc.createRscWireFrameShapes(); - - if(hodoPaneRsc!=null){ - hodoPaneRsc.setSoundingLys(soundingLys); - hodoPaneRsc.createRscHodoWindShapeAll(); - } - } + } + } - public void applySfcEditing(float tp, float dp, float ws, float wd, float pressure){ - currentSoundingLayerIndex =nsharpNative.nsharpLib.sfc(); - NcSoundingLayer layer = this.soundingLys.get(currentSoundingLayerIndex); - layer.setTemperature(tp); - layer.setDewpoint(dp); - layer.setWindDirection(wd); - layer.setWindSpeed(ws); - layer.setPressure(pressure); - //re-populate snd data to nsharp native code lib for later calculating - nsharpNative.populateSndgData(soundingLys); - if(skewtPaneRsc!=null) - skewtPaneRsc.setSoundingLys(soundingLys); - if(hodoPaneRsc!=null) - hodoPaneRsc.setSoundingLys(soundingLys); - if(insetPaneRsc!=null) - insetPaneRsc.setSoundingLys(soundingLys); - if(witoPaneRsc!=null) - witoPaneRsc.setSoundingLys(soundingLys); - if(dataPaneRsc!=null) - dataPaneRsc.setSoundingLys(soundingLys); - } - public void updateLayer(int layerIndex, float tp, float dp, float ws, float wd, float pressure){ - if(layerIndex <0 || layerIndex >= soundingLys.size()) - return; - currentSoundingLayerIndex =layerIndex; - NcSoundingLayer layer = soundingLys.get(currentSoundingLayerIndex); - layer.setGeoHeight(nsharpNative.nsharpLib.ihght(pressure)); - layer.setTemperature(tp); - layer.setDewpoint(dp); - layer.setWindDirection(wd); - layer.setWindSpeed(ws); - layer.setPressure(pressure); - //re-populate snd data to nsharp native code lib for later calculating - Collections.sort(soundingLys,NsharpDataHandling.reversePressureHeightWindComparator()); - nsharpNative.populateSndgData(soundingLys); - //get storm motion wind data after populate sounding from NsharpLib - //refresh test area if it is shown now - NsharpShowTextDialog textarea = NsharpShowTextDialog.getAccess(); - if(textarea != null){ - textarea.refreshTextData(); - } - if(skewtPaneRsc!=null){ - skewtPaneRsc.setSoundingLys(soundingLys); - //CHIN:::fix edit zoom issue skewtPaneRsc.handleResize(); - skewtPaneRsc.createRscWireFrameShapes(); - } - if(hodoPaneRsc!=null){ - hodoPaneRsc.setSoundingLys(soundingLys); - hodoPaneRsc.createRscHodoWindShapeAll(); - } - if(insetPaneRsc!=null){ - insetPaneRsc.setSoundingLys(soundingLys); - insetPaneRsc.createInsetWireFrameShapes(); - } - if(witoPaneRsc!=null) { - witoPaneRsc.setSoundingLys(soundingLys); - witoPaneRsc.createAllWireFrameShapes(); - } - if(dataPaneRsc!=null) - dataPaneRsc.setSoundingLys(soundingLys); - } - public void addNewLayer(float tp, float dp, float ws, float wd, float pressure){ - //NsharpBackgroundResource bkRsc = descriptor.getSkewTBkGResource(); - //currentSoundingLayer =layerIndex; - NcSoundingLayer layer = new NcSoundingLayer(); - layer.setGeoHeight(nsharpNative.nsharpLib.ihght(pressure)); - layer.setTemperature(tp); - layer.setDewpoint(dp); - layer.setWindDirection(wd); - layer.setWindSpeed(ws); - layer.setPressure(pressure); - soundingLys.add(layer); - //re-populate snd data to nsharp native code lib for later calculating - Collections.sort(soundingLys,NsharpDataHandling.reversePressureHeightWindComparator()); - nsharpNative.populateSndgData(soundingLys); - //get storm motion wind data after populate sounding from NsharpLib - //refresh text area if it is shown now - NsharpShowTextDialog textarea = NsharpShowTextDialog.getAccess(); - if(textarea != null){ - textarea.refreshTextData(); - } - if(skewtPaneRsc!=null){ - skewtPaneRsc.setSoundingLys(soundingLys); - //CHIN:::fix edit zoom issue skewtPaneRsc.handleResize(); - skewtPaneRsc.createRscWireFrameShapes(); - } - if(hodoPaneRsc!=null){ - hodoPaneRsc.setSoundingLys(soundingLys); - hodoPaneRsc.createRscHodoWindShapeAll(); - } - if(insetPaneRsc!=null){ - insetPaneRsc.setSoundingLys(soundingLys); - insetPaneRsc.createInsetWireFrameShapes(); - } - if(witoPaneRsc!=null) { - witoPaneRsc.setSoundingLys(soundingLys); - witoPaneRsc.createAllWireFrameShapes(); - } - if(dataPaneRsc!=null) - dataPaneRsc.setSoundingLys(soundingLys); - } - - + public void applyMovingTempLine() { + if (skewtPaneRsc == null) + return; + Coordinate inC = NsharpWxMath.reverseSkewTXY(skewtPaneRsc.getWorld() + .unMap(interactiveTempPointCoordinate)); + float inTemp = (float) inC.x; + currentSoundingLayerIndex = skewtPaneRsc.getCurrentSoundingLayerIndex(); + currentTempCurveType = skewtPaneRsc.getCurrentTempCurveType(); + float currentLayerTemp, currentLayerDewP; + float smallestGap = skewtPaneRsc.getTempDewPtSmallestGap(); + float tempShiftedDist; + currentLayerTemp = soundingLys.get(currentSoundingLayerIndex) + .getTemperature(); + currentLayerDewP = soundingLys.get(currentSoundingLayerIndex) + .getDewpoint(); + if (currentTempCurveType == TEMP_TYPE) { + if (inTemp < currentLayerTemp) { + // shift to left, tempShiftedDist should be a negative number + if ((currentLayerTemp - inTemp) > smallestGap) { + tempShiftedDist = -smallestGap; + } else { + tempShiftedDist = inTemp - currentLayerTemp; + } + } else { + // shift to right, tempShiftedDist should be a positive number + tempShiftedDist = inTemp - currentLayerTemp; + } + } else { + if (inTemp < currentLayerDewP) { + // shift to left, tempShiftedDist should be a negative number + tempShiftedDist = inTemp - currentLayerDewP; + } else { + // shift to right, tempShiftedDist should be a positive number + if ((inTemp - currentLayerDewP) > smallestGap) { + tempShiftedDist = smallestGap; + } else { + tempShiftedDist = inTemp - currentLayerDewP; + } + } + } + for (NcSoundingLayer layer : soundingLys) { + float t; + if (currentTempCurveType == TEMP_TYPE) { + t = layer.getTemperature(); + if (t != NsharpNativeConstants.NSHARP_NATIVE_INVALID_DATA) { + layer.setTemperature(t + tempShiftedDist); + } + } else { + t = layer.getDewpoint(); + if (t != NsharpNativeConstants.NSHARP_NATIVE_INVALID_DATA) { + layer.setDewpoint(t + tempShiftedDist); + } + } + } + // re-populate snd data to nsharp native code lib for later calculating + nsharpNative.populateSndgData(soundingLys); + // get storm motion wind data after populate sounding from NsharpLib + skewtPaneRsc.setSoundingLys(soundingLys); + // CHIN:::fix edit zoom issue skewtPaneRsc.handleResize(); + skewtPaneRsc.createRscWireFrameShapes(); + if (hodoPaneRsc != null) { + hodoPaneRsc.setSoundingLys(soundingLys); + hodoPaneRsc.createRscHodoWindShapeAll(); + } + } + public void applyInteractiveTempPoint() { + if (skewtPaneRsc == null) + return; + Coordinate inC = NsharpWxMath.reverseSkewTXY(skewtPaneRsc.getWorld() + .unMap(interactiveTempPointCoordinate)); + double inTemp = inC.x; + currentSoundingLayerIndex = skewtPaneRsc.getCurrentSoundingLayerIndex(); + NcSoundingLayer layer = this.soundingLys.get(currentSoundingLayerIndex); + currentTempCurveType = skewtPaneRsc.getCurrentTempCurveType(); + // System.out.println("applyInteractiveTempPoint called pressure " + + // inC.y + " temp "+ inTemp + + // " currentTempCurveType " + currentTempCurveType ); - public void setGraphConfigProperty(NsharpGraphProperty graphConfigProperty) { - this.graphConfigProperty = graphConfigProperty; - int tempOffset = graphConfigProperty.getTempOffset(); - NsharpWxMath.setTempOffset(tempOffset); - if(skewtPaneRsc!=null){ - skewtPaneRsc.setGraphConfigProperty(graphConfigProperty); - skewtPaneRsc.handleResize(); - skewtPaneRsc.getSkewTBackground().setGraphConfigProperty(graphConfigProperty); - } - if(hodoPaneRsc!=null) { - hodoPaneRsc.setGraphConfigProperty(graphConfigProperty); - hodoPaneRsc.createRscHodoWindShapeAll(); - } - if(witoPaneRsc!=null) { - witoPaneRsc.setGraphConfigProperty(graphConfigProperty); - witoPaneRsc.createAllWireFrameShapes(); - } - if(insetPaneRsc!=null){ - insetPaneRsc.setGraphConfigProperty(graphConfigProperty); - insetPaneRsc.createInsetWireFrameShapes(); - } - } - - - public NsharpGraphProperty getGraphConfigProperty() { - return graphConfigProperty; - } + if (currentTempCurveType == TEMP_TYPE) { + if (inTemp < layer.getDewpoint()) + // temp can not be lower than dew point + layer.setTemperature(layer.getDewpoint()); + else + layer.setTemperature((float) inTemp); + } else { + if (inTemp > layer.getTemperature()) + // dew point can not be higher than temp + layer.setDewpoint(layer.getTemperature()); + else + layer.setDewpoint((float) inTemp); + } + // re-populate snd data to nsharp native code lib for later calculating + nsharpNative.populateSndgData(soundingLys); + // get storm motion wind data after populate sounding from NsharpLib + skewtPaneRsc.setSoundingLys(soundingLys); + // CHIN:::fix edit zoom issue skewtPaneRsc.handleResize(); + skewtPaneRsc.createRscWireFrameShapes(); - public void setLinePropertyMap( - HashMap linePropertyMap) { - this.linePropertyMap = linePropertyMap; - if(skewtPaneRsc!=null){ - skewtPaneRsc.setLinePropertyMap(linePropertyMap); - skewtPaneRsc.handleResize(); - } - if(hodoPaneRsc!=null){ - hodoPaneRsc.setLinePropertyMap(linePropertyMap); - hodoPaneRsc.createRscHodoWindShapeAll(); - } - if(timeStnPaneRsc!=null) - timeStnPaneRsc.setLinePropertyMap(linePropertyMap); - } - private void updatePageOrderArray(){ - pageDisplayOrderNumberArray[NsharpConstants.PAGE_SUMMARY1 ] = dataPageProperty.getSummary1Page(); - pageDisplayOrderNumberArray[NsharpConstants.PAGE_SUMMARY2 ] = dataPageProperty.getSummary2Page(); - pageDisplayOrderNumberArray[NsharpConstants.PAGE_PARCEL_DATA ] = dataPageProperty.getParcelDataPage(); - pageDisplayOrderNumberArray[NsharpConstants.PAGE_THERMODYNAMIC_DATA ] = dataPageProperty.getThermodynamicDataPage(); - pageDisplayOrderNumberArray[NsharpConstants.PAGE_OPC_DATA ] = dataPageProperty.getOpcDataPage(); - pageDisplayOrderNumberArray[NsharpConstants.PAGE_MIXING_HEIGHT] = dataPageProperty.getMixingHeightPage(); - pageDisplayOrderNumberArray[NsharpConstants.PAGE_STORM_RELATIVE ] = dataPageProperty.getStormRelativePage(); - pageDisplayOrderNumberArray[NsharpConstants.PAGE_MEAN_WIND ] = dataPageProperty.getMeanWindPage(); - pageDisplayOrderNumberArray[NsharpConstants.PAGE_CONVECTIVE_INITIATION ] = dataPageProperty.getConvectiveInitiationPage(); - pageDisplayOrderNumberArray[NsharpConstants.PAGE_SEVERE_POTENTIAL ] = dataPageProperty.getSeverePotentialPage(); - } - public void setDataPageProperty(NsharpDataPageProperty dataPageProperty) { - this.dataPageProperty = dataPageProperty; - updatePageOrderArray(); - if(dataPaneRsc!=null) - dataPaneRsc.setPageDisplayOrderNumberArray(pageDisplayOrderNumberArray, dataPageProperty.getNumberPagePerDisplay()); - } + if (hodoPaneRsc != null) { + hodoPaneRsc.setSoundingLys(soundingLys); + hodoPaneRsc.createRscHodoWindShapeAll(); + } + } + public void applySfcEditing(float tp, float dp, float ws, float wd, + float pressure) { + currentSoundingLayerIndex = nsharpNative.nsharpLib.sfc(); + NcSoundingLayer layer = this.soundingLys.get(currentSoundingLayerIndex); + layer.setTemperature(tp); + layer.setDewpoint(dp); + layer.setWindDirection(wd); + layer.setWindSpeed(ws); + layer.setPressure(pressure); + // re-populate snd data to nsharp native code lib for later calculating + nsharpNative.populateSndgData(soundingLys); + if (skewtPaneRsc != null) + skewtPaneRsc.setSoundingLys(soundingLys); + if (hodoPaneRsc != null) + hodoPaneRsc.setSoundingLys(soundingLys); + if (insetPaneRsc != null) + insetPaneRsc.setSoundingLys(soundingLys); + if (witoPaneRsc != null) + witoPaneRsc.setSoundingLys(soundingLys); + if (dataPaneRsc != null) + dataPaneRsc.setSoundingLys(soundingLys); + } - public void handleTimeLineActConfig(List tlList, NsharpConstants.ActState actSt){ - for(String tlStr: tlList){ - for(NsharpOperationElement tl: timeElementList){ - if(tlStr.equals(tl.getElementDescription())){ - tl.setActionState( actSt); - break; - } - } - } - } - public void handleStationActConfig(List stnList, NsharpConstants.ActState actSt){ - for(String tlStr: stnList){ - for(NsharpOperationElement stn: stnElementList){ - if(tlStr.equals(stn.getElementDescription())){ - stn.setActionState( actSt); - break; - } - } - } - } + public void updateLayer(int layerIndex, float tp, float dp, float ws, + float wd, float pressure) { + if (layerIndex < 0 || layerIndex >= soundingLys.size()) + return; + currentSoundingLayerIndex = layerIndex; + NcSoundingLayer layer = soundingLys.get(currentSoundingLayerIndex); + layer.setGeoHeight(nsharpNative.nsharpLib.ihght(pressure)); + layer.setTemperature(tp); + layer.setDewpoint(dp); + layer.setWindDirection(wd); + layer.setWindSpeed(ws); + layer.setPressure(pressure); + // re-populate snd data to nsharp native code lib for later calculating + Collections.sort(soundingLys, + NsharpDataHandling.reversePressureHeightWindComparator()); + nsharpNative.populateSndgData(soundingLys); + // get storm motion wind data after populate sounding from NsharpLib + // refresh test area if it is shown now + NsharpShowTextDialog textarea = NsharpShowTextDialog.getAccess(); + if (textarea != null) { + textarea.refreshTextData(); + } + if (skewtPaneRsc != null) { + skewtPaneRsc.setSoundingLys(soundingLys); + // CHIN:::fix edit zoom issue skewtPaneRsc.handleResize(); + skewtPaneRsc.createRscWireFrameShapes(); + } + if (hodoPaneRsc != null) { + hodoPaneRsc.setSoundingLys(soundingLys); + hodoPaneRsc.createRscHodoWindShapeAll(); + } + if (insetPaneRsc != null) { + insetPaneRsc.setSoundingLys(soundingLys); + insetPaneRsc.createInsetWireFrameShapes(); + } + if (witoPaneRsc != null) { + witoPaneRsc.setSoundingLys(soundingLys); + witoPaneRsc.createAllWireFrameShapes(); + } + if (dataPaneRsc != null) + dataPaneRsc.setSoundingLys(soundingLys); + } - public void handleSndTypeActConfig(List sndTypeList, NsharpConstants.ActState actSt){ - for(String tlStr: sndTypeList){ - for(NsharpOperationElement sndType: sndElementList){ - if(tlStr.equals(sndType.getElementDescription())){ - sndType.setActionState( actSt); - break; - } - } - } - } + public void addNewLayer(float tp, float dp, float ws, float wd, + float pressure) { + // NsharpBackgroundResource bkRsc = descriptor.getSkewTBkGResource(); + // currentSoundingLayer =layerIndex; + NcSoundingLayer layer = new NcSoundingLayer(); + layer.setGeoHeight(nsharpNative.nsharpLib.ihght(pressure)); + layer.setTemperature(tp); + layer.setDewpoint(dp); + layer.setWindDirection(wd); + layer.setWindSpeed(ws); + layer.setPressure(pressure); + soundingLys.add(layer); + // re-populate snd data to nsharp native code lib for later calculating + Collections.sort(soundingLys, + NsharpDataHandling.reversePressureHeightWindComparator()); + nsharpNative.populateSndgData(soundingLys); + // get storm motion wind data after populate sounding from NsharpLib + // refresh text area if it is shown now + NsharpShowTextDialog textarea = NsharpShowTextDialog.getAccess(); + if (textarea != null) { + textarea.refreshTextData(); + } + if (skewtPaneRsc != null) { + skewtPaneRsc.setSoundingLys(soundingLys); + // CHIN:::fix edit zoom issue skewtPaneRsc.handleResize(); + skewtPaneRsc.createRscWireFrameShapes(); + } + if (hodoPaneRsc != null) { + hodoPaneRsc.setSoundingLys(soundingLys); + hodoPaneRsc.createRscHodoWindShapeAll(); + } + if (insetPaneRsc != null) { + insetPaneRsc.setSoundingLys(soundingLys); + insetPaneRsc.createInsetWireFrameShapes(); + } + if (witoPaneRsc != null) { + witoPaneRsc.setSoundingLys(soundingLys); + witoPaneRsc.createAllWireFrameShapes(); + } + if (dataPaneRsc != null) + dataPaneRsc.setSoundingLys(soundingLys); + } - public int getCurrentTextChapter() { - return currentTextChapter; - } + public void setGraphConfigProperty(NsharpGraphProperty graphConfigProperty) { + this.graphConfigProperty = graphConfigProperty; + int tempOffset = graphConfigProperty.getTempOffset(); + NsharpWxMath.setTempOffset(tempOffset); + if (skewtPaneRsc != null) { + skewtPaneRsc.setGraphConfigProperty(graphConfigProperty); + skewtPaneRsc.handleResize(); + skewtPaneRsc.getSkewTBackground().setGraphConfigProperty( + graphConfigProperty); + } + if (hodoPaneRsc != null) { + hodoPaneRsc.setGraphConfigProperty(graphConfigProperty); + hodoPaneRsc.createRscHodoWindShapeAll(); + } + if (witoPaneRsc != null) { + witoPaneRsc.setGraphConfigProperty(graphConfigProperty); + witoPaneRsc.createAllWireFrameShapes(); + } + if (insetPaneRsc != null) { + insetPaneRsc.setGraphConfigProperty(graphConfigProperty); + insetPaneRsc.createInsetWireFrameShapes(); + } + } + public NsharpGraphProperty getGraphConfigProperty() { + return graphConfigProperty; + } - public float getCurrentParcelLayerPressure() { - return currentParcelLayerPressure; - } + public void setLinePropertyMap( + HashMap linePropertyMap) { + this.linePropertyMap = linePropertyMap; + if (skewtPaneRsc != null) { + skewtPaneRsc.setLinePropertyMap(linePropertyMap); + skewtPaneRsc.handleResize(); + } + if (hodoPaneRsc != null) { + hodoPaneRsc.setLinePropertyMap(linePropertyMap); + hodoPaneRsc.createRscHodoWindShapeAll(); + } + if (timeStnPaneRsc != null) + timeStnPaneRsc.setLinePropertyMap(linePropertyMap); + } + private void updatePageOrderArray() { + pageDisplayOrderNumberArray[NsharpConstants.PAGE_SUMMARY1] = dataPageProperty + .getSummary1Page(); + pageDisplayOrderNumberArray[NsharpConstants.PAGE_SUMMARY2] = dataPageProperty + .getSummary2Page(); + pageDisplayOrderNumberArray[NsharpConstants.PAGE_PARCEL_DATA] = dataPageProperty + .getParcelDataPage(); + pageDisplayOrderNumberArray[NsharpConstants.PAGE_THERMODYNAMIC_DATA] = dataPageProperty + .getThermodynamicDataPage(); + pageDisplayOrderNumberArray[NsharpConstants.PAGE_OPC_DATA] = dataPageProperty + .getOpcDataPage(); + pageDisplayOrderNumberArray[NsharpConstants.PAGE_MIXING_HEIGHT] = dataPageProperty + .getMixingHeightPage(); + pageDisplayOrderNumberArray[NsharpConstants.PAGE_STORM_RELATIVE] = dataPageProperty + .getStormRelativePage(); + pageDisplayOrderNumberArray[NsharpConstants.PAGE_MEAN_WIND] = dataPageProperty + .getMeanWindPage(); + pageDisplayOrderNumberArray[NsharpConstants.PAGE_CONVECTIVE_INITIATION] = dataPageProperty + .getConvectiveInitiationPage(); + pageDisplayOrderNumberArray[NsharpConstants.PAGE_SEVERE_POTENTIAL] = dataPageProperty + .getSeverePotentialPage(); + } - public NsharpSkewTPaneResource getSkewtPaneRsc() { - return skewtPaneRsc; - } + public void setDataPageProperty(NsharpDataPageProperty dataPageProperty) { + this.dataPageProperty = dataPageProperty; + updatePageOrderArray(); + if (dataPaneRsc != null) + dataPaneRsc.setPageDisplayOrderNumberArray( + pageDisplayOrderNumberArray, + dataPageProperty.getNumberPagePerDisplay()); + } + public void handleTimeLineActConfig(List tlList, + NsharpConstants.ActState actSt) { + for (String tlStr : tlList) { + for (NsharpOperationElement tl : timeElementList) { + if (tlStr.equals(tl.getElementDescription())) { + tl.setActionState(actSt); + break; + } + } + } + } - public NsharpHodoPaneResource getHodoPaneRsc() { - return hodoPaneRsc; - } + public void handleStationActConfig(List stnList, + NsharpConstants.ActState actSt) { + for (String tlStr : stnList) { + for (NsharpOperationElement stn : stnElementList) { + if (tlStr.equals(stn.getElementDescription())) { + stn.setActionState(actSt); + break; + } + } + } + } + public void handleSndTypeActConfig(List sndTypeList, + NsharpConstants.ActState actSt) { + for (String tlStr : sndTypeList) { + for (NsharpOperationElement sndType : sndElementList) { + if (tlStr.equals(sndType.getElementDescription())) { + sndType.setActionState(actSt); + break; + } + } + } + } - public NsharpSoundingElementStateProperty getPreSndProfileProp() { - return preSndProfileProp; - } - - + public int getCurrentTextChapter() { + return currentTextChapter; + } + public float getCurrentParcelLayerPressure() { + return currentParcelLayerPressure; + } - public int getCurTimeLinePage() { - return curTimeLinePage; - } + public NsharpSkewTPaneResource getSkewtPaneRsc() { + return skewtPaneRsc; + } + public NsharpHodoPaneResource getHodoPaneRsc() { + return hodoPaneRsc; + } - public int getCurrentInsetPage() { - return currentInsetPage; - } + public NsharpSoundingElementStateProperty getPreSndProfileProp() { + return preSndProfileProp; + } + public int getCurTimeLinePage() { + return curTimeLinePage; + } - public int getCurrentSoundingLayerIndex() { - return currentSoundingLayerIndex; - } + public int getCurrentInsetPage() { + return currentInsetPage; + } + public int getCurrentSoundingLayerIndex() { + return currentSoundingLayerIndex; + } - public IFrameCoordinator.FrameChangeOperation getCurrentOpDirection() { - return currentOpDirection; - } + public IFrameCoordinator.FrameChangeOperation getCurrentOpDirection() { + return currentOpDirection; + } + public NsharpSoundingElementStateProperty getCurSndProfileProp() { + return curSndProfileProp; + } - public NsharpSoundingElementStateProperty getCurSndProfileProp() { - return curSndProfileProp; - } + public int getCurStnIdPage() { + return curStnIdPage; + } + public int getCurSndPage() { + return curSndPage; + } - public int getCurStnIdPage() { - return curStnIdPage; - } + public HashMap getElementColorMap() { + return elementColorMap; + } + public int getTotalTimeLinePage() { + return totalTimeLinePage; + } - public int getCurSndPage() { - return curSndPage; - } + public int getTotalStnIdPage() { + return totalStnIdPage; + } + public int getTotalSndPage() { + return totalSndPage; + } - public HashMap getElementColorMap() { - return elementColorMap; - } + public void repopulateSndgData() { + nsharpNative.populateSndgData(soundingLys); + } + public NsharpWitoPaneResource getWitoPaneRsc() { + return witoPaneRsc; + } - public int getTotalTimeLinePage() { - return totalTimeLinePage; - } + public NsharpInsetPaneResource getInsetPaneRsc() { + return insetPaneRsc; + } + public NsharpSpcGraphsPaneResource getSpcGraphsPaneRsc() { + return spcGraphsPaneRsc; + } - public int getTotalStnIdPage() { - return totalStnIdPage; - } - - - public int getTotalSndPage() { - return totalSndPage; - } + public NsharpDataPaneResource getDataPaneRsc() { + return dataPaneRsc; + } + public void setTimeStnBoxData(int cnYOrig, int dtNextPage_end, int dtYOrig, + int dtXOrig, int dtWidth, int charHeight) { + this.charHeight = charHeight; + this.dtYOrig = dtYOrig; + this.dtXOrig = dtXOrig; + this.dtWidth = dtWidth; + this.cnYOrig = cnYOrig; + this.dtNextPageEnd = dtNextPage_end; + calculateTimeStnBoxData(); + } - public void repopulateSndgData(){ - nsharpNative.populateSndgData(soundingLys); - } + public void refreshPane() { + for (int i = 0; i < displayArray.length; i++) { + displayArray[i].refresh(); + } + } + public String getPaneConfigurationName() { + return paneConfigurationName; + } - public NsharpWitoPaneResource getWitoPaneRsc() { - return witoPaneRsc; - } + private void calculateTimeStnBoxData() { + // set total time line group and stn id list page number + numTimeLinePerPage = (cnYOrig - dtNextPageEnd) / charHeight; + if (numTimeLinePerPage <= 0) + numTimeLinePerPage = 1; + // System.out.println("numTimeLinePerPage="+numTimeLinePerPage); + totalTimeLinePage = timeElementList.size() / numTimeLinePerPage; + if (timeElementList.size() % numTimeLinePerPage != 0) + totalTimeLinePage = totalTimeLinePage + 1; + curTimeLinePage = currentTimeElementListIndex / numTimeLinePerPage + 1; + totalStnIdPage = stnElementList.size() / numTimeLinePerPage; + if (stnElementList.size() % numTimeLinePerPage != 0) + totalStnIdPage++; + curStnIdPage = currentStnElementListIndex / numTimeLinePerPage + 1; + totalSndPage = sndElementList.size() / numTimeLinePerPage; + if (sndElementList.size() % numTimeLinePerPage != 0) + totalSndPage++; + curSndPage = currentSndElementListIndex / numTimeLinePerPage + 1; + } + /* + * Return size of stnTimeSndTable Note that not all elements in this table + * has sounding data loaded. Therefore, returned size may be much bigger + * than the number of actual loaded sounding data frame. + */ + public int getFrameCount() { + return timeElementList.size() * sndElementList.size() + * stnElementList.size(); + } - public NsharpInsetPaneResource getInsetPaneRsc() { - return insetPaneRsc; - } - + /* + * return "accumulated" index to stnTimeSndTable of current displayed + * sounding data + */ + public int getCurrentIndex() { + int index = 0; + if (currentSndElementListIndex >= 0 && currentStnElementListIndex >= 0 + && currentTimeElementListIndex >= 0) { + index = currentSndElementListIndex + currentTimeElementListIndex + * sndElementList.size() + currentStnElementListIndex + * timeElementList.size() * sndElementList.size(); + } + return index; + } - - public NsharpSpcGraphsPaneResource getSpcGraphsPaneRsc() { - return spcGraphsPaneRsc; - } - - - public NsharpDataPaneResource getDataPaneRsc() { - return dataPaneRsc; - } - public void setTimeStnBoxData(int cnYOrig,int dtNextPage_end, int dtYOrig , int dtXOrig, int dtWidth, int charHeight){ - this.charHeight = charHeight; - this.dtYOrig = dtYOrig; - this.dtXOrig = dtXOrig; - this.dtWidth = dtWidth; - this.cnYOrig = cnYOrig; - this.dtNextPageEnd = dtNextPage_end; - calculateTimeStnBoxData(); - } - - public void refreshPane(){ - for(int i =0; i< displayArray.length ; i++){ - displayArray[i].refresh(); - } - } - - - public String getPaneConfigurationName() { - return paneConfigurationName; - } - - private void calculateTimeStnBoxData(){ - //set total time line group and stn id list page number - numTimeLinePerPage = (cnYOrig-dtNextPageEnd)/charHeight; - if(numTimeLinePerPage<=0) - numTimeLinePerPage=1; - //System.out.println("numTimeLinePerPage="+numTimeLinePerPage); - totalTimeLinePage = timeElementList.size()/numTimeLinePerPage ; - if(timeElementList.size()%numTimeLinePerPage != 0) - totalTimeLinePage= totalTimeLinePage+1; - curTimeLinePage = currentTimeElementListIndex/numTimeLinePerPage+1; - totalStnIdPage = stnElementList.size()/numTimeLinePerPage; - if(stnElementList.size()%numTimeLinePerPage != 0) - totalStnIdPage++; - curStnIdPage= currentStnElementListIndex/numTimeLinePerPage + 1; - totalSndPage = sndElementList.size()/numTimeLinePerPage; - if(sndElementList.size()%numTimeLinePerPage != 0) - totalSndPage++; - curSndPage= currentSndElementListIndex/numTimeLinePerPage + 1; - } - - /* - * Return size of stnTimeSndTable - * Note that not all elements in this table has sounding data loaded. - * Therefore, returned size may be much bigger than the number of actual loaded sounding data frame. - */ - public int getFrameCount(){ - return timeElementList.size() * sndElementList.size()* stnElementList.size(); - } - /* - * return "accumulated" index to stnTimeSndTable of current displayed sounding data - */ - public int getCurrentIndex() { - int index = 0; - if(currentSndElementListIndex >= 0 && currentStnElementListIndex >=0 && currentTimeElementListIndex >=0){ - index = currentSndElementListIndex - + currentTimeElementListIndex * sndElementList.size() - + currentStnElementListIndex * timeElementList.size() * sndElementList.size(); - } - return index; - } - /* - * set current displayed sounding data using the input "accumulated" index (to stnTimeSndTable) - * return false: If input index is not valid or sounding data is not loaded for input index - * return true: if set successfully - */ - public boolean setCurrentIndex( int index) { - if(index < 0 || index >= (timeElementList.size() * sndElementList.size() * stnElementList.size())){ - //System.out.println("invalid index="+index); - return false; - } - int tempStni, tempSndi, tempTmi; - tempStni = index / (timeElementList.size() * sndElementList.size()); - tempTmi = (index % (timeElementList.size() * sndElementList.size()))/ sndElementList.size(); - tempSndi = (index % (timeElementList.size() * sndElementList.size()))% sndElementList.size(); - if(timeElementList.get(tempTmi).getActionState() == NsharpConstants.ActState.INACTIVE || - stnElementList.get(tempStni).getActionState() == NsharpConstants.ActState.INACTIVE || - sndElementList.get(tempSndi).getActionState() == NsharpConstants.ActState.INACTIVE || - stnTimeSndTable.get(tempStni).get(tempTmi).get(tempSndi)== null - ) - { - //System.out.println("invalid element="+index); - return false; - } - previousTimeLineStateListIndex = currentTimeElementListIndex; - currentStnElementListIndex = tempStni; - currentTimeElementListIndex =tempTmi; - currentSndElementListIndex = tempSndi; - setCurSndProfileProp(); - curTimeLinePage = currentTimeElementListIndex/numTimeLinePerPage + 1; - curSndPage= currentSndElementListIndex/numTimeLinePerPage + 1; - curStnIdPage= currentStnElementListIndex/numTimeLinePerPage + 1; - setCurrentSoundingLayerInfo(); - resetData(); - refreshPane(); - return true; - } + /* + * set current displayed sounding data using the input "accumulated" index + * (to stnTimeSndTable) return false: If input index is not valid or + * sounding data is not loaded for input index return true: if set + * successfully + */ + public boolean setCurrentIndex(int index) { + if (index < 0 + || index >= (timeElementList.size() * sndElementList.size() * stnElementList + .size())) { + // System.out.println("invalid index="+index); + return false; + } + int tempStni, tempSndi, tempTmi; + tempStni = index / (timeElementList.size() * sndElementList.size()); + tempTmi = (index % (timeElementList.size() * sndElementList.size())) + / sndElementList.size(); + tempSndi = (index % (timeElementList.size() * sndElementList.size())) + % sndElementList.size(); + if (timeElementList.get(tempTmi).getActionState() == NsharpConstants.ActState.INACTIVE + || stnElementList.get(tempStni).getActionState() == NsharpConstants.ActState.INACTIVE + || sndElementList.get(tempSndi).getActionState() == NsharpConstants.ActState.INACTIVE + || stnTimeSndTable.get(tempStni).get(tempTmi).get(tempSndi) == null) { + // System.out.println("invalid element="+index); + return false; + } + previousTimeLineStateListIndex = currentTimeElementListIndex; + currentStnElementListIndex = tempStni; + currentTimeElementListIndex = tempTmi; + currentSndElementListIndex = tempSndi; + setCurSndProfileProp(); + curTimeLinePage = currentTimeElementListIndex / numTimeLinePerPage + 1; + curSndPage = currentSndElementListIndex / numTimeLinePerPage + 1; + curStnIdPage = currentStnElementListIndex / numTimeLinePerPage + 1; + setCurrentSoundingLayerInfo(); + resetData(); + refreshPane(); + return true; + } } - diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/view/NsharpPaletteWindow.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/view/NsharpPaletteWindow.java index b501957a15..0693ee07e6 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/view/NsharpPaletteWindow.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/view/NsharpPaletteWindow.java @@ -13,7 +13,8 @@ * 03/16/2010 229 Chin Chen Initial coding * 03/11/2013 972 Greg Hull NatlCntrsEditor * 09/03/2013 1031 Greg Hull try 5 times to initialize the inventory. - * + * 01/08/2014 Chin Chen Only initializing inventory when in NCP + * 01/13/2014 Chin Chen TTR829- when interpolation, edit graph is allowed * * * @author Chin Chen @@ -80,22 +81,22 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, effBulkShearBtn, stpBtn, shipBtn, winterBtn, fireBtn, hailBtn, sarsBtn, cfgBtn; - private Shell shell; + private Shell shell; - private Label spcGplbl; + private Label spcGplbl; - private Composite parent; + private Composite parent; - private Group spcGp; + private Group spcGp; private boolean overlayIsOn = false, compareStnIsOn = false, compareSndIsOn = false, compareTmIsOn = false; protected boolean interpolateIsOn = false, editGraphOn = false; - private static String INTP_OFF = " Interp(off) "; + private static String INTP_OFF = " Interp(off) "; - private static String INTP_ON = " Interp(on) "; + private static String INTP_ON = " Interp(on) "; private static String COMP_STN_OFF = "CompStn(off)"; @@ -117,9 +118,9 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, protected static String EDIT_GRAPH_ON = "EditGraph(on) "; - private IWorkbenchPage page; + private IWorkbenchPage page; - private NsharpPrintHandle printHandle; + private NsharpPrintHandle printHandle; private Font newFont; @@ -134,163 +135,163 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, private int currentGraphMode = NsharpConstants.GRAPH_SKEWT; - private String paneConfigurationName; + private String paneConfigurationName; - private static NsharpConstants.SPCGraph leftGraph = NsharpConstants.SPCGraph.EBS; + private static NsharpConstants.SPCGraph leftGraph = NsharpConstants.SPCGraph.EBS; - private static NsharpConstants.SPCGraph rightGraph = NsharpConstants.SPCGraph.STP; + private static NsharpConstants.SPCGraph rightGraph = NsharpConstants.SPCGraph.STP; - private boolean spcGpCreated = false; + private boolean spcGpCreated = false; - public static NsharpPaletteWindow getInstance() { + public static NsharpPaletteWindow getInstance() { if (VizPerspectiveListener.getCurrentPerspectiveManager() != null) { if (VizPerspectiveListener.getCurrentPerspectiveManager() .getPerspectiveId().equals(D2D5Pane.ID_PERSPECTIVE)) - return d2dInstance; + return d2dInstance; else if (VizPerspectiveListener.getCurrentPerspectiveManager() .getPerspectiveId() .equals(NmapCommon.NatlCntrsPerspectiveID)) - return ncpInstance; - } - return instance; - } + return ncpInstance; + } + return instance; + } + + public int getCurrentGraphMode() { + return currentGraphMode; + } - public int getCurrentGraphMode() { - return currentGraphMode; - } - public void restorePaletteWindow(String paneConfigurationName, int currentGraphMode, boolean interpolateIsOn, boolean overlayIsOn, boolean compareStnIsOn, boolean compareTmIsOn, boolean editGraphOn, boolean compareSndIsOn) { // System.out.println("restorePaletteWindow "+ this.toString()); - updateSpcGraphBtn(paneConfigurationName); - this.currentGraphMode = currentGraphMode; - this.interpolateIsOn = interpolateIsOn; - this.overlayIsOn = overlayIsOn; - this.compareStnIsOn = compareStnIsOn; - this.compareSndIsOn = compareSndIsOn; - this.compareTmIsOn = compareTmIsOn; - this.editGraphOn = editGraphOn; - graphModeBtnSkew.setEnabled(true); - graphModeBtnIcing.setEnabled(true); - graphModeBtnTurb.setEnabled(true); + updateSpcGraphBtn(paneConfigurationName); + this.currentGraphMode = currentGraphMode; + this.interpolateIsOn = interpolateIsOn; + this.overlayIsOn = overlayIsOn; + this.compareStnIsOn = compareStnIsOn; + this.compareSndIsOn = compareSndIsOn; + this.compareTmIsOn = compareTmIsOn; + this.editGraphOn = editGraphOn; + graphModeBtnSkew.setEnabled(true); + graphModeBtnIcing.setEnabled(true); + graphModeBtnTurb.setEnabled(true); if (currentGraphMode == NsharpConstants.GRAPH_SKEWT) { - graphModeBtnSkew.setBackground(colorBlue); - graphModeBtnTurb.setBackground(colorGrey); - graphModeBtnIcing.setBackground(colorGrey); - graphEditBtn.setEnabled(true); - dataEditBtn.setEnabled(true); + graphModeBtnSkew.setBackground(colorBlue); + graphModeBtnTurb.setBackground(colorGrey); + graphModeBtnIcing.setBackground(colorGrey); + graphEditBtn.setEnabled(true); + dataEditBtn.setEnabled(true); compareTmBtn.setEnabled(true); compareSndBtn.setEnabled(true); compareStnBtn.setEnabled(true); overlayBtn.setEnabled(true); - interpBtn.setEnabled(true); - overlayBtn.setText(OVLY_OFF); - interpBtn.setText(INTP_OFF); - graphEditBtn.setText(EDIT_GRAPH_OFF); - compareTmBtn.setText(COMP_TM_OFF); - compareSndBtn.setText(COMP_SND_OFF); - compareStnBtn.setText(COMP_STN_OFF); + interpBtn.setEnabled(true); + overlayBtn.setText(OVLY_OFF); + interpBtn.setText(INTP_OFF); + graphEditBtn.setText(EDIT_GRAPH_OFF); + compareTmBtn.setText(COMP_TM_OFF); + compareSndBtn.setText(COMP_SND_OFF); + compareStnBtn.setText(COMP_STN_OFF); if (interpolateIsOn) { - graphEditBtn.setEnabled(false); - dataEditBtn.setEnabled(false); + //TTR829 graphEditBtn.setEnabled(false); + //dataEditBtn.setEnabled(false); compareTmBtn.setEnabled(false); compareSndBtn.setEnabled(false); compareStnBtn.setEnabled(false); overlayBtn.setEnabled(false); - interpBtn.setText(INTP_ON); + interpBtn.setText(INTP_ON); } else if (overlayIsOn) { - overlayBtn.setText(OVLY_ON); - graphEditBtn.setEnabled(false); - dataEditBtn.setEnabled(false); + overlayBtn.setText(OVLY_ON); + graphEditBtn.setEnabled(false); + dataEditBtn.setEnabled(false); compareTmBtn.setEnabled(false); compareSndBtn.setEnabled(false); compareStnBtn.setEnabled(false); - interpBtn.setEnabled(false); - graphModeBtnIcing.setEnabled(false); - graphModeBtnTurb.setEnabled(false); + interpBtn.setEnabled(false); + graphModeBtnIcing.setEnabled(false); + graphModeBtnTurb.setEnabled(false); } else if (compareStnIsOn) { - compareStnBtn.setText(COMP_STN_ON); - graphEditBtn.setEnabled(false); - dataEditBtn.setEnabled(false); + compareStnBtn.setText(COMP_STN_ON); + graphEditBtn.setEnabled(false); + dataEditBtn.setEnabled(false); compareTmBtn.setEnabled(false); compareSndBtn.setEnabled(false); overlayBtn.setEnabled(false); - interpBtn.setEnabled(false); - graphModeBtnIcing.setEnabled(false); - graphModeBtnTurb.setEnabled(false); + interpBtn.setEnabled(false); + graphModeBtnIcing.setEnabled(false); + graphModeBtnTurb.setEnabled(false); } else if (compareSndIsOn) { - compareSndBtn.setText(COMP_SND_ON); - graphEditBtn.setEnabled(false); - dataEditBtn.setEnabled(false); + compareSndBtn.setText(COMP_SND_ON); + graphEditBtn.setEnabled(false); + dataEditBtn.setEnabled(false); compareTmBtn.setEnabled(false); compareStnBtn.setEnabled(false); overlayBtn.setEnabled(false); - interpBtn.setEnabled(false); - graphModeBtnIcing.setEnabled(false); - graphModeBtnTurb.setEnabled(false); + interpBtn.setEnabled(false); + graphModeBtnIcing.setEnabled(false); + graphModeBtnTurb.setEnabled(false); } else if (compareTmIsOn) { - compareTmBtn.setText(COMP_TM_ON); + compareTmBtn.setText(COMP_TM_ON); compareSndBtn.setEnabled(false); - graphEditBtn.setEnabled(false); - dataEditBtn.setEnabled(false); + graphEditBtn.setEnabled(false); + dataEditBtn.setEnabled(false); compareStnBtn.setEnabled(false); overlayBtn.setEnabled(false); - interpBtn.setEnabled(false); - graphModeBtnIcing.setEnabled(false); - graphModeBtnTurb.setEnabled(false); + interpBtn.setEnabled(false); + graphModeBtnIcing.setEnabled(false); + graphModeBtnTurb.setEnabled(false); } else if (editGraphOn) { - graphEditBtn.setText(EDIT_GRAPH_ON); - dataEditBtn.setEnabled(false); + graphEditBtn.setText(EDIT_GRAPH_ON); + dataEditBtn.setEnabled(false); compareStnBtn.setEnabled(false); compareTmBtn.setEnabled(false); compareSndBtn.setEnabled(false); overlayBtn.setEnabled(false); - interpBtn.setEnabled(false); - graphModeBtnIcing.setEnabled(false); - graphModeBtnTurb.setEnabled(false); - } - + interpBtn.setEnabled(false); + graphModeBtnIcing.setEnabled(false); + graphModeBtnTurb.setEnabled(false); + } + } else if (currentGraphMode == NsharpConstants.GRAPH_TURB) { - graphModeBtnTurb.setBackground(colorBlue); - graphModeBtnSkew.setBackground(colorGrey); - graphModeBtnIcing.setBackground(colorGrey); - graphEditBtn.setEnabled(false); - dataEditBtn.setEnabled(false); + graphModeBtnTurb.setBackground(colorBlue); + graphModeBtnSkew.setBackground(colorGrey); + graphModeBtnIcing.setBackground(colorGrey); + graphEditBtn.setEnabled(false); + dataEditBtn.setEnabled(false); compareTmBtn.setEnabled(false); compareSndBtn.setEnabled(false); compareStnBtn.setEnabled(false); overlayBtn.setEnabled(false); if (interpolateIsOn) - interpBtn.setText(INTP_ON); - else - interpBtn.setText(INTP_OFF); - + interpBtn.setText(INTP_ON); + else + interpBtn.setText(INTP_OFF); + } else if (currentGraphMode == NsharpConstants.GRAPH_ICING) { - graphModeBtnIcing.setBackground(colorBlue); - graphModeBtnSkew.setBackground(colorGrey); - graphModeBtnTurb.setBackground(colorGrey); - graphEditBtn.setEnabled(false); - dataEditBtn.setEnabled(false); + graphModeBtnIcing.setBackground(colorBlue); + graphModeBtnSkew.setBackground(colorGrey); + graphModeBtnTurb.setBackground(colorGrey); + graphEditBtn.setEnabled(false); + dataEditBtn.setEnabled(false); compareTmBtn.setEnabled(false); compareSndBtn.setEnabled(false); compareStnBtn.setEnabled(false); overlayBtn.setEnabled(false); if (interpolateIsOn) - interpBtn.setText(INTP_ON); - else - interpBtn.setText(INTP_OFF); - } - } + interpBtn.setText(INTP_ON); + else + interpBtn.setText(INTP_OFF); + } + } - public static NsharpConstants.SPCGraph getLeftGraph() { - return leftGraph; - } + public static NsharpConstants.SPCGraph getLeftGraph() { + return leftGraph; + } - public static NsharpConstants.SPCGraph getRightGraph() { - return rightGraph; - } + public static NsharpConstants.SPCGraph getRightGraph() { + return rightGraph; + } private Color colorGrey = new Color(Display.getDefault(), 211, 211, 211); @@ -300,184 +301,188 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, private void updateSPCGraphs() { if (leftGraph == NsharpConstants.SPCGraph.EBS || rightGraph == NsharpConstants.SPCGraph.EBS) { - effBulkShearBtn.setBackground(colorBlue); + effBulkShearBtn.setBackground(colorBlue); } else { - effBulkShearBtn.setBackground(colorGrey); - } + effBulkShearBtn.setBackground(colorGrey); + } if (leftGraph == NsharpConstants.SPCGraph.STP || rightGraph == NsharpConstants.SPCGraph.STP) { - stpBtn.setBackground(colorBlue); + stpBtn.setBackground(colorBlue); } else { - stpBtn.setBackground(colorGrey); - } + stpBtn.setBackground(colorGrey); + } if (leftGraph == NsharpConstants.SPCGraph.SHIP || rightGraph == NsharpConstants.SPCGraph.SHIP) { - shipBtn.setBackground(colorBlue); + shipBtn.setBackground(colorBlue); } else { - shipBtn.setBackground(colorGrey); - } + shipBtn.setBackground(colorGrey); + } if (leftGraph == NsharpConstants.SPCGraph.WINTER || rightGraph == NsharpConstants.SPCGraph.WINTER) { - winterBtn.setBackground(colorBlue); + winterBtn.setBackground(colorBlue); } else { - winterBtn.setBackground(colorGrey); - } + winterBtn.setBackground(colorGrey); + } if (leftGraph == NsharpConstants.SPCGraph.FIRE || rightGraph == NsharpConstants.SPCGraph.FIRE) { - fireBtn.setBackground(colorBlue); + fireBtn.setBackground(colorBlue); } else { - fireBtn.setBackground(colorGrey); - } + fireBtn.setBackground(colorGrey); + } if (leftGraph == NsharpConstants.SPCGraph.HAIL || rightGraph == NsharpConstants.SPCGraph.HAIL) { - hailBtn.setBackground(colorBlue); + hailBtn.setBackground(colorBlue); } else { - hailBtn.setBackground(colorGrey); - } + hailBtn.setBackground(colorGrey); + } if (leftGraph == NsharpConstants.SPCGraph.SARS || rightGraph == NsharpConstants.SPCGraph.SARS) { - sarsBtn.setBackground(colorBlue); + sarsBtn.setBackground(colorBlue); } else { - sarsBtn.setBackground(colorGrey); - } - NsharpResourceHandler rsc = getRscHandler(); + sarsBtn.setBackground(colorGrey); + } + NsharpResourceHandler rsc = getRscHandler(); if (rsc != null && rsc.getSpcGraphsPaneRsc() != null) { - rsc.getSpcGraphsPaneRsc().setGraphs(leftGraph, rightGraph); - } - - } + rsc.getSpcGraphsPaneRsc().setGraphs(leftGraph, rightGraph); + } - public void setAndOpenMb(String msg) { - if (mb != null) { - mb.setMessage(msg); - try { - mb.open(); + } + + public void setAndOpenMb(String msg) { + if (mb != null) { + mb.setMessage(msg); + try { + mb.open(); } catch (Exception e) { // e.printStackTrace(); - } - } - } + } + } + } - public NsharpPaletteWindow() { - super(); - instance = this; + public NsharpPaletteWindow() { + super(); + instance = this; + boolean imD2d=false; //fixMark:NcInventory if (VizPerspectiveListener.getCurrentPerspectiveManager() != null) { if (VizPerspectiveListener.getCurrentPerspectiveManager() - .getPerspectiveId().equals(D2D5Pane.ID_PERSPECTIVE)) - d2dInstance = this; + .getPerspectiveId().equals(D2D5Pane.ID_PERSPECTIVE)){ + d2dInstance = this; + imD2d = true;//fixMark:NcInventory + } else if (VizPerspectiveListener.getCurrentPerspectiveManager() .getPerspectiveId() .equals(NmapCommon.NatlCntrsPerspectiveID)) - ncpInstance = this; - } + ncpInstance = this; + } // System.out.println("view NsharpPaletteWindow constructed!! "+ // this.toString()); - printHandle = NsharpPrintHandle.getPrintHandle(); - shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + printHandle = NsharpPrintHandle.getPrintHandle(); + shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); mb = new MessageBox(shell, SWT.ICON_WARNING | SWT.OK); mb.setMessage("Data is not loaded yet!"); - NsharpConfigManager configMgr = NsharpConfigManager.getInstance(); + NsharpConfigManager configMgr = NsharpConfigManager.getInstance(); NsharpConfigStore configStore = configMgr .retrieveNsharpConfigStoreFromFs(); NsharpGraphProperty graphConfigProperty = configStore .getGraphProperty(); - paneConfigurationName = graphConfigProperty.getPaneConfigurationName(); - - for( int a=1 ; a<=5 ; a++ ) { - if( NsharpGridInventory.getInstance().isInitialized() ) { - break; - } - - try { - NsharpGridInventory.getInstance().initialize(); - } - catch (VizException e) { - // TODO : could call createInventory() here but for now this will be considered - // an error since the grid inventory should/must be on the server. - System.out.println("NsharpGridInventory initialize attempt #"+a+" failed"); + paneConfigurationName = graphConfigProperty.getPaneConfigurationName(); + if(!imD2d){//fixMark:NcInventory + for( int a=1 ; a<=5 ; a++ ) { + if( NsharpGridInventory.getInstance().isInitialized() ) { + break; + } - try { Thread.sleep(a*500); } catch (InterruptedException e1) { } - } - } - - if( !NsharpGridInventory.getInstance().isInitialized() ) { - // TODO : change to a confirm to create an inventory. - MessageDialog errDlg = new MessageDialog( - PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Error", null, - "Unable to find an Inventory to support Grid Model times. Please wait while one"+ - " is created.", MessageDialog.ERROR, - new String[] { "OK" }, 0); - errDlg.open(); - - try { - NsharpGridInventory.getInstance().createInventory(); - } - catch (VizException e) { - errDlg = new MessageDialog( - PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Error", null, - "Error creating Inventory to support Grid Model times.", MessageDialog.ERROR, - new String[] { "OK" }, 0); - errDlg.open(); - } - } - } + try { + NsharpGridInventory.getInstance().initialize(); + } + catch (VizException e) { + // TODO : could call createInventory() here but for now this will be considered + // an error since the grid inventory should/must be on the server. + System.out.println("NsharpGridInventory initialize attempt #"+a+" failed"); - /** - * Invoked by the workbench to initialize this View. - */ + try { Thread.sleep(a*500); } catch (InterruptedException e1) { } + } + } + + if( !NsharpGridInventory.getInstance().isInitialized() ) { + // TODO : change to a confirm to create an inventory. + MessageDialog errDlg = new MessageDialog( + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Error", null, + "Unable to find an Inventory to support Grid Model times. Please wait while one"+ + " is created.", MessageDialog.ERROR, + new String[] { "OK" }, 0); + errDlg.open(); + + try { + NsharpGridInventory.createInventory(); + } + catch (VizException e) { + errDlg = new MessageDialog( + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Error", null, + "Error creating Inventory to support Grid Model times.", MessageDialog.ERROR, + new String[] { "OK" }, 0); + errDlg.open(); + } + } + } + } + + /** + * Invoked by the workbench to initialize this View. + */ public void init(IViewSite site) { // System.out.println("NsharpPaletteWindow inited!!"+ this.toString()); - try { + try { super.init(site); } catch (PartInitException pie) { - pie.printStackTrace(); + pie.printStackTrace(); - } + } - page = site.getPage(); - page.addPartListener(this); + page = site.getPage(); + page.addPartListener(this); - NsharpMapResource.registerMouseHandler(); + NsharpMapResource.registerMouseHandler(); // Chin : to fix Ticket#11034:::: // get several control information back from SkewT resource, in the case // that // NsharpPaletteWindow view was disposed and re-constructed while SkewT // resource is still alive. // This case applied to D2D implementation. - NsharpResourceHandler rsc = getRscHandler(); + NsharpResourceHandler rsc = getRscHandler(); if (rsc != null) { - interpolateIsOn = rsc.isInterpolateIsOn(); - overlayIsOn = rsc.isOverlayIsOn(); - compareStnIsOn = rsc.isCompareStnIsOn(); - editGraphOn = rsc.isEditGraphOn(); - compareSndIsOn = rsc.isCompareSndIsOn(); - compareTmIsOn = rsc.isCompareTmIsOn(); - } + interpolateIsOn = rsc.isInterpolateIsOn(); + overlayIsOn = rsc.isOverlayIsOn(); + compareStnIsOn = rsc.isCompareStnIsOn(); + editGraphOn = rsc.isEditGraphOn(); + compareSndIsOn = rsc.isCompareSndIsOn(); + compareTmIsOn = rsc.isCompareTmIsOn(); + } - } + } - /** - * Disposes resource. invoked by the workbench - */ - public void dispose() { + /** + * Disposes resource. invoked by the workbench + */ + public void dispose() { // System.out.println("NsharpPaletteWindow "+this.toString()+" dispose() called!! isEditorVisible="+ // isEditorVisible); if (!isEditorVisible) { - NsharpMapResource.unregisterMouseHandler(); - instance = null; - d2dInstance = null; - ncpInstance = null; - return; + NsharpMapResource.unregisterMouseHandler(); + instance = null; + d2dInstance = null; + ncpInstance = null; + return; } else { - super.dispose(); + super.dispose(); currentGraphMode = NsharpConstants.GRAPH_SKEWT; - isEditorVisible = false; - NatlCntrsEditor editor = NsharpMapResource.getMapEditor(); + isEditorVisible = false; + NatlCntrsEditor editor = NsharpMapResource.getMapEditor(); if (editor != null) { for (IRenderableDisplay display : UiUtil .getDisplaysFromContainer(editor)) { @@ -494,97 +499,97 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, if (rp.getResource() instanceof NsharpMapResource) { NsharpMapResource rsc = (NsharpMapResource) rp .getResource(); - rsc.unload(); + rsc.unload(); display.getDescriptor().getResourceList() .removePreRemoveListener(rsc); - } - } - } - } + } + } + } + } if (newFont != null) { - newFont.dispose(); + newFont.dispose(); newFont = null; - } /* - * remove the workbench part listener - */ - page.removePartListener(this); + } /* + * remove the workbench part listener + */ + page.removePartListener(this); try { if (NsharpLoadDialog.getAccess() != null) { - NsharpLoadDialog.getAccess().close(); - } + NsharpLoadDialog.getAccess().close(); + } } catch (Exception e) { - } + } instance = null; - d2dInstance = null; - ncpInstance = null; - } - } + d2dInstance = null; + ncpInstance = null; + } + } - protected boolean checkLoadedData() { - NsharpEditor editor = NsharpEditor.getActiveNsharpEditor(); - if (editor == null) { - mb.open(); - return false; - } - NsharpResourceHandler rsc = editor.getRscHandler(); + protected boolean checkLoadedData() { + NsharpEditor editor = NsharpEditor.getActiveNsharpEditor(); + if (editor == null) { + mb.open(); + return false; + } + NsharpResourceHandler rsc = editor.getRscHandler(); if (rsc == null) { - mb.open(); - return false; - } - return true; - } + mb.open(); + return false; + } + return true; + } protected NsharpResourceHandler getRscHandler() { - NsharpEditor editor = NsharpEditor.getActiveNsharpEditor(); - if (editor == null) { - - return null; - } - NsharpResourceHandler rsc = editor.getRscHandler(); - if (rsc == null) - return null; - - return rsc; - } + NsharpEditor editor = NsharpEditor.getActiveNsharpEditor(); + if (editor == null) { + + return null; + } + NsharpResourceHandler rsc = editor.getRscHandler(); + if (rsc == null) + return null; + + return rsc; + } public void createDataControlGp(Composite parent) { - this.parent = parent; + this.parent = parent; Group textModeGp = new Group(parent, SWT.SHADOW_OUT); textModeGp.setLayout(new RowLayout(SWT.HORIZONTAL)); textModeGp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - Font font = textModeGp.getFont(); - FontData[] fontData = font.getFontData(); - for (int i = 0; i < fontData.length; i++) { - fontData[i].setHeight(7); + Font font = textModeGp.getFont(); + FontData[] fontData = font.getFontData(); + for (int i = 0; i < fontData.length; i++) { + fontData[i].setHeight(7); // fontData[i].setName("courier"); - } - newFont = new Font(font.getDevice(), fontData); - - loadBtn = new Button(textModeGp, SWT.PUSH); - loadBtn.setFont(newFont); - loadBtn.setText(" Load "); + } + newFont = new Font(font.getDevice(), fontData); + + loadBtn = new Button(textModeGp, SWT.PUSH); + loadBtn.setFont(newFont); + loadBtn.setText(" Load "); loadBtn.setEnabled(true); // loadBtn.setSize(btnWidth,pushbtnHeight); loadBtn.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { Shell shell = PlatformUI.getWorkbench() .getActiveWorkbenchWindow().getShell(); - NsharpLoadDialog loadDia = NsharpLoadDialog.getInstance(shell); + NsharpLoadDialog loadDia = NsharpLoadDialog.getInstance(shell); if (loadDia != null) { // System.out.println("Load Button is calling dialog open()"); - loadDia.open(); - } - } + loadDia.open(); + } + } }); - - unloadBtn = new Button(textModeGp, SWT.PUSH); - unloadBtn.setFont(newFont); - unloadBtn.setText(" UnLoad "); + + unloadBtn = new Button(textModeGp, SWT.PUSH); + unloadBtn.setFont(newFont); + unloadBtn.setText(" UnLoad "); unloadBtn.setEnabled(true); // loadBtn.setSize(btnWidth,pushbtnHeight); unloadBtn.addListener(SWT.MouseUp, new Listener() { @@ -598,88 +603,88 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, if (unloadDia != null) { // System.out.println("Load Button is calling dialog open()"); - unloadDia.open(); + unloadDia.open(); - } - } - } + } + } + } }); - // Push buttons for SAVE - Button saveBtn = new Button(textModeGp, SWT.PUSH); - saveBtn.setFont(newFont); - saveBtn.setText(" Save "); + // Push buttons for SAVE + Button saveBtn = new Button(textModeGp, SWT.PUSH); + saveBtn.setFont(newFont); + saveBtn.setText(" Save "); saveBtn.setEnabled(true); // saveBtn.setSize(btnWidth,pushbtnHeight); saveBtn.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { if (checkLoadedData()) { - // Action to save text report - NsharpSaveHandle.saveFile(shell); - } - } + // Action to save text report + NsharpSaveHandle.saveFile(shell); + } + } }); - // Push buttons for CONFIGURE - cfgBtn = new Button(textModeGp, SWT.PUSH); - cfgBtn.setFont(newFont); - cfgBtn.setText(" Configure "); - cfgBtn.setEnabled(true); + // Push buttons for CONFIGURE + cfgBtn = new Button(textModeGp, SWT.PUSH); + cfgBtn.setFont(newFont); + cfgBtn.setText(" Configure "); + cfgBtn.setEnabled(true); // cfgBtn.setSize(btnWidth,pushbtnHeight); cfgBtn.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { Shell shell = PlatformUI.getWorkbench() .getActiveWorkbenchWindow().getShell(); // CHin, new develop if(checkLoadedData()) { // NsharpParametersSelectionConfigDialog dia = // NsharpParametersSelectionConfigDialog.getInstance(shell); - NsharpConfigDialog dia = NsharpConfigDialog.getInstance(shell); + NsharpConfigDialog dia = NsharpConfigDialog.getInstance(shell); if (dia != null) { - dia.open(); - } + dia.open(); + } // } - } + } }); - Button resetBtn = new Button(textModeGp, SWT.PUSH); - resetBtn.setFont(newFont); - resetBtn.setText(" Reset "); + Button resetBtn = new Button(textModeGp, SWT.PUSH); + resetBtn.setFont(newFont); + resetBtn.setText(" Reset "); resetBtn.setEnabled(true); resetBtn.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { // RESET should turn off everything... shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow() .getShell(); - cfgBtn.setEnabled(true); - overlayIsOn = false; - overlayBtn.setText(OVLY_OFF); - overlayBtn.setEnabled(true); - compareStnIsOn = false; - compareStnBtn.setText(COMP_STN_OFF); - compareStnBtn.setEnabled(true); - compareTmIsOn = false; - compareTmBtn.setText(COMP_TM_OFF); - compareTmBtn.setEnabled(true); - compareSndIsOn = false; - compareSndBtn.setText(COMP_SND_OFF); - compareSndBtn.setEnabled(true); - interpolateIsOn = false; - interpBtn.setText(INTP_OFF); - interpBtn.setEnabled(true); - editGraphOn = false; - graphEditBtn.setEnabled(true); - dataEditBtn.setEnabled(true); - graphModeBtnIcing.setEnabled(true); - graphModeBtnTurb.setEnabled(true); - graphEditBtn.setText(EDIT_GRAPH_OFF); + cfgBtn.setEnabled(true); + overlayIsOn = false; + overlayBtn.setText(OVLY_OFF); + overlayBtn.setEnabled(true); + compareStnIsOn = false; + compareStnBtn.setText(COMP_STN_OFF); + compareStnBtn.setEnabled(true); + compareTmIsOn = false; + compareTmBtn.setText(COMP_TM_OFF); + compareTmBtn.setEnabled(true); + compareSndIsOn = false; + compareSndBtn.setText(COMP_SND_OFF); + compareSndBtn.setEnabled(true); + interpolateIsOn = false; + interpBtn.setText(INTP_OFF); + interpBtn.setEnabled(true); + editGraphOn = false; + graphEditBtn.setEnabled(true); + dataEditBtn.setEnabled(true); + graphModeBtnIcing.setEnabled(true); + graphModeBtnTurb.setEnabled(true); + graphEditBtn.setText(EDIT_GRAPH_OFF); currentGraphMode = NsharpConstants.GRAPH_SKEWT; - NsharpEditor editor = NsharpEditor.getActiveNsharpEditor(); + NsharpEditor editor = NsharpEditor.getActiveNsharpEditor(); if (editor != null && editor.getRscHandler() != null) { // note: resetRsc will reset currentPage, overlay, compare, // interpolate flag in Resource - editor.getRscHandler().resetRsc(); + editor.getRscHandler().resetRsc(); // issue#18 - issue list if (editor.getRscHandler().getDataPaneRsc() != null) { editor.getRscHandler().getDataPaneRsc() @@ -688,39 +693,39 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, NsharpParcelDialog parcelDia = NsharpParcelDialog .getInstance(shell); if (parcelDia != null) { - parcelDia.reset(); - } + parcelDia.reset(); + } // editor.getNsharpSkewTDescriptor().getSkewtResource().resetRsc();// // need to called it twice to make refresh worked...dont // know why // know that current editor is NsharpSkewT editor, refresh // it. - editor.refresh(); + editor.refresh(); NsharpShowTextDialog textarea = NsharpShowTextDialog .getAccess(); if (textarea != null) { - textarea.refreshTextData(); - } - } + textarea.refreshTextData(); + } + } if (NsharpParcelDialog.getAccess() != null) { - NsharpParcelDialog.getAccess().resetUserDefParcel(); - } - } + NsharpParcelDialog.getAccess().resetUserDefParcel(); + } + } }); - Button resetGfBtn = new Button(textModeGp, SWT.PUSH); - resetGfBtn.setFont(newFont); - resetGfBtn.setText("Reset Display"); + Button resetGfBtn = new Button(textModeGp, SWT.PUSH); + resetGfBtn.setFont(newFont); + resetGfBtn.setText("Reset Display"); resetGfBtn.setEnabled(true); resetGfBtn.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { - NsharpEditor editor = NsharpEditor.getActiveNsharpEditor(); - editor.resetGraph(); - } - }); + public void handleEvent(Event event) { + NsharpEditor editor = NsharpEditor.getActiveNsharpEditor(); + editor.resetGraph(); + } + }); - Button parcelBtn = new Button(textModeGp, SWT.PUSH); - parcelBtn.setFont(newFont); - parcelBtn.setText(" Parcel "); + Button parcelBtn = new Button(textModeGp, SWT.PUSH); + parcelBtn.setFont(newFont); + parcelBtn.setText(" Parcel "); parcelBtn.setEnabled(true); // parcelBtn.setSize(btnWidth,pushbtnHeight); parcelBtn.addListener(SWT.MouseUp, new Listener() { @@ -733,397 +738,399 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, if (parcelDia != null) { // System.out.println("calling parcel dialog open()"); - parcelDia.open(); + parcelDia.open(); - } - } - } + } + } + } }); - // Push buttons for NEXT PAGE info - Button nextpageBtn = new Button(textModeGp, SWT.PUSH); - nextpageBtn.setFont(newFont); - nextpageBtn.setText(" Next Data "); - nextpageBtn.setEnabled(true); + // Push buttons for NEXT PAGE info + Button nextpageBtn = new Button(textModeGp, SWT.PUSH); + nextpageBtn.setFont(newFont); + nextpageBtn.setText(" Next Data "); + nextpageBtn.setEnabled(true); nextpageBtn.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow() .getShell(); if (checkLoadedData()) { - NsharpResourceHandler rsc = getRscHandler(); + NsharpResourceHandler rsc = getRscHandler(); if (rsc != null) { - rsc.setNextTextChapter(); - rsc.refreshPane(); - } - } - } + rsc.setNextTextChapter(); + rsc.refreshPane(); + } + } + } }); - - // Push buttons for NEXT INSET PAGE info - Button nextInsetBtn = new Button(textModeGp, SWT.PUSH); - nextInsetBtn.setFont(newFont); - nextInsetBtn.setText(" Next Inset "); - nextInsetBtn.setEnabled(true); + + // Push buttons for NEXT INSET PAGE info + Button nextInsetBtn = new Button(textModeGp, SWT.PUSH); + nextInsetBtn.setFont(newFont); + nextInsetBtn.setText(" Next Inset "); + nextInsetBtn.setEnabled(true); nextInsetBtn.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow() .getShell(); if (checkLoadedData()) { - NsharpResourceHandler rsc = getRscHandler(); + NsharpResourceHandler rsc = getRscHandler(); if (rsc != null) { - rsc.setNextInsetPage(); - rsc.refreshPane(); - } - } - } + rsc.setNextInsetPage(); + rsc.refreshPane(); + } + } + } }); - - // Push buttons for interpolate - interpBtn = new Button(textModeGp, SWT.PUSH); - interpBtn.setFont(newFont); + + // Push buttons for interpolate + interpBtn = new Button(textModeGp, SWT.PUSH); + interpBtn.setFont(newFont); interpBtn.setEnabled(true); if (interpolateIsOn) { - interpBtn.setText(INTP_ON); + interpBtn.setText(INTP_ON); } else { - interpBtn.setText(INTP_OFF); - } + interpBtn.setText(INTP_OFF); + } interpBtn.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow() .getShell(); if (checkLoadedData()) { if (interpolateIsOn == false) { - interpolateIsOn = true; - interpBtn.setText(INTP_ON); - graphEditBtn.setEnabled(false); - dataEditBtn.setEnabled(false); + interpolateIsOn = true; + interpBtn.setText(INTP_ON); + //TTR829 graphEditBtn.setEnabled(false); + //dataEditBtn.setEnabled(false); compareTmBtn.setEnabled(false); compareSndBtn.setEnabled(false); compareStnBtn.setEnabled(false); overlayBtn.setEnabled(false); } else { - interpolateIsOn = false; - interpBtn.setText(INTP_OFF); - if (currentGraphMode == NsharpConstants.GRAPH_SKEWT) { - graphEditBtn.setEnabled(true); - dataEditBtn.setEnabled(true); + interpolateIsOn = false; + interpBtn.setText(INTP_OFF); + if (currentGraphMode == NsharpConstants.GRAPH_SKEWT && editGraphOn == false) { + //TTR829 graphEditBtn.setEnabled(true); + dataEditBtn.setEnabled(true); compareTmBtn.setEnabled(true); compareSndBtn.setEnabled(true); compareStnBtn.setEnabled(true); overlayBtn.setEnabled(true); - } - } + } + } // note:call resetInfoOnInterpolate() and pass interpolate // flag to Resource - NsharpEditor editor = NsharpEditor.getActiveNsharpEditor(); + NsharpEditor editor = NsharpEditor.getActiveNsharpEditor(); if (editor != null) { - try { + try { editor.getRscHandler().resetInfoOnInterpolate( interpolateIsOn); - } catch (CloneNotSupportedException e) { - e.printStackTrace(); - } + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } // know that current editor is NsharpSkewT editor, // refresh it. - editor.refresh(); - + editor.refresh(); + NsharpShowTextDialog textarea = NsharpShowTextDialog .getAccess(); if (textarea != null) { - textarea.refreshTextData(); - } - } - } - } + textarea.refreshTextData(); + } + } + } + } }); - NsharpResourceHandler rscHandler = getRscHandler(); - - // Push buttons for OVERLAY info - overlayBtn = new Button(textModeGp, SWT.PUSH); - overlayBtn.setFont(newFont); + NsharpResourceHandler rscHandler = getRscHandler(); + + // Push buttons for OVERLAY info + overlayBtn = new Button(textModeGp, SWT.PUSH); + overlayBtn.setFont(newFont); if (overlayIsOn) { - overlayBtn.setText(OVLY_ON); + overlayBtn.setText(OVLY_ON); overlayBtn.setEnabled(true); } else { - overlayBtn.setText(OVLY_OFF); + overlayBtn.setText(OVLY_OFF); // comparison and overlay is mutual exclusive if ((rscHandler != null) && (rscHandler.isCompareStnIsOn() || rscHandler.isCompareTmIsOn() || rscHandler .isCompareSndIsOn())) overlayBtn.setEnabled(false); - else + else overlayBtn.setEnabled(true); - } + } overlayBtn.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow() .getShell(); if (overlayIsOn == false) { - overlayIsOn = true; - overlayBtn.setText(OVLY_ON); - compareStnBtn.setEnabled(false); - compareTmBtn.setEnabled(false); - compareSndBtn.setEnabled(false); - graphEditBtn.setEnabled(false); - dataEditBtn.setEnabled(false); + overlayIsOn = true; + overlayBtn.setText(OVLY_ON); + compareStnBtn.setEnabled(false); + compareTmBtn.setEnabled(false); + compareSndBtn.setEnabled(false); + graphEditBtn.setEnabled(false); + dataEditBtn.setEnabled(false); graphModeBtnTurb.setEnabled(false); graphModeBtnIcing.setEnabled(false); interpBtn.setEnabled(false); cfgBtn.setEnabled(false); } else { - overlayIsOn = false; - overlayBtn.setText(OVLY_OFF); - compareStnBtn.setEnabled(true); - compareTmBtn.setEnabled(true); - compareSndBtn.setEnabled(true); - graphEditBtn.setEnabled(true); - dataEditBtn.setEnabled(true); + overlayIsOn = false; + overlayBtn.setText(OVLY_OFF); + compareStnBtn.setEnabled(true); + compareTmBtn.setEnabled(true); + compareSndBtn.setEnabled(true); + graphEditBtn.setEnabled(true); + dataEditBtn.setEnabled(true); graphModeBtnTurb.setEnabled(true); graphModeBtnIcing.setEnabled(true); interpBtn.setEnabled(true); cfgBtn.setEnabled(true); - } - NsharpResourceHandler rsc = getRscHandler(); + } + NsharpResourceHandler rsc = getRscHandler(); if (rsc != null) { - rsc.setOverlayIsOn(overlayIsOn); - rsc.refreshPane(); - } - } + rsc.setOverlayIsOn(overlayIsOn); + rsc.refreshPane(); + } + } }); - // Push buttons for CompByStn info - compareStnBtn = new Button(textModeGp, SWT.PUSH); - compareStnBtn.setFont(newFont); + // Push buttons for CompByStn info + compareStnBtn = new Button(textModeGp, SWT.PUSH); + compareStnBtn.setFont(newFont); if (compareStnIsOn) { - compareStnBtn.setText(COMP_STN_ON); + compareStnBtn.setText(COMP_STN_ON); compareStnBtn.setEnabled(true); } else { // comparison and overlay is mutual exclusive - compareStnBtn.setText(COMP_STN_OFF); + compareStnBtn.setText(COMP_STN_OFF); if ((rscHandler != null) && (rscHandler.isOverlayIsOn() || rscHandler.isCompareTmIsOn() || rscHandler .isCompareSndIsOn())) compareStnBtn.setEnabled(false); - else + else compareStnBtn.setEnabled(true); - } + } compareStnBtn.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow() .getShell(); if (compareStnIsOn == false) { - compareStnIsOn = true; - compareStnBtn.setText(COMP_STN_ON); - overlayBtn.setEnabled(false); + compareStnIsOn = true; + compareStnBtn.setText(COMP_STN_ON); + overlayBtn.setEnabled(false); compareTmBtn.setEnabled(false); - compareSndBtn.setEnabled(false); - graphEditBtn.setEnabled(false); - dataEditBtn.setEnabled(false); + compareSndBtn.setEnabled(false); + graphEditBtn.setEnabled(false); + dataEditBtn.setEnabled(false); graphModeBtnTurb.setEnabled(false); graphModeBtnIcing.setEnabled(false); interpBtn.setEnabled(false); cfgBtn.setEnabled(false); } else { - compareStnIsOn = false; - compareStnBtn.setText(COMP_STN_OFF); - overlayBtn.setEnabled(true); + compareStnIsOn = false; + compareStnBtn.setText(COMP_STN_OFF); + overlayBtn.setEnabled(true); compareTmBtn.setEnabled(true); - compareSndBtn.setEnabled(true); - graphEditBtn.setEnabled(true); - dataEditBtn.setEnabled(true); + compareSndBtn.setEnabled(true); + graphEditBtn.setEnabled(true); + dataEditBtn.setEnabled(true); graphModeBtnTurb.setEnabled(true); graphModeBtnIcing.setEnabled(true); interpBtn.setEnabled(true); cfgBtn.setEnabled(true); - } - NsharpResourceHandler rsc = getRscHandler(); + } + NsharpResourceHandler rsc = getRscHandler(); if (rsc != null) { - rsc.setCompareStnIsOn(compareStnIsOn); - rsc.refreshPane(); - } - - } + rsc.setCompareStnIsOn(compareStnIsOn); + rsc.refreshPane(); + } + + } }); - // Push buttons for CompByTm info - compareTmBtn = new Button(textModeGp, SWT.PUSH); - compareTmBtn.setFont(newFont); + // Push buttons for CompByTm info + compareTmBtn = new Button(textModeGp, SWT.PUSH); + compareTmBtn.setFont(newFont); if (compareTmIsOn) { - compareTmBtn.setText(COMP_TM_ON); + compareTmBtn.setText(COMP_TM_ON); compareTmBtn.setEnabled(true); } else { // comparison and overlay is mutual exclusive - compareTmBtn.setText(COMP_TM_OFF); + compareTmBtn.setText(COMP_TM_OFF); if ((rscHandler != null) && (rscHandler.isOverlayIsOn() || rscHandler.isCompareStnIsOn() || rscHandler .isCompareSndIsOn())) compareTmBtn.setEnabled(false); - else + else compareTmBtn.setEnabled(true); - } + } compareTmBtn.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow() .getShell(); if (compareTmIsOn == false) { - compareTmIsOn = true; - compareTmBtn.setText(COMP_TM_ON); - compareSndBtn.setEnabled(false); - overlayBtn.setEnabled(false); + compareTmIsOn = true; + compareTmBtn.setText(COMP_TM_ON); + compareSndBtn.setEnabled(false); + overlayBtn.setEnabled(false); compareStnBtn.setEnabled(false); - graphEditBtn.setEnabled(false); - dataEditBtn.setEnabled(false); + graphEditBtn.setEnabled(false); + dataEditBtn.setEnabled(false); graphModeBtnTurb.setEnabled(false); graphModeBtnIcing.setEnabled(false); interpBtn.setEnabled(false); cfgBtn.setEnabled(false); } else { - compareTmIsOn = false; - compareTmBtn.setText(COMP_TM_OFF); - compareSndBtn.setEnabled(true); - overlayBtn.setEnabled(true); + compareTmIsOn = false; + compareTmBtn.setText(COMP_TM_OFF); + compareSndBtn.setEnabled(true); + overlayBtn.setEnabled(true); compareStnBtn.setEnabled(true); - graphEditBtn.setEnabled(true); - dataEditBtn.setEnabled(true); + graphEditBtn.setEnabled(true); + dataEditBtn.setEnabled(true); graphModeBtnTurb.setEnabled(true); graphModeBtnIcing.setEnabled(true); interpBtn.setEnabled(true); cfgBtn.setEnabled(true); - } - NsharpResourceHandler rsc = getRscHandler(); + } + NsharpResourceHandler rsc = getRscHandler(); if (rsc != null) { - rsc.setCompareTmIsOn(compareTmIsOn); - rsc.refreshPane(); - } - - } + rsc.setCompareTmIsOn(compareTmIsOn); + rsc.refreshPane(); + } + + } }); - // Push buttons for CompBySrc info - compareSndBtn = new Button(textModeGp, SWT.PUSH); - compareSndBtn.setFont(newFont); + // Push buttons for CompBySrc info + compareSndBtn = new Button(textModeGp, SWT.PUSH); + compareSndBtn.setFont(newFont); if (compareSndIsOn) { - compareSndBtn.setText(COMP_SND_ON); + compareSndBtn.setText(COMP_SND_ON); compareSndBtn.setEnabled(true); } else { // comparison and overlay is mutual exclusive - compareSndBtn.setText(COMP_SND_OFF); + compareSndBtn.setText(COMP_SND_OFF); if ((rscHandler != null) && (rscHandler.isOverlayIsOn() || rscHandler.isCompareStnIsOn() || rscHandler .isCompareTmIsOn())) compareSndBtn.setEnabled(false); - else + else compareSndBtn.setEnabled(true); - } + } compareSndBtn.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow() .getShell(); if (compareSndIsOn == false) { - compareSndIsOn = true; - compareSndBtn.setText(COMP_SND_ON); - overlayBtn.setEnabled(false); + compareSndIsOn = true; + compareSndBtn.setText(COMP_SND_ON); + overlayBtn.setEnabled(false); compareStnBtn.setEnabled(false); compareTmBtn.setEnabled(false); - graphEditBtn.setEnabled(false); - dataEditBtn.setEnabled(false); + graphEditBtn.setEnabled(false); + dataEditBtn.setEnabled(false); graphModeBtnTurb.setEnabled(false); graphModeBtnIcing.setEnabled(false); interpBtn.setEnabled(false); cfgBtn.setEnabled(false); } else { - compareSndIsOn = false; - compareSndBtn.setText(COMP_SND_OFF); - overlayBtn.setEnabled(true); + compareSndIsOn = false; + compareSndBtn.setText(COMP_SND_OFF); + overlayBtn.setEnabled(true); compareStnBtn.setEnabled(true); compareTmBtn.setEnabled(true); - graphEditBtn.setEnabled(true); - dataEditBtn.setEnabled(true); + graphEditBtn.setEnabled(true); + dataEditBtn.setEnabled(true); graphModeBtnTurb.setEnabled(true); graphModeBtnIcing.setEnabled(true); interpBtn.setEnabled(true); cfgBtn.setEnabled(true); - } - NsharpResourceHandler rsc = getRscHandler(); + } + NsharpResourceHandler rsc = getRscHandler(); if (rsc != null) { - rsc.setCompareSndIsOn(compareSndIsOn); - rsc.refreshPane(); - } - - } + rsc.setCompareSndIsOn(compareSndIsOn); + rsc.refreshPane(); + } + + } }); - - dataEditBtn = new Button(textModeGp, SWT.PUSH); - dataEditBtn.setFont(newFont); - dataEditBtn.setText(" Edit Data "); + + dataEditBtn = new Button(textModeGp, SWT.PUSH); + dataEditBtn.setFont(newFont); + dataEditBtn.setText(" Edit Data "); if (interpolateIsOn || editGraphOn) dataEditBtn.setEnabled(false); - else + else dataEditBtn.setEnabled(true); dataEditBtn.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { if (checkLoadedData()) { Shell shell = PlatformUI.getWorkbench() .getActiveWorkbenchWindow().getShell(); NsharpEditDataDialog editDia = NsharpEditDataDialog .getInstance(shell); if (editDia != null) { - editDia.open(); - } - } - } + editDia.open(); + } + } + } }); - graphEditBtn = new Button(textModeGp, SWT.PUSH); - graphEditBtn.setFont(newFont); + graphEditBtn = new Button(textModeGp, SWT.PUSH); + graphEditBtn.setFont(newFont); graphEditBtn.setEnabled(true); if (editGraphOn) { - graphEditBtn.setText(EDIT_GRAPH_ON); - dataEditBtn.setEnabled(false); + graphEditBtn.setText(EDIT_GRAPH_ON); + dataEditBtn.setEnabled(false); interpBtn.setEnabled(false); } else { - graphEditBtn.setText(EDIT_GRAPH_OFF); - dataEditBtn.setEnabled(true); + graphEditBtn.setText(EDIT_GRAPH_OFF); + dataEditBtn.setEnabled(true); interpBtn.setEnabled(true); - } + } graphEditBtn.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { if (checkLoadedData()) { if (editGraphOn) { editGraphOn = false; - graphEditBtn.setText(EDIT_GRAPH_OFF); - graphModeBtnIcing.setEnabled(true); - graphModeBtnTurb.setEnabled(true); - dataEditBtn.setEnabled(true); - interpBtn.setEnabled(true); - compareTmBtn.setEnabled(true); - compareSndBtn.setEnabled(true); - compareStnBtn.setEnabled(true); - overlayBtn.setEnabled(true); + graphEditBtn.setText(EDIT_GRAPH_OFF); + if(interpolateIsOn == false){ //TTR829 + graphModeBtnIcing.setEnabled(true); + graphModeBtnTurb.setEnabled(true); + dataEditBtn.setEnabled(true); + //interpBtn.setEnabled(true);TTR829 + compareTmBtn.setEnabled(true); + compareSndBtn.setEnabled(true); + compareStnBtn.setEnabled(true); + overlayBtn.setEnabled(true); + } } else { editGraphOn = true; - graphEditBtn.setText(EDIT_GRAPH_ON); - graphModeBtnIcing.setEnabled(false); - graphModeBtnTurb.setEnabled(false); + graphEditBtn.setText(EDIT_GRAPH_ON); + graphModeBtnIcing.setEnabled(false); + graphModeBtnTurb.setEnabled(false); dataEditBtn.setEnabled(false); - interpBtn.setEnabled(false); + //interpBtn.setEnabled(false); compareTmBtn.setEnabled(false); compareSndBtn.setEnabled(false); compareStnBtn.setEnabled(false); overlayBtn.setEnabled(false); - } - NsharpResourceHandler rsc = getRscHandler(); + } + NsharpResourceHandler rsc = getRscHandler(); if (rsc != null) { - rsc.setEditGraphOn(editGraphOn); - rsc.refreshPane(); - } - } - } + rsc.setEditGraphOn(editGraphOn); + rsc.refreshPane(); + } + } + } }); /* * Button bndryMotionBtn = new Button(textModeGp, SWT.PUSH); @@ -1135,437 +1142,443 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, * NsharpShowTextDialog.getInstance( shell ); if(osDia != null) * osDia.open(); } } } ); */ - - // Push buttons for show text info - Button showtextBtn = new Button(textModeGp, SWT.PUSH); - showtextBtn.setFont(newFont); - showtextBtn.setText(" Show Text "); + + // Push buttons for show text info + Button showtextBtn = new Button(textModeGp, SWT.PUSH); + showtextBtn.setFont(newFont); + showtextBtn.setText(" Show Text "); showtextBtn.setEnabled(true); showtextBtn.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow() .getShell(); if (checkLoadedData()) { NsharpShowTextDialog osDia = NsharpShowTextDialog .getInstance(shell); if (osDia != null) - osDia.open(); - } - } + osDia.open(); + } + } }); Group graphModeGp = new Group(textModeGp, SWT.SHADOW_ETCHED_IN); graphModeGp.setLayout(new RowLayout(SWT.HORIZONTAL));// new GridLayout( // 2, false ) ); - - // Push buttons for graphMode + + // Push buttons for graphMode graphModeBtnSkew = new Button(graphModeGp, SWT.PUSH); - graphModeBtnSkew.setFont(newFont); - graphModeBtnSkew.setText("S"); + graphModeBtnSkew.setFont(newFont); + graphModeBtnSkew.setText("S"); graphModeBtnSkew.setEnabled(true); // colorButtonOriginalBg= graphModeBtnSkew.getBackground(); - rscHandler = getRscHandler(); + rscHandler = getRscHandler(); if (rscHandler != null) { - currentGraphMode = rscHandler.getCurrentGraphMode(); - } + currentGraphMode = rscHandler.getCurrentGraphMode(); + } graphModeBtnSkew.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { if (currentGraphMode != NsharpConstants.GRAPH_SKEWT) { currentGraphMode = NsharpConstants.GRAPH_SKEWT; - graphModeBtnSkew.setBackground(colorBlue); - graphModeBtnTurb.setBackground(colorGrey); - graphModeBtnIcing.setBackground(colorGrey); + graphModeBtnSkew.setBackground(colorBlue); + graphModeBtnTurb.setBackground(colorGrey); + graphModeBtnIcing.setBackground(colorGrey); if (!interpolateIsOn) { - graphEditBtn.setEnabled(true); - dataEditBtn.setEnabled(true); + graphEditBtn.setEnabled(true); + dataEditBtn.setEnabled(true); compareTmBtn.setEnabled(true); compareSndBtn.setEnabled(true); compareStnBtn.setEnabled(true); overlayBtn.setEnabled(true); } else { - graphEditBtn.setEnabled(false); - dataEditBtn.setEnabled(false); + graphEditBtn.setEnabled(false); + dataEditBtn.setEnabled(false); compareTmBtn.setEnabled(false); compareSndBtn.setEnabled(false); compareStnBtn.setEnabled(false); overlayBtn.setEnabled(false); - } - NsharpResourceHandler rsc = getRscHandler(); + } + NsharpResourceHandler rsc = getRscHandler(); if (rsc != null) { - rsc.setCurrentGraphMode(currentGraphMode); + rsc.setCurrentGraphMode(currentGraphMode); // rsc.getSkewtPaneRsc().handleResize(); - } + } - } - } + } + } }); - graphModeBtnTurb = new Button(graphModeGp, SWT.PUSH); - graphModeBtnTurb.setFont(newFont); - graphModeBtnTurb.setText("T"); + graphModeBtnTurb = new Button(graphModeGp, SWT.PUSH); + graphModeBtnTurb.setFont(newFont); + graphModeBtnTurb.setText("T"); graphModeBtnTurb.setEnabled(true); graphModeBtnTurb.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { if (currentGraphMode != NsharpConstants.GRAPH_TURB) { currentGraphMode = NsharpConstants.GRAPH_TURB; - graphModeBtnTurb.setBackground(colorBlue); - graphModeBtnSkew.setBackground(colorGrey); - graphModeBtnIcing.setBackground(colorGrey); - graphEditBtn.setEnabled(false); - dataEditBtn.setEnabled(false); + graphModeBtnTurb.setBackground(colorBlue); + graphModeBtnSkew.setBackground(colorGrey); + graphModeBtnIcing.setBackground(colorGrey); + graphEditBtn.setEnabled(false); + dataEditBtn.setEnabled(false); compareTmBtn.setEnabled(false); compareSndBtn.setEnabled(false); compareStnBtn.setEnabled(false); overlayBtn.setEnabled(false); - NsharpResourceHandler rsc = getRscHandler(); + NsharpResourceHandler rsc = getRscHandler(); if (rsc != null) { - rsc.setCurrentGraphMode(currentGraphMode); - rsc.getSkewtPaneRsc().handleResize(); - } - } - } + rsc.setCurrentGraphMode(currentGraphMode); + rsc.getSkewtPaneRsc().handleResize(); + } + } + } }); - graphModeBtnIcing = new Button(graphModeGp, SWT.PUSH); - graphModeBtnIcing.setFont(newFont); - graphModeBtnIcing.setText("I"); + graphModeBtnIcing = new Button(graphModeGp, SWT.PUSH); + graphModeBtnIcing.setFont(newFont); + graphModeBtnIcing.setText("I"); graphModeBtnIcing.setEnabled(true); graphModeBtnIcing.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { if (currentGraphMode != NsharpConstants.GRAPH_ICING) { currentGraphMode = NsharpConstants.GRAPH_ICING; - graphModeBtnIcing.setBackground(colorBlue); - graphModeBtnSkew.setBackground(colorGrey); - graphModeBtnTurb.setBackground(colorGrey); - graphEditBtn.setEnabled(false); - dataEditBtn.setEnabled(false); + graphModeBtnIcing.setBackground(colorBlue); + graphModeBtnSkew.setBackground(colorGrey); + graphModeBtnTurb.setBackground(colorGrey); + graphEditBtn.setEnabled(false); + dataEditBtn.setEnabled(false); compareTmBtn.setEnabled(false); compareSndBtn.setEnabled(false); compareStnBtn.setEnabled(false); overlayBtn.setEnabled(false); - NsharpResourceHandler rsc = getRscHandler(); + NsharpResourceHandler rsc = getRscHandler(); if (rsc != null) { - rsc.setCurrentGraphMode(currentGraphMode); - rsc.getSkewtPaneRsc().handleResize(); - } - } - } + rsc.setCurrentGraphMode(currentGraphMode); + rsc.getSkewtPaneRsc().handleResize(); + } + } + } }); if (currentGraphMode == NsharpConstants.GRAPH_SKEWT) { - graphModeBtnSkew.setBackground(colorBlue); - graphModeBtnTurb.setBackground(colorGrey); - graphModeBtnIcing.setBackground(colorGrey); + graphModeBtnSkew.setBackground(colorBlue); + graphModeBtnTurb.setBackground(colorGrey); + graphModeBtnIcing.setBackground(colorGrey); } else if (currentGraphMode == NsharpConstants.GRAPH_TURB) { - graphModeBtnTurb.setBackground(colorBlue); - graphModeBtnSkew.setBackground(colorGrey); - graphModeBtnIcing.setBackground(colorGrey); + graphModeBtnTurb.setBackground(colorBlue); + graphModeBtnSkew.setBackground(colorGrey); + graphModeBtnIcing.setBackground(colorGrey); } else if (currentGraphMode == NsharpConstants.GRAPH_ICING) { - graphModeBtnIcing.setBackground(colorBlue); - graphModeBtnSkew.setBackground(colorGrey); - graphModeBtnTurb.setBackground(colorGrey); - } + graphModeBtnIcing.setBackground(colorBlue); + graphModeBtnSkew.setBackground(colorGrey); + graphModeBtnTurb.setBackground(colorGrey); + } - // Push buttons for Print - Button printBtn = new Button(textModeGp, SWT.PUSH); - printBtn.setFont(newFont); - printBtn.setText(" Print "); + // Push buttons for Print + Button printBtn = new Button(textModeGp, SWT.PUSH); + printBtn.setFont(newFont); + printBtn.setText(" Print "); printBtn.setEnabled(true); printBtn.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow() .getShell(); // 12.7.1 testing if(checkLoadedData()) { if (true) { - printHandle.handlePrint(""); - } - } + printHandle.handlePrint(""); + } + } }); - + if (paneConfigurationName.equals(NsharpConstants.PANE_SPCWS_CFG_STR)) - createSPCGp(); - + createSPCGp(); + if (rscHandler != null) { restorePaletteWindow(paneConfigurationName, rscHandler.getCurrentGraphMode(), - rscHandler.isInterpolateIsOn(), rscHandler.isOverlayIsOn(), + rscHandler.isInterpolateIsOn(), rscHandler.isOverlayIsOn(), rscHandler.isCompareStnIsOn(), rscHandler.isCompareTmIsOn(), rscHandler.isEditGraphOn(), rscHandler.isCompareSndIsOn()); - } - parent.redraw(); - } - + } + parent.redraw(); + } + private void createSPCGp() { // System.out.println("createSPCGp.........................................."); spcGp = new Group(parent, SWT.SHADOW_OUT); spcGp.setLayout(new RowLayout(SWT.HORIZONTAL)); spcGp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - spcGplbl = new Label(spcGp, SWT.NO); - spcGplbl.setText("SPC Graphs"); + spcGplbl = new Label(spcGp, SWT.NO); + spcGplbl.setText("SPC Graphs"); if (paneConfigurationName.equals(NsharpConstants.PANE_SPCWS_CFG_STR)) { spcGplbl.setEnabled(true); } else { spcGplbl.setEnabled(false); - } - effBulkShearBtn = new Button(spcGp, SWT.PUSH); - effBulkShearBtn.setFont(newFont); - effBulkShearBtn.setText("EBS Stats "); + } + effBulkShearBtn = new Button(spcGp, SWT.PUSH); + effBulkShearBtn.setFont(newFont); + effBulkShearBtn.setText("EBS Stats "); if (paneConfigurationName.equals(NsharpConstants.PANE_SPCWS_CFG_STR)) { effBulkShearBtn.setEnabled(true); } else { effBulkShearBtn.setEnabled(false); - } + } effBulkShearBtn.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { if (leftGraph != NsharpConstants.SPCGraph.EBS && rightGraph != NsharpConstants.SPCGraph.EBS) { - rightGraph = leftGraph; - leftGraph = NsharpConstants.SPCGraph.EBS; - updateSPCGraphs(); - } - } + rightGraph = leftGraph; + leftGraph = NsharpConstants.SPCGraph.EBS; + updateSPCGraphs(); + } + } }); - stpBtn = new Button(spcGp, SWT.PUSH); - stpBtn.setFont(newFont); - stpBtn.setText("STP Stats "); + stpBtn = new Button(spcGp, SWT.PUSH); + stpBtn.setFont(newFont); + stpBtn.setText("STP Stats "); if (paneConfigurationName.equals(NsharpConstants.PANE_SPCWS_CFG_STR)) { stpBtn.setEnabled(true); } else { stpBtn.setEnabled(false); - } + } stpBtn.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { if (leftGraph != NsharpConstants.SPCGraph.STP && rightGraph != NsharpConstants.SPCGraph.STP) { - rightGraph = leftGraph; - leftGraph = NsharpConstants.SPCGraph.STP; - updateSPCGraphs(); - } - } + rightGraph = leftGraph; + leftGraph = NsharpConstants.SPCGraph.STP; + updateSPCGraphs(); + } + } }); - - shipBtn = new Button(spcGp, SWT.PUSH); - shipBtn.setFont(newFont); - shipBtn.setText("SHIP Stats"); + + shipBtn = new Button(spcGp, SWT.PUSH); + shipBtn.setFont(newFont); + shipBtn.setText("SHIP Stats"); if (paneConfigurationName.equals(NsharpConstants.PANE_SPCWS_CFG_STR)) { shipBtn.setEnabled(true); } else { shipBtn.setEnabled(false); - } + } shipBtn.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { if (leftGraph != NsharpConstants.SPCGraph.SHIP && rightGraph != NsharpConstants.SPCGraph.SHIP) { - rightGraph = leftGraph; - leftGraph = NsharpConstants.SPCGraph.SHIP; - updateSPCGraphs(); - } - } + rightGraph = leftGraph; + leftGraph = NsharpConstants.SPCGraph.SHIP; + updateSPCGraphs(); + } + } }); - winterBtn = new Button(spcGp, SWT.PUSH); - winterBtn.setFont(newFont); - winterBtn.setText(" WINTER "); + winterBtn = new Button(spcGp, SWT.PUSH); + winterBtn.setFont(newFont); + winterBtn.setText(" WINTER "); if (paneConfigurationName.equals(NsharpConstants.PANE_SPCWS_CFG_STR)) { winterBtn.setEnabled(true); } else { winterBtn.setEnabled(false); - } + } winterBtn.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { if (leftGraph != NsharpConstants.SPCGraph.WINTER && rightGraph != NsharpConstants.SPCGraph.WINTER) { - rightGraph = leftGraph; - leftGraph = NsharpConstants.SPCGraph.WINTER; - updateSPCGraphs(); - } - } + rightGraph = leftGraph; + leftGraph = NsharpConstants.SPCGraph.WINTER; + updateSPCGraphs(); + } + } }); - fireBtn = new Button(spcGp, SWT.PUSH); - fireBtn.setFont(newFont); - fireBtn.setText(" FIRE "); + fireBtn = new Button(spcGp, SWT.PUSH); + fireBtn.setFont(newFont); + fireBtn.setText(" FIRE "); if (paneConfigurationName.equals(NsharpConstants.PANE_SPCWS_CFG_STR)) { fireBtn.setEnabled(true); } else { fireBtn.setEnabled(false); - } + } fireBtn.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { if (leftGraph != NsharpConstants.SPCGraph.FIRE && rightGraph != NsharpConstants.SPCGraph.FIRE) { - rightGraph = leftGraph; - leftGraph = NsharpConstants.SPCGraph.FIRE; - updateSPCGraphs(); - } - } + rightGraph = leftGraph; + leftGraph = NsharpConstants.SPCGraph.FIRE; + updateSPCGraphs(); + } + } }); - hailBtn = new Button(spcGp, SWT.PUSH); - hailBtn.setFont(newFont); - hailBtn.setText(" HAIL "); + hailBtn = new Button(spcGp, SWT.PUSH); + hailBtn.setFont(newFont); + hailBtn.setText(" HAIL "); if (paneConfigurationName.equals(NsharpConstants.PANE_SPCWS_CFG_STR)) { hailBtn.setEnabled(true); } else { hailBtn.setEnabled(false); - } + } hailBtn.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { if (leftGraph != NsharpConstants.SPCGraph.HAIL && rightGraph != NsharpConstants.SPCGraph.HAIL) { - rightGraph = leftGraph; - leftGraph = NsharpConstants.SPCGraph.HAIL; - updateSPCGraphs(); - } - } + rightGraph = leftGraph; + leftGraph = NsharpConstants.SPCGraph.HAIL; + updateSPCGraphs(); + } + } }); - sarsBtn = new Button(spcGp, SWT.PUSH); - sarsBtn.setFont(newFont); - sarsBtn.setText(" SARS "); + sarsBtn = new Button(spcGp, SWT.PUSH); + sarsBtn.setFont(newFont); + sarsBtn.setText(" SARS "); if (paneConfigurationName.equals(NsharpConstants.PANE_SPCWS_CFG_STR)) { sarsBtn.setEnabled(true); } else { sarsBtn.setEnabled(false); - } + } sarsBtn.addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { + public void handleEvent(Event event) { if (leftGraph != NsharpConstants.SPCGraph.SARS && rightGraph != NsharpConstants.SPCGraph.SARS) { - rightGraph = leftGraph; - leftGraph = NsharpConstants.SPCGraph.SARS; - updateSPCGraphs(); - } - } + rightGraph = leftGraph; + leftGraph = NsharpConstants.SPCGraph.SARS; + updateSPCGraphs(); + } + } }); - updateSPCGraphs(); - spcGpCreated = true; - parent.layout(); - } + updateSPCGraphs(); + spcGpCreated = true; + parent.layout(); + } private void disposeSpcGp() { - spcGplbl.dispose(); - effBulkShearBtn.dispose(); - stpBtn.dispose(); - shipBtn.dispose(); - winterBtn.dispose(); - fireBtn.dispose(); - hailBtn.dispose(); - sarsBtn.dispose(); - spcGp.dispose(); - - spcGplbl = null; - effBulkShearBtn = null; - stpBtn = null; - shipBtn = null; - winterBtn = null; - fireBtn = null; - hailBtn = null; - sarsBtn = null; - spcGp = null; - } + spcGplbl.dispose(); + effBulkShearBtn.dispose(); + stpBtn.dispose(); + shipBtn.dispose(); + winterBtn.dispose(); + fireBtn.dispose(); + hailBtn.dispose(); + sarsBtn.dispose(); + spcGp.dispose(); - public boolean isEditorVisible() { - return isEditorVisible; - } + spcGplbl = null; + effBulkShearBtn = null; + stpBtn = null; + shipBtn = null; + winterBtn = null; + fireBtn = null; + hailBtn = null; + sarsBtn = null; + spcGp = null; + } + + public boolean isEditorVisible() { + return isEditorVisible; + } + + public void setEditorVisible(boolean isEditorVisible) { + this.isEditorVisible = isEditorVisible; + } - public void setEditorVisible(boolean isEditorVisible) { - this.isEditorVisible = isEditorVisible; - } - public void updateSpcGraphBtn(String paneConfigurationName) { - this.paneConfigurationName = paneConfigurationName; + this.paneConfigurationName = paneConfigurationName; if (paneConfigurationName.equals(NsharpConstants.PANE_SPCWS_CFG_STR)) { if (spcGpCreated == false) { - createSPCGp(); - } + createSPCGp(); + } } else { if (spcGpCreated) { - spcGpCreated = false; + spcGpCreated = false; if (spcGp != null) { - disposeSpcGp(); - parent.layout(); - } - - } - } - - } - - /** + disposeSpcGp(); + parent.layout(); + } + + } + } + + } + + /** * Invoked by the workbench, this method sets up the SWT controls for the * nsharp palette - */ + */ - @Override - public void createPartControl(Composite parent) { + @Override + public void createPartControl(Composite parent) { // System.out.println("nlist @"+NsharpConstants.getNlistFile()); parent.setLayout(new GridLayout(1, true)); - createDataControlGp(parent); - } + createDataControlGp(parent); + } - @Override - public void widgetDefaultSelected(SelectionEvent e) { - // TODO Auto-generated method stub + @Override + public void widgetDefaultSelected(SelectionEvent e) { + // TODO Auto-generated method stub - } + } - @Override - public void widgetSelected(SelectionEvent e) { - // TODO Auto-generated method stub + @Override + public void widgetSelected(SelectionEvent e) { + // TODO Auto-generated method stub - } + } - @Override - public void widgetDisposed(DisposeEvent e) { + @Override + public void widgetDisposed(DisposeEvent e) { - } + } - private IContextActivation context; + private IContextActivation context; - @Override - public void partActivated(IWorkbenchPart part) { + @Override + public void partActivated(IWorkbenchPart part) { if (context == null) { - IContextService ctxSvc = (IContextService) PlatformUI - .getWorkbench().getService(IContextService.class); + IContextService ctxSvc = (IContextService) PlatformUI + .getWorkbench().getService(IContextService.class); context = ctxSvc .activateContext("gov.noaa.nws.ncep.ui.nsharp.nsharpContext"); - // System.out.println("Activated " + context.getContextId()); + // System.out.println("Activated " + context.getContextId()); } if (part instanceof NsharpPaletteWindow) { NsharpMapResource rsc = NsharpMapResource.getMapRsc(); if (rsc != null) { rsc.setEditable(true); - } - } + } + } } - @Override - public void partBroughtToTop(IWorkbenchPart part) { - // TODO Auto-generated method stub + @Override + public void partBroughtToTop(IWorkbenchPart part) { + // TODO Auto-generated method stub - } + } - @Override - public void partClosed(IWorkbenchPart part) { - } + @Override + public void partClosed(IWorkbenchPart part) { + //System.out.println("view closed "); + /*FixMark:SwapPaneShowText + NsharpShowTextDialog textarea = NsharpShowTextDialog.getAccess(); + if(textarea != null){ + textarea.close(); + }//end FixMark:SwapPaneShowText */ - @Override - public void partDeactivated(IWorkbenchPart part) { - if (context != null) { - - IContextService ctxSvc = (IContextService) PlatformUI - .getWorkbench().getService(IContextService.class); - ctxSvc.deactivateContext(context); - // System.out.println("Deactivated " + context.getContextId()); - context = null; - } + } - } + @Override + public void partDeactivated(IWorkbenchPart part) { + if (context != null) { - @Override - public void partOpened(IWorkbenchPart part) { - // TODO Auto-generated method stub + IContextService ctxSvc = (IContextService) PlatformUI + .getWorkbench().getService(IContextService.class); + ctxSvc.deactivateContext(context); + //System.out.println("view Deactivated " + context.getContextId()); + context = null; + } + } - } + @Override + public void partOpened(IWorkbenchPart part) { + // TODO Auto-generated method stub - @Override - public void setFocus() { - // TODO Auto-generated method stub + } - } + @Override + public void setFocus() { + // TODO Auto-generated method stub + + } } diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/ccfpTimes.xml b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/ccfpTimes.xml index 6d7d48a1bb..86e6747790 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/ccfpTimes.xml +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/ccfpTimes.xml @@ -13,8 +13,8 @@ --> - \ No newline at end of file diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/contoursInfo.xml b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/contoursInfo.xml index b9ca098df5..4f2dd6a46f 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/contoursInfo.xml +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/contoursInfo.xml @@ -1,7 +1,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + - + diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/vaa/vaaEditQUICK.xslt b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/vaa/vaaEditQUICK.xslt index c35bb09961..22bc15ebbd 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/vaa/vaaEditQUICK.xslt +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/vaa/vaaEditQUICK.xslt @@ -10,15 +10,13 @@ SUMMIT ELEV: -ADVISORY NR: +ADVISORY NR: / -INFO SOURCE:   -ERUPTION DETAILS: - +INFO SOURCE:   +ERUPTION DETAILS: RMK: NXT ADVISORY: - diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/watchbox/SEL.xlt b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/watchbox/SEL.xlt index 35a8eacd57..0610e44c9b 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/watchbox/SEL.xlt +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/watchbox/SEL.xlt @@ -83,7 +83,11 @@ - TORNADOES...HAIL TO + + TORNADOES... + + + HAIL TO INCHES IN DIAMETER...THUNDERSTORM WIND @@ -102,7 +106,9 @@ TEST - TORNADO WATCH AREA IS APPROXIMATELY ALONG AND + + + WATCH AREA IS APPROXIMATELY ALONG AND STATUTE @@ -197,7 +203,9 @@ - REMEMBER...A TORNADO WATCH MEANS CONDITIONS ARE FAVORABLE FOR + REMEMBER...A + + WATCH MEANS CONDITIONS ARE FAVORABLE FOR TORNADOES AND SEVERE THUNDERSTORMS IN AND CLOSE TO THE WATCH @@ -228,7 +236,11 @@ - AVIATION...TORNADOES AND A FEW SEVERE THUNDERSTORMS WITH HAIL + AVIATION... + + TORNADOES AND + + A FEW SEVERE THUNDERSTORMS WITH HAIL SURFACE AND ALOFT TO diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/watchbox/SEV.xlt b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/watchbox/SEV.xlt index a578b7c331..dd3aca12c1 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/watchbox/SEV.xlt +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/watchbox/SEV.xlt @@ -12,6 +12,8 @@ Change Log: B. Yin/Chugach 03/10 Initial Coding + B. Yin/SGT 12/13 TTR 904 change county list string + --> @@ -33,8 +35,9 @@ TEST - - TORNADO WATCH # + + + WATCH # HAS BEEN ISSUED BY THE NWS STORM PREDICTION CENTER @@ -63,8 +66,14 @@ . - COUNTIES INCLUDED ARE - + + + PARISHES INCLUDED ARE + + + COUNTIES INCLUDED ARE + + diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/watchbox/WOU.xlt b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/watchbox/WOU.xlt index b2516b5ccb..f52ea8a6b2 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/watchbox/WOU.xlt +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/watchbox/WOU.xlt @@ -38,8 +38,8 @@ TEST... - - TORNADO WATCH OUTLINE UPDATE FOR WT + + WATCH OUTLINE UPDATE FOR WT ...TEST @@ -52,7 +52,8 @@ - TORNADO WATCH + + WATCH IS IN EFFECT UNTIL diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/watchbox/WatchText.xlt b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/watchbox/WatchText.xlt index 8b6b494db6..09a2202522 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/watchbox/WatchText.xlt +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/watchbox/WatchText.xlt @@ -10,6 +10,8 @@ Change Log: B. Yin/Chugach 03/10 Initial Coding + B. Yin/SGT 12/13 TTR 904 change county list string + --> @@ -34,7 +36,7 @@ - + VALID TIME: @@ -121,10 +123,10 @@ - UGC State County Name Lat/Lon FIPS WFO + UGC State County Name Lat/Lon FIPS WFO - + diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/watchbox/getCoastalWaters.xlt b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/watchbox/getCoastalWaters.xlt index 7717bf3b95..30e6dfb3a2 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/watchbox/getCoastalWaters.xlt +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/watchbox/getCoastalWaters.xlt @@ -12,6 +12,7 @@ Change Log: B. Yin/Chugach 05/10 Initial Coding + B. Yin/SGT 12/13 TTR 904 change county list string --> @@ -20,7 +21,7 @@ - + diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/watchbox/getStateLine.xlt b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/watchbox/getStateLine.xlt index 587fe86fde..1db8113450 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/watchbox/getStateLine.xlt +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/watchbox/getStateLine.xlt @@ -12,6 +12,8 @@ Change Log: B. Yin/Chugach 03/10 Initial Coding + B. Yin/SGT 12/13 TTR 904 change county list string + --> @@ -20,12 +22,9 @@ C - + - - - - diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/plugin.xml b/ncep/gov.noaa.nws.ncep.ui.pgen/plugin.xml index 946cfbad5c..85d66286e2 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/plugin.xml +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/plugin.xml @@ -24,6 +24,11 @@ id="gov.noaa.nws.ncep.ui.pgen.rsc.PgenDualDraw" name="Pgen Dual Point Drawing"> + + + + @@ -2963,6 +2972,18 @@ className="Arc" commandId="gov.noaa.nws.ncep.ui.pgen.rsc.PgenDualDraw" icon="icons/cirsolid.gif" /> + + + * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Nov 4, 2013 TTR 752 jwu Initial creation + * + * + * + * @author jwu + * @version 1.0 + */ + +public class PgenAutoPlacement { + + private static final double START_ANGLE = 45.0;; + + private PgenRangeRecord textBox; + + private PgenRangeRecord polygonBox; + + private PgenRangeRecord arrowBox; + + private List activeRanges; + + private PgenRangeRecord screenBox; + + private boolean checkCenter; + + private double angleIncrement; + + private double distIncrement; + + private GeometryFactory gf; + + /** + * @param textBox + * @param arrowBox + * @param activeRanges + * @param screenBox + * @param checkCenter + * @param angleIncrement + * @param distIncrement + */ + public PgenAutoPlacement(PgenRangeRecord textBox, + PgenRangeRecord polygonBox, PgenRangeRecord arrowBox, + List activeRanges, PgenRangeRecord screenBox, + boolean checkCenter, double angleIncrement, double distIncrement) { + super(); + this.textBox = textBox; + this.polygonBox = polygonBox; + this.arrowBox = arrowBox; + this.activeRanges = activeRanges; + this.screenBox = screenBox; + this.checkCenter = checkCenter; + this.angleIncrement = angleIncrement; + this.distIncrement = distIncrement; + + gf = new GeometryFactory(); + } + + /** + * @param textBox + * the textBox to set + */ + public void setTextBox(PgenRangeRecord textBox) { + this.textBox = textBox; + } + + /** + * @param polygonBox + * the polygonBox to set + */ + public void setPolygonBox(PgenRangeRecord polygonBox) { + this.polygonBox = polygonBox; + } + + /** + * @param activeRanges + * the activeRanges to set + */ + public void setActiveRanges(List activeRanges) { + this.activeRanges = activeRanges; + } + + /** + * @param screenBox + * the screenBox to set + */ + public void setScreenBox(PgenRangeRecord screenBox) { + this.screenBox = screenBox; + } + + /** + * @param checkCenter + * the checkCenter to set + */ + public void setCheckCenter(boolean checkCenter) { + this.checkCenter = checkCenter; + } + + /** + * @param angleIncrement + * the angleIncrement to set + */ + public void setAngleIncrement(double angleIncrement) { + this.angleIncrement = angleIncrement; + } + + /** + * @param distIncrement + * the distIncrement to set + */ + public void setDistIncrement(double distIncrement) { + this.distIncrement = distIncrement; + } + + /** + * Generate a JTS polygon from a set of points. + * + * @param points + * array of points + * @return + */ + public static Geometry pointsToGeometry(Coordinate[] points, + boolean closed, GeometryFactory gf) { + + Geometry geom; + if (points == null || points.length == 0) { + geom = null; + } else if (points.length == 1) { + CoordinateArraySequence cas = new CoordinateArraySequence(points); + geom = new Point(cas, new GeometryFactory()); + } else if (points.length == 2) { + geom = pointsToLineString(points, gf); + } else { + if (closed) { + geom = pointsToPolygon(points, gf); + } else { + geom = pointsToLineString(points, gf); + } + } + + return geom; + } + + /** + * Generate a JTS polygon from a set of points. + * + * @param pots + * list of points + * @return + */ + public static Geometry pointsToGeometry(List pts, + boolean closed, GeometryFactory gf) { + + if (pts == null || pts.size() == 0) + return null; + + Coordinate[] points = new Coordinate[pts.size()]; + pts.toArray(points); + + return pointsToGeometry(points, closed, gf); + } + + /** + * Generate a JTS LineString from a set of points. + * + * @param points + * array of points + * @return + */ + public static Geometry pointsToLineString(Coordinate[] points, + GeometryFactory gf) { + + CoordinateArraySequence cas = new CoordinateArraySequence(points); + + return new LineString(cas, gf); + } + + /** + * Generate a JTS polygon from a set of points. + * + * It is assumed that the first point is not repeated at the end in the + * input array of point. + * + * @param points + * array of points + * @return + */ + public static Polygon pointsToPolygon(Coordinate[] points, + GeometryFactory gf) { + + Coordinate[] coords = Arrays.copyOf(points, points.length + 1); + coords[coords.length - 1] = coords[0]; + + CoordinateArraySequence cas = new CoordinateArraySequence(coords); + LinearRing ring = new LinearRing(cas, gf); + + Polygon polygon = new Polygon(ring, null, gf); + + return polygon; + } + + /** + * Find a location to place the text box so the box won't intersect its + * linked polygon and all other geometries. + * + * @param points + * array of points + * @return PgenRangeRecord + */ + public PgenRangeRecord[] placeTextBox() { + + PgenRangeRecord[] newrr = new PgenRangeRecord[2]; + + Geometry textgeo = pointsToGeometry(textBox.getExtent(), true, gf); + Geometry textgeo1 = pointsToGeometry(textBox.getExtentWithoutBuffer(), + true, gf); + // Geometry ccfpbox = pointsToGeometry(polygonBox.getExtent(), gf); + Geometry ccfpgeo = pointsToGeometry(polygonBox.getPoints(), true, gf); + + GeometryCollection gc = buildGC(activeRanges, gf); + + // Place the text in the centroid of the CCFP polygon. + newrr[0] = this.textBox; + newrr[1] = new PgenRangeRecord(); // no arrow needed. + if (checkCenter && textgeo1.within(ccfpgeo)) { + + if (gc == null || (gc != null && !gc.intersects(textgeo1))) { + // newrr[0] = this.textBox; + // newrr[1] = new PgenRangeRecord(); // no arrow needed. + return newrr; + } + } + + // Start from the center direction to find the first location. + double screenWidth = screenBox.getExtent().get(1).x + - screenBox.getExtent().get(0).x; + + // remember the start location (center) + PgenRangeRecord startLoc = textBox.copy(); + + // angleIncrement = 5.0; + // distIncrement = 1.25; + double unit = screenWidth * distIncrement / 100; + + // Find how many round of horizontal increments needed to reach the + // farest of the screen. + double maxDist = textBox.maxExtention(screenBox); + int nrounds = (int) (maxDist / unit) + 1; + + // Find the number of trials in one round. + int numOfRotations = (int) (360 / angleIncrement + 0.05); + + double radius = 0; + double ang, xdir, ydir; + boolean firstAvailable = false; + + for (int jj = 0; jj < nrounds; jj++) { + radius = unit + jj * unit; // distance increment + for (int ii = 0; ii < numOfRotations; ii++) { + ang = Math.toRadians(START_ANGLE - ii * angleIncrement); // anti-clockwise + xdir = radius * Math.cos(ang); + ydir = radius * Math.sin(ang); + + // Move box and make sure it is visible in screen. + PgenRangeRecord newBox = moveTextBox(startLoc, xdir, ydir); + PgenRangeRecord newArrow = new PgenRangeRecord(); // no arrow + // needed.; + if (!newBox.within(screenBox)) + continue; + + /* + * check if the box intersects the polygon and then check if it + * intersects all other geometries. Remember the first box that + * found outside of the polygon. + */ + textgeo = pointsToGeometry(newBox.getExtent(), true, gf); + boolean insideCcfp = textgeo.within(ccfpgeo); + if (insideCcfp || !textgeo.intersects(ccfpgeo)) { + // if ( !textgeo.intersects(ccfpgeo)) { + + if (!insideCcfp) { + newArrow = findArrow(newBox, ccfpgeo, gc); + } + + // Remember the first one. + if (!firstAvailable) { + newrr[0] = newBox.copy(); + newrr[1] = newArrow.copy(); + firstAvailable = true; + } + + if (gc == null || (gc != null && !gc.intersects(textgeo))) { + /* + * to do - let's check if the arrow does not intersect + * with other geometries, except the CCFP polygon and + * the text box? + */ + if (!insideCcfp + && (gc != null && gc.getNumGeometries() > 0)) { + Geometry arrowgeo = pointsToGeometry( + newArrow.getPoints(), false, gf); + boolean validArrow = true; + for (int kk = 0; kk < gc.getNumGeometries(); kk++) { + if (arrowgeo.intersects(gc.getGeometryN(kk))) { + validArrow = false; + break; + } + } + + if (!validArrow) { + continue; + } + } + + newrr[0] = newBox; + newrr[1] = newArrow; + return newrr; + } + } + } + } + + return newrr; + + } + + /* + * Move the text box (range record) as specified. + */ + private PgenRangeRecord moveTextBox(PgenRangeRecord rr, double xinc, + double yinc) { + + PgenRangeRecord newrr = rr.copy(); + for (Coordinate pt : newrr.getExtent()) { + pt.x += xinc; + pt.y += yinc; + } + + for (Coordinate pt : newrr.getPoints()) { + pt.x += xinc; + pt.y += yinc; + } + + return newrr; + + } + + /* + * Put all geometries that need to be checked agaist into a + * GeometryCollection. + */ + private GeometryCollection buildGC(List ranges, + GeometryFactory gf) { + GeometryCollection ngc = null; + List rangeGeos = new ArrayList(); + for (PgenRangeRecord rr : ranges) { + if (rr.getPoints() != null && rr.getPoints().size() > 0) { + if (rr.getPoints().size() > 1) { + rangeGeos.add(pointsToGeometry(rr.getPoints(), + rr.isClosed(), gf)); + } else { + Geometry ego = pointsToGeometry(rr.getExtent(), true, gf); + if (ego != null) { + rangeGeos + .add(pointsToGeometry(rr.getExtent(), true, gf)); + } + } + } + } + + if (rangeGeos.size() > 0) { + ngc = new GeometryCollection( + rangeGeos.toArray(new Geometry[rangeGeos.size()]), gf); + } + + return ngc; + + } + + /* + * Find an arrow that will not intersect with a list of geometries. + */ + private PgenRangeRecord findArrow(PgenRangeRecord textBox, + Geometry polygonGeo, GeometryCollection gc) { + + // First use arrow from text centroid to polygon centroid. + List arrow = new ArrayList(); + Point polyCenter = polygonGeo.getCentroid(); + Coordinate textCenter = textBox.getPoints().get(0); + + arrow.add(textCenter); + arrow.add(new Coordinate(polyCenter.getX(), polyCenter.getY())); + + // Now starts from the intersection point of the arrow with the text + Geometry arrowGeo = pointsToGeometry(arrow, false, gf); + Geometry textGeo = pointsToGeometry(textBox.getExtentWithoutBuffer(), + true, gf); + + Geometry interPt = arrowGeo.intersection(textGeo); + + arrow.remove(0); + if (interPt.getNumPoints() > 1) { + arrow.add(0, interPt.getCoordinates()[1]); + } else { + arrow.add(0, interPt.getCoordinates()[0]); + } + Geometry firstArrowGeo = pointsToGeometry(arrow, false, gf); + + return new PgenRangeRecord(firstArrowGeo.getCoordinates(), false); + + // if (gc == null + // || (gc != null && gc.getNumGeometries() > 0 && firstArrowGeo + // .intersects(gc))) { + // return new PgenRangeRecord(firstArrowGeo.getCoordinates()); + // } else { + // return new PgenRangeRecord(firstArrowGeo.getCoordinates()); + // } + + } + +} diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/PgenPreferences.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/PgenPreferences.java index 9d390be410..157c08a9ef 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/PgenPreferences.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/PgenPreferences.java @@ -36,8 +36,10 @@ import org.eclipse.ui.IWorkbenchPreferencePage; * 02/10/11 ? B. Yin Add maximum distance to be selected * 02/11 #405 J. Wu Added P_WORKING_DIR. * 05/11 ? J. Wu Added P_COMP_COORD - * 08/11 #335 J. Wu Added P_BASE_DIR - * 04/29 #977 S. Gilbert PGEN Database support + * 08/11 #335 J. Wu Added P_BASE_DIR + * 04/12 #977 S. Gilbert PGEN Database support + * 11/13 TTR752 J. Wu Added P_AUTOPLACE_TEXT + * 12/13 TTR776 J. Wu Added P_LAYER_MERGE * * * @@ -77,6 +79,13 @@ public class PgenPreferences extends FieldEditorPreferencePage implements // public final static String CED_COMP_COORD = "ced/0;0;0|KS+"; public final static String STR_COMP_COORD = "str/90;-97;0|19.00;-119.00;47.00;-56.00"; + // Preference to place text box automatically (CCFP); + public final static String P_AUTOPLACE_TEXT = "PGEN_AUTOPLACE_TEXT"; + + private BooleanFieldEditor autoPlaceText; + + public final static String P_LAYER_MERGE = "P_LAYER_MERGE"; + private BooleanFieldEditor layerLink; public PgenPreferences() { @@ -132,6 +141,21 @@ public class PgenPreferences extends FieldEditorPreferencePage implements getFieldEditorParent()); this.addField(projCombo); + autoPlaceText = new BooleanFieldEditor(P_AUTOPLACE_TEXT, + "&Text Auto Placement (where applicable)", + BooleanFieldEditor.DEFAULT, getFieldEditorParent()); + this.addField(autoPlaceText); + + ComboFieldEditor layerMerge = new ComboFieldEditor(P_LAYER_MERGE, + "&Default Action for PGEN Layer Merge:", new String[][] { + { "Take no action", "0" }, + { "Add all as new layers", "2" }, + { "Replace all like name layers", "3" }, + { "Merge all like name layers", "4" }, + { "Merge all into active layer", "5" }, }, + getFieldEditorParent()); + this.addField(layerMerge); + } /* @@ -170,7 +194,15 @@ public class PgenPreferences extends FieldEditorPreferencePage implements } } } else if (event.getSource() instanceof ComboFieldEditor) { - GfaClip.getInstance().updateGfaBoundsInGrid(); + String prefname = ((ComboFieldEditor) event.getSource()) + .getPreferenceName(); + if (prefname.equals(P_COMP_COORD)) { + GfaClip.getInstance().updateGfaBoundsInGrid(); + } else if (prefname.equals(P_LAYER_MERGE)) { + String nvalue = event.getNewValue().toString(); + Activator.getDefault().getPreferenceStore() + .setValue(prefname, Integer.parseInt(nvalue)); + } } else if (event.getSource() instanceof IntegerFieldEditor) { IntegerFieldEditor iField = (IntegerFieldEditor) event.getSource(); if (iField.getPreferenceName().equals(P_AUTO_FREQ)) { diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/PgenRangeRecord.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/PgenRangeRecord.java new file mode 100644 index 0000000000..bf2df8e557 --- /dev/null +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/PgenRangeRecord.java @@ -0,0 +1,323 @@ +/* + * gov.noaa.nws.ncep.ui.pgen + * + * November 2013 + * + * This code has been developed by the NCEP/SIB for use in the AWIPS2 system. + */ + +package gov.noaa.nws.ncep.ui.pgen; + +import java.util.ArrayList; +import java.util.List; + +import com.vividsolutions.jts.geom.Coordinate; + +/** + * Class used to hold the range record for a PGEN element. + * + *
+ * SOFTWARE HISTORY
+ * Date         Ticket#     Engineer    Description
+ * ------------ ----------  ----------- --------------------------
+ * 11/13                    J. Wu       Initial Creation.
+ * 
+ * 
+ * + * @author J. Wu + * @version 0.1 + */ +public class PgenRangeRecord { + + public static final double RANGE_OFFSET = 10; + + private List points; + + private List extent; + + private boolean closed; + + /** + * @param extent + * @param points + */ + public PgenRangeRecord() { + super(); + this.extent = new ArrayList(); + this.points = new ArrayList(); + this.closed = false; + } + + /** + * @param extent + * @param points + */ + public PgenRangeRecord(List points, boolean closed) { + super(); + this.points = new ArrayList(); + this.extent = new ArrayList(); + if (points != null && points.size() > 0) { + for (Coordinate cc : points) { + this.points.add(new Coordinate(cc.x, cc.y)); + } + + this.extent.addAll(buildRangeBox(this.points, RANGE_OFFSET)); + } + + this.closed = closed; + } + + /** + * @param extent + * @param points + */ + public PgenRangeRecord(Coordinate[] points, boolean closed) { + super(); + this.points = new ArrayList(); + this.extent = new ArrayList(); + if (points != null && points.length > 0) { + for (Coordinate cc : points) { + this.points.add(new Coordinate(cc.x, cc.y)); + } + + this.extent.addAll(buildRangeBox(this.points, RANGE_OFFSET)); + } + this.closed = closed; + } + + /** + * @param extent + * @param points + */ + public PgenRangeRecord(List extent, List points, + boolean closed) { + super(); + this.extent = extent; + this.points = points; + this.closed = closed; + } + + /** + * @return the extent + */ + public List getExtent() { + return extent; + } + + /** + * @return the extent + */ + public List getExtentWithoutBuffer() { + + List rngBox = new ArrayList(); + rngBox.add(new Coordinate(this.extent.get(0).x + RANGE_OFFSET, + this.extent.get(0).y - PgenRangeRecord.RANGE_OFFSET)); + rngBox.add(new Coordinate(this.extent.get(1).x - RANGE_OFFSET, + this.extent.get(1).y - RANGE_OFFSET)); + rngBox.add(new Coordinate(this.extent.get(2).x - RANGE_OFFSET, + this.extent.get(2).y + RANGE_OFFSET)); + rngBox.add(new Coordinate(this.extent.get(3).x + RANGE_OFFSET, + this.extent.get(3).y + RANGE_OFFSET)); + + return rngBox; + + } + + /** + * @param extent + * the extent to set + */ + public void setExtent(List extent) { + this.extent = extent; + } + + /** + * @param extent + * @param points + */ + public void setRange(List extent, List points, + boolean closed) { + this.extent = extent; + this.points = points; + this.closed = closed; + } + + /** + * @return the points + */ + public List getPoints() { + return points; + } + + /** + * @param points + * the points to set + */ + public void setPoints(List points) { + this.points = points; + } + + /** + * @return the closed flag + */ + public boolean isClosed() { + return closed; + } + + /** + * @param closed + * the closed to set + */ + public void setClosed(boolean closed) { + this.closed = closed; + } + + /** + * @param points + * the points to set + */ + public void setPointsOnly(List points, boolean closed) { + if (points != null) { + if (points != null && points.size() > 0) { + for (Coordinate cc : points) { + this.points.add(new Coordinate(cc.x, cc.y)); + } + + this.extent.addAll(buildRangeBox(this.points, RANGE_OFFSET)); + } + } + + this.closed = closed; + } + + /** + * @param extent + * @param points + */ + public static List buildRangeBox(List points, + double buffer) { + + List rangeBox = new ArrayList(); + + // Find the extent in x, y direction. + double max_x = points.get(0).x; + double max_y = points.get(0).y; + double min_x = points.get(0).x; + double min_y = points.get(0).y; + for (Coordinate pp : points) { + max_x = Math.max(max_x, pp.x); + min_x = Math.min(min_x, pp.x); + max_y = Math.max(max_y, pp.y); + min_y = Math.min(min_y, pp.y); + } + + // Add buffer + max_x += buffer; + min_x -= buffer; + max_y += buffer; + min_y -= buffer; + + // Build a rectangle (start from lower_left, go counter clockwise. + rangeBox.add(new Coordinate(min_x, max_y)); + rangeBox.add(new Coordinate(max_x, max_y)); + rangeBox.add(new Coordinate(max_x, min_y)); + rangeBox.add(new Coordinate(min_x, min_y)); + + return rangeBox; + } + + /** + * @return the max in x direction + */ + public double getMaxx() { + if (extent != null && extent.size() > 2) { + return Math.max(extent.get(0).x, extent.get(2).x); + } else { + return Double.NaN; + } + } + + /** + * @return the min in x direction + */ + public double getMinx() { + if (extent != null && extent.size() > 2) { + return Math.min(extent.get(0).x, extent.get(2).x); + } else { + return Double.NaN; + } + } + + /** + * @return the max in y direction + */ + public double getMaxy() { + if (extent != null && extent.size() > 2) { + return Math.max(extent.get(0).y, extent.get(2).y); + } else { + return Double.NaN; + } + } + + /** + * @return the min in y direction + */ + public double getMiny() { + if (extent != null && extent.size() > 2) { + return Math.min(extent.get(0).y, extent.get(2).y); + } else { + return Double.NaN; + } + } + + /** + * Check if this record is within another record. + */ + public boolean within(PgenRangeRecord rr) { + + return (this.getMaxx() < rr.getMaxx() && this.getMinx() > rr.getMinx() + && this.getMaxy() < rr.getMaxy() && this.getMiny() > rr + .getMiny()); + } + + /** + * Get the farest distance this record can placed within another record. + */ + public double maxExtention(PgenRangeRecord rr) { + double maxd = Double.MIN_VALUE; + for (int ii = 0; ii < extent.size(); ii++) { + maxd = Math.max( + maxd, + (extent.get(ii).x - rr.getExtent().get(ii).x) + * (extent.get(ii).x - rr.getExtent().get(ii).x) + + (extent.get(ii).y - rr.getExtent().get(ii).y) + * (extent.get(ii).y - rr.getExtent().get(ii).y)); + } + + return Math.sqrt(maxd); + } + + /** + * Deep copy + */ + public PgenRangeRecord copy() { + PgenRangeRecord newprr = new PgenRangeRecord(); + if (this.points != null && this.points.size() > 0) { + for (Coordinate cc : this.points) { + newprr.getPoints().add(new Coordinate(cc.x, cc.y)); + } + } + + if (this.extent != null && this.extent.size() > 0) { + for (Coordinate cc : this.extent) { + newprr.getExtent().add(new Coordinate(cc.x, cc.y)); + } + } + + newprr.closed = closed; + + return newprr; + + } + +} diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/PgenUtil.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/PgenUtil.java index 2c128cd247..deb52c3f9e 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/PgenUtil.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/PgenUtil.java @@ -61,16 +61,7 @@ import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.VerifyEvent; -import org.eclipse.swt.events.VerifyListener; -import org.eclipse.swt.layout.FormAttachment; -import org.eclipse.swt.layout.FormData; -import org.eclipse.swt.layout.FormLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IEditorInput; @@ -119,1619 +110,1779 @@ import com.vividsolutions.jts.linearref.LocationIndexedLine; * ------------ ---------- ----------- -------------------------- * * 04/22/09 #99 Greg Hull Moved some methods to NmapUiUtils - * 05/15/09 #116 B. Yin Added validateLatLonTextField - * 05/15/09 #116 B. Yin Added text/symbol drawing mode methods - * 08/03/09 #116 B. Yin changed validateLatLonTextField - * to validateNumberTextField + * 05/15/09 #116 B. Yin Added validateLatLonTextField + * 05/15/09 #116 B. Yin Added text/symbol drawing mode methods + * 08/03/09 #116 B. Yin changed validateLatLonTextField + * to validateNumberTextField * 09/30/09 #169 Greg Hull NCMapEditor - * 10/15/09 #160 G. Zhang INTL Sigmet LatLonPre/Post pend - * 12/10/09 #167 J. Wu Added contours drawing method - * 05/04/10 #267 B. Yin Added a method to load 'SetCont' tool for outlook - * 03/10 #223 M.Laryukhin Added Gfa - * 04/10 #165 G.Zhang Modified LatLonPre/Post pend formatting - * 07/10 #215 J. Wu Added calendarToGempakDattim() - * 09/10 #63 J. Wu Added CURRENT_WORKING_DIRCTORY - * 09/10 #304 B. Yin Added a method to load a tool editing LabeledLine + * 10/15/09 #160 G. Zhang INTL Sigmet LatLonPre/Post pend + * 12/10/09 #167 J. Wu Added contours drawing method + * 05/04/10 #267 B. Yin Added a method to load 'SetCont' tool for outlook + * 03/10 #223 M.Laryukhin Added Gfa + * 04/10 #165 G.Zhang Modified LatLonPre/Post pend formatting + * 07/10 #215 J. Wu Added calendarToGempakDattim() + * 09/10 #63 J. Wu Added CURRENT_WORKING_DIRCTORY + * 09/10 #304 B. Yin Added a method to load a tool editing LabeledLine * 10/10 #310 S. Gilbert Added PgenMode - * 02/11 #405 J. Wu Set CURRENT_WORKING_DIRCTORY to user-defined directory - * in the PGEN preference page - * 03/11 J. Wu Added getSphPolyArea() && getPolyArea() - * 05/11 J. Wu Added methods to setup/covert between lat/lon - * and a custom coordinate. - * 08/11 J. Wu Added getPgenOprDirectory() + * 02/11 #405 J. Wu Set CURRENT_WORKING_DIRCTORY to user-defined directory + * in the PGEN preference page + * 03/11 J. Wu Added getSphPolyArea() && getPolyArea() + * 05/11 J. Wu Added methods to setup/covert between lat/lon + * and a custom coordinate. + * 08/11 J. Wu Added getPgenOprDirectory() * 03/12 #611 S. Gurung Added computePoint() - * 03/12 #704 B. Yin Move applyStylesheet() here from ProdType - * 05/12 #708 J. Wu Add methods to retrieve current data frame time. - * 05/12 #769 B. Yin Moved the creation of UTC time from TCA dialog to here. + * 03/12 #704 B. Yin Move applyStylesheet() here from ProdType + * 05/12 #708 J. Wu Add methods to retrieve current data frame time. + * 05/12 #769 B. Yin Moved the creation of UTC time from TCA dialog to here. * 03/13 #972 G. Hull add isNatlCntrsEditor() - * 03/13 #927 B. Yin Moved isUnmovable from the PgenSelectTool class. - * 06/13 #1000 J. Wu Added utility function writePgenFile(). - * 07/26 TTR J. Wu Extract "DEL_PART" in DeletePartCommand into deleteLinePart(). + * 03/13 #927 B. Yin Moved isUnmovable from the PgenSelectTool class. + * 06/13 #1000 J. Wu Added utility function writePgenFile(). + * 07/26 TTR J. Wu Extract "DEL_PART" in DeletePartCommand into deleteLinePart(). + * 12/13 #1089 B. Yin Removed the UTC time functions to a new class. + * 12/13 #1091 J. Wu Added getLayerMergeOption() * * * - * @author + * @author * @version 1 */ public class PgenUtil { - - /** - * SINGLE mode is used to display and interact with the same PGEN data on every Editor, while - * MULTIPLE mode allows users to have a separate PGEN instance in each Editor. - * @author sgilbert - * - */ - public static enum PgenMode { SINGLE, MULTIPLE }; - - private static PgenResourceData rscData = null; - - /* - * A computational coordinate system allowing conversion between lat/lon and - * a customized 800x600 grid coordinate via PgenPreference (projection, garea). - */ - private static CoordinateTransform coordTrans = null; - - /* - * Pgen Palette view ID is also defined in plugin.xml. - */ - public static final String VIEW_ID = "gov.noaa.nws.ncep.ui.PGEN"; - - /* - * Statute miles to meters - */ - public static final float SM2M = 1609.34f; - - /* - * Nautical miles to meters - */ - public static final float NM2M = 1852.0f; - - /* - * Prefix and postfix for PGEN temporary recovery files. - */ - public static final String RECOVERY_PREFIX = "pgen_session."; - public static final String RECOVERY_POSTFIX = ".tmp"; - public static final String PGEN_PROD_DIR = "prod"; - public static final String PGEN_XML_DIR = "xml"; - public static final String PGEN_TEXT_PROD_DIR = "text"; - - /* - * Format string patterns for Lat/Lon Pre/Postpend - */ - public static final String FOUR_ZERO = "0000"; - public static final String FIVE_ZERO = "00000"; - - //Default CAVE window title string - public static final String CaveTitle = "CAVE"; /** - * Check the given editor for a PgenResource. If editor is null then the current Nmap Editor is used. If found, return it. + * SINGLE mode is used to display and interact with the same PGEN data on + * every Editor, while MULTIPLE mode allows users to have a separate PGEN + * instance in each Editor. + * + * @author sgilbert + * + */ + public static enum PgenMode { + SINGLE, MULTIPLE + }; + + private static PgenResourceData rscData = null; + + /* + * A computational coordinate system allowing conversion between lat/lon and + * a customized 800x600 grid coordinate via PgenPreference (projection, + * garea). + */ + private static CoordinateTransform coordTrans = null; + + /* + * Pgen Palette view ID is also defined in plugin.xml. + */ + public static final String VIEW_ID = "gov.noaa.nws.ncep.ui.PGEN"; + + /* + * Statute miles to meters + */ + public static final float SM2M = 1609.34f; + + /* + * Nautical miles to meters + */ + public static final float NM2M = 1852.0f; + + /* + * Prefix and postfix for PGEN temporary recovery files. + */ + public static final String RECOVERY_PREFIX = "pgen_session."; + + public static final String RECOVERY_POSTFIX = ".tmp"; + + public static final String PGEN_PROD_DIR = "prod"; + + public static final String PGEN_XML_DIR = "xml"; + + public static final String PGEN_TEXT_PROD_DIR = "text"; + + /* + * Format string patterns for Lat/Lon Pre/Postpend + */ + public static final String FOUR_ZERO = "0000"; + + public static final String FIVE_ZERO = "00000"; + + // Default CAVE window title string + // public static String caveTitle = "CAVE"; + public static String caveTitle = null; + + /** + * Check the given editor for a PgenResource. If editor is null then the + * current Nmap Editor is used. If found, return it. + * * @param editor * @return reference to a PgenResource */ public static final PgenResource findPgenResource(AbstractEditor editor) { -// return (PgenResource)NmapUiUtils.findResource( PgenResource.class, editor ); - return (PgenResource)findResource( PgenResource.class, editor ); + // return (PgenResource)NmapUiUtils.findResource( PgenResource.class, + // editor ); + return (PgenResource) findResource(PgenResource.class, editor); } /** * Check the given display pane for a PgenResource. If found, return it. + * * @param pane * @return reference to a PgenResource */ public static final PgenResource findPgenResourceInPane(IDisplayPane pane) { - - if( pane == null ) return null; - ResourceList rscList = pane.getDescriptor().getResourceList(); + if (pane == null) + return null; - for( ResourcePair rp : rscList ) { - AbstractVizResource rsc = rp.getResource(); + ResourceList rscList = pane.getDescriptor().getResourceList(); - if( rsc.getClass() == PgenResource.class ) { - return (PgenResource)rsc; - } - } + for (ResourcePair rp : rscList) { + AbstractVizResource rsc = rp.getResource(); - return null; + if (rsc.getClass() == PgenResource.class) { + return (PgenResource) rsc; + } + } + + return null; } - /** - * set current ModalTool to Selecting mode - */ + /** + * set current ModalTool to Selecting mode + */ public static final void setSelectingMode() { - - setCommandMode("gov.noaa.nws.ncep.ui.pgen.rsc.PgenSelect"); + + setCommandMode("gov.noaa.nws.ncep.ui.pgen.rsc.PgenSelect"); } - - /** - * set current ModalTool to "MultiSelect" mode - */ + + /** + * set current ModalTool to "MultiSelect" mode + */ public static final void setMultiSelectMode() { - - setCommandMode("gov.noaa.nws.ncep.ui.pgen.rsc.PgenMultiSelect"); + + setCommandMode("gov.noaa.nws.ncep.ui.pgen.rsc.PgenMultiSelect"); } - - /** - * set current ModalTool to "DelectObj" mode - */ + + /** + * set current ModalTool to "DelectObj" mode + */ public static final void setDelObjMode() { - setCommandMode("gov.noaa.nws.ncep.ui.pgen.rsc.PgenDeleteObj"); - } - - private static final void setCommandMode(String command){ + setCommandMode("gov.noaa.nws.ncep.ui.pgen.rsc.PgenDeleteObj"); + } + + private static final void setCommandMode(String command) { IEditorPart part = EditorUtil.getActiveEditor(); - - if ( part == null ) return; - - ICommandService service = (ICommandService) part.getSite().getService( ICommandService.class ); + + if (part == null) + return; + + ICommandService service = (ICommandService) part.getSite().getService( + ICommandService.class); Command cmd = service.getCommand(command); if (cmd != null) { - - try { - HashMap params = new HashMap(); - params.put("editor", part); - ExecutionEvent exec = new ExecutionEvent(cmd, params, null, null); - cmd.executeWithChecks(exec); + try { + HashMap params = new HashMap(); + params.put("editor", part); + ExecutionEvent exec = new ExecutionEvent(cmd, params, null, + null); - } catch (Exception e) { - - e.printStackTrace(); - } + cmd.executeWithChecks(exec); + + } catch (Exception e) { + + e.printStackTrace(); + } } } - + /** - * Set the drawing mode to symbol. - * When drawing a symbol with a text, this method is called after the text is finished - * to return to the symbol-drawing mode. + * Set the drawing mode to symbol. When drawing a symbol with a text, this + * method is called after the text is finished to return to the + * symbol-drawing mode. + * * @param symbolType */ - public static final void setDrawingSymbolMode(String symbolCat, String symbolType, - boolean usePrevColor, AbstractDrawableComponent adc) { + public static final void setDrawingSymbolMode(String symbolCat, + String symbolType, boolean usePrevColor, + AbstractDrawableComponent adc) { IEditorPart part = EditorUtil.getActiveEditor(); - ICommandService service = (ICommandService) part.getSite().getService( ICommandService.class ); - Command cmd = service.getCommand("gov.noaa.nws.ncep.ui.pgen.rsc.PgenSingleDraw"); + ICommandService service = (ICommandService) part.getSite().getService( + ICommandService.class); + Command cmd = service + .getCommand("gov.noaa.nws.ncep.ui.pgen.rsc.PgenSingleDraw"); if (cmd != null) { - - try { - HashMap params = new HashMap(); - params.put("editor", part); - params.put("name", symbolType); - params.put("className", symbolCat); - params.put("usePrevColor", new Boolean(usePrevColor).toString()); - ExecutionEvent exec = new ExecutionEvent(cmd, params, adc, null); + try { + HashMap params = new HashMap(); + params.put("editor", part); + params.put("name", symbolType); + params.put("className", symbolCat); + params.put("usePrevColor", new Boolean(usePrevColor).toString()); - cmd.executeWithChecks(exec); + ExecutionEvent exec = new ExecutionEvent(cmd, params, adc, null); - } catch (Exception e) { - - e.printStackTrace(); - } + cmd.executeWithChecks(exec); + + } catch (Exception e) { + + e.printStackTrace(); + } } } - + /** * Set the drawing mode to general text. - * @param addLabel - whether to add the text to a symbol - * @param symbolType - used to return to the symbol-drawing mode - * @param useSymbolColor - whether to use symbol's color + * + * @param addLabel + * - whether to add the text to a symbol + * @param symbolType + * - used to return to the symbol-drawing mode + * @param useSymbolColor + * - whether to use symbol's color */ - public static final void setDrawingTextMode(boolean addLabel, boolean usePrevColor, String defaultTxt, - AbstractDrawableComponent adc) { + public static final void setDrawingTextMode(boolean addLabel, + boolean usePrevColor, String defaultTxt, + AbstractDrawableComponent adc) { IEditorPart part = EditorUtil.getActiveEditor(); - ICommandService service = (ICommandService) part.getSite().getService( ICommandService.class ); - Command cmd = service.getCommand("gov.noaa.nws.ncep.ui.pgen.rsc.PgenTextDraw"); + ICommandService service = (ICommandService) part.getSite().getService( + ICommandService.class); + Command cmd = service + .getCommand("gov.noaa.nws.ncep.ui.pgen.rsc.PgenTextDraw"); if (cmd != null) { - - try { - HashMap params = new HashMap(); - params.put("editor", part); - params.put("name", "General Text"); - params.put("className", "Text"); - params.put("addLabel", new Boolean(addLabel).toString()); - params.put("usePrevColor", new Boolean(usePrevColor).toString()); - params.put("defaultTxt", defaultTxt); - ExecutionEvent exec = new ExecutionEvent(cmd, params, adc, null); + try { + HashMap params = new HashMap(); + params.put("editor", part); + params.put("name", "General Text"); + params.put("className", "Text"); + params.put("addLabel", new Boolean(addLabel).toString()); + params.put("usePrevColor", new Boolean(usePrevColor).toString()); + params.put("defaultTxt", defaultTxt); - cmd.executeWithChecks(exec); + ExecutionEvent exec = new ExecutionEvent(cmd, params, adc, null); - } catch (Exception e) { - - e.printStackTrace(); - } + cmd.executeWithChecks(exec); + + } catch (Exception e) { + + e.printStackTrace(); + } } } - + /** * Set the drawing mode to drawing the Gfa text. * * @param lastUsedGfa */ public static final void setDrawingGfaTextMode(Gfa lastUsedGfa) { - IEditorPart part = EditorUtil.getActiveEditor(); - ICommandService service = (ICommandService) part.getSite().getService(ICommandService.class); - Command cmd = service.getCommand("gov.noaa.nws.ncep.ui.pgen.rsc.PgenGfaDraw"); + IEditorPart part = EditorUtil.getActiveEditor(); + ICommandService service = (ICommandService) part.getSite().getService( + ICommandService.class); + Command cmd = service + .getCommand("gov.noaa.nws.ncep.ui.pgen.rsc.PgenGfaDraw"); - if (cmd != null) { + if (cmd != null) { - try { - HashMap params = new HashMap(); - params.put("editor", part); - params.put("name", "GFA"); - params.put("className", "MET"); - StringBuilder sb = new StringBuilder(""); - - for (String s : lastUsedGfa.getString()) { - sb.append(s).append(",,"); // ,, delimited - } - if (lastUsedGfa.getString() != null && lastUsedGfa.getString().length > 0) { - sb.setLength(sb.length() - 2); - } - params.put("startGfaText", "true"); - params.put("lastUsedGfa", lastUsedGfa); + try { + HashMap params = new HashMap(); + params.put("editor", part); + params.put("name", "GFA"); + params.put("className", "MET"); + StringBuilder sb = new StringBuilder(""); - ExecutionEvent exec = new ExecutionEvent(cmd, params, null, null); + for (String s : lastUsedGfa.getString()) { + sb.append(s).append(",,"); // ,, delimited + } + if (lastUsedGfa.getString() != null + && lastUsedGfa.getString().length > 0) { + sb.setLength(sb.length() - 2); + } + params.put("startGfaText", "true"); + params.put("lastUsedGfa", lastUsedGfa); - cmd.executeWithChecks(exec); + ExecutionEvent exec = new ExecutionEvent(cmd, params, null, + null); - } catch (Exception e) { + cmd.executeWithChecks(exec); + + } catch (Exception e) { + + e.printStackTrace(); + } + } + } - e.printStackTrace(); - } - } - } - /** * Set the drawing mode to watch status line. */ public static final void setDrawingStatusLineMode(WatchBox wb) { IEditorPart part = EditorUtil.getActiveEditor(); - ICommandService service = (ICommandService) part.getSite().getService( ICommandService.class ); - Command cmd = service.getCommand("gov.noaa.nws.ncep.ui.pgen.rsc.PgenWatchStatusLineDraw"); + ICommandService service = (ICommandService) part.getSite().getService( + ICommandService.class); + Command cmd = service + .getCommand("gov.noaa.nws.ncep.ui.pgen.rsc.PgenWatchStatusLineDraw"); if (cmd != null) { - - try { - HashMap params = new HashMap(); - params.put("editor", part); - params.put("name", "STATUS_LINE"); - params.put("className", "Watch"); - ExecutionEvent exec = new ExecutionEvent(cmd, params, wb, null); + try { + HashMap params = new HashMap(); + params.put("editor", part); + params.put("name", "STATUS_LINE"); + params.put("className", "Watch"); - cmd.executeWithChecks(exec); + ExecutionEvent exec = new ExecutionEvent(cmd, params, wb, null); - } catch (Exception e) { - - e.printStackTrace(); - } + cmd.executeWithChecks(exec); + + } catch (Exception e) { + + e.printStackTrace(); + } } } - + /** * Set the drawing mode to watch status line. */ public static final void setDrawingFrontMode(Line front) { IEditorPart part = EditorUtil.getActiveEditor(); - ICommandService service = (ICommandService) part.getSite().getService( ICommandService.class ); - Command cmd = service.getCommand("gov.noaa.nws.ncep.ui.pgen.rsc.PgenMultiDraw"); + ICommandService service = (ICommandService) part.getSite().getService( + ICommandService.class); + Command cmd = service + .getCommand("gov.noaa.nws.ncep.ui.pgen.rsc.PgenMultiDraw"); if (cmd != null) { - - try { - HashMap params = new HashMap(); - params.put("editor", part); - params.put("name", front.getPgenType()); - params.put("className", front.getPgenCategory()); - ExecutionEvent exec = new ExecutionEvent(cmd, params, front, null); + try { + HashMap params = new HashMap(); + params.put("editor", part); + params.put("name", front.getPgenType()); + params.put("className", front.getPgenCategory()); - cmd.executeWithChecks(exec); + ExecutionEvent exec = new ExecutionEvent(cmd, params, front, + null); - } catch (Exception e) { - - e.printStackTrace(); - } + cmd.executeWithChecks(exec); + + } catch (Exception e) { + + e.printStackTrace(); + } } } - + /** * Load the 'Set continue Line' tool for outlooks. */ public static final void loadOutlookSetContTool(Outlook otlk) { IEditorPart part = EditorUtil.getActiveEditor(); - ICommandService service = (ICommandService) part.getSite().getService( ICommandService.class ); - Command cmd = service.getCommand("gov.noaa.nws.ncep.ui.pgen.rsc.PgenOutlookSetCont"); + ICommandService service = (ICommandService) part.getSite().getService( + ICommandService.class); + Command cmd = service + .getCommand("gov.noaa.nws.ncep.ui.pgen.rsc.PgenOutlookSetCont"); if (cmd != null) { - - try { - HashMap params = new HashMap(); - params.put("editor", part); - params.put("name", "Outlook"); - params.put("className", ""); - - ExecutionEvent exec = new ExecutionEvent(cmd, params, otlk, null); - cmd.executeWithChecks(exec); + try { + HashMap params = new HashMap(); + params.put("editor", part); + params.put("name", "Outlook"); + params.put("className", ""); - } catch (Exception e) { - - e.printStackTrace(); - } + ExecutionEvent exec = new ExecutionEvent(cmd, params, otlk, + null); + + cmd.executeWithChecks(exec); + + } catch (Exception e) { + + e.printStackTrace(); + } } } - + /** - * Load the TCA drawing tool. - * @param de TCAElement to load into the TcaAttrDlg when the tool is loaded + * Load the TCA drawing tool. + * + * @param de + * TCAElement to load into the TcaAttrDlg when the tool is loaded */ - public static final void loadTCATool( DrawableElement de) { + public static final void loadTCATool(DrawableElement de) { IEditorPart part = EditorUtil.getActiveEditor(); - ICommandService service = (ICommandService) part.getSite().getService( ICommandService.class ); + ICommandService service = (ICommandService) part.getSite().getService( + ICommandService.class); Command cmd = service.getCommand("gov.noaa.nws.ncep.ui.pgen.tca"); if (cmd != null && de instanceof TCAElement) { - - try { - HashMap params = new HashMap(); - params.put("editor", part); - params.put("name", de.getPgenType() ); - params.put("className", de.getPgenCategory()); - - ExecutionEvent exec = new ExecutionEvent(cmd, params, de, null); - cmd.executeWithChecks(exec); + try { + HashMap params = new HashMap(); + params.put("editor", part); + params.put("name", de.getPgenType()); + params.put("className", de.getPgenCategory()); - } catch (Exception e) { - - e.printStackTrace(); - } + ExecutionEvent exec = new ExecutionEvent(cmd, params, de, null); + + cmd.executeWithChecks(exec); + + } catch (Exception e) { + + e.printStackTrace(); + } } } - + /** - * Load the watch box modifying tool. - * @param de WatchBox to load when the tool is loaded + * Load the watch box modifying tool. + * + * @param de + * WatchBox to load when the tool is loaded */ - public static final void loadWatchBoxModifyTool( DrawableElement de) { + public static final void loadWatchBoxModifyTool(DrawableElement de) { IEditorPart part = EditorUtil.getActiveEditor(); - ICommandService service = (ICommandService) part.getSite().getService( ICommandService.class ); - Command cmd = service.getCommand("gov.noaa.nws.ncep.ui.pgen.rsc.PgenWatchBoxModify"); + ICommandService service = (ICommandService) part.getSite().getService( + ICommandService.class); + Command cmd = service + .getCommand("gov.noaa.nws.ncep.ui.pgen.rsc.PgenWatchBoxModify"); if (cmd != null && de instanceof WatchBox) { - - try { - HashMap params = new HashMap(); - params.put("editor", part); - params.put("name", de.getPgenType() ); - params.put("className", de.getPgenCategory()); - - ExecutionEvent exec = new ExecutionEvent(cmd, params, de, null); - cmd.executeWithChecks(exec); + try { + HashMap params = new HashMap(); + params.put("editor", part); + params.put("name", de.getPgenType()); + params.put("className", de.getPgenCategory()); - } catch (Exception e) { - - e.printStackTrace(); - } + ExecutionEvent exec = new ExecutionEvent(cmd, params, de, null); + + cmd.executeWithChecks(exec); + + } catch (Exception e) { + + e.printStackTrace(); + } } } - + /** - * Load the LabeledLine modifying tool. - * @param ll - LabeledLine to edit when the tool is loaded + * Load the LabeledLine modifying tool. + * + * @param ll + * - LabeledLine to edit when the tool is loaded */ - public static final void loadLabeledLineModifyTool( LabeledLine ll ) { + public static final void loadLabeledLineModifyTool(LabeledLine ll) { IEditorPart part = EditorUtil.getActiveEditor(); - ICommandService service = (ICommandService) part.getSite().getService( ICommandService.class ); - Command cmd = service.getCommand("gov.noaa.nws.ncep.ui.pgen.rsc.PgenLabeledLineModify"); + ICommandService service = (ICommandService) part.getSite().getService( + ICommandService.class); + Command cmd = service + .getCommand("gov.noaa.nws.ncep.ui.pgen.rsc.PgenLabeledLineModify"); - if (cmd != null ) { - - try { - HashMap params = new HashMap(); - params.put("editor", part); - params.put("name", ll.getPgenType() ); - params.put("className", ll.getPgenCategory()); - - if("CCFP_SIGMET".equals(ll.getPgenType()) ){ - params.put("type", ((gov.noaa.nws.ncep.ui.pgen.sigmet.Ccfp)ll).getSigmet().getType() ); - } - - ExecutionEvent exec = new ExecutionEvent(cmd, params, ll, null); + if (cmd != null) { - cmd.executeWithChecks(exec); + try { + HashMap params = new HashMap(); + params.put("editor", part); + params.put("name", ll.getPgenType()); + params.put("className", ll.getPgenCategory()); - } catch (Exception e) { - - e.printStackTrace(); - } + if ("CCFP_SIGMET".equals(ll.getPgenType())) { + params.put("type", + ((gov.noaa.nws.ncep.ui.pgen.sigmet.Ccfp) ll) + .getSigmet().getType()); + } + + ExecutionEvent exec = new ExecutionEvent(cmd, params, ll, null); + + cmd.executeWithChecks(exec); + + } catch (Exception e) { + + e.printStackTrace(); + } } } + /** - * Load the LabeledLine modifying tool. - * @param ll - LabeledLine to edit when the tool is loaded + * Load the LabeledLine modifying tool. + * + * @param ll + * - LabeledLine to edit when the tool is loaded */ - public static final void loadTcmTool( DrawableElement elem ) { + public static final void loadTcmTool(DrawableElement elem) { IEditorPart part = EditorUtil.getActiveEditor(); - ICommandService service = (ICommandService) part.getSite().getService( ICommandService.class ); - Command cmd = service.getCommand("gov.noaa.nws.ncep.ui.pgen.rsc.PgenTCMtool"); + ICommandService service = (ICommandService) part.getSite().getService( + ICommandService.class); + Command cmd = service + .getCommand("gov.noaa.nws.ncep.ui.pgen.rsc.PgenTCMtool"); - if (cmd != null ) { - - try { - HashMap params = new HashMap(); - params.put("editor", part); - params.put("name", elem.getPgenType() ); - params.put("className", elem.getPgenCategory()); - - ExecutionEvent exec = new ExecutionEvent(cmd, params, elem, null); + if (cmd != null) { - cmd.executeWithChecks(exec); + try { + HashMap params = new HashMap(); + params.put("editor", part); + params.put("name", elem.getPgenType()); + params.put("className", elem.getPgenCategory()); - } catch (Exception e) { - - e.printStackTrace(); - } + ExecutionEvent exec = new ExecutionEvent(cmd, params, elem, + null); + + cmd.executeWithChecks(exec); + + } catch (Exception e) { + + e.printStackTrace(); + } } - } + } + /** - * Load the outlook drawing tool. + * Load the outlook drawing tool. */ public static final void loadOutlookDrawingTool() { IEditorPart part = EditorUtil.getActiveEditor(); - ICommandService service = (ICommandService) part.getSite().getService( ICommandService.class ); - Command cmd = service.getCommand("gov.noaa.nws.ncep.ui.pgen.outlookDraw"); + ICommandService service = (ICommandService) part.getSite().getService( + ICommandService.class); + Command cmd = service + .getCommand("gov.noaa.nws.ncep.ui.pgen.outlookDraw"); - if (cmd != null ) { - - try { - HashMap params = new HashMap(); - params.put("editor", part); - params.put("name", "Outlook" ); - params.put("className", ""); - - ExecutionEvent exec = new ExecutionEvent(cmd, params, null, null); + if (cmd != null) { - cmd.executeWithChecks(exec); + try { + HashMap params = new HashMap(); + params.put("editor", part); + params.put("name", "Outlook"); + params.put("className", ""); - } catch (Exception e) { - - e.printStackTrace(); - } + ExecutionEvent exec = new ExecutionEvent(cmd, params, null, + null); + + cmd.executeWithChecks(exec); + + } catch (Exception e) { + + e.printStackTrace(); + } } - } - + } + /** * Create a new PgenResource and add it to the current editor. + * * @return the PgenResource */ public static final PgenResource createNewResource() { - PgenResource drawingLayer = null; -// NCMapEditor editor = NmapUiUtils.getActiveNatlCntrsEditor(); - AbstractEditor editor = getActiveEditor(); - if(editor != null){ - try { - switch ( getPgenMode() ) { - case SINGLE: - /* - * Use existing (or new) PgenResourceData to construct new Resources to - * add to each Pane's ResourceList - */ - if ( rscData == null ) { - rscData = new PgenResourceData(); - } - for ( IDisplayPane pane : editor.getDisplayPanes() ) { - IDescriptor idesc = pane.getDescriptor(); - if ( idesc.getResourceList().size() > 0 ) { - drawingLayer = rscData.construct(new LoadProperties(), idesc); - //System.out.println("NEW pgen resource: "+drawingLayer); - idesc.getResourceList().add( drawingLayer ); - idesc.getResourceList().addPreRemoveListener( drawingLayer ); - drawingLayer.init( pane.getTarget()); - } - } - break; - case MULTIPLE: - /* - * Add a new PgenResourceData and Resource to active Pane's ResourceList - */ - IMapDescriptor desc = (IMapDescriptor) editor.getActiveDisplayPane().getRenderableDisplay().getDescriptor(); - drawingLayer = new PgenResourceData().construct(new LoadProperties(), desc); - desc.getResourceList().add( drawingLayer ); - desc.getResourceList().addPreRemoveListener( drawingLayer ); - drawingLayer.init( editor.getActiveDisplayPane().getTarget()); - break; - } + PgenResource drawingLayer = null; + // NCMapEditor editor = NmapUiUtils.getActiveNatlCntrsEditor(); + AbstractEditor editor = getActiveEditor(); + if (editor != null) { + try { + switch (getPgenMode()) { + case SINGLE: + /* + * Use existing (or new) PgenResourceData to construct new + * Resources to add to each Pane's ResourceList + */ + if (rscData == null) { + rscData = new PgenResourceData(); + } + for (IDisplayPane pane : editor.getDisplayPanes()) { + IDescriptor idesc = pane.getDescriptor(); + if (idesc.getResourceList().size() > 0) { + drawingLayer = rscData.construct( + new LoadProperties(), idesc); + // System.out.println("NEW pgen resource: "+drawingLayer); + idesc.getResourceList().add(drawingLayer); + idesc.getResourceList().addPreRemoveListener( + drawingLayer); + drawingLayer.init(pane.getTarget()); + } + } + break; + case MULTIPLE: + /* + * Add a new PgenResourceData and Resource to active Pane's + * ResourceList + */ + IMapDescriptor desc = (IMapDescriptor) editor + .getActiveDisplayPane().getRenderableDisplay() + .getDescriptor(); + drawingLayer = new PgenResourceData().construct( + new LoadProperties(), desc); + desc.getResourceList().add(drawingLayer); + desc.getResourceList().addPreRemoveListener(drawingLayer); + drawingLayer + .init(editor.getActiveDisplayPane().getTarget()); + break; + } - } catch (Exception e) { - e.printStackTrace(); - } + } catch (Exception e) { + e.printStackTrace(); + } } return drawingLayer; } - + /* - * Refresh the PGEN drawing editor. - */ - public static final void refresh() { -// if( NmapUiUtils.getActiveNatlCntrsEditor() != null ) -// NmapUiUtils.getActiveNatlCntrsEditor().refresh(); - if( getActiveEditor() != null ) - getActiveEditor().refresh(); + * Refresh the PGEN drawing editor. + */ + public static final void refresh() { + // if( NmapUiUtils.getActiveNatlCntrsEditor() != null ) + // NmapUiUtils.getActiveNatlCntrsEditor().refresh(); + if (getActiveEditor() != null) + getActiveEditor().refresh(); } /** - * This method checks if the content in a text filed is a valid double. It - * should be called in a verify-listener of the text field. + * This method checks if the content in a text filed is a valid double. It + * should be called in a verify-listener of the text field. * - * @param event - Event that activates the listener. - * @return - true if the text is a valid double. + * @param event + * - Event that activates the listener. + * @return - true if the text is a valid double. */ - public static final boolean validateNumberTextField( Event event ){ - - boolean valid = false; - - /* - * Only validate text field - */ - if ( event.widget instanceof Text ){ - - Text latLonText = (Text)event.widget; - StringBuffer str = new StringBuffer(latLonText.getText()); - - // if the event is from key press, insert the text, - // otherwise, replace the text - if ( event.keyCode != 0 ){ - str.insert(event.start,event.text); - } - - try { - Double.valueOf( new String(str) ); - valid = true; - } - catch (NumberFormatException e){ - valid = false; - } - - /* - * The first character can be '-' or '.' - */ - if ( !valid && ((( event.start == 0 ) && (event.character =='-' || event.character == '.' ) )|| - (( str.length() == 1) && (str.charAt(0)=='-' || str.charAt(0)=='.')))){ - valid= true; - } - else if ( valid && - ( event.character == 'd' || event.character == 'D' || - event.character == 'f' || event.character == 'F' || - event.character == 'e' || event.character == 'E' )) { - /* - * 'D/d', 'F/f', and 'E/e' can be in or at the end of a Java number, but we - * do not want them in lat/lon - */ - valid = false; - } - } - - return valid; - + public static final boolean validateNumberTextField(Event event) { + + boolean valid = false; + + /* + * Only validate text field + */ + if (event.widget instanceof Text) { + + Text latLonText = (Text) event.widget; + StringBuffer str = new StringBuffer(latLonText.getText()); + + // if the event is from key press, insert the text, + // otherwise, replace the text + if (event.keyCode != 0) { + str.insert(event.start, event.text); + } + + try { + Double.valueOf(new String(str)); + valid = true; + } catch (NumberFormatException e) { + valid = false; + } + + /* + * The first character can be '-' or '.' + */ + if (!valid + && (((event.start == 0) && (event.character == '-' || event.character == '.')) || ((str + .length() == 1) && (str.charAt(0) == '-' || str + .charAt(0) == '.')))) { + valid = true; + } else if (valid + && (event.character == 'd' || event.character == 'D' + || event.character == 'f' || event.character == 'F' + || event.character == 'e' || event.character == 'E')) { + /* + * 'D/d', 'F/f', and 'E/e' can be in or at the end of a Java + * number, but we do not want them in lat/lon + */ + valid = false; + } + } + + return valid; + } - - public static boolean validatePositiveInteger( VerifyEvent ve ) { - - boolean stat = false; - - if ( ve.widget instanceof Text ) { - Text advnum = (Text)ve.widget; - StringBuffer str = new StringBuffer(advnum.getText()); - str.replace(ve.start, ve.end, ve.text); - if ( str.toString().isEmpty() ) return true; - - try { - if ( Integer.parseInt(str.toString()) > 0 ) return true; - } - catch ( NumberFormatException nfe ) { - return false; - } - - return false; - } - - return stat; - } - /** - * Converts an array of lat/lons to pixel coordinates - * @param pts An array of points in lat/lon coordinates - * @param mapDescriptor Descriptoer to use for world to pixel transform - * @return The array of points in pixel coordinates - */ - public static final double[][] latlonToPixel( Coordinate[] pts, IMapDescriptor mapDescriptor ) { - double[] point = new double[3]; - double[][] pixels = new double[pts.length][3]; + public static boolean validatePositiveInteger(VerifyEvent ve) { - for ( int i=0; i< pts.length; i++ ) { - point[0] = pts[i].x; - point[1] = pts[i].y; - point[2] = 0.0; - pixels[i] = mapDescriptor.worldToPixel(point); - } - - return pixels; - } - - /** - * Gets the current site id from the localization Manager - * @return - */ - public static String getCurrentOffice() { - - String wfo = LocalizationManager.getInstance().getCurrentSite(); - if ( wfo.equalsIgnoreCase("none") || wfo.isEmpty() ) wfo = new String("KNHC"); + boolean stat = false; + + if (ve.widget instanceof Text) { + Text advnum = (Text) ve.widget; + StringBuffer str = new StringBuffer(advnum.getText()); + str.replace(ve.start, ve.end, ve.text); + + if (str.toString().isEmpty()) + return true; + + try { + if (Integer.parseInt(str.toString()) > 0) + return true; + } catch (NumberFormatException nfe) { + return false; + } + + return false; + } + + return stat; + } - return wfo; - } - - /** - * Converts an array of lat/lons to text; the format is "N","S","E", and/or "W" prepended - * @param coors An array of points in lat/lon coordinates - * @return The String showing lat/lons in text string - */ - public static final String getLatLonStringPrepend(Coordinate[] coors, boolean isLineTypeArea){ - String twoSpace = gov.noaa.nws.ncep.ui.pgen.sigmet.SigmetInfo.LINE_SEPERATER; - StringBuilder result = new StringBuilder(); - for(Coordinate coor : coors){ - - result.append(coor.y>=0 ? 'N':'S'); - int y = (int)Math.abs(coor.y*100); - result.append( new DecimalFormat(FOUR_ZERO).format(y) ); - - result.append(coor.x>=0 ? 'E':'W'); - int x = (int)Math.abs(coor.x*100); - result.append( new DecimalFormat(FIVE_ZERO).format(x) ); - - result.append(twoSpace); - } - if( isLineTypeArea )result.append(result.toString().split(twoSpace)[0]); - return result.toString(); - } - - /** - * Converts an array of lat/lons to text; the format is "N","S","E", and/or "W" postpended - * @param coors An array of points in lat/lon coordinates - * @return The String showing lat/lons in text string - */ - public static final String getLatLonStringPostpend(Coordinate[] coors, boolean isLineTypeArea){ - String twoSpace = gov.noaa.nws.ncep.ui.pgen.sigmet.SigmetInfo.LINE_SEPERATER; - StringBuilder result = new StringBuilder(); - for(Coordinate coor : coors){ - - int y = (int)Math.abs(coor.y*100); - result.append( new DecimalFormat(FOUR_ZERO).format(y) ); - result.append(coor.y>=0 ? 'N':'S'); - - int x = (int)Math.abs(coor.x*100); - result.append( new DecimalFormat(FIVE_ZERO).format(x) ); - result.append(coor.x>=0 ? 'E':'W'); - - result.append(twoSpace); - } - if( isLineTypeArea )result.append(result.toString().split(twoSpace)[0]); - return result.toString(); - } - /** - * Load the Contours drawing tool. - * @param de Contours to load into the ContoursAttrDlg when the tool is loaded + * Converts an array of lat/lons to pixel coordinates + * + * @param pts + * An array of points in lat/lon coordinates + * @param mapDescriptor + * Descriptoer to use for world to pixel transform + * @return The array of points in pixel coordinates */ - public static final void loadContoursTool( Contours de ) { + public static final double[][] latlonToPixel(Coordinate[] pts, + IMapDescriptor mapDescriptor) { + double[] point = new double[3]; + double[][] pixels = new double[pts.length][3]; + + for (int i = 0; i < pts.length; i++) { + point[0] = pts[i].x; + point[1] = pts[i].y; + point[2] = 0.0; + pixels[i] = mapDescriptor.worldToPixel(point); + } + + return pixels; + } + + /** + * Gets the current site id from the localization Manager + * + * @return + */ + public static String getCurrentOffice() { + + String wfo = LocalizationManager.getInstance().getCurrentSite(); + if (wfo.equalsIgnoreCase("none") || wfo.isEmpty()) + wfo = new String("KNHC"); + + return wfo; + } + + /** + * Converts an array of lat/lons to text; the format is "N","S","E", and/or + * "W" prepended + * + * @param coors + * An array of points in lat/lon coordinates + * @return The String showing lat/lons in text string + */ + public static final String getLatLonStringPrepend(Coordinate[] coors, + boolean isLineTypeArea) { + String twoSpace = gov.noaa.nws.ncep.ui.pgen.sigmet.SigmetInfo.LINE_SEPERATER; + StringBuilder result = new StringBuilder(); + for (Coordinate coor : coors) { + + result.append(coor.y >= 0 ? 'N' : 'S'); + int y = (int) Math.abs(coor.y * 100); + result.append(new DecimalFormat(FOUR_ZERO).format(y)); + + result.append(coor.x >= 0 ? 'E' : 'W'); + int x = (int) Math.abs(coor.x * 100); + result.append(new DecimalFormat(FIVE_ZERO).format(x)); + + result.append(twoSpace); + } + if (isLineTypeArea) + result.append(result.toString().split(twoSpace)[0]); + return result.toString(); + } + + /** + * Converts an array of lat/lons to text; the format is "N","S","E", and/or + * "W" postpended + * + * @param coors + * An array of points in lat/lon coordinates + * @return The String showing lat/lons in text string + */ + public static final String getLatLonStringPostpend(Coordinate[] coors, + boolean isLineTypeArea) { + String twoSpace = gov.noaa.nws.ncep.ui.pgen.sigmet.SigmetInfo.LINE_SEPERATER; + StringBuilder result = new StringBuilder(); + for (Coordinate coor : coors) { + + int y = (int) Math.abs(coor.y * 100); + result.append(new DecimalFormat(FOUR_ZERO).format(y)); + result.append(coor.y >= 0 ? 'N' : 'S'); + + int x = (int) Math.abs(coor.x * 100); + result.append(new DecimalFormat(FIVE_ZERO).format(x)); + result.append(coor.x >= 0 ? 'E' : 'W'); + + result.append(twoSpace); + } + if (isLineTypeArea) + result.append(result.toString().split(twoSpace)[0]); + return result.toString(); + } + + /** + * Load the Contours drawing tool. + * + * @param de + * Contours to load into the ContoursAttrDlg when the tool is + * loaded + */ + public static final void loadContoursTool(Contours de) { IEditorPart part = EditorUtil.getActiveEditor(); - ICommandService service = (ICommandService) part.getSite().getService( ICommandService.class ); + ICommandService service = (ICommandService) part.getSite().getService( + ICommandService.class); Command cmd = service.getCommand("gov.noaa.nws.ncep.ui.pgen.contours"); - - if ( cmd != null ) { - - try { - HashMap params = new HashMap(); - params.put("editor", part); - - if ( de != null ) { - params.put("name", de.getPgenType() ); - params.put("className", de.getPgenCategory()); - } - else { - params.put("name", "Contours" ); - params.put("className", "MET" ); - } - - ExecutionEvent exec = new ExecutionEvent(cmd, params, de, null); - cmd.executeWithChecks(exec); + if (cmd != null) { - } catch (Exception e) { - - e.printStackTrace(); - } + try { + HashMap params = new HashMap(); + params.put("editor", part); + + if (de != null) { + params.put("name", de.getPgenType()); + params.put("className", de.getPgenCategory()); + } else { + params.put("name", "Contours"); + params.put("className", "MET"); + } + + ExecutionEvent exec = new ExecutionEvent(cmd, params, de, null); + + cmd.executeWithChecks(exec); + + } catch (Exception e) { + + e.printStackTrace(); + } } } - - /** - * Trigger the selecting tool with a selected element. - */ - public static final void setSelectingMode( AbstractDrawableComponent de ) { + + /** + * Trigger the selecting tool with a selected element. + */ + public static final void setSelectingMode(AbstractDrawableComponent de) { IEditorPart part = EditorUtil.getActiveEditor(); - ICommandService service = (ICommandService) part.getSite().getService( ICommandService.class ); - Command cmd = service.getCommand("gov.noaa.nws.ncep.ui.pgen.rsc.PgenSelect"); + ICommandService service = (ICommandService) part.getSite().getService( + ICommandService.class); + Command cmd = service + .getCommand("gov.noaa.nws.ncep.ui.pgen.rsc.PgenSelect"); - if ( cmd != null ) { - - try { - HashMap params = new HashMap(); - params.put("editor", part); - ExecutionEvent exec = new ExecutionEvent(cmd, params, de, null); + if (cmd != null) { - cmd.executeWithChecks(exec); + try { + HashMap params = new HashMap(); + params.put("editor", part); + ExecutionEvent exec = new ExecutionEvent(cmd, params, de, null); - } catch (Exception e) { - - e.printStackTrace(); - } + cmd.executeWithChecks(exec); + + } catch (Exception e) { + + e.printStackTrace(); + } } } /** * Returns the name of the directory that holds PGEN recovery files + * * @return */ public static String getTempWorkDir() { - IPreferenceStore prefs = Activator.getDefault().getPreferenceStore(); - return prefs.getString(PgenPreferences.P_RECOVERY_DIR); + IPreferenceStore prefs = Activator.getDefault().getPreferenceStore(); + return prefs.getString(PgenPreferences.P_RECOVERY_DIR); } - + /** - * + * * @return */ public static PgenMode getPgenMode() { - IPreferenceStore prefs = Activator.getDefault().getPreferenceStore(); - String name = prefs.getString(PgenPreferences.P_PGEN_MODE); - PgenMode mode = PgenMode.valueOf(name); - return mode; + IPreferenceStore prefs = Activator.getDefault().getPreferenceStore(); + String name = prefs.getString(PgenPreferences.P_PGEN_MODE); + PgenMode mode = PgenMode.valueOf(name); + return mode; } - + /** * Indicates whether PGEN layers should be linked with the editor */ public static boolean doesLayerLink() { - IPreferenceStore prefs = Activator.getDefault().getPreferenceStore(); - return prefs.getBoolean(PgenPreferences.P_LAYER_LINK); + IPreferenceStore prefs = Activator.getDefault().getPreferenceStore(); + return prefs.getBoolean(PgenPreferences.P_LAYER_LINK); } - - /* - * Checks to see if a file exists. If so, pop up a dialog asking for permission - * to overwrite the file. - */ - public static boolean checkFileStatus(String filename) { - boolean canWrite = false; - File f = new File(filename); - - if ( f.exists() ) { - // display confirmation dialog - String msg = "File " + filename + " already exists. Overwrite?"; - MessageDialog confirmDlg = new MessageDialog( - PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), - "Confirm", null, msg, - MessageDialog.QUESTION, new String[]{"OK", "Cancel"}, 0); - confirmDlg.open(); + /* + * Checks to see if a file exists. If so, pop up a dialog asking for + * permission to overwrite the file. + */ + public static boolean checkFileStatus(String filename) { - if ( confirmDlg.getReturnCode() == MessageDialog.OK ) { - canWrite = true; - } - } else { - canWrite = true; - } + boolean canWrite = false; + File f = new File(filename); + + if (f.exists()) { + // display confirmation dialog + String msg = "File " + filename + " already exists. Overwrite?"; + MessageDialog confirmDlg = new MessageDialog(PlatformUI + .getWorkbench().getActiveWorkbenchWindow().getShell(), + "Confirm", null, msg, MessageDialog.QUESTION, new String[] { + "OK", "Cancel" }, 0); + confirmDlg.open(); + + if (confirmDlg.getReturnCode() == MessageDialog.OK) { + canWrite = true; + } + } else { + canWrite = true; + } return canWrite; - } - + } + /** * Convert a java.util.Calendar to a GEMPAK date/time string + * * @return */ - public static String calendarToGempakDattim( Calendar jdattim ) { - - String gDattim = null; - - if ( jdattim != null ) { - - String gstr = ""; - - int year = jdattim.get(Calendar.YEAR); - gstr += year - year/100 * 100; - - int month = jdattim.get(Calendar.MONTH) + 1; - if ( month < 10 ) { - gstr += "0"; - } - gstr += month; - - int day = jdattim.get(Calendar.DAY_OF_MONTH); - if ( day < 10 ) { - gstr += "0"; - } - gstr += day; - - gstr += "/"; - - int hour = jdattim.get(Calendar.HOUR_OF_DAY); - if ( hour < 10 ) { - gstr += "0"; - } - gstr += hour; - - int minute = jdattim.get(Calendar.MINUTE); - if ( minute < 10 ) { - gstr += "0"; - } - gstr += minute; - - gDattim = new String( gstr ); - } - - return gDattim; - + public static String calendarToGempakDattim(Calendar jdattim) { + + String gDattim = null; + + if (jdattim != null) { + + String gstr = ""; + + int year = jdattim.get(Calendar.YEAR); + gstr += year - year / 100 * 100; + + int month = jdattim.get(Calendar.MONTH) + 1; + if (month < 10) { + gstr += "0"; + } + gstr += month; + + int day = jdattim.get(Calendar.DAY_OF_MONTH); + if (day < 10) { + gstr += "0"; + } + gstr += day; + + gstr += "/"; + + int hour = jdattim.get(Calendar.HOUR_OF_DAY); + if (hour < 10) { + gstr += "0"; + } + gstr += hour; + + int minute = jdattim.get(Calendar.MINUTE); + if (minute < 10) { + gstr += "0"; + } + gstr += minute; + + gDattim = new String(gstr); + } + + return gDattim; + } - - + /** - * The current working directory may be changed in eclipse.sh or cave.sh, so it - * may not be the directory where you are running them. To get around, We save - * and export it as "CURRENT_WORKING_DIRECTORY". - * - * Set to a user-defined directory in PGEN preference. - */ -// public static String CURRENT_WORKING_DIRECTORY = System.getenv( "CURRENT_WORKING_DIRECTORY" ); - public static String CURRENT_WORKING_DIRECTORY = System.getProperty("user.home"); - - public static String getWorkingDirectory() { - return Activator.getDefault().getPreferenceStore().getString( PgenPreferences.P_WORKING_DIR ); - } - - /** - * This function merges two labels of the input LabeledLine(ll) that are - * at the same location(loc) into one label(one text with several arrowed lines)/ - * @param ll - LabeledLine - * @param loc - Location - * @param me - map editor + * The current working directory may be changed in eclipse.sh or cave.sh, so + * it may not be the directory where you are running them. To get around, We + * save and export it as "CURRENT_WORKING_DIRECTORY". + * + * Set to a user-defined directory in PGEN preference. */ -// static public void mergeLabels(LabeledLine ll, Coordinate loc, NCMapEditor mapEditor ){ - static public LabeledLine mergeLabels(LabeledLine ll, Label testLbl, Coordinate loc, AbstractEditor mapEditor, PgenResource rsc - ){ - - //label at location loc. - // Label testLbl = null; - - //label close to testLbl - Label mergeLbl = null; - - //translate lat/lon to screen coordinate - double scnLoc[] = mapEditor.translateInverseClick( loc ); + // public static String CURRENT_WORKING_DIRECTORY = System.getenv( + // "CURRENT_WORKING_DIRECTORY" ); + public static String CURRENT_WORKING_DIRECTORY = System + .getProperty("user.home"); - //search for the closest two labels at loc - Layer activeLayer = rsc.getActiveLayer(); - Iterator it = activeLayer.getComponentIterator(); - LabeledLine nearestLine = null; - while( it.hasNext() ){ - AbstractDrawableComponent adc =it.next(); - if ( adc instanceof LabeledLine && ((LabeledLine)adc).getPgenType().equalsIgnoreCase(ll.getPgenType())){ - LabeledLine lline = (LabeledLine)adc; - for ( Label lbl : lline.getLabels() ){ - if ( Math.abs(lbl.getSpe().getLocation().x - loc.x) < 0.0001 && - Math.abs(lbl.getSpe().getLocation().y - loc.y) < 0.0001 ) { + public static String getWorkingDirectory() { + return Activator.getDefault().getPreferenceStore() + .getString(PgenPreferences.P_WORKING_DIR); + } - //get the label at loc - // testLbl = lbl; - } - else { + /** + * This function merges two labels of the input LabeledLine(ll) that are at + * the same location(loc) into one label(one text with several arrowed + * lines)/ + * + * @param ll + * - LabeledLine + * @param loc + * - Location + * @param me + * - map editor + */ + // static public void mergeLabels(LabeledLine ll, Coordinate loc, + // NCMapEditor mapEditor ){ + static public LabeledLine mergeLabels(LabeledLine ll, Label testLbl, + Coordinate loc, AbstractEditor mapEditor, PgenResource rsc) { - //calculate distance from lbl to scnLoc - double scnPt[] = mapEditor.translateInverseClick(lbl.getSpe().getLocation()); - double dist = Math.sqrt( (scnLoc[0]-scnPt[0]) * (scnLoc[0]-scnPt[0]) - +(scnLoc[1]-scnPt[1]) * (scnLoc[1]-scnPt[1]) ); + // label at location loc. + // Label testLbl = null; + + // label close to testLbl + Label mergeLbl = null; + + // translate lat/lon to screen coordinate + double scnLoc[] = mapEditor.translateInverseClick(loc); + + // search for the closest two labels at loc + Layer activeLayer = rsc.getActiveLayer(); + Iterator it = activeLayer + .getComponentIterator(); + LabeledLine nearestLine = null; + while (it.hasNext()) { + AbstractDrawableComponent adc = it.next(); + if (adc instanceof LabeledLine + && ((LabeledLine) adc).getPgenType().equalsIgnoreCase( + ll.getPgenType())) { + LabeledLine lline = (LabeledLine) adc; + for (Label lbl : lline.getLabels()) { + if (Math.abs(lbl.getSpe().getLocation().x - loc.x) < 0.0001 + && Math.abs(lbl.getSpe().getLocation().y - loc.y) < 0.0001) { + + // get the label at loc + // testLbl = lbl; + } else { + + // calculate distance from lbl to scnLoc + double scnPt[] = mapEditor.translateInverseClick(lbl + .getSpe().getLocation()); + double dist = Math.sqrt((scnLoc[0] - scnPt[0]) + * (scnLoc[0] - scnPt[0]) + + (scnLoc[1] - scnPt[1]) + * (scnLoc[1] - scnPt[1])); + + if (dist < 20) { // 20 is the screen distance. + // a label in this range(<20) is considered as being + // at the same location + mergeLbl = lbl; + nearestLine = (LabeledLine) adc; + break; + } + } + } + } + if (mergeLbl != null) + break; + } + + // add all arrow lines of one label to the other label and remove the + // second label + if (testLbl != null && mergeLbl != null) { + for (Line ln : testLbl.getArrows()) { + mergeLbl.addArrow(ln); + ln.removePoint(0); + ln.addPoint(0, mergeLbl.getSpe().getLocation()); + } + // ll.add(mergeLbl); + ll.remove(testLbl); + } + + if (nearestLine != null) { + Iterator iterator = nearestLine + .getComponentIterator(); + while (iterator.hasNext()) { + ll.add(iterator.next()); + } + } + + return nearestLine; + } - if ( dist < 20 ){ // 20 is the screen distance. - // a label in this range(<20) is considered as being at the same location - mergeLbl = lbl; - nearestLine = (LabeledLine)adc; - break; - } - } - } - } - if ( mergeLbl != null ) break; - } - - //add all arrow lines of one label to the other label and remove the second label - if ( testLbl != null && mergeLbl != null ){ - for ( Line ln : testLbl.getArrows()) { - mergeLbl.addArrow(ln); - ln.removePoint(0); - ln.addPoint(0, mergeLbl.getSpe().getLocation()); - } - // ll.add(mergeLbl); - ll.remove(testLbl); - } - - if ( nearestLine != null ){ - Iterator iterator = nearestLine.getComponentIterator(); - while ( iterator.hasNext() ){ - ll.add(iterator.next() ); - } - } - - return nearestLine; - } - /** * Removes the current PgenResourceData object */ - public static void resetResourceData() { - rscData = null; - } - - /** - * Retrieve the last used tool - public static AbstractModalTool getLastUsedTool() { - - AbstractModalTool lastTool = null; - - AbstractVizPerspectiveManager mgr = VizPerspectiveListener - .getCurrentPerspectiveManager(); - if ( mgr != null) { - lastTool = mgr.getToolManager().getLastModalTool(); - } - - return lastTool; - } + public static void resetResourceData() { + rscData = null; + } + + /** + * Retrieve the last used tool public static AbstractModalTool + * getLastUsedTool() { + * + * AbstractModalTool lastTool = null; + * + * AbstractVizPerspectiveManager mgr = VizPerspectiveListener + * .getCurrentPerspectiveManager(); if ( mgr != null) { lastTool = + * mgr.getToolManager().getLastModalTool(); } + * + * return lastTool; } */ - - - /** - * This function computes the area of a spherical polygon on the earth - * - * Note: The ANSI C code is adapted and modified from the article - * "Computing the Area of a Spherical Polygon" - * by Robert D. Miller, - * in "Graphics Gems IV", Academic Press, 1994. - * - * @param pts[] polygon points in map coordinates - * @return area area in unit of square nautical miles. - */ - public static double getSphPolyArea ( Coordinate ptsin[] ) - { - - final double HalfPi = 1.5707963267948966192313, - Degree = 57.295779513082320876798, // degrees per radian - M2NM = 5.4e-4F, // meter to nautical mile - RADIUS = 6371200.0F, // earth radius - GDIFFD= 0.000001; - int jj, kk; - double Lam1, Lam2, Beta1, Beta2, CosB1, CosB2, HavA; - double T, A, B, C, S, sum, excess; + /** + * This function computes the area of a spherical polygon on the earth + * + * Note: The ANSI C code is adapted and modified from the article + * "Computing the Area of a Spherical Polygon" by Robert D. Miller, in + * "Graphics Gems IV", Academic Press, 1994. + * + * @param pts + * [] polygon points in map coordinates + * @return area area in unit of square nautical miles. + */ + public static double getSphPolyArea(Coordinate ptsin[]) { - /*---------------------------------------------------------------------*/ + final double HalfPi = 1.5707963267948966192313, Degree = 57.295779513082320876798, // degrees + // per + // radian + M2NM = 5.4e-4F, // meter to nautical mile + RADIUS = 6371200.0F, // earth radius + GDIFFD = 0.000001; - int npts = ptsin.length; - double[] tmplat = new double[ npts]; - double[] tmplon = new double[ npts]; - - - /* - * Convert from degrees to radians and save into local arrays - */ - for ( jj = 0; jj < npts; jj++ ) { - tmplat[jj] = ptsin[jj].y / Degree; - tmplon[jj] = ptsin[jj].x / Degree; - } - + int jj, kk; + double Lam1, Lam2, Beta1, Beta2, CosB1, CosB2, HavA; + double T, A, B, C, S, sum, excess; - /* - * Calculate the area in spherical degrees. - */ - sum = 0; - Lam2 = 0.0; - Beta2 = 0.0; - CosB2 = 0.0; - for ( jj = 0; jj < npts; jj++ ) - { - kk = jj + 1; - if ( jj == 0 ) { - Lam1= (double)tmplon[jj]; Beta1= (double)tmplat[jj]; - Lam2= (double)tmplon[jj+1]; Beta2= (double)tmplat[jj+1]; - CosB1= Math.cos(Beta1); CosB2= Math.cos(Beta2); - } - else { - kk = (jj+1) % (npts); - Lam1= Lam2; Beta1= Beta2; - Lam2= (double)tmplon[kk]; Beta2= (double)tmplat[kk]; - CosB1= CosB2; CosB2= Math.cos(Beta2); - } + /*---------------------------------------------------------------------*/ - if ( !(Math.abs(Lam1-Lam2) < GDIFFD) ) { - - double a = ( 1.0 - Math.cos(Beta2-Beta1) ) / 2.0; - double b = ( 1.0 - Math.cos(Lam2-Lam1) ) / 2.0; - HavA = a + CosB1*CosB2*b; + int npts = ptsin.length; + double[] tmplat = new double[npts]; + double[] tmplon = new double[npts]; - A = 2 * Math.asin ( Math.sqrt ( HavA ) ); - B = HalfPi - Beta2; - C = HalfPi - Beta1; - S = 0.5 * ( A + B + C ); - T = Math.tan(S/2) * Math.tan((S-A)/2) * Math.tan((S-B)/2) * Math.tan((S-C)/2); + /* + * Convert from degrees to radians and save into local arrays + */ + for (jj = 0; jj < npts; jj++) { + tmplat[jj] = ptsin[jj].y / Degree; + tmplon[jj] = ptsin[jj].x / Degree; + } - excess = Math.abs ( 4 * Math.atan ( Math.sqrt ( Math.abs(T) ) ) ) * Degree; - if ( Lam2 < Lam1 ) excess = -excess; + /* + * Calculate the area in spherical degrees. + */ + sum = 0; + Lam2 = 0.0; + Beta2 = 0.0; + CosB2 = 0.0; + for (jj = 0; jj < npts; jj++) { + kk = jj + 1; + if (jj == 0) { + Lam1 = (double) tmplon[jj]; + Beta1 = (double) tmplat[jj]; + Lam2 = (double) tmplon[jj + 1]; + Beta2 = (double) tmplat[jj + 1]; + CosB1 = Math.cos(Beta1); + CosB2 = Math.cos(Beta2); + } else { + kk = (jj + 1) % (npts); + Lam1 = Lam2; + Beta1 = Beta2; + Lam2 = (double) tmplon[kk]; + Beta2 = (double) tmplat[kk]; + CosB1 = CosB2; + CosB2 = Math.cos(Beta2); + } - sum = sum + excess; - } - } + if (!(Math.abs(Lam1 - Lam2) < GDIFFD)) { - double area = Math.abs ( sum ); + double a = (1.0 - Math.cos(Beta2 - Beta1)) / 2.0; + double b = (1.0 - Math.cos(Lam2 - Lam1)) / 2.0; + HavA = a + CosB1 * CosB2 * b; - /* - * Convert into "square nautical miles". - */ - double radius = RADIUS*M2NM; /* The Earth's radius in nautical miles*/ - - area *= ( (radius) * (radius) / Degree ); + A = 2 * Math.asin(Math.sqrt(HavA)); + B = HalfPi - Beta2; + C = HalfPi - Beta1; + S = 0.5 * (A + B + C); + T = Math.tan(S / 2) * Math.tan((S - A) / 2) + * Math.tan((S - B) / 2) * Math.tan((S - C) / 2); - return area; - } - - /** - * This function computes the area of polygon on the earth. - * @param poly polygon in map coordinates - * @return area area in unit of square nautical miles. - */ - public static double getSphPolyArea ( Polygon poly ) - { - double extnl_area = getSphPolyArea( poly.getExteriorRing().getCoordinates() ); - - double intnl_area = 0.0; - for ( int nn = 0; nn < poly.getNumInteriorRing(); nn++ ) { - intnl_area += getSphPolyArea( poly.getInteriorRingN( nn ).getCoordinates() ); - System.out.println( "internal??" ); - } - - return ( extnl_area - intnl_area ); - } + excess = Math.abs(4 * Math.atan(Math.sqrt(Math.abs(T)))) + * Degree; + if (Lam2 < Lam1) + excess = -excess; - /** - * This function computes the area of a geometry on the earth. - * @param geom geometry in map coordinate. - * @return area area in unit of square nautical miles. - */ - public static double getSphPolyArea ( Geometry geom ) - { - double area = 0.0; - if ( geom instanceof Polygon ) { - area = getSphPolyArea( (Polygon)geom ); - } - else if ( geom instanceof MultiPolygon ) { - MultiPolygon mp = (MultiPolygon)geom; - for( int nn = 0; nn < mp.getNumGeometries(); nn++ ) { - area += getSphPolyArea( (Polygon)mp.getGeometryN( nn ) ); - } - } + sum = sum + excess; + } + } - return area; - } - - /** - * This function computes the area of polygon in grid coordinate. - * - * Note: the input is assumed to be in grid coordinate. - * - * @param poly polygon in grid coordinates - * @return area area in unit of square nautical miles. - */ - public static double getSphPolyAreaInGrid ( Polygon poly ) - { - - Coordinate[] ring = poly.getExteriorRing().getCoordinates(); - Coordinate[] ringInMap = gridToLatlon( ring ); - double extnl_area = getSphPolyArea( ringInMap ); - - double intnl_area = 0.0; - for ( int nn = 0; nn < poly.getNumInteriorRing(); nn++ ) { - ring = poly.getInteriorRingN( nn ).getCoordinates(); - ringInMap = gridToLatlon( ring ); - intnl_area += getSphPolyArea( ring ); - } - - return ( extnl_area - intnl_area ); - } - - /** - * This function computes the area of a geometry on the earth. - * @param geom geometry in GRID coordinate. - * @return area area in unit of square nautical miles. - */ - public static double getSphPolyAreaInGrid ( Geometry geom ) - { - double area = 0.0; - if ( geom instanceof Polygon ) { - area = getSphPolyAreaInGrid( (Polygon)geom ); - } else if ( geom instanceof MultiPolygon ) { - MultiPolygon mp = (MultiPolygon)geom; - for( int nn = 0; nn < mp.getNumGeometries(); nn++ ) { - area += getSphPolyAreaInGrid( (Polygon)mp.getGeometryN( nn ) ); - } - } + double area = Math.abs(sum); - return area; - } + /* + * Convert into "square nautical miles". + */ + double radius = RADIUS * M2NM; /* The Earth's radius in nautical miles */ - - /** - * This function computes the area of polygon on the earth but requires - * to build a local projection and math transform - * Note: it may throw exception for invalid polygon. - * - * @param poly polygon in map coordinates - * @return area area in unit of square nautical miles. - */ - public static double getPolyArea ( Polygon poly ) - { + area *= ((radius) * (radius) / Degree); + + return area; + } + + /** + * This function computes the area of polygon on the earth. + * + * @param poly + * polygon in map coordinates + * @return area area in unit of square nautical miles. + */ + public static double getSphPolyArea(Polygon poly) { + double extnl_area = getSphPolyArea(poly.getExteriorRing() + .getCoordinates()); + + double intnl_area = 0.0; + for (int nn = 0; nn < poly.getNumInteriorRing(); nn++) { + intnl_area += getSphPolyArea(poly.getInteriorRingN(nn) + .getCoordinates()); + System.out.println("internal??"); + } + + return (extnl_area - intnl_area); + } + + /** + * This function computes the area of a geometry on the earth. + * + * @param geom + * geometry in map coordinate. + * @return area area in unit of square nautical miles. + */ + public static double getSphPolyArea(Geometry geom) { double area = 0.0; - try { + if (geom instanceof Polygon) { + area = getSphPolyArea((Polygon) geom); + } else if (geom instanceof MultiPolygon) { + MultiPolygon mp = (MultiPolygon) geom; + for (int nn = 0; nn < mp.getNumGeometries(); nn++) { + area += getSphPolyArea((Polygon) mp.getGeometryN(nn)); + } + } + + return area; + } + + /** + * This function computes the area of polygon in grid coordinate. + * + * Note: the input is assumed to be in grid coordinate. + * + * @param poly + * polygon in grid coordinates + * @return area area in unit of square nautical miles. + */ + public static double getSphPolyAreaInGrid(Polygon poly) { + + Coordinate[] ring = poly.getExteriorRing().getCoordinates(); + Coordinate[] ringInMap = gridToLatlon(ring); + double extnl_area = getSphPolyArea(ringInMap); + + double intnl_area = 0.0; + for (int nn = 0; nn < poly.getNumInteriorRing(); nn++) { + ring = poly.getInteriorRingN(nn).getCoordinates(); + ringInMap = gridToLatlon(ring); + intnl_area += getSphPolyArea(ring); + } + + return (extnl_area - intnl_area); + } + + /** + * This function computes the area of a geometry on the earth. + * + * @param geom + * geometry in GRID coordinate. + * @return area area in unit of square nautical miles. + */ + public static double getSphPolyAreaInGrid(Geometry geom) { + double area = 0.0; + if (geom instanceof Polygon) { + area = getSphPolyAreaInGrid((Polygon) geom); + } else if (geom instanceof MultiPolygon) { + MultiPolygon mp = (MultiPolygon) geom; + for (int nn = 0; nn < mp.getNumGeometries(); nn++) { + area += getSphPolyAreaInGrid((Polygon) mp.getGeometryN(nn)); + } + } + + return area; + } + + /** + * This function computes the area of polygon on the earth but requires to + * build a local projection and math transform Note: it may throw exception + * for invalid polygon. + * + * @param poly + * polygon in map coordinates + * @return area area in unit of square nautical miles. + */ + public static double getPolyArea(Polygon poly) { + double area = 0.0; + try { org.opengis.referencing.crs.ProjectedCRS localProjectionCRS = MapUtil - .constructStereographic(MapUtil.AWIPS_EARTH_RADIUS, - MapUtil.AWIPS_EARTH_RADIUS, poly.getCentroid() - .getY(), poly.getCentroid().getX()); + .constructStereographic(MapUtil.AWIPS_EARTH_RADIUS, + MapUtil.AWIPS_EARTH_RADIUS, poly.getCentroid() + .getY(), poly.getCentroid().getX()); MathTransform mt; mt = MapUtil.getTransformFromLatLon(localProjectionCRS); - Geometry newIntersectInLocalProj = JTS.transform(poly,mt); + Geometry newIntersectInLocalProj = JTS.transform(poly, mt); double areaInMeters = newIntersectInLocalProj.getArea(); - + area = areaInMeters / PgenUtil.NM2M / PgenUtil.NM2M; - - } catch (Exception e) { + + } catch (Exception e) { e.printStackTrace(); } - - return area; - } - - /** + + return area; + } + + /** * Returns projection for PGEN computational coordinate + * * @return */ public static String getPgenCompCoordProj() { - IPreferenceStore prefs = Activator.getDefault().getPreferenceStore(); - String coordStr = prefs.getString( PgenPreferences.P_COMP_COORD ); - String[] s = coordStr.split( "\\|" ); - return s[ 0 ]; + IPreferenceStore prefs = Activator.getDefault().getPreferenceStore(); + String coordStr = prefs.getString(PgenPreferences.P_COMP_COORD); + String[] s = coordStr.split("\\|"); + return s[0]; } /** * Returns GRAEA for PGEN computational coordinate + * * @return */ public static String getPgenCompCoordGarea() { - IPreferenceStore prefs = Activator.getDefault().getPreferenceStore(); - String coordStr = prefs.getString( PgenPreferences.P_COMP_COORD ); - String[] s = coordStr.split( "\\|" ); - return s[ 1 ]; + IPreferenceStore prefs = Activator.getDefault().getPreferenceStore(); + String coordStr = prefs.getString(PgenPreferences.P_COMP_COORD); + String[] s = coordStr.split("\\|"); + return s[1]; } - + /** * Returns a custom CoordinateTransform for use. + * * @return */ public static CoordinateTransform getCompCoord() { - - if ( coordTrans == null || - !coordTrans.getProjection().equals( getPgenCompCoordProj() ) || - !coordTrans.getGarea().equals( getPgenCompCoordGarea() ) ) { - - coordTrans = new CoordinateTransform( getPgenCompCoordProj(), - getPgenCompCoordGarea(), 800, 600 ); - } - - return coordTrans; - + + if (coordTrans == null + || !coordTrans.getProjection().equals(getPgenCompCoordProj()) + || !coordTrans.getGarea().equals(getPgenCompCoordGarea())) { + + coordTrans = new CoordinateTransform(getPgenCompCoordProj(), + getPgenCompCoordGarea(), 800, 600); + } + + return coordTrans; + } - - - /** - * Convert a set of lat/lon points into a custom grid coordinate. - * - * @param lonlat points to be converted - * @return - */ - public static Coordinate[] latlonToGrid( Coordinate[] lonlat ) { - - return getCompCoord().worldToGrid( lonlat ); - } - /** - * Convert a set of points in a custom grid coordinate to lat/lon points. - * - * @param lonlat points to be converted - * @return - */ - public static Coordinate[] gridToLatlon( Coordinate[] gridpts ) { - - return getCompCoord().gridToWorld( gridpts ); - } + /** + * Convert a set of lat/lon points into a custom grid coordinate. + * + * @param lonlat + * points to be converted + * @return + */ + public static Coordinate[] latlonToGrid(Coordinate[] lonlat) { - /** - * Convert a list of lat/lon points into a custom grid coordinate. - * - * @param lonlat points to be converted - * @return - */ - public static ArrayList latlonToGrid( ArrayList lonlat ) { - - Coordinate[] aa = new Coordinate[ lonlat.size() ]; - - aa = PgenUtil.latlonToGrid( lonlat.toArray( aa ) ); - - return new ArrayList( Arrays.asList( aa ) ); - } + return getCompCoord().worldToGrid(lonlat); + } - /** - * Convert a list of points in a custom grid coordinate to lat/lon points. - * - * @param lonlat points to be converted - * @return - */ - public static ArrayList gridToLatlon( ArrayList gridpts ) { - - Coordinate[] aa = new Coordinate[ gridpts.size() ]; - - aa = PgenUtil.gridToLatlon( gridpts.toArray( aa ) ); - - return new ArrayList( Arrays.asList( aa ) ); - - } - - /** - * Returns the base directory for storing/access PGEN operation product file. + /** + * Convert a set of points in a custom grid coordinate to lat/lon points. + * + * @param lonlat + * points to be converted + * @return + */ + public static Coordinate[] gridToLatlon(Coordinate[] gridpts) { + + return getCompCoord().gridToWorld(gridpts); + } + + /** + * Convert a list of lat/lon points into a custom grid coordinate. + * + * @param lonlat + * points to be converted + * @return + */ + public static ArrayList latlonToGrid( + ArrayList lonlat) { + + Coordinate[] aa = new Coordinate[lonlat.size()]; + + aa = PgenUtil.latlonToGrid(lonlat.toArray(aa)); + + return new ArrayList(Arrays.asList(aa)); + } + + /** + * Convert a list of points in a custom grid coordinate to lat/lon points. + * + * @param lonlat + * points to be converted + * @return + */ + public static ArrayList gridToLatlon( + ArrayList gridpts) { + + Coordinate[] aa = new Coordinate[gridpts.size()]; + + aa = PgenUtil.gridToLatlon(gridpts.toArray(aa)); + + return new ArrayList(Arrays.asList(aa)); + + } + + /** + * Returns the base directory for storing/access PGEN operation product + * file. + * * @return */ public static String getPgenOprDirectory() { - return Activator.getDefault().getPreferenceStore().getString( PgenPreferences.P_OPR_DIR ); + return Activator.getDefault().getPreferenceStore() + .getString(PgenPreferences.P_OPR_DIR); } /** * Returns the file path of the current PGEN activity + * * @return */ - public static String getPgenActivityPath(){ - String pdName = PgenSession.getInstance().getPgenResource().getActiveProduct().getType(); - ProductType pt = ProductConfigureDialog.getProductTypes().get( pdName); - if ( pt != null ) pdName = pt.getType(); - - //String pd1 = pdName.replaceAll(" ", "_"); - - return PgenUtil.getPgenOprDirectory() + File.separator + pdName; + public static String getPgenActivityPath() { + String pdName = PgenSession.getInstance().getPgenResource() + .getActiveProduct().getType(); + ProductType pt = ProductConfigureDialog.getProductTypes().get(pdName); + if (pt != null) + pdName = pt.getType(); + + // String pd1 = pdName.replaceAll(" ", "_"); + + return PgenUtil.getPgenOprDirectory() + File.separator + pdName; } - + /** * Returns the file path of the current PGEN activity products + * * @return */ - public static String getPgenActivityProdPath(){ - - return PgenUtil.getPgenActivityPath() + File.separator + PGEN_PROD_DIR; + public static String getPgenActivityProdPath() { + + return PgenUtil.getPgenActivityPath() + File.separator + PGEN_PROD_DIR; } - + /** * Returns the file path of the current PGEN activity products + * * @return */ - public static String getPgenActivityTextProdPath(){ - - - return PgenUtil.getPgenActivityProdPath() + File.separator + PGEN_TEXT_PROD_DIR; - } + public static String getPgenActivityTextProdPath() { + + return PgenUtil.getPgenActivityProdPath() + File.separator + + PGEN_TEXT_PROD_DIR; + } + /** * Returns the file path of the current PGEN activity xml files + * * @return */ - public static String getPgenActivityXmlPath(){ - - return PgenUtil.getPgenActivityPath() + File.separator + PGEN_XML_DIR; + public static String getPgenActivityXmlPath() { + + return PgenUtil.getPgenActivityPath() + File.separator + PGEN_XML_DIR; } - - /** - * Format a Calendar date into a string of "DDMMYYYY" - */ - public static String formatDate( Calendar cal ) { - - StringBuilder dstr = new StringBuilder(); - - int day = cal.get( Calendar.DAY_OF_MONTH ); - if ( day < 10 ) { - dstr.append( "0" + day ); - } - else { - dstr.append( day ); - } - - int mon = cal.get( Calendar.MONTH ) + 1; - if ( mon < 10 ) { - dstr.append( "0" + mon ); - } - else { - dstr.append( mon ); - } - - dstr.append( cal.get( Calendar.YEAR ) ); - - return dstr.toString(); - } - /** - * Parse the environmental variables to get a full path file name. -// * Default path will be the user's PGEN_OPR directory. - * @param filename - * @return a full path file name or unchanged if no "/" in the input file name - */ - public static String parsePgenFileName( String fileName ) { - - String parsedFile = fileName; + /** + * Format a Calendar date into a string of "DDMMYYYY" + */ + public static String formatDate(Calendar cal) { - if ( fileName != null ) { - if ( fileName.contains( File.separator ) ) { + StringBuilder dstr = new StringBuilder(); - String[] items = fileName.split( File.separator ); - StringBuilder stb = new StringBuilder(); - if ( fileName.startsWith( File.separator ) ) { - stb.append( File.separator ); - } + int day = cal.get(Calendar.DAY_OF_MONTH); + if (day < 10) { + dstr.append("0" + day); + } else { + dstr.append(day); + } - for ( String str : items ) { - if ( str.equals(".") ) { - stb.append( System.getProperty("user.home") ); - } - else if ( str.startsWith( "$") && System.getenv( str.substring(1) ) != null ) { - stb.append( System.getenv( str.substring(1) ) ); - } - else { - stb.append( str ); - } + int mon = cal.get(Calendar.MONTH) + 1; + if (mon < 10) { + dstr.append("0" + mon); + } else { + dstr.append(mon); + } - stb.append( File.separator ); - } + dstr.append(cal.get(Calendar.YEAR)); - parsedFile = stb.toString(); + return dstr.toString(); + } - if ( !fileName.endsWith( File.separator ) ) { - parsedFile = parsedFile.substring( 0, parsedFile.length() - 1 ); - } - } -// else { -// parsedFile = new String( PgenUtil.getPgenOprDirectory() + -// File.separator + fileName ); -// } - } - - return parsedFile; - } + /** + * Parse the environmental variables to get a full path file name. // * + * Default path will be the user's PGEN_OPR directory. + * + * @param filename + * @return a full path file name or unchanged if no "/" in the input file + * name + */ + public static String parsePgenFileName(String fileName) { - /** - * This function computes the resulting coordinate (latitude/longitude point) - * based on the coordinate (latitude/longitude point) passed, a distance and a - * direction. - * - * @param coor coordinate of the point (lat/lon) - * @param dist distance (nautical mile) - * @param dir direction (degrees from N) - * @return newCoor coordinate of the new point created - */ - public static Coordinate computePoint(Coordinate coor, float dist, float dir) { - final double PI = 3.14159265, - HALFPI = PI / 2.0, - TWOPI = 2.0 * PI, - DTR = PI / 180.0, // Degrees to Radians - RTD = 180.0 / PI, // Radians to Degrees - RADIUS = 6371200.0F, // Earth radius - NM2M = 1852.0F; - - /* - * Convert the input values to radians. - */ + String parsedFile = fileName; - double direction = (double) dir * DTR; - double lat = (double) coor.y * DTR; - double lon = (double) coor.x * DTR; - double distance = (double) dist * NM2M/ RADIUS; - - double dLat = Math.asin( Math.sin(lat) * Math.cos(distance) + Math.cos(lat) * Math.sin(distance) * Math.cos(direction)); - double dLon, dLt, dLn; - - /* - * Make sure the longitude is between -180 and +180 degrees. - */ - lon = lon - (double)( (double)((int)(lon / TWOPI)) * TWOPI ); - if ( lon < -PI ) lon = lon + TWOPI; - if ( lon > PI ) lon = lon - TWOPI; + if (fileName != null) { + if (fileName.contains(File.separator)) { - /* - * Compute the delta longitude. If the initial latitude is either - * pole, then use the original longitude, otherwise, compute - * the new longitude. - */ - if ( (Math.abs(lat - 90.0F) < 0.000001) || (Math.abs(-lat - 90.0F) < 0.000001) ) { - dLon = lon; - } - else { - dLon = Math.atan2( Math.sin(direction) * Math.sin(distance) * Math.cos(lat), - Math.cos(distance)-Math.sin(lat)*Math.sin(dLat)); - dLon = (lon+dLon + PI % TWOPI) - PI; - } - - /* - * Make sure that latitude is between -90 and +90 degrees. - * Adjust the longitude, if necessary. - */ - dLt = dLat - (double)( (double)((int)(dLat/PI)) * PI ); + String[] items = fileName.split(File.separator); + StringBuilder stb = new StringBuilder(); + if (fileName.startsWith(File.separator)) { + stb.append(File.separator); + } - if ( dLt > HALFPI ) { - dLt = PI - dLt; - dLon = -dLon; - } - if ( dLt < -HALFPI ) { - dLt = -PI - dLt; - dLon = -dLon; - } - - /* - * Make sure the longitude is between -180 and +180 degrees. - */ - dLn = dLon - (double)( (double)((int)(dLon/TWOPI)) * TWOPI ); - if ( dLn < -PI ) dLn = dLn + TWOPI; - if ( dLn > PI ) dLn = dLn - TWOPI; + for (String str : items) { + if (str.equals(".")) { + stb.append(System.getProperty("user.home")); + } else if (str.startsWith("$") + && System.getenv(str.substring(1)) != null) { + stb.append(System.getenv(str.substring(1))); + } else { + stb.append(str); + } + + stb.append(File.separator); + } + + parsedFile = stb.toString(); + + if (!fileName.endsWith(File.separator)) { + parsedFile = parsedFile.substring(0, + parsedFile.length() - 1); + } + } + // else { + // parsedFile = new String( PgenUtil.getPgenOprDirectory() + + // File.separator + fileName ); + // } + } + + return parsedFile; + } + + /** + * This function computes the resulting coordinate (latitude/longitude + * point) based on the coordinate (latitude/longitude point) passed, a + * distance and a direction. + * + * @param coor + * coordinate of the point (lat/lon) + * @param dist + * distance (nautical mile) + * @param dir + * direction (degrees from N) + * @return newCoor coordinate of the new point created + */ + public static Coordinate computePoint(Coordinate coor, float dist, float dir) { + final double PI = 3.14159265, HALFPI = PI / 2.0, TWOPI = 2.0 * PI, DTR = PI / 180.0, // Degrees + // to + // Radians + RTD = 180.0 / PI, // Radians to Degrees + RADIUS = 6371200.0F, // Earth radius + NM2M = 1852.0F; + + /* + * Convert the input values to radians. + */ + + double direction = (double) dir * DTR; + double lat = (double) coor.y * DTR; + double lon = (double) coor.x * DTR; + double distance = (double) dist * NM2M / RADIUS; + + double dLat = Math.asin(Math.sin(lat) * Math.cos(distance) + + Math.cos(lat) * Math.sin(distance) * Math.cos(direction)); + double dLon, dLt, dLn; + + /* + * Make sure the longitude is between -180 and +180 degrees. + */ + lon = lon - (double) ((double) ((int) (lon / TWOPI)) * TWOPI); + if (lon < -PI) + lon = lon + TWOPI; + if (lon > PI) + lon = lon - TWOPI; + + /* + * Compute the delta longitude. If the initial latitude is either pole, + * then use the original longitude, otherwise, compute the new + * longitude. + */ + if ((Math.abs(lat - 90.0F) < 0.000001) + || (Math.abs(-lat - 90.0F) < 0.000001)) { + dLon = lon; + } else { + dLon = Math.atan2( + Math.sin(direction) * Math.sin(distance) * Math.cos(lat), + Math.cos(distance) - Math.sin(lat) * Math.sin(dLat)); + dLon = (lon + dLon + PI % TWOPI) - PI; + } + + /* + * Make sure that latitude is between -90 and +90 degrees. Adjust the + * longitude, if necessary. + */ + dLt = dLat - (double) ((double) ((int) (dLat / PI)) * PI); + + if (dLt > HALFPI) { + dLt = PI - dLt; + dLon = -dLon; + } + if (dLt < -HALFPI) { + dLt = -PI - dLt; + dLon = -dLon; + } + + /* + * Make sure the longitude is between -180 and +180 degrees. + */ + dLn = dLon - (double) ((double) ((int) (dLon / TWOPI)) * TWOPI); + if (dLn < -PI) + dLn = dLn + TWOPI; + if (dLn > PI) + dLn = dLn - TWOPI; + + // Convert the new position to degrees and create coordinate based on + // new lat/lon + Coordinate newCoor = new Coordinate((float) (dLn * RTD), + (float) (dLt * RTD)); + return newCoor; + } - // Convert the new position to degrees and create coordinate based on new lat/lon - Coordinate newCoor = new Coordinate((float)(dLn * RTD), (float)(dLt * RTD)); - return newCoor; - } - /** * Apply the style sheet on the DOMSource and generate text + * * @param dSource * @param xsltName * @return */ - static public String applyStyleSheet(DOMSource dSource, String xsltName ){ + static public String applyStyleSheet(DOMSource dSource, String xsltName) { - String ret = ""; - if ( xsltName != null && !xsltName.isEmpty() ){ - File xslt = new File( xsltName); - if ( xslt.canRead() ){ - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); + String ret = ""; + if (xsltName != null && !xsltName.isEmpty()) { + File xslt = new File(xsltName); + if (xslt.canRead()) { - try{ - TransformerFactory tf = TransformerFactory.newInstance(); - StreamSource myStylesheetSrc = new StreamSource(xslt); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); - Transformer t = tf.newTransformer(myStylesheetSrc); + try { + TransformerFactory tf = TransformerFactory.newInstance(); + StreamSource myStylesheetSrc = new StreamSource(xslt); - t.transform(dSource, new StreamResult(baos)); - - ret = new String(baos.toByteArray()); - }catch(Exception e){ - System.out.println(e.getMessage()); - } - } - } + Transformer t = tf.newTransformer(myStylesheetSrc); + + t.transform(dSource, new StreamResult(baos)); + + ret = new String(baos.toByteArray()); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + } + } return ret; } - - /** - * Based on apache's WordUtils to wrap the long lines - * of OBS/Fcst info - * - * @param String str1: the line to be wrapped - * @param int wrapLength: the line's desired length - * @param String newLineStr:the new line string - * @param boolean wrapLongWords: if to wrapped long words - * @return String: the wrapped String - */ - - public static String wrap(String str1, int wrapLength, String newLineStr, boolean wrapLongWords) { + + /** + * Based on apache's WordUtils to wrap the long lines of OBS/Fcst info + * + * @param String + * str1: the line to be wrapped + * @param int wrapLength: the line's desired length + * @param String + * newLineStr:the new line string + * @param boolean wrapLongWords: if to wrapped long words + * @return String: the wrapped String + */ + + public static String wrap(String str1, int wrapLength, String newLineStr, + boolean wrapLongWords) { if (str1 == null) { return ""; } if (newLineStr == null) { newLineStr = System.getProperty("line.separator"); - + } if (wrapLength < 1) { wrapLength = 1; } int inputLineLength1 = str1.length(); int offset = 0; - StringBuffer wrappedLine = new StringBuffer (inputLineLength1 + 32); - + StringBuffer wrappedLine = new StringBuffer(inputLineLength1 + 32); + String[] lines = str1.split(newLineStr); - - for(int i=0; i wrapLength) { - if (str.charAt(offset) == ' ') { - offset++; - continue; - } - int spaceToWrapAt = str.lastIndexOf(' ', wrapLength + offset); - - if (spaceToWrapAt >= offset) { - // normal case - wrappedLine.append(str.substring(offset, spaceToWrapAt)); - wrappedLine.append(newLineStr); - offset = spaceToWrapAt + 1; - - } else { - // really long word or URL - if (wrapLongWords) { - // wrap really long word one line at a time - wrappedLine.append(str.substring(offset, wrapLength + offset)); - wrappedLine.append(newLineStr); - offset += wrapLength; - } else { - // do not wrap really long word, just extend beyond limit - spaceToWrapAt = str.indexOf(' ', wrapLength + offset); - if (spaceToWrapAt >= 0) { - wrappedLine.append(str.substring(offset, spaceToWrapAt)); - wrappedLine.append(newLineStr); - offset = spaceToWrapAt + 1; - } else { - wrappedLine.append(str.substring(offset)); - offset = inputLineLength; - } - } - } - } - - // Whatever is left in line is short enough to just pass through - wrappedLine.append(str.substring(offset)).append(newLineStr); - } + + for (int i = 0; i < lines.length; i++) { + offset = 0; + int inputLineLength = lines[i].length(); + + if (lines[i].length() < wrapLength) { + + wrappedLine.append(lines[i]).append(newLineStr); + + } else { + String str = lines[i]; + while ((inputLineLength - offset) > wrapLength) { + if (str.charAt(offset) == ' ') { + offset++; + continue; + } + int spaceToWrapAt = str.lastIndexOf(' ', wrapLength + + offset); + + if (spaceToWrapAt >= offset) { + // normal case + wrappedLine + .append(str.substring(offset, spaceToWrapAt)); + wrappedLine.append(newLineStr); + offset = spaceToWrapAt + 1; + + } else { + // really long word or URL + if (wrapLongWords) { + // wrap really long word one line at a time + wrappedLine.append(str.substring(offset, wrapLength + + offset)); + wrappedLine.append(newLineStr); + offset += wrapLength; + } else { + // do not wrap really long word, just extend beyond + // limit + spaceToWrapAt = str.indexOf(' ', wrapLength + + offset); + if (spaceToWrapAt >= 0) { + wrappedLine.append(str.substring(offset, + spaceToWrapAt)); + wrappedLine.append(newLineStr); + offset = spaceToWrapAt + 1; + } else { + wrappedLine.append(str.substring(offset)); + offset = inputLineLength; + } + } + } + } + + // Whatever is left in line is short enough to just pass through + wrappedLine.append(str.substring(offset)).append(newLineStr); + } } return wrappedLine.toString(); } - + /** * Get a reference to the current editor, if it is a AbstractEditor. * - * Copy from NmapUiUtils.getActiveNatlCntrsEditor() - to remove dependency on ui.display. + * Copy from NmapUiUtils.getActiveNatlCntrsEditor() - to remove dependency + * on ui.display. */ public static final AbstractEditor getActiveEditor() { // bsteffen change to EditorUtils @@ -1743,35 +1894,35 @@ public class PgenUtil { return null; } } - - /* - * Check if a workbench part is NCMapEditor - */ - public static boolean isNatlCntrsEditor( IWorkbenchPart part ){ - if( part instanceof AbstractEditor ) { - - IEditorInput edInput = ((AbstractEditor)part).getEditorInput(); - - if( edInput instanceof EditorInput ) { - - PaneManager pmngr = ((EditorInput)edInput).getPaneManager(); - - if( pmngr instanceof INatlCntrsPaneManager ) { - - NcDisplayType dispType = ((INatlCntrsPaneManager)pmngr).getDisplayType(); - - // if other display types are supported then add them here. - // - if( dispType.equals( NcDisplayType.NMAP_DISPLAY ) ) { - return true; - } - } - } - } - return false; - } - + /* + * Check if a workbench part is NCMapEditor + */ + public static boolean isNatlCntrsEditor(IWorkbenchPart part) { + if (part instanceof AbstractEditor) { + + IEditorInput edInput = ((AbstractEditor) part).getEditorInput(); + + if (edInput instanceof EditorInput) { + + PaneManager pmngr = ((EditorInput) edInput).getPaneManager(); + + if (pmngr instanceof INatlCntrsPaneManager) { + + NcDisplayType dispType = ((INatlCntrsPaneManager) pmngr) + .getDisplayType(); + + // if other display types are supported then add them here. + // + if (dispType.equals(NcDisplayType.NMAP_DISPLAY)) { + return true; + } + } + } + } + return false; + } + // TODO: Do we need to look in all the panes or just the active (or the // selected panes) // @@ -1799,17 +1950,25 @@ public class PgenUtil { return null; } - + /** - * Modify the title of the CAVE to "CAVE:title". + * Append title to the current CAVE title - save the original title for + * restoring when exiting PGEN. */ public static final void setCaveTitle(String title) { - if (PlatformUI.getWorkbench().getActiveWorkbenchWindow() != null - && PlatformUI.getWorkbench().getActiveWorkbenchWindow() - .getShell() != null) { - PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell() - .setText( CaveTitle + ":" + title ); - } + + if (PlatformUI.getWorkbench().getActiveWorkbenchWindow() != null + && PlatformUI.getWorkbench().getActiveWorkbenchWindow() + .getShell() != null) { + // Save the existing title to reset. + if (caveTitle == null) { + caveTitle = PlatformUI.getWorkbench() + .getActiveWorkbenchWindow().getShell().getText(); + } + + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell() + .setText(caveTitle + " (" + title + ")"); + } } @@ -1817,32 +1976,36 @@ public class PgenUtil { * Reset the title of the CAVE to "CAVE". */ public static final void resetCaveTitle() { - PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell() - .setText( CaveTitle ); + if (caveTitle != null) { + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell() + .setText(caveTitle); + } } - + /* - * Get an NCP editor's name/id. - * + * Get an NCP editor's name/id. + * * This must be called with an ncp editor. - */ - public static NcDisplayName getDisplayName( AbstractEditor ed ) { - if( !isNatlCntrsEditor( ed ) ) { - return null; - } - - return ((INatlCntrsPaneManager)((EditorInput)ed.getEditorInput()).getPaneManager()).getDisplayName(); + */ + public static NcDisplayName getDisplayName(AbstractEditor ed) { + if (!isNatlCntrsEditor(ed)) { + return null; + } + + return ((INatlCntrsPaneManager) ((EditorInput) ed.getEditorInput()) + .getPaneManager()).getDisplayName(); } - + /* * (non-Javadoc) * * @see com.raytheon.viz.ui.editor.IMultiPaneEditor#getNumberofPanes() */ - public static int getNumberofPanes( AbstractEditor editor ) { - return ((EditorInput)editor.getEditorInput()).getPaneManager().getNumberofPanes(); + public static int getNumberofPanes(AbstractEditor editor) { + return ((EditorInput) editor.getEditorInput()).getPaneManager() + .getNumberofPanes(); } - + /* * (non-Javadoc) * @@ -1850,9 +2013,10 @@ public class PgenUtil { * com.raytheon.viz.ui.editor.IMultiPaneEditor#addSelectedPaneChangedListener * (com.raytheon.viz.ui.editor.ISelectedPanesChangedListener) */ - public static void addSelectedPaneChangedListener( AbstractEditor editor, + public static void addSelectedPaneChangedListener(AbstractEditor editor, ISelectedPanesChangedListener listener) { - ((EditorInput)editor.getEditorInput()).getPaneManager().addSelectedPaneChangedListener(listener); + ((EditorInput) editor.getEditorInput()).getPaneManager() + .addSelectedPaneChangedListener(listener); } /* @@ -1862,362 +2026,342 @@ public class PgenUtil { * com.raytheon.viz.ui.editor.IMultiPaneEditor#removeSelectedPaneChangedListener * (com.raytheon.viz.ui.editor.ISelectedPanesChangedListener) */ - public static void removeSelectedPaneChangedListener( AbstractEditor editor, + public static void removeSelectedPaneChangedListener(AbstractEditor editor, ISelectedPanesChangedListener listener) { - ((EditorInput)editor.getEditorInput()).getPaneManager().removeSelectedPaneChangedListener(listener); + ((EditorInput) editor.getEditorInput()).getPaneManager() + .removeSelectedPaneChangedListener(listener); } + /** + * Retrieve the current data frame time in format of "yyMMdd/HHmm". + * + * Note - this method is modified from + * FramDataDisply.updateFrameDataDisplay(). + * + * @param + * @return a time string in format of "yyMMdd/HHmm" + */ + public static String getCurrentFrameTime() { + return getFrameTime(getCurrentFrameCalendar()); + } - /** - * Retrieve the current data frame time in format of "yyMMdd/HHmm". - * - * Note - this method is modified from FramDataDisply.updateFrameDataDisplay(). - * - * @param - * @return a time string in format of "yyMMdd/HHmm" - */ - public static String getCurrentFrameTime() { - return getFrameTime( getCurrentFrameCalendar() ); - } - - /** - * Retrieve the current data frame's Calendar time. - * - * @param - * @return a Calendar - */ - public static Calendar getCurrentFrameCalendar() { - - Calendar cal = null; - - if( EditorUtil.getActiveEditor() != null) { - - AbstractEditor absEditor = (AbstractEditor)EditorUtil.getActiveEditor(); - - MapDescriptor mapDescriptor = (MapDescriptor)absEditor.getActiveDisplayPane().getRenderableDisplay().getDescriptor(); + /** + * Retrieve the current data frame's Calendar time. + * + * @param + * @return a Calendar + */ + public static Calendar getCurrentFrameCalendar() { - if ( mapDescriptor != null ) { + Calendar cal = null; - int currentFrame = mapDescriptor.getFramesInfo().getFrameIndex(); - - DataTime[] frameTimes = mapDescriptor.getFramesInfo().getFrameTimes(); - - if ( frameTimes != null && currentFrame >= 0 ) { - cal = frameTimes[ currentFrame].getValidTime(); - } - } - } - - return cal; + if (EditorUtil.getActiveEditor() != null) { - } + AbstractEditor absEditor = (AbstractEditor) EditorUtil + .getActiveEditor(); - /** - * Build a frame time in format of "yyMMdd/HHmm" from a Calendar . - * - * @param cal a Calendar - * @return a time string in format of "yyMMdd/HHmm" - */ - public static String getFrameTime( Calendar cal ) { + MapDescriptor mapDescriptor = (MapDescriptor) absEditor + .getActiveDisplayPane().getRenderableDisplay() + .getDescriptor(); - String frameTimeString = ""; - - if( cal != null) { - - SimpleDateFormat FRAME_DATE_FORMAT = new SimpleDateFormat( "EEE yyMMdd/HHmm") ; - FRAME_DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT")); - - String fTimeString = new String( FRAME_DATE_FORMAT.format( cal.getTime() ) ); - if ( fTimeString != null && fTimeString.trim().length() > 0 ) { - String[] ftArrays = fTimeString.split(" "); - if ( ftArrays.length > 1 ) { - frameTimeString = ftArrays[ 1 ]; - } - } - } - - return frameTimeString; + if (mapDescriptor != null) { - } + int currentFrame = mapDescriptor.getFramesInfo() + .getFrameIndex(); - /** - * Get a Calendar by incrementing "HH:MM" to a given Calendar. - * By default, one hour is added to the give Calendar. - * - * @param calIn Calendar - * @param interval a timeString as "HH:MM" - * @return a Calendar - */ - public static Calendar getNextCalendar( Calendar calIn, String interval ) { + DataTime[] frameTimes = mapDescriptor.getFramesInfo() + .getFrameTimes(); + + if (frameTimes != null && currentFrame >= 0) { + cal = frameTimes[currentFrame].getValidTime(); + } + } + } + + return cal; + + } + + /** + * Build a frame time in format of "yyMMdd/HHmm" from a Calendar . + * + * @param cal + * a Calendar + * @return a time string in format of "yyMMdd/HHmm" + */ + public static String getFrameTime(Calendar cal) { + + String frameTimeString = ""; + + if (cal != null) { + + SimpleDateFormat FRAME_DATE_FORMAT = new SimpleDateFormat( + "EEE yyMMdd/HHmm"); + FRAME_DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT")); + + String fTimeString = new String(FRAME_DATE_FORMAT.format(cal + .getTime())); + if (fTimeString != null && fTimeString.trim().length() > 0) { + String[] ftArrays = fTimeString.split(" "); + if (ftArrays.length > 1) { + frameTimeString = ftArrays[1]; + } + } + } + + return frameTimeString; + + } + + /** + * Get a Calendar by incrementing "HH:MM" to a given Calendar. By default, + * one hour is added to the give Calendar. + * + * @param calIn + * Calendar + * @param interval + * a timeString as "HH:MM" + * @return a Calendar + */ + public static Calendar getNextCalendar(Calendar calIn, String interval) { Calendar nCal = null; - - if ( calIn != null ) { - long ftime = calIn.getTimeInMillis(); - long ntime = 60 * 60 * 1000; - if ( interval != null & interval.trim().length() > 0 ) { - String[] intTimes = interval.split( ":" ); - if ( intTimes.length > 1 ) { - ntime = Integer.parseInt( intTimes[0] ) * 60 * 60 * 1000 + - Integer.parseInt( intTimes[1] ) * 60 * 1000 ; - } - else { - ntime = Integer.parseInt( intTimes[0] ) * 60 * 1000 ; - } - } - nCal = Calendar.getInstance(); - nCal.setTimeInMillis( ftime + ntime ); + if (calIn != null) { + long ftime = calIn.getTimeInMillis(); + long ntime = 60 * 60 * 1000; + if (interval != null & interval.trim().length() > 0) { + String[] intTimes = interval.split(":"); + if (intTimes.length > 1) { + ntime = Integer.parseInt(intTimes[0]) * 60 * 60 * 1000 + + Integer.parseInt(intTimes[1]) * 60 * 1000; + } else { + ntime = Integer.parseInt(intTimes[0]) * 60 * 1000; + } + } + + nCal = Calendar.getInstance(); + nCal.setTimeInMillis(ftime + ntime); } - - return nCal; - } - - - /** - * Create a UTC time text widget - */ - public static Text setUTCTimeTextField( Composite parent, final Text validTime, Calendar cal, Control topWidget, int offset ){ - - validTime.setTextLimit(4); - validTime.setText( getInitialTime(cal )); - validTime.addVerifyListener( new VerifyListener(){ + return nCal; - @Override - public void verifyText(VerifyEvent ve) { - final char BACKSPACE = 0x08; - final char DELETE = 0x7F; - - if ( Character.isDigit(ve.character) || Character.UNASSIGNED == ve.character || - ve.character == BACKSPACE || ve.character == DELETE ) ve.doit = true; - else { - ve.doit = false; - Display.getCurrent().beep(); - } - }} ); - - validTime.addModifyListener( new ModifyListener() { + } - @Override - public void modifyText(ModifyEvent e) { - if ( isTimeValid( validTime.getText() ) ) - validTime.setBackground( Display.getCurrent().getSystemColor( SWT.COLOR_WHITE)); - else - validTime.setBackground( Display.getCurrent().getSystemColor( SWT.COLOR_RED)); - } - - }); - - org.eclipse.swt.widgets.Label utcLabel = new org.eclipse.swt.widgets.Label(parent,SWT.NONE); - utcLabel.setText("UTC"); - FormData fd = new FormData(); - parent.setLayout( new FormLayout()); - if ( topWidget != null ) fd.top = new FormAttachment(topWidget,offset, SWT.BOTTOM); - fd.left = new FormAttachment(validTime, 5, SWT.RIGHT); - utcLabel.setLayoutData(fd); - - return validTime; - } - - /** - * check if the input string is a valid time + /** + * Simulate a mouse down event. + * + * @param x + * @param y + * @param button + * @param mapEditor */ - public static boolean isTimeValid(String text) { - int time = Integer.parseInt(text); - int hour = time / 100; - int minute = time % 100; - - if ( hour >= 0 && hour <= 23 && - minute >= 00 && minute <=59 ) return true; - - return false; - } - - /** - * Get the time string in the format HH00 from the input calendar time. - */ - public static String getInitialTime(Calendar now ) { - - - int minute = now.get(Calendar.MINUTE); - if ( minute >= 15 ) now.add(Calendar.HOUR_OF_DAY, 1); - int hour = now.get(Calendar.HOUR_OF_DAY); + public static void simulateMouseDown(int x, int y, int button, + AbstractEditor mapEditor) { + Event me = new Event(); + me.display = mapEditor.getActiveDisplayPane().getDisplay(); + me.button = 1; + me.type = SWT.MouseDown; + me.x = x; + me.y = y; + mapEditor.getMouseManager().handleEvent(me); + } - return String.format("%02d00", hour); - } - /** - * Simulate a mouse down event. - * @param x - * @param y - * @param button - * @param mapEditor - */ - public static void simulateMouseDown(int x, int y, int button, AbstractEditor mapEditor ){ - Event me = new Event(); - me.display = mapEditor.getActiveDisplayPane().getDisplay(); - me.button = 1; - me.type = SWT.MouseDown; - me.x = x; - me.y = y; - mapEditor.getMouseManager().handleEvent(me); - } - - - /** - * telling if the DE is NOT movable. - * @param DrawableElement: the DE to be judged. + * telling if the DE is NOT movable. + * + * @param DrawableElement + * : the DE to be judged. * @return boolean: true not movable. */ - public static boolean isUnmovable(DrawableElement tmpEl){ - if(tmpEl instanceof Volcano ) - return true; - - if(tmpEl instanceof Sigmet ){ - Sigmet vaCloud = (Sigmet)tmpEl; - String type = vaCloud.getType(); - - if(type != null && (type.contains("WINDS")||(type.contains(Sigmet.ISOLATED)))) - return true; - } - - return false; + public static boolean isUnmovable(DrawableElement tmpEl) { + if (tmpEl instanceof Volcano) + return true; + + if (tmpEl instanceof Sigmet) { + Sigmet vaCloud = (Sigmet) tmpEl; + String type = vaCloud.getType(); + + if (type != null + && (type.contains("WINDS") || (type + .contains(Sigmet.ISOLATED)))) + return true; + } + + return false; } - - /* - * Write a set of points into a PGEN file - each point represents the location of a Symbol. - */ - public static void writePgenFile( String path, String fname, String symName, Color symClr, - double size, List pts ) { - - //Default product/layer to hold symbols - Product activeProduct = new Product("Default", "Default", "Default", - new ProductInfo(), new ProductTime(), new ArrayList() ); - - Layer activeLayer = new Layer(); - activeProduct.addLayer( activeLayer ); - - List productList = new ArrayList(); - productList.add( activeProduct ); - - for ( Coordinate c : pts ) { - Symbol cmm = new Symbol( null, new Color[] {symClr}, - 1.0F, size, false, c, "Symbol", symName ); - activeLayer.add( cmm ); - } - Products filePrds1 = ProductConverter.convert( productList ); + /* + * Write a set of points into a PGEN file - each point represents the + * location of a Symbol. + */ + public static void writePgenFile(String path, String fname, String symName, + Color symClr, double size, List pts) { + + // Default product/layer to hold symbols + Product activeProduct = new Product("Default", "Default", "Default", + new ProductInfo(), new ProductTime(), new ArrayList()); + + Layer activeLayer = new Layer(); + activeProduct.addLayer(activeLayer); + + List productList = new ArrayList(); + productList.add(activeProduct); + + for (Coordinate c : pts) { + Symbol cmm = new Symbol(null, new Color[] { symClr }, 1.0F, size, + false, c, "Symbol", symName); + activeLayer.add(cmm); + } + + Products filePrds1 = ProductConverter.convert(productList); String aa = path + "/" + fname; - FileTools.write( aa, filePrds1 ); - } + FileTools.write(aa, filePrds1); + } - /** - * Delete part of a line. - * @param List: line to be partially deleted. - * @param boolean: flag to indicate if a line is closed or open. - * @param Coordinate: first clicked point on line. - * @param Coordinate: second clicked point on line. - * @return List> a list of new lines. - */ - public static List> deleteLinePart( List linePoints, boolean closed, - Coordinate point1, Coordinate point2 ) { - - ArrayList> listOfNewLines = new ArrayList>(); - - Coordinate firstPt; - Coordinate secondPt; - LocationIndexedLine lil; - LinearLocation firstLoc, secondLoc; - - GeometryFactory gf = new GeometryFactory(); + /** + * Delete part of a line. + * + * @param List + * : line to be partially deleted. + * @param boolean: flag to indicate if a line is closed or open. + * @param Coordinate + * : first clicked point on line. + * @param Coordinate + * : second clicked point on line. + * @return List> a list of new lines. + */ + public static List> deleteLinePart( + List linePoints, boolean closed, Coordinate point1, + Coordinate point2) { - /* - * For each given point, find the location of its closest point on the line. - * Save order of points along line. - */ - Coordinate lps[] = new Coordinate[ linePoints.size() ]; - linePoints.toArray( lps ); - CoordinateList clist = new CoordinateList( lps ); - if ( closed ) clist.closeRing(); - LineString ls = gf.createLineString( clist.toCoordinateArray() ); - lil = new LocationIndexedLine(ls); - LinearLocation loc1 = lil.project(point1); - LinearLocation loc2 = lil.project(point2); - if ( loc1.compareTo(loc2) <= 0 ) { - firstLoc = loc1; - secondLoc = loc2; - firstPt = point1; - secondPt = point2; - } - else { - firstLoc = loc2; - secondLoc = loc1; - firstPt = point2; - secondPt = point1; - } - - /* - * Delete open/closed line differently. - */ - if ( !closed ) { - if ( lil.getStartIndex().compareTo( firstLoc ) == 0 && - lil.getEndIndex().getSegmentIndex() == secondLoc.getSegmentIndex() ){ - //Both points selected were endpoints, remove whole element, no new lines. - } - else if ( lil.getStartIndex().compareTo( firstLoc ) == 0 || - lil.getEndIndex().getSegmentIndex() == secondLoc.getSegmentIndex() ) { + ArrayList> listOfNewLines = new ArrayList>(); - //One point selected was an endpoint, remove part from one end to get a new line. - ArrayList newLine = new ArrayList(); - if ( lil.getStartIndex().compareTo( firstLoc ) == 0 ){ - newLine.add(secondPt); - newLine.addAll( linePoints.subList( secondLoc.getSegmentIndex()+1, linePoints.size() )); - } - else if ( lil.getEndIndex().getSegmentIndex() == secondLoc.getSegmentIndex() ){ - newLine.addAll( linePoints.subList( 0, firstLoc.getSegmentIndex()+1 )); - newLine.add(firstPt); - } + Coordinate firstPt; + Coordinate secondPt; + LocationIndexedLine lil; + LinearLocation firstLoc, secondLoc; - if ( newLine.size() >= 2 ) listOfNewLines.add( newLine ); - } - else { - //remove part in the middle of line, create two new lines. - ArrayList newLine1 = new ArrayList( linePoints.subList(0, firstLoc.getSegmentIndex()+1 )); - newLine1.add( firstPt ); + GeometryFactory gf = new GeometryFactory(); + + /* + * For each given point, find the location of its closest point on the + * line. Save order of points along line. + */ + Coordinate lps[] = new Coordinate[linePoints.size()]; + linePoints.toArray(lps); + CoordinateList clist = new CoordinateList(lps); + if (closed) + clist.closeRing(); + LineString ls = gf.createLineString(clist.toCoordinateArray()); + lil = new LocationIndexedLine(ls); + LinearLocation loc1 = lil.project(point1); + LinearLocation loc2 = lil.project(point2); + if (loc1.compareTo(loc2) <= 0) { + firstLoc = loc1; + secondLoc = loc2; + firstPt = point1; + secondPt = point2; + } else { + firstLoc = loc2; + secondLoc = loc1; + firstPt = point2; + secondPt = point1; + } + + /* + * Delete open/closed line differently. + */ + if (!closed) { + if (lil.getStartIndex().compareTo(firstLoc) == 0 + && lil.getEndIndex().getSegmentIndex() == secondLoc + .getSegmentIndex()) { + // Both points selected were endpoints, remove whole element, no + // new lines. + } else if (lil.getStartIndex().compareTo(firstLoc) == 0 + || lil.getEndIndex().getSegmentIndex() == secondLoc + .getSegmentIndex()) { + + // One point selected was an endpoint, remove part from one end + // to get a new line. + ArrayList newLine = new ArrayList(); + if (lil.getStartIndex().compareTo(firstLoc) == 0) { + newLine.add(secondPt); + newLine.addAll(linePoints.subList( + secondLoc.getSegmentIndex() + 1, linePoints.size())); + } else if (lil.getEndIndex().getSegmentIndex() == secondLoc + .getSegmentIndex()) { + newLine.addAll(linePoints.subList(0, + firstLoc.getSegmentIndex() + 1)); + newLine.add(firstPt); + } + + if (newLine.size() >= 2) + listOfNewLines.add(newLine); + } else { + // remove part in the middle of line, create two new lines. + ArrayList newLine1 = new ArrayList( + linePoints.subList(0, firstLoc.getSegmentIndex() + 1)); + newLine1.add(firstPt); + + ArrayList newLine2 = new ArrayList(); + newLine2.add(secondPt); + newLine2.addAll(linePoints.subList( + secondLoc.getSegmentIndex() + 1, linePoints.size())); + + if (newLine1.size() >= 2) + listOfNewLines.add(newLine1); + if (newLine2.size() >= 2) + listOfNewLines.add(newLine2); + } + } else { // closed line + + ArrayList newLine = new ArrayList(); + + int pointsBetween = secondLoc.getSegmentIndex() + - firstLoc.getSegmentIndex(); + + if (pointsBetween > (linePoints.size() - pointsBetween)) { + // if there are more points between pt1 and pt2, remove the + // other part. + newLine.add(firstPt); + newLine.addAll(linePoints.subList( + firstLoc.getSegmentIndex() + 1, + secondLoc.getSegmentIndex() + 1)); + newLine.add(secondPt); + } else { + newLine.add(secondPt); + newLine.addAll(linePoints.subList( + secondLoc.getSegmentIndex() + 1, linePoints.size())); + newLine.addAll(linePoints.subList(0, + firstLoc.getSegmentIndex() + 1)); + newLine.add(firstPt); + } + + listOfNewLines.add(newLine); + } + + return listOfNewLines; + } + + /** + * Returns text auto placement flag + * + * @return + */ + public static boolean getTextAutoPlacement() { + IPreferenceStore prefs = Activator.getDefault().getPreferenceStore(); + return prefs.getBoolean(PgenPreferences.P_AUTOPLACE_TEXT); + } + + /** + * Returns the default PGEN layer merge option. + * + * @return + */ + public static int getLayerMergeOption() { + IPreferenceStore prefs = Activator.getDefault().getPreferenceStore(); + return prefs.getInt(PgenPreferences.P_LAYER_MERGE); + } - ArrayList newLine2 = new ArrayList(); - newLine2.add( secondPt ); - newLine2.addAll( linePoints.subList( secondLoc.getSegmentIndex()+1, linePoints.size() ) ); - - if ( newLine1.size() >= 2 ) listOfNewLines.add( newLine1 ); - if ( newLine2.size() >= 2 ) listOfNewLines.add( newLine2 ); - } - } - else { //closed line - - ArrayList newLine = new ArrayList(); - - int pointsBetween = secondLoc.getSegmentIndex() - firstLoc.getSegmentIndex(); - - if ( pointsBetween > (linePoints.size() - pointsBetween) ) { - //if there are more points between pt1 and pt2, remove the other part. - newLine.add( firstPt ); - newLine.addAll( linePoints.subList( firstLoc.getSegmentIndex()+1, - secondLoc.getSegmentIndex()+1 )); - newLine.add( secondPt ); - } - else { - newLine.add( secondPt ); - newLine.addAll(linePoints.subList( secondLoc.getSegmentIndex()+1, linePoints.size() )); - newLine.addAll(linePoints.subList(0, firstLoc.getSegmentIndex()+1 )); - newLine.add( firstPt ); - } - - listOfNewLines.add( newLine ); - } - - return listOfNewLines; - } - } diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/AttrDlg.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/AttrDlg.java index bacfa82534..2e3a9c4962 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/AttrDlg.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/AttrDlg.java @@ -8,9 +8,23 @@ package gov.noaa.nws.ncep.ui.pgen.attrdialog; -import java.util.ArrayList; -import java.awt.Color; +import gov.noaa.nws.ncep.ui.pgen.PgenUtil; +import gov.noaa.nws.ncep.ui.pgen.attrdialog.vaadialog.VaaCloudDlg; +import gov.noaa.nws.ncep.ui.pgen.attrdialog.vaadialog.VolcanoVaaAttrDlg; +import gov.noaa.nws.ncep.ui.pgen.display.IAttribute; +import gov.noaa.nws.ncep.ui.pgen.elements.AbstractDrawableComponent; +import gov.noaa.nws.ncep.ui.pgen.elements.DECollection; +import gov.noaa.nws.ncep.ui.pgen.elements.DrawableElement; +import gov.noaa.nws.ncep.ui.pgen.elements.Jet; +import gov.noaa.nws.ncep.ui.pgen.rsc.PgenResource; +import gov.noaa.nws.ncep.ui.pgen.sigmet.AbstractSigmet; +import gov.noaa.nws.ncep.ui.pgen.sigmet.Sigmet; +import java.awt.Color; +import java.util.ArrayList; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; @@ -21,26 +35,14 @@ import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.jface.dialogs.IDialogConstants; import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.viz.ui.editor.AbstractEditor; -import gov.noaa.nws.ncep.ui.pgen.PgenUtil; -import gov.noaa.nws.ncep.ui.pgen.rsc.PgenResource; -import gov.noaa.nws.ncep.ui.pgen.elements.AbstractDrawableComponent; -import gov.noaa.nws.ncep.ui.pgen.elements.DECollection; -import gov.noaa.nws.ncep.ui.pgen.elements.DrawableElement; -import gov.noaa.nws.ncep.ui.pgen.display.IAttribute; -import gov.noaa.nws.ncep.ui.pgen.elements.Jet; //import gov.noaa.nws.ncep.viz.ui.display.NCMapEditor; -import gov.noaa.nws.ncep.ui.pgen.sigmet.*; -import gov.noaa.nws.ncep.ui.pgen.attrdialog.vaadialog.*; /** - * This class is the abstract class that all PGEN attribute dialogs - * extend from. + * This class is the abstract class that all PGEN attribute dialogs extend from. * *
  * SOFTWARE HISTORY
@@ -62,454 +64,492 @@ import gov.noaa.nws.ncep.ui.pgen.attrdialog.vaadialog.*;
  * 03/13		#928		B. Yin		Make the button bar smaller.
  * 04/13 		#874		B. Yin		Handle collection when OK is pressed for multi-selection.
  * 04/13        TTR399      J. Wu  		Make the dialog compact
- *
+ * 
  * 
* - * @author B. Yin + * @author B. Yin */ -//public abstract class AttrDlg extends CaveJFACEDialog implements IAttribute { +// public abstract class AttrDlg extends CaveJFACEDialog implements IAttribute { public abstract class AttrDlg extends Dialog implements IAttribute { - - public static int ctrlBtnWidth = 70; - public static int ctrlBtnHeight = 28; -// public static int ctrlBtnWidth = 90; -// public static int ctrlBtnHeight = 30; - - /** - * A handler to the current PGEN drawing layer, which is used to - * get the selected element. - */ - protected PgenResource drawingLayer = null; - - /** - * A handler to the current map editor. The map editor is used to - * redraw the drawing layer when user click on 'OK'. - */ -// protected NCMapEditor mapEditor = null; - protected AbstractEditor mapEditor = null; - protected String pgenCategory = null; - protected String pgenType = null; - protected static final int CHK_WIDTH = 16; - protected static final int CHK_HEIGHT = 28; - - protected static String mouseHandlerName = null; - protected static AbstractDrawableComponent de = null; - - protected Point shellLocation; - - /** - * AttrDlg constructor - * @param parShell - * @throws VizException - */ - public AttrDlg(Shell parShell) throws VizException { - + + public static int ctrlBtnWidth = 70; + + public static int ctrlBtnHeight = 28; + + // public static int ctrlBtnWidth = 90; + // public static int ctrlBtnHeight = 30; + + /** + * A handler to the current PGEN drawing layer, which is used to get the + * selected element. + */ + protected PgenResource drawingLayer = null; + + /** + * A handler to the current map editor. The map editor is used to redraw the + * drawing layer when user click on 'OK'. + */ + protected AbstractEditor mapEditor = null; + + protected String pgenCategory = null; + + protected String pgenType = null; + + protected static final int CHK_WIDTH = 16; + + protected static final int CHK_HEIGHT = 28; + + protected static String mouseHandlerName = null; + + protected static AbstractDrawableComponent de = null; + + protected Point shellLocation; + + /** + * AttrDlg constructor + * + * @param parShell + * @throws VizException + */ + public AttrDlg(Shell parShell) throws VizException { + super(parShell); - this.setShellStyle(SWT.TITLE | SWT.MODELESS | SWT.CLOSE ); - - } + this.setShellStyle(SWT.TITLE | SWT.MODELESS | SWT.CLOSE); - @Override - public void createButtonsForButtonBar(Composite parent){ - ((GridLayout)parent.getLayout()).verticalSpacing = 0; - ((GridLayout)parent.getLayout()).marginHeight = 3; - - super.createButtonsForButtonBar(parent); - this.getButton(IDialogConstants.CANCEL_ID).setEnabled(false); - this.getButton(IDialogConstants.OK_ID).setEnabled(false); - - this.getButton(IDialogConstants.CANCEL_ID).setLayoutData( new GridData(ctrlBtnWidth,ctrlBtnHeight)); - this.getButton(IDialogConstants.OK_ID).setLayoutData( new GridData(ctrlBtnWidth,ctrlBtnHeight)); - - } - - @Override - public Control createButtonBar(Composite parent){ - - Control bar = super.createButtonBar(parent); - GridData gd = new GridData(SWT.CENTER, SWT.DEFAULT, true, false); - gd.heightHint = ctrlBtnHeight + 5; - - bar.setLayoutData(gd); - return bar; - - } - - /* - * Called when "X" button on window is clicked. - * @see org.eclipse.jface.window.Window#handleShellCloseEvent() - */ - @Override - public void handleShellCloseEvent() { - drawingLayer.removeSelected(); - drawingLayer.removeGhostLine(); - super.handleShellCloseEvent(); - PgenUtil.setSelectingMode(); - } - - public abstract void setAttrForDlg(IAttribute ia); - - /** - * Sets the PGEN drawing layer - * @param dl - */ - public void setDrawingLayer( PgenResource dl ){ - - this.drawingLayer = dl; - - } - - /** - * Sets the map editor - * @param me - */ -// public void setMapEditor( NCMapEditor me ){ - public void setMapEditor( AbstractEditor me ){ - this.mapEditor = me; - } - - /** - * Updates the selected element and redraws the PGEN layer. - */ - public void okPressed(){ - - /* - * JetBarb/Jet/Hash/JetText cannot be multi-selected and they are - * separated from those that can be multi-selected. - */ - DrawableElement de = drawingLayer.getSelectedDE(); - if ( de != null && - ( de instanceof Jet.JetBarb || - de instanceof Jet.JetHash || - de instanceof Jet.JetText || - de instanceof Jet.JetLine ) ){ - - DrawableElement newEl = (DrawableElement)de.copy(); - - //for jet barb, we need replace the whole jet for undo working - if ( de instanceof Jet.JetBarb ){ - DECollection wind = (DECollection) de.getParent(); - if ( wind != null && wind.getCollectionName().equalsIgnoreCase("WindInfo")){ - DECollection parent = (DECollection) wind.getParent(); - if( parent != null && parent.getCollectionName().equalsIgnoreCase("jet")){ - Jet oldJet = (Jet)parent; - Jet newJet = oldJet.copy(); - DECollection newWind = wind.copy(); - newJet.replace(newJet.getNearestComponent(((Jet.JetBarb)de).getLocation()), newWind); - drawingLayer.replaceElement(oldJet, newJet); - - newWind.replace(newWind.getNearestComponent(((Jet.JetBarb)de).getLocation()), newEl); - if (newEl instanceof Jet.JetBarb ){ - newEl.update(this); - ((Jet.JetBarb) newEl).setSpeed(((Jet.JetBarb)newEl).getSpeed()); - JetAttrDlg.getInstance(this.getShell()).updateBarbTemplate( (Jet.JetBarb)newEl ); - } - } - } - } - else { - newEl.update(this); - drawingLayer.replaceElement(de, newEl); - - //reset the jet line attributes - if ( de instanceof Jet.JetLine){ - AbstractDrawableComponent adc = AttrSettings.getInstance().getSettings().get( "JET" ); - if ( adc instanceof Jet ){ - ((Jet)adc).getJetLine().update(this); - } - } - else if ( de instanceof Jet.JetHash ){ - JetAttrDlg.getInstance(this.getShell()).updateHashTemplate((Jet.JetHash)newEl ); - } - else if ( de instanceof Jet.JetText ){ - JetAttrDlg.getInstance(this.getShell()).updateFlTemplate((Jet.JetText)newEl ); - } - } - - drawingLayer.removeSelected(); - drawingLayer.setSelected(newEl); - } - else { - - ArrayList adcList = null; - ArrayList newList = new ArrayList() ; - - // get the list of selected elements - if ( drawingLayer != null ) { - adcList = (ArrayList) drawingLayer.getAllSelected(); - } - - if ( adcList != null && !adcList.isEmpty() ){ - DrawableElement newEl = null; - //loop through the list and update attributes - for ( AbstractDrawableComponent adc : adcList){ - - DrawableElement el = adc.getPrimaryDE(); - - if ( el != null ){ - - // Create a copy of the currently selected element - newEl = (DrawableElement)el.copy(); - - // Update the new Element with these current attributes - newEl.update(this); - - if ( adc instanceof DECollection && el.getParent() == adc ){ - //for collections - DECollection dec = (DECollection) adc.copy(); - dec.remove(dec.getPrimaryDE()); - dec.add(0, newEl); - newList.add(dec); - } - else { - newList.add(newEl); - } - } - } - - if ( newEl != null ){ - AttrSettings.getInstance().setSettings( newEl ); - } - - ArrayList oldList = new ArrayList(adcList); - drawingLayer.replaceElements(null, oldList, newList); - } - - drawingLayer.removeSelected(); - - //set new elements as selected - for ( AbstractDrawableComponent adc : newList ){ - drawingLayer.addSelected(adc); - } - - } - - if ( mapEditor != null ) { - mapEditor.refresh(); - } - - } - - /** - * Removes ghost line, handle bars, and closes the dialog - */ - public void cancelPressed(){ - - drawingLayer.removeSelected(); - drawingLayer.removeGhostLine(); - super.cancelPressed(); - - } - - /** - * Set the location of the dialog - */ - public int open(){ - - if ( this.getShell() == null ){ - this.create(); - } - if(shellLocation == null){ - this.getShell().setLocation(this.getShell().getParent().getLocation()); - } else { - getShell().setLocation(shellLocation); - } - - final Shell shell = this.getShell(); - // When the editor pane is being activated, the tool manager will re-activate all tools and thus - // the PGEN attribute dialog will re-open. However if the PGEN palette gets activated by a mouse - // click (or mouse over) before the attribute dialog is open, you will get an exception that - // activates PGEN palette in the middle of activating the editor. The reason why this happens is that - // the shell open() method forces the display to dispatch the click event on PGEN palette, which - // activates the PGEN palette. - // To prevent this happens, the super.open() method must be invoked after the editor has been activated. - // We put super.open() in the UI thread, which is the same thread the activation is running, so that - // it is invoked after the activation. --bingfan 8/10/12 - Display.getDefault().asyncExec(new Runnable() { - @Override - public void run() { - // while (Display.getDefault().readAndDispatch()) { - //wait for events to finish before continue - // } - if (!( shell == null || shell.isDisposed() )) { // make sure the dialog is not closed - AttrDlg.super.open(); - } - } - }); - - return OK; - } - - /** - * Save location of the dialog. - */ - public boolean close() { - if(getShell() != null){ - Rectangle bounds = getShell().getBounds(); - shellLocation = new Point(bounds.x, bounds.y); - } - return super.close(); - } - - /** - * Enables the 'OK' button and the 'Cancel' button - */ - public void enableButtons(){ - - this.getButton(IDialogConstants.CANCEL_ID).setEnabled(true); - this.getButton(IDialogConstants.OK_ID).setEnabled(true); - - } - - /** - * Sets the Pgen type, which will be used when creating an new - * element from the 'Place symbol' button - * @param pgenType - */ - public void setPgenType( String pgenType ){ - - this.pgenType = pgenType; - - } - - /** - * Sets the Pgen type, which will be used when creating an new - * element from the 'Place symbol' button - * @param pgenType - */ - public void setPgenCategory( String pgenCategory ){ - - this.pgenCategory = pgenCategory; - - } - /** - * Common interface for ISinglePoint and IMultiPoint. - */ - public Color[] getColors(){ - return null; - } - - public float getLineWidth(){ - return 1.0f; } - - public double getSizeScale(){ - return 1.0; - } - - public String getType(){ - return null; - } - - //to be override by subclasses - public void setType(String type){ - - } - /** + @Override + public void createButtonsForButtonBar(Composite parent) { + ((GridLayout) parent.getLayout()).verticalSpacing = 0; + ((GridLayout) parent.getLayout()).marginHeight = 3; + + super.createButtonsForButtonBar(parent); + this.getButton(IDialogConstants.CANCEL_ID).setEnabled(false); + this.getButton(IDialogConstants.OK_ID).setEnabled(false); + + this.getButton(IDialogConstants.CANCEL_ID).setLayoutData( + new GridData(ctrlBtnWidth, ctrlBtnHeight)); + this.getButton(IDialogConstants.OK_ID).setLayoutData( + new GridData(ctrlBtnWidth, ctrlBtnHeight)); + + } + + @Override + public Control createButtonBar(Composite parent) { + + Control bar = super.createButtonBar(parent); + GridData gd = new GridData(SWT.CENTER, SWT.DEFAULT, true, false); + gd.heightHint = ctrlBtnHeight + 5; + + bar.setLayoutData(gd); + return bar; + + } + + /* + * Called when "X" button on window is clicked. + * + * @see org.eclipse.jface.window.Window#handleShellCloseEvent() + */ + @Override + public void handleShellCloseEvent() { + drawingLayer.removeSelected(); + drawingLayer.removeGhostLine(); + super.handleShellCloseEvent(); + PgenUtil.setSelectingMode(); + } + + public abstract void setAttrForDlg(IAttribute ia); + + /** + * Sets the PGEN drawing layer + * + * @param dl + */ + public void setDrawingLayer(PgenResource dl) { + + this.drawingLayer = dl; + + } + + /** + * Sets the map editor + * + * @param me + */ + // public void setMapEditor( NCMapEditor me ){ + public void setMapEditor(AbstractEditor me) { + this.mapEditor = me; + } + + /** + * Updates the selected element and redraws the PGEN layer. + */ + public void okPressed() { + + /* + * JetBarb/Jet/Hash/JetText cannot be multi-selected and they are + * separated from those that can be multi-selected. + */ + DrawableElement de = drawingLayer.getSelectedDE(); + if (de != null + && (de instanceof Jet.JetBarb || de instanceof Jet.JetHash + || de instanceof Jet.JetText || de instanceof Jet.JetLine)) { + + DrawableElement newEl = (DrawableElement) de.copy(); + + // for jet barb, we need replace the whole jet for undo working + if (de instanceof Jet.JetBarb) { + DECollection wind = (DECollection) de.getParent(); + if (wind != null + && wind.getCollectionName() + .equalsIgnoreCase("WindInfo")) { + DECollection parent = (DECollection) wind.getParent(); + if (parent != null + && parent.getCollectionName().equalsIgnoreCase( + "jet")) { + Jet oldJet = (Jet) parent; + Jet newJet = oldJet.copy(); + DECollection newWind = wind.copy(); + newJet.replace(newJet + .getNearestComponent(((Jet.JetBarb) de) + .getLocation()), newWind); + drawingLayer.replaceElement(oldJet, newJet); + + newWind.replace(newWind + .getNearestComponent(((Jet.JetBarb) de) + .getLocation()), newEl); + if (newEl instanceof Jet.JetBarb) { + newEl.update(this); + ((Jet.JetBarb) newEl) + .setSpeed(((Jet.JetBarb) newEl).getSpeed()); + JetAttrDlg.getInstance(this.getShell()) + .updateBarbTemplate((Jet.JetBarb) newEl); + } + } + } + } else { + newEl.update(this); + drawingLayer.replaceElement(de, newEl); + + // reset the jet line attributes + if (de instanceof Jet.JetLine) { + AbstractDrawableComponent adc = AttrSettings.getInstance() + .getSettings().get("JET"); + if (adc instanceof Jet) { + ((Jet) adc).getJetLine().update(this); + } + } else if (de instanceof Jet.JetHash) { + JetAttrDlg.getInstance(this.getShell()).updateHashTemplate( + (Jet.JetHash) newEl); + } else if (de instanceof Jet.JetText) { + JetAttrDlg.getInstance(this.getShell()).updateFlTemplate( + (Jet.JetText) newEl); + } + } + + drawingLayer.removeSelected(); + drawingLayer.setSelected(newEl); + } else { + + ArrayList adcList = null; + ArrayList newList = new ArrayList(); + + // get the list of selected elements + if (drawingLayer != null) { + adcList = (ArrayList) drawingLayer + .getAllSelected(); + } + + if (adcList != null && !adcList.isEmpty()) { + DrawableElement newEl = null; + // loop through the list and update attributes + for (AbstractDrawableComponent adc : adcList) { + + DrawableElement el = adc.getPrimaryDE(); + + if (el != null) { + + // Create a copy of the currently selected element + newEl = (DrawableElement) el.copy(); + + // Update the new Element with these current attributes + newEl.update(this); + + if (adc instanceof DECollection + && el.getParent() == adc) { + // for collections + DECollection dec = (DECollection) adc.copy(); + dec.remove(dec.getPrimaryDE()); + dec.add(0, newEl); + newList.add(dec); + } else { + newList.add(newEl); + } + } + } + + if (newEl != null) { + AttrSettings.getInstance().setSettings(newEl); + } + + ArrayList oldList = new ArrayList( + adcList); + drawingLayer.replaceElements(null, oldList, newList); + } + + drawingLayer.removeSelected(); + + // set new elements as selected + for (AbstractDrawableComponent adc : newList) { + drawingLayer.addSelected(adc); + } + + } + + if (mapEditor != null) { + mapEditor.refresh(); + } + + } + + /** + * Removes ghost line, handle bars, and closes the dialog + */ + public void cancelPressed() { + + drawingLayer.removeSelected(); + drawingLayer.removeGhostLine(); + super.cancelPressed(); + + } + + /** + * Set the location of the dialog + */ + public int open() { + + if (this.getShell() == null) { + this.create(); + } + if (shellLocation == null) { + this.getShell().setLocation( + this.getShell().getParent().getLocation()); + } else { + getShell().setLocation(shellLocation); + } + + final Shell shell = this.getShell(); + // When the editor pane is being activated, the tool manager will + // re-activate all tools and thus + // the PGEN attribute dialog will re-open. However if the PGEN palette + // gets activated by a mouse + // click (or mouse over) before the attribute dialog is open, you will + // get an exception that + // activates PGEN palette in the middle of activating the editor. The + // reason why this happens is that + // the shell open() method forces the display to dispatch the click + // event on PGEN palette, which + // activates the PGEN palette. + // To prevent this happens, the super.open() method must be invoked + // after the editor has been activated. + // We put super.open() in the UI thread, which is the same thread the + // activation is running, so that + // it is invoked after the activation. --bingfan 8/10/12 + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + // while (Display.getDefault().readAndDispatch()) { + // wait for events to finish before continue + // } + if (!(shell == null || shell.isDisposed())) { // make sure the + // dialog is not + // closed + AttrDlg.super.open(); + } + } + }); + + return OK; + } + + /** + * Save location of the dialog. + */ + public boolean close() { + if (getShell() != null) { + Rectangle bounds = getShell().getBounds(); + shellLocation = new Point(bounds.x, bounds.y); + } + return super.close(); + } + + /** + * Enables the 'OK' button and the 'Cancel' button + */ + public void enableButtons() { + + this.getButton(IDialogConstants.CANCEL_ID).setEnabled(true); + this.getButton(IDialogConstants.OK_ID).setEnabled(true); + + } + + /** + * Sets the Pgen type, which will be used when creating an new element from + * the 'Place symbol' button + * + * @param pgenType + */ + public void setPgenType(String pgenType) { + + this.pgenType = pgenType; + + } + + /** + * Sets the Pgen type, which will be used when creating an new element from + * the 'Place symbol' button + * + * @param pgenType + */ + public void setPgenCategory(String pgenCategory) { + + this.pgenCategory = pgenCategory; + + } + + /** + * Common interface for ISinglePoint and IMultiPoint. + */ + public Color[] getColors() { + return null; + } + + public float getLineWidth() { + return 1.0f; + } + + public double getSizeScale() { + return 1.0; + } + + public String getType() { + return null; + } + + // to be override by subclasses + public void setType(String type) { + + } + + /** * Add a horizontal separator to the display. */ - public static void addSeparator(Composite top ) { + public static void addSeparator(Composite top) { GridData gd = new GridData(GridData.FILL_HORIZONTAL); Label sepLbl = new Label(top, SWT.SEPARATOR | SWT.HORIZONTAL); sepLbl.setLayoutData(gd); } - - public void setMouseHandlerName(String name){ - mouseHandlerName = name; - } - - public void setDrawableElement(AbstractDrawableComponent adc){ - if ( adc instanceof DrawableElement ){ - DrawableElement de = (DrawableElement)adc; - if("INTL_SIGMET".equals(pgenType)){ - ((SigmetAttrDlg)this).setSigmet(de); - ((SigmetAttrDlg)this).copyEditableAttrToSigmetAttrDlg((Sigmet)de); - }else if("VOLC_SIGMET".equals(pgenType)){ - ((VolcanoVaaAttrDlg)this).setVolcano(de); - }else if("VACL_SIGMET".equals(pgenType)){ - ((VaaCloudDlg)this).setSigmet(de); - } else if("SIGMET".equalsIgnoreCase(pgenCategory)){ - if("CCFP_SIGMET".equals(pgenType)) { - ((gov.noaa.nws.ncep.ui.pgen.attrdialog.vaadialog.CcfpAttrDlg)this).setAbstractSigmet(de); - return; - } - - ((SigmetCommAttrDlg)this).setAbstractSigmet(de); - ((SigmetCommAttrDlg)this).copyEditableAttrToSigmetAttrDlg((AbstractSigmet)de); - } - else { - AttrDlg.de = de; - } - } - else { - AttrDlg.de = adc; - } - } - - public AbstractDrawableComponent getDrawableElement(){ - return de; + public void setMouseHandlerName(String name) { + mouseHandlerName = name; } - /** - * Set default attributes for the current pgen type. - */ - public void setDefaultAttr(){ + public void setDrawableElement(AbstractDrawableComponent adc) { + if (adc instanceof DrawableElement) { + DrawableElement de = (DrawableElement) adc; + if ("INTL_SIGMET".equals(pgenType)) { + ((SigmetAttrDlg) this).setSigmet(de); + ((SigmetAttrDlg) this) + .copyEditableAttrToSigmetAttrDlg((Sigmet) de); + } else if ("VOLC_SIGMET".equals(pgenType)) { + ((VolcanoVaaAttrDlg) this).setVolcano(de); + } else if ("VACL_SIGMET".equals(pgenType)) { + ((VaaCloudDlg) this).setSigmet(de); + } else if ("SIGMET".equalsIgnoreCase(pgenCategory)) { - AbstractDrawableComponent adc = AttrSettings.getInstance().getSettings().get( pgenType ); - if ( adc != null ) { - setAttr( adc ); - } + if ("CCFP_SIGMET".equals(pgenType)) { + ((gov.noaa.nws.ncep.ui.pgen.attrdialog.vaadialog.CcfpAttrDlg) this) + .setAbstractSigmet(de); + return; + } + ((SigmetCommAttrDlg) this).setAbstractSigmet(de); + ((SigmetCommAttrDlg) this) + .copyEditableAttrToSigmetAttrDlg((AbstractSigmet) de); + } else { + AttrDlg.de = de; + } + } else { + AttrDlg.de = adc; + } } - + + public AbstractDrawableComponent getDrawableElement() { + return de; + } + /** - * Set dialog attributes with values of adc. - */ - public void setAttr( AbstractDrawableComponent adc ){ - if ( adc instanceof IAttribute ){ - setAttrForDlg( (IAttribute)adc); - } + * Set default attributes for the current pgen type. + */ + public void setDefaultAttr() { + + AbstractDrawableComponent adc = AttrSettings.getInstance() + .getSettings().get(pgenType); + if (adc != null) { + setAttr(adc); + } + + } + + /** + * Set dialog attributes with values of adc. + */ + public void setAttr(AbstractDrawableComponent adc) { + if (adc instanceof IAttribute) { + setAttrForDlg((IAttribute) adc); + } } /** * check if it is in 'add line' mode (for labeled lines) + * * @return */ - public boolean isAddLineMode(){ - return false; + public boolean isAddLineMode() { + return false; } - + /** * reset toggle buttons for labeled line dialog */ - public void resetLabeledLineBtns(){ - - } - - /* - * Create a GridLayout without any spacing and no equal width. - */ - protected GridLayout getCompactGridLayout(int numCol) { - return getGridLayout( numCol,false, 0, 0, 0, 0); - } + public void resetLabeledLineBtns() { - /* - * Create a GridLayout with specified numCol, equal_width, marginHeight, - * marginWidth, horizontalSpacing, and verticalSpacing - */ - protected GridLayout getGridLayout(int numCol, boolean equal_width, - int marginHeight, int marginWidth, int horizontalSpacing, int verticalSpacing) { - - GridLayout gl = new GridLayout( numCol, equal_width ); + } + + /* + * Create a GridLayout without any spacing and no equal width. + */ + protected GridLayout getCompactGridLayout(int numCol) { + return getGridLayout(numCol, false, 0, 0, 0, 0); + } + + /* + * Create a GridLayout with specified numCol, equal_width, marginHeight, + * marginWidth, horizontalSpacing, and verticalSpacing + */ + protected GridLayout getGridLayout(int numCol, boolean equal_width, + int marginHeight, int marginWidth, int horizontalSpacing, + int verticalSpacing) { + + GridLayout gl = new GridLayout(numCol, equal_width); gl.marginHeight = marginHeight; gl.marginWidth = marginWidth; gl.horizontalSpacing = horizontalSpacing; gl.verticalSpacing = verticalSpacing; - - return gl; - } + + return gl; + } } diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/AttrDlgFactory.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/AttrDlgFactory.java index cd397fa937..e9c66c8ae6 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/AttrDlgFactory.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/AttrDlgFactory.java @@ -8,14 +8,15 @@ package gov.noaa.nws.ncep.ui.pgen.attrdialog; +import gov.noaa.nws.ncep.ui.pgen.attrdialog.vaadialog.VaaCloudDlg; +import gov.noaa.nws.ncep.ui.pgen.attrdialog.vaadialog.VolcanoVaaAttrDlg; import gov.noaa.nws.ncep.ui.pgen.elements.Track; -import gov.noaa.nws.ncep.ui.pgen.attrdialog.vaadialog.*; import org.eclipse.swt.widgets.Shell; /** * This class is to create attribute dialogs for PGEN elements. - * + * *
  * SOFTWARE HISTORY
  * Date       	Ticket#		Engineer	Description
@@ -40,205 +41,200 @@ import org.eclipse.swt.widgets.Shell;
  * 02/11        #318        S. Gilbert  Added Distance Display Options Dialog
  * 08/11		#?			B. Yin		Added Pgen Inc/Dec 
  * 06/12        #734        J. Zeng     Add SPENES
+ * 11/13        #1065       J. Wu       Added kink lines.
  * 
* - * @author B. Yin + * @author B. Yin */ public class AttrDlgFactory { - - /** - * Creates attribute dialog by invoking the getInstance() method. - * - * @param pgenCategory Category corresponding to the DE's pgenCategory specifying a - * class in the Pgen Palette. - * @param parShell parent Shell - * @return - */ - - public static AttrDlg createAttrDlg( String pgenCategory, String pgenType, Shell parShell ){ - - if ( pgenCategory == null ) { - return null; - } - - if ((pgenCategory.equalsIgnoreCase("Lines")) || - // (pgenCategory.equalsIgnoreCase("Front")) || - ((pgenType != null) && pgenType.equalsIgnoreCase("STATUS_LINE"))) { - - return LineAttrDlg.getInstance( parShell ); - - } - - else if (pgenCategory.equalsIgnoreCase("Front")) { - return FrontAttrDlg.getInstance( parShell ); - } - - else if ((pgenCategory.equalsIgnoreCase("Marker")) || - (pgenCategory.equalsIgnoreCase("Symbol")) || - (pgenCategory.equalsIgnoreCase("Combo")) ) { - - if (pgenType != null && (pgenType.equalsIgnoreCase("PRESENT_WX_201"))){ - return VolcanoAttrDlg.getInstance( parShell ); - } - else { - AttrDlg symDlg = LabeledSymbolAttrDlg.getInstance( parShell ); - symDlg.setPgenCategory(pgenCategory); - symDlg.setPgenType(pgenType); - return symDlg; - } - - } - else if ( pgenCategory.equalsIgnoreCase("Text" ) ) { - - if ( pgenType != null && pgenType.equalsIgnoreCase("AVIATION_TEXT") ) { - return AvnTextAttrDlg.getInstance( parShell ); - } - else if ( pgenType != null && pgenType.equalsIgnoreCase("MID_LEVEL_CLOUD") ) { - return MidLevelCloudAttrDlg.getInstance( parShell ); - } - else { - return TextAttrDlg.getInstance( parShell ); - } - - } + /** + * Creates attribute dialog by invoking the getInstance() method. + * + * @param pgenCategory + * Category corresponding to the DE's pgenCategory specifying a + * class in the Pgen Palette. + * @param parShell + * parent Shell + * @return + */ - else if ( pgenCategory.equalsIgnoreCase("Arc" ) ) { - - return ArcAttrDlg.getInstance( parShell ); - - } - else if ( pgenCategory.equalsIgnoreCase(Track.TRACK_PGEN_CATEGORY) ) { - - return TrackAttrDlg.getInstance( parShell ); - - } - else if ( pgenCategory.equalsIgnoreCase(Track.TRACK_INFO_DLG_CATEGORY_NAME) ) { - - return TrackExtrapPointInfoDlg.getInstance( parShell ); - - } - else if ( pgenCategory.equalsIgnoreCase( "Vector" ) ) { - - return VectorAttrDlg.getInstance( parShell ); - - } - else if ( pgenCategory.equalsIgnoreCase( "Extrap" ) ) { - - return PgenExtrapDlg.getInstance( parShell ); - - } - else if ( pgenCategory.equalsIgnoreCase( "Interp" ) ) { - - return PgenInterpDlg.getInstance( parShell ); - - } - else if ( pgenCategory.equalsIgnoreCase( "IncDec" ) ) { - - return IncDecDlg.getInstance( parShell ); - - } - else if ( pgenCategory.equalsIgnoreCase( "Distance" ) ) { - - return PgenDistanceDlg.getInstance( parShell ); - - } - else if ( pgenCategory.equalsIgnoreCase( "From" ) ) { - - return FromAttrDlg.getInstance( parShell ); - - } - else if ( pgenCategory.equalsIgnoreCase( "Cycle" ) ) { - - return CycleDlg.getInstance( parShell ); - - } - else if ( pgenCategory.equalsIgnoreCase( "Prod_AIRMET" ) ) { - - return GfaFormatAttrDlg.getInstance( parShell ); - - } - else if (pgenType != null && pgenType.equalsIgnoreCase("Jet")){ - - return JetAttrDlg.getInstance(parShell); - } - else if (pgenType != null && pgenType.equalsIgnoreCase("Outlook")){ - return OutlookAttrDlg.getInstance(parShell); - } - else if ( pgenType != null && pgenType.equalsIgnoreCase("TCA") ) { - - return TcaAttrDlg.getInstance( parShell ); - - } - else if ( pgenType != null && pgenType.equalsIgnoreCase("WatchBox") ) { - - return WatchBoxAttrDlg.getInstance( parShell ); - - } - else if ((pgenType != null) && pgenType.equalsIgnoreCase("SPENES")) { - return SpenesAttrDlg.getInstance( parShell ); + public static AttrDlg createAttrDlg(String pgenCategory, String pgenType, + Shell parShell) { - } - else if ( pgenType != null && pgenType.equalsIgnoreCase("TCM") ) { - - return TcmAttrDlg.getInstance( parShell ); - - } - else if ( pgenType != null && pgenType.equalsIgnoreCase("Cloud") ) { - - return CloudAttrDlg.getInstance( parShell ); - - } - else if ( pgenType != null && pgenType.equalsIgnoreCase("Turbulence") ) { - - return TurbAttrDlg.getInstance( parShell ); - - } - else if ( pgenType != null && pgenType.equalsIgnoreCase("Contours") ) { - - return ContoursAttrDlg.getInstance( parShell ); - - } - else if(pgenCategory.equalsIgnoreCase("SIGMET") ){ - - if(pgenType != null && pgenType.equalsIgnoreCase("INTL_SIGMET")) { - SigmetAttrDlg sigAttrDlg = SigmetAttrDlg.getInstance( parShell ); - sigAttrDlg.setPgenCategory(pgenCategory); - sigAttrDlg.setPgenType(pgenType); - return sigAttrDlg; - }else if(pgenType != null && pgenType.equalsIgnoreCase("VOLC_SIGMET")){ - VolcanoVaaAttrDlg vaaDlg = VolcanoVaaAttrDlg.getInstance(parShell); - vaaDlg.setPgenCategory(pgenCategory); - vaaDlg.setPgenType(pgenType); - vaaDlg.setFromSelection(true); - return vaaDlg; - }else if(pgenType != null && pgenType.equalsIgnoreCase("VACL_SIGMET")){ - VaaCloudDlg vacDlg = VaaCloudDlg.getInstance(parShell); - vacDlg.setPgenCategory(pgenCategory); - vacDlg.setPgenType(pgenType); - return vacDlg; - - }else if(pgenType != null && pgenType.equalsIgnoreCase("CCFP_SIGMET")){ - gov.noaa.nws.ncep.ui.pgen.attrdialog.vaadialog.CcfpAttrDlg sigAttrDlg = - gov.noaa.nws.ncep.ui.pgen.attrdialog.vaadialog.CcfpAttrDlg.getInstance( parShell ); - sigAttrDlg.setPgenCategory(pgenCategory); - sigAttrDlg.setPgenType(pgenType); - return sigAttrDlg; - }else {//(pgenType != null && pgenType.equalsIgnoreCase("CONV_SIGMET")) { - SigmetCommAttrDlg sigAttrDlg = SigmetCommAttrDlg.getInstance( parShell ); - sigAttrDlg.setPgenCategory(pgenCategory); - sigAttrDlg.setPgenType(pgenType); - return sigAttrDlg; - } - } - else if ("GFA".equalsIgnoreCase(pgenType)){ - - return GfaAttrDlg.getInstance( parShell ); - - } - else return null; - - } + if (pgenCategory == null) { + return null; + } + + if ((pgenCategory.equalsIgnoreCase("Lines")) + || ((pgenType != null) && pgenType + .equalsIgnoreCase("STATUS_LINE"))) { + + if ((pgenType != null) + && (pgenType.equalsIgnoreCase("KINK_LINE_1") || pgenType + .equalsIgnoreCase("KINK_LINE_2"))) { + return KinkLineAttrDlg.getInstance(parShell); + } else { + return LineAttrDlg.getInstance(parShell); + } + + } else if (pgenCategory.equalsIgnoreCase("Front")) { + return FrontAttrDlg.getInstance(parShell); + } + + else if ((pgenCategory.equalsIgnoreCase("Marker")) + || (pgenCategory.equalsIgnoreCase("Symbol")) + || (pgenCategory.equalsIgnoreCase("Combo"))) { + + if (pgenType != null + && (pgenType.equalsIgnoreCase("PRESENT_WX_201"))) { + return VolcanoAttrDlg.getInstance(parShell); + } else { + AttrDlg symDlg = LabeledSymbolAttrDlg.getInstance(parShell); + symDlg.setPgenCategory(pgenCategory); + symDlg.setPgenType(pgenType); + return symDlg; + } + + } + + else if (pgenCategory.equalsIgnoreCase("Text")) { + + if (pgenType != null && pgenType.equalsIgnoreCase("AVIATION_TEXT")) { + return AvnTextAttrDlg.getInstance(parShell); + } else if (pgenType != null + && pgenType.equalsIgnoreCase("MID_LEVEL_CLOUD")) { + return MidLevelCloudAttrDlg.getInstance(parShell); + } else { + return TextAttrDlg.getInstance(parShell); + } + + } + + else if (pgenCategory.equalsIgnoreCase("Arc")) { + + return ArcAttrDlg.getInstance(parShell); + + } else if (pgenCategory.equalsIgnoreCase(Track.TRACK_PGEN_CATEGORY)) { + + return TrackAttrDlg.getInstance(parShell); + + } else if (pgenCategory + .equalsIgnoreCase(Track.TRACK_INFO_DLG_CATEGORY_NAME)) { + + return TrackExtrapPointInfoDlg.getInstance(parShell); + + } else if (pgenCategory.equalsIgnoreCase("Vector")) { + + return VectorAttrDlg.getInstance(parShell); + + } else if (pgenCategory.equalsIgnoreCase("Extrap")) { + + return PgenExtrapDlg.getInstance(parShell); + + } else if (pgenCategory.equalsIgnoreCase("Interp")) { + + return PgenInterpDlg.getInstance(parShell); + + } else if (pgenCategory.equalsIgnoreCase("IncDec")) { + + return IncDecDlg.getInstance(parShell); + + } else if (pgenCategory.equalsIgnoreCase("Distance")) { + + return PgenDistanceDlg.getInstance(parShell); + + } else if (pgenCategory.equalsIgnoreCase("From")) { + + return FromAttrDlg.getInstance(parShell); + + } else if (pgenCategory.equalsIgnoreCase("Cycle")) { + + return CycleDlg.getInstance(parShell); + + } else if (pgenCategory.equalsIgnoreCase("Prod_AIRMET")) { + + return GfaFormatAttrDlg.getInstance(parShell); + + } else if (pgenType != null && pgenType.equalsIgnoreCase("Jet")) { + + return JetAttrDlg.getInstance(parShell); + } else if (pgenType != null && pgenType.equalsIgnoreCase("Outlook")) { + return OutlookAttrDlg.getInstance(parShell); + } else if (pgenType != null && pgenType.equalsIgnoreCase("TCA")) { + + return TcaAttrDlg.getInstance(parShell); + + } else if (pgenType != null && pgenType.equalsIgnoreCase("WatchBox")) { + + return WatchBoxAttrDlg.getInstance(parShell); + + } else if ((pgenType != null) && pgenType.equalsIgnoreCase("SPENES")) { + return SpenesAttrDlg.getInstance(parShell); + + } else if (pgenType != null && pgenType.equalsIgnoreCase("TCM")) { + + return TcmAttrDlg.getInstance(parShell); + + } else if (pgenType != null && pgenType.equalsIgnoreCase("Cloud")) { + + return CloudAttrDlg.getInstance(parShell); + + } else if (pgenType != null && pgenType.equalsIgnoreCase("Turbulence")) { + + return TurbAttrDlg.getInstance(parShell); + + } else if (pgenType != null && pgenType.equalsIgnoreCase("Contours")) { + + return ContoursAttrDlg.getInstance(parShell); + + } else if (pgenCategory.equalsIgnoreCase("SIGMET")) { + + if (pgenType != null && pgenType.equalsIgnoreCase("INTL_SIGMET")) { + SigmetAttrDlg sigAttrDlg = SigmetAttrDlg.getInstance(parShell); + sigAttrDlg.setPgenCategory(pgenCategory); + sigAttrDlg.setPgenType(pgenType); + return sigAttrDlg; + } else if (pgenType != null + && pgenType.equalsIgnoreCase("VOLC_SIGMET")) { + VolcanoVaaAttrDlg vaaDlg = VolcanoVaaAttrDlg + .getInstance(parShell); + vaaDlg.setPgenCategory(pgenCategory); + vaaDlg.setPgenType(pgenType); + vaaDlg.setFromSelection(true); + return vaaDlg; + } else if (pgenType != null + && pgenType.equalsIgnoreCase("VACL_SIGMET")) { + VaaCloudDlg vacDlg = VaaCloudDlg.getInstance(parShell); + vacDlg.setPgenCategory(pgenCategory); + vacDlg.setPgenType(pgenType); + return vacDlg; + + } else if (pgenType != null + && pgenType.equalsIgnoreCase("CCFP_SIGMET")) { + gov.noaa.nws.ncep.ui.pgen.attrdialog.vaadialog.CcfpAttrDlg sigAttrDlg = gov.noaa.nws.ncep.ui.pgen.attrdialog.vaadialog.CcfpAttrDlg + .getInstance(parShell); + sigAttrDlg.setPgenCategory(pgenCategory); + sigAttrDlg.setPgenType(pgenType); + return sigAttrDlg; + } else {// (pgenType != null && + // pgenType.equalsIgnoreCase("CONV_SIGMET")) { + SigmetCommAttrDlg sigAttrDlg = SigmetCommAttrDlg + .getInstance(parShell); + sigAttrDlg.setPgenCategory(pgenCategory); + sigAttrDlg.setPgenType(pgenType); + return sigAttrDlg; + } + } else if ("GFA".equalsIgnoreCase(pgenType)) { + + return GfaAttrDlg.getInstance(parShell); + + } + + else + return null; + + } } diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/AttrSettings.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/AttrSettings.java index 370ef134d3..a7645e251a 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/AttrSettings.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/AttrSettings.java @@ -10,6 +10,12 @@ package gov.noaa.nws.ncep.ui.pgen.attrdialog; import gov.noaa.nws.ncep.ui.pgen.PgenStaticDataProvider; import gov.noaa.nws.ncep.ui.pgen.elements.AbstractDrawableComponent; +import gov.noaa.nws.ncep.ui.pgen.elements.DECollection; +import gov.noaa.nws.ncep.ui.pgen.elements.DrawableElement; +import gov.noaa.nws.ncep.ui.pgen.elements.Layer; +import gov.noaa.nws.ncep.ui.pgen.elements.Line; +import gov.noaa.nws.ncep.ui.pgen.elements.Outlook; +import gov.noaa.nws.ncep.ui.pgen.elements.Product; import gov.noaa.nws.ncep.ui.pgen.elements.Text; import gov.noaa.nws.ncep.ui.pgen.elements.Track; import gov.noaa.nws.ncep.ui.pgen.file.FileTools; @@ -20,6 +26,7 @@ import gov.noaa.nws.ncep.ui.pgen.productmanage.ProductConfigureDialog; import java.io.File; import java.util.Calendar; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.TimeZone; @@ -41,7 +48,7 @@ import com.raytheon.uf.viz.core.exception.VizException; * 08/11 ? B. Yin Put current time for Storm Track * 11/11 ? B. Yin Load settings for different Activity Type. * 09/12 B. Hebbard Merge changes by RTS OB12.9.1 (format only, this file) - * + * 10/13 TTR768 J. Wu Load/set default attributes for outlook labels (Text). * * * @author J. Wu @@ -51,13 +58,20 @@ public class AttrSettings { private static AttrSettings INSTANCE = null; + /** + * General Settings. + */ private static HashMap settings = null; - - private static String settingsTblLocal = "." + File.separator; - public static String settingsFileName = "settings_tbl.xml"; - - /** + + /** + * Settings for outlook. + */ + public static String outlookSettingsFileName = "outlooksettings.xml"; + private static HashMap outlookLineSettings = null; + private static HashMap outlookLabelSettings = null; + + /** * Private constructor * * @throws VizException @@ -66,6 +80,8 @@ public class AttrSettings { super(); settings = new HashMap(); loadSettingsTable(); + + loadOutlookSettings(); } /** @@ -97,6 +113,20 @@ public class AttrSettings { return settings; } + /** + * Gets the default line settings for outlook loaded from the outlooksettings.xml. + */ + public HashMap getOutlookLineSettings() { + return outlookLineSettings; + } + + /** + * Gets the default label (text) settings for outlook loaded from the outlooksettings.xml. + */ + public HashMap getOutlookLabelSettings() { + return outlookLabelSettings; + } + /** * @param value * the DrawableElement to set gilbert: noticed this wasn't being @@ -125,15 +155,14 @@ public class AttrSettings { } /** - * Load default settings from settings_tbl.xml First try to load from user's - * local directory; if not found, load the base directory. + * Load default settings from settings_tbl.xml from localization. */ private void loadSettingsTable() { /* * Get the settings table file from localization */ - File settingsFile = PgenStaticDataProvider.getProvider().getFile( + File settingsFile = PgenStaticDataProvider.getProvider().getFile( PgenStaticDataProvider.getProvider().getPgenLocalizationRoot() + settingsFileName); @@ -144,6 +173,9 @@ public class AttrSettings { loadPgenSettings( settingsFile.getAbsolutePath() ); } + /** + * Load default settings defined for an PGEN activity. + */ public void loadProdSettings( String prodName ){ if ( prodName == null || prodName.isEmpty() ){ @@ -171,6 +203,9 @@ public class AttrSettings { } } + /** + * Read in a settings file from the input file. + */ public boolean loadPgenSettings( String fileName ){ boolean ret = false; @@ -180,57 +215,122 @@ public class AttrSettings { File sFile = new File( fileName ); try { - if ( sFile.canRead() ){ - Products products = FileTools.read( fileName ); - - List prds; - - prds = ProductConverter.convert( products ); - - for ( gov.noaa.nws.ncep.ui.pgen.elements.Product p:prds ) { - - for (gov.noaa.nws.ncep.ui.pgen.elements.Layer layer : p - .getLayers()) { - - for (gov.noaa.nws.ncep.ui.pgen.elements.AbstractDrawableComponent de : layer - .getDrawables()) { - - String pgenID = null; - pgenID = de.getPgenType(); + if ( sFile.canRead() ){ + Products products = FileTools.read( fileName ); - if ( pgenID != null ) { - newSettings.put( pgenID, de ); - } - - if ( pgenID.equalsIgnoreCase("General Text")){ - ((Text)de).setText(new String[]{""}); - } else if (pgenID.equalsIgnoreCase("STORM_TRACK")) { - //set Track time to current time - Calendar cal1 = Calendar.getInstance(TimeZone - .getTimeZone("GMT")); - Calendar cal2 = (Calendar)cal1.clone(); - cal2.add(Calendar.HOUR_OF_DAY, 1); - - ((Track)de).setFirstTimeCalendar( cal1); - ((Track)de).setSecondTimeCalendar( cal2); + List prds; - } - } - } - } - - if ( newSettings.size() > 0 ) { - settings.clear(); - settings.putAll(newSettings); - ret = true; - } - - } + prds = ProductConverter.convert( products ); + + for ( gov.noaa.nws.ncep.ui.pgen.elements.Product p:prds ) { + + for (gov.noaa.nws.ncep.ui.pgen.elements.Layer layer : p + .getLayers()) { + + for (gov.noaa.nws.ncep.ui.pgen.elements.AbstractDrawableComponent de : layer + .getDrawables()) { + + String pgenID = null; + pgenID = de.getPgenType(); + + if ( pgenID != null ) { + newSettings.put( pgenID, de ); + } + + if ( pgenID.equalsIgnoreCase("General Text")){ + ((Text)de).setText(new String[]{""}); + } else if (pgenID.equalsIgnoreCase("STORM_TRACK")) { + //set Track time to current time + Calendar cal1 = Calendar.getInstance(TimeZone + .getTimeZone("GMT")); + Calendar cal2 = (Calendar)cal1.clone(); + cal2.add(Calendar.HOUR_OF_DAY, 1); + + ((Track)de).setFirstTimeCalendar( cal1); + ((Track)de).setSecondTimeCalendar( cal2); + + } + } + } + } + + if ( newSettings.size() > 0 ) { + settings.clear(); + settings.putAll(newSettings); + ret = true; + } + + } } catch (Exception e) { ret = false; } return ret; } + + /** + * Load default settings from outlooksettings.xml + * + * Setting is a hash map with outlook type and label string as keys. + */ + private static void loadOutlookSettings() { + + if ( outlookLineSettings == null ) { + outlookLineSettings = new HashMap(); + } + + if ( outlookLabelSettings == null ) { + outlookLabelSettings = new HashMap(); + } + + String settingFile = PgenStaticDataProvider.getProvider().getFileAbsolutePath( + PgenStaticDataProvider.getProvider().getPgenLocalizationRoot() + outlookSettingsFileName ); + + gov.noaa.nws.ncep.ui.pgen.file.Products products = FileTools.read( settingFile ); + + if ( products != null ){ + List prds; + + prds = ProductConverter.convert( products ); + + for ( Product p:prds ) { + + for ( Layer layer:p.getLayers() ) { + + Iterator it = layer.getComponentIterator(); + while( it.hasNext()){ + AbstractDrawableComponent adc = it.next(); + if ( adc.getName().equalsIgnoreCase("OUTLOOK")) { + Iterator itLn = ((Outlook)adc).getComponentIterator(); + while ( itLn.hasNext() ){ + AbstractDrawableComponent lnGrp = itLn.next(); + if ( lnGrp.getName().equalsIgnoreCase(Outlook.OUTLOOK_LABELED_LINE) ) { + String key = null; + Line ln = null; + Text txt = null; + Iterator itDe = ((DECollection)lnGrp).createDEIterator(); + while( itDe.hasNext() ){ + DrawableElement de = itDe.next(); + if( de instanceof Text ){ + txt = (Text)de; + key = ((Outlook)adc).getOutlookType() + txt.getText()[0]; + } + else if ( de instanceof Line ){ + ln = (Line) de; + } + } + + if ( key != null && ln != null ){ + outlookLineSettings.put( key, ln ); + outlookLabelSettings.put( key, txt ); + } + } + } + } + } + } + } + } + } } diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/ContoursAttrDlg.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/ContoursAttrDlg.java index 43930caa5d..369013ccba 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/ContoursAttrDlg.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/ContoursAttrDlg.java @@ -8,8 +8,6 @@ package gov.noaa.nws.ncep.ui.pgen.attrdialog; - -import gov.noaa.nws.ncep.gempak.parameters.core.contourinterval.CINT; import gov.noaa.nws.ncep.ui.pgen.PgenSession; import gov.noaa.nws.ncep.ui.pgen.PgenUtil; import gov.noaa.nws.ncep.ui.pgen.contours.ContourCircle; @@ -78,7 +76,6 @@ import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.viz.ui.perspectives.VizPerspectiveListener; import com.vividsolutions.jts.geom.Coordinate; - /** * Singleton attribute dialog for Contours. * @@ -101,3135 +98,3304 @@ import com.vividsolutions.jts.geom.Coordinate; * 08/11 #? J. Wu TTR78: keep line/symbol/label attr window open. * 01/12 #? J. Wu Fixed exceptions when closing the dialog. * 05/12 756 B. Yin Fixed the place symbol exception + * 12/13 1084 J. Wu Add table-control for Cint in contoursInfo.xml * * - * @author J. Wu + * @author J. Wu */ -public class ContoursAttrDlg extends AttrDlg implements IContours, SelectionListener, ILine { - - private static ContoursAttrDlg INSTANCE = null; - - private static ContoursInfoDlg contoursInfoDlg = null; - private static GraphToGridParamDialog g2gDlg = null; +public class ContoursAttrDlg extends AttrDlg implements IContours, + SelectionListener, ILine { - /** - * Defines which type of DE to be drawn. - */ + private static ContoursAttrDlg INSTANCE = null; + + private static ContoursInfoDlg contoursInfoDlg = null; + + private static GraphToGridParamDialog g2gDlg = null; + + /** + * Defines which type of DE to be drawn. + */ public static enum ContourDrawingStatus { DRAW_LINE, DRAW_SYMBOL, DRAW_CIRCLE, SELECT } - + private ContourDrawingStatus drawingStatus = ContourDrawingStatus.DRAW_LINE; - - private String contourParm = "HGMT"; - private String contourLevel = "1000"; - - private String contourFcstHr = "f000"; - - private Calendar contourTime1 = (Calendar)Calendar.getInstance(); - private Calendar contourTime2 = (Calendar)Calendar.getInstance(); - private String contourCint = "10/0/100"; - - private final String SELECT_CONTOURLINE = "Select"; - private final String ADD_CONTOURLINE = "Add"; - private final String DELETE_CONTOURLINE = "Delete"; - - private final int MAX_QUICK_SYMBOLS = 15; - private int numOfQuickSymbols = 2; - - private Composite top; - private Group attrComp; - private Group textGrp; - - private Composite infoComp = null; - private Button infoBtn = null; - private Text labelTxt = null; - private Button lineClosedBtn = null; - private Button lineTypeBtn = null; - - private Composite labelGrp= null; - private ArrayList