13.5.2-2 baseline

Former-commit-id: 6cecce21eb6a7c9b72d7a61936dcbe4f4688fba9
This commit is contained in:
Steve Harris 2013-08-29 15:01:29 -04:00
parent 73dd0f166c
commit 4a47fb97c5
77 changed files with 5798 additions and 1713 deletions

2
MHSEmulator/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
out/
*.jar

Binary file not shown.

Binary file not shown.

View file

@ -5,10 +5,30 @@ import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.InetAddress;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Library module for MHS emulator.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* ??? ?? ???? bphillip Initial creation
* Jul 15, 2013 #2099 dgilling Use safer exception handling for file I/O.
*
* </pre>
*
* @author bphillip
* @version 1.0
*/
public class MhsUtil {
public static final SimpleDateFormat logDateFormat = new SimpleDateFormat(
@ -19,32 +39,51 @@ public class MhsUtil {
public static final String END_TOKEN = "------!!!!END!!!!------";
public static final File MY_MHS_FILE = new File(
"/awips2/.myMHS");
public static final File MY_MHS_FILE = new File("/awips2/.myMHS");
public static final File MSG_ID_FILE = new File(
"/awips2/.msgCount");
public static final File MSG_ID_FILE = new File("/awips2/.msgCount");
public static String getMsgId() throws Exception {
if (!MSG_ID_FILE.exists()) {
MSG_ID_FILE.createNewFile();
BufferedWriter out = new BufferedWriter(new FileWriter(MSG_ID_FILE));
out.write("0");
out.close();
private MhsUtil() {
throw new AssertionError();
}
public static String getMsgId() throws IOException {
if (MSG_ID_FILE.createNewFile()) {
BufferedWriter out = null;
try {
out = new BufferedWriter(new FileWriter(MSG_ID_FILE));
out.write("0");
} finally {
if (out != null) {
out.close();
}
}
}
BufferedReader in = null;
in = new BufferedReader(new FileReader(MSG_ID_FILE));
String msgId = in.readLine().trim();
int newMsgNumber = Integer.parseInt(msgId) + 1;
in.close();
BufferedWriter out = new BufferedWriter(new FileWriter(MSG_ID_FILE));
out.write(String.valueOf(newMsgNumber));
out.close();
for (int i = msgId.length(); i < 6; i++) {
msgId = "0" + msgId;
int newMsgNumber;
try {
in = new BufferedReader(new FileReader(MSG_ID_FILE));
String msgId = in.readLine().trim();
newMsgNumber = Integer.parseInt(msgId) + 1;
} finally {
if (in != null) {
in.close();
}
}
return msgId;
BufferedWriter out = null;
try {
out = new BufferedWriter(new FileWriter(MSG_ID_FILE));
out.write(String.valueOf(newMsgNumber));
} finally {
if (out != null) {
out.close();
}
}
NumberFormat formatter = new DecimalFormat("000000");
return formatter.format(newMsgNumber);
}
public static int byteArrayToInt(byte[] b, int offset) {
@ -73,26 +112,26 @@ public class MhsUtil {
logFile = new File(logDir
+ InetAddress.getLocalHost().getCanonicalHostName() + "-"
+ mode + "-" + MhsUtil.logDateFormat.format(new Date()));
logFile.createNewFile();
if (logFile != null) {
if (!logFile.exists()) {
logFile.createNewFile();
}
}
message += MhsUtil.logMsgFormat.format(new Date());
for (Object obj : msg) {
message += obj.toString() + " ";
}
message += "\n";
BufferedWriter out = new BufferedWriter(new FileWriter(logFile,
true));
out.write(message.trim());
out.write("\n");
out.close();
BufferedWriter out = null;
try {
out = new BufferedWriter(new FileWriter(logFile, true));
out.write(message.trim());
out.write("\n");
} finally {
if (out != null) {
out.close();
}
}
} catch (Exception e) {
// ignore
e.printStackTrace();
}
}

View file

@ -1,59 +1,68 @@
package mhs.core;
import java.io.File;
import java.io.FileFilter;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Properties;
public class RsyncThread extends Thread {
/**
* TODO Add Description
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* ??? ?? ???? bphillip Initial creation
* Jul 15, 2013 #2099 dgilling Modify to support recursive file listing
* since export grids dir structure uses
* multiple folders.
*
* </pre>
*
* @author bphillip
* @version 1.0
*/
public class RsyncThread implements Runnable {
private static final Map<String, Long> fileVersion = new HashMap<String, Long>();
private Properties props;
private Map<String, Long> fileVersion;
public RsyncThread(Properties props) {
this.props = props;
fileVersion = new HashMap<String, Long>();
this.setDaemon(true);
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
String exportGridsDir = props.getProperty("EXPORT_GRIDS");
String centralServerDir = props.getProperty("CENTRAL_SERVER");
String packScriptDir = props.getProperty("UTIL_DIR");
String exportGridsDir = (String) props.getProperty("EXPORT_GRIDS");
String centralServerDir = (String) props
.getProperty("CENTRAL_SERVER");
File[] fileList = new File(exportGridsDir).listFiles();
Collection<File> fileList = listCdfFiles(new File(exportGridsDir));
for (File file : fileList) {
if (file.isFile()) {
String currentFilePath = file.getPath();
String currentFilePath = null;
for (File file : fileList) {
if (file.isDirectory()) {
continue;
boolean copy = true;
if ((fileVersion.containsKey(currentFilePath))
&& (fileVersion.get(currentFilePath) >= file
.lastModified())) {
copy = false;
}
currentFilePath = file.getPath();
boolean copy = false;
if (fileVersion.containsKey(currentFilePath)) {
if (fileVersion.get(currentFilePath).longValue() != file
.lastModified()) {
copy = true;
}
} else {
copy = true;
}
if (copy) {
String[] copyCmd = new String[] {
centralServerDir + "/../util/packageFile",file.getPath(),
centralServerDir + "/../util/",
file.getName().substring(0, 3), centralServerDir };
packScriptDir + "/packageFile", currentFilePath,
packScriptDir, file.getName().substring(0, 3),
centralServerDir };
try {
Runtime.getRuntime().exec(copyCmd);
fileVersion.put(file.getPath(), file.lastModified());
fileVersion.put(currentFilePath, file.lastModified());
} catch (Exception e) {
e.printStackTrace();
}
@ -61,4 +70,34 @@ public class RsyncThread extends Thread {
}
}
}
private Collection<File> listCdfFiles(File path) {
Collection<File> fileList = new LinkedList<File>();
FileFilter cdfFilter = new FileFilter() {
@Override
public boolean accept(File pathname) {
return (pathname.isDirectory() || pathname.getName().endsWith(
".netcdf"));
}
};
innerListFiles(path, fileList, cdfFilter);
return fileList;
}
private void innerListFiles(File path, Collection<File> fileList,
FileFilter filter) {
try {
File[] matchingFiles = path.listFiles(filter);
for (File file : matchingFiles) {
if (file.isDirectory()) {
innerListFiles(file, fileList, filter);
} else if (file.isFile()) {
fileList.add(file);
}
}
} catch (SecurityException e) {
e.printStackTrace();
}
}
}

View file

@ -1,5 +1,6 @@
package mhs.core;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
@ -7,27 +8,64 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* TODO Add Description
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* ??? ?? ???? bphillip Initial creation
* Jul 15, 2013 #2009 dgilling Code cleanup.
* Jul 23, 2013 #2009 dgilling Fix NullPointerException on start up.
*
* </pre>
*
* @author bphillip
* @version 1.0
*/
public class SocketSrv {
private File propertiesFile;
private boolean runRsync;
private String myMHS;
private Properties serverProps;
private ExecutorService mhsRequestHandler;
private ScheduledExecutorService rsyncThread;
private int fileIndex = 0;
private String fileBase;
private Properties serverProps;
private String configDir;
private String centralServerDir;
@ -38,131 +76,191 @@ public class SocketSrv {
private Map<Integer, String> commandMap;
private RsyncThread rsync;
private String propertiesFile;
private String myMHS;
private int serverPort;
public static void main(String[] args) {
if (!System.getProperty("user.name").equals("root")) {
System.out
.println("Socket Server must be run as root user! Current user: "
+ System.getProperty("user.name"));
System.exit(1);
}
File propertiesFile = new File(args[0]);
String mhsId = args[1];
boolean startRsync = Boolean.parseBoolean(args[2]);
if (!propertiesFile.isFile()) {
System.out.println("Specified properties file ["
+ propertiesFile.toString() + "] does not exist. Exiting.");
System.exit(1);
}
try {
SocketSrv srv = null;
srv = new SocketSrv(args[0], args[1], args[2]);
srv.run();
final SocketSrv server = new SocketSrv(propertiesFile, mhsId,
startRsync);
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
server.shutdown();
}
});
server.run();
} catch (Exception e) {
e.printStackTrace();
}
}
private SocketSrv(String propertiesFile, String myMHS, String startRsync)
throws Exception {
this.propertiesFile = propertiesFile;
this.myMHS = myMHS;
writeMyMHS(myMHS);
private SocketSrv(File propertiesFile, String mhsId, boolean startRsync)
throws UnknownHostException, IOException {
System.out.println("Setting up server ("
+ InetAddress.getLocalHost().getCanonicalHostName() + ")");
commandMap = new HashMap<Integer, String>();
configDir = propertiesFile.substring(0,
propertiesFile.lastIndexOf(File.separator) + 1);
loadProperties(true);
if (startRsync.equals("true")) {
System.out.println("Starting Rsync Thread...");
rsync = new RsyncThread(serverProps);
rsync.start();
System.out.println("Rsync Thread started!");
}
}
this.propertiesFile = propertiesFile;
this.myMHS = mhsId;
this.runRsync = startRsync;
private void writeMyMHS(String myMHS) throws Exception {
BufferedWriter out = new BufferedWriter(new FileWriter(
MhsUtil.MY_MHS_FILE));
out.write(myMHS + "\n");
out.write(this.propertiesFile);
out.close();
}
writeMyMHS(myMHS);
private void loadProperties(boolean print) throws Exception {
serverProps = new Properties();
FileInputStream fis = new FileInputStream(propertiesFile);
serverProps.load(fis);
fis.close();
fileBase = serverProps.getProperty("DATA_FOLDER");
centralServerDir = serverProps.getProperty("CENTRAL_SERVER");
binDir = serverProps.getProperty("UTIL_DIR");
this.commandMap = new HashMap<Integer, String>();
this.configDir = this.propertiesFile.getParent();
loadProperties();
loadRcvHandlerTable();
if (print) {
System.out.println(" Received Data directory: " + fileBase);
System.out.println("Central Server Data Directory: "
+ centralServerDir);
System.out.println(" Config directory: " + configDir);
this.fileBase = serverProps.getProperty("DATA_FOLDER");
this.centralServerDir = serverProps.getProperty("CENTRAL_SERVER");
this.binDir = serverProps.getProperty("UTIL_DIR");
this.serverPort = Integer.parseInt(serverProps
.getProperty("SERVER_PORT"));
System.out.println("\tReceived Data directory: " + fileBase);
System.out.println("\tCentral Server Data Directory: "
+ centralServerDir);
System.out.println("\tConfig directory: " + configDir);
this.mhsRequestHandler = Executors.newSingleThreadExecutor();
if (this.runRsync) {
System.out.println("Starting Rsync Thread...");
this.rsyncThread = Executors.newSingleThreadScheduledExecutor();
}
}
public void run() throws Exception {
public void run() throws IOException {
if (rsyncThread != null) {
Runnable rsyncJob = new RsyncThread(serverProps);
rsyncThread
.scheduleWithFixedDelay(rsyncJob, 1, 1, TimeUnit.SECONDS);
}
int port = Integer.parseInt((String) serverProps.get("SERVER_PORT"));
ServerSocket srv = new ServerSocket(port);
ServerSocket socket = new ServerSocket(serverPort);
while (!mhsRequestHandler.isShutdown()) {
try {
log("Waiting for connections...");
final Socket conn = socket.accept();
Runnable processTask = new Runnable() {
while (true) {
log("Waiting for connections...");
Socket socket = srv.accept();
InetSocketAddress client = (InetSocketAddress) socket
.getRemoteSocketAddress();
log("Connected to client: " + client.getHostName() + " at "
+ client);
loadProperties(false);
String sender = getMhsOfSender(client);
log("Message is from: " + sender);
InputStream in = socket.getInputStream();
byte[] message = null;
Map<String, String> params = new HashMap<String, String>();
String flag = "";
while (true) {
if (in.available() == 0) {
Thread.sleep(100);
continue;
}
message = getMessage(in);
if (message.length < 50) {
String strMessage = new String(message);
if (strMessage.equals(MhsUtil.END_TOKEN)) {
log("Disconnected from client: " + client);
if (params.containsKey("-c")) {
executeAction(sender, params);
files.clear();
params.clear();
flag = "";
@Override
public void run() {
try {
handleRequest(conn);
} catch (Exception e) {
e.printStackTrace();
}
break;
}
if (strMessage.startsWith("-")) {
flag = strMessage;
} else {
params.put(flag, strMessage);
}
} else {
log("File Received of size: " + message.length);
files.add(writeToFile(myMHS + "-" + params.get("-MSGID"),
message));
};
mhsRequestHandler.execute(processTask);
} catch (RejectedExecutionException e) {
if (!mhsRequestHandler.isShutdown()) {
e.printStackTrace();
}
}
}
}
public void shutdown() {
mhsRequestHandler.shutdown();
if (rsyncThread != null) {
rsyncThread.shutdown();
}
}
private void handleRequest(Socket connection) throws IOException,
InterruptedException {
InetSocketAddress client = (InetSocketAddress) connection
.getRemoteSocketAddress();
log("Connected to client: " + client.getHostName() + " at " + client);
loadProperties();
String sender = getMhsOfSender(client);
log("Message is from: " + sender);
InputStream in = connection.getInputStream();
byte[] message = null;
Map<String, String> params = new HashMap<String, String>();
String flag = "";
while (true) {
if (in.available() == 0) {
Thread.sleep(100);
continue;
}
message = getMessage(in);
if (message.length < 50) {
String strMessage = new String(message);
if (strMessage.equals(MhsUtil.END_TOKEN)) {
log("Disconnected from client: " + client);
if (params.containsKey("-c")) {
executeAction(sender, params);
files.clear();
params.clear();
flag = "";
}
break;
}
if (strMessage.startsWith("-")) {
flag = strMessage;
} else {
params.put(flag, strMessage);
}
} else {
log("File Received of size: " + message.length);
files.add(writeToFile(myMHS + "-" + params.get("-MSGID"),
message));
}
}
}
private void writeMyMHS(String myMHS) throws IOException {
BufferedWriter out = null;
try {
out = new BufferedWriter(new FileWriter(MhsUtil.MY_MHS_FILE));
out.write(myMHS + "\n");
out.write(propertiesFile.getPath());
} finally {
if (out != null) {
out.close();
}
}
}
private void loadProperties() throws IOException {
FileInputStream fis = null;
try {
fis = new FileInputStream(propertiesFile);
Properties newProps = new Properties();
newProps.load(fis);
serverProps = newProps;
} finally {
if (fis != null) {
fis.close();
}
}
}
private void executeAction(String sender, Map<String, String> params)
throws Exception {
throws IOException, InterruptedException {
int action = Integer.parseInt(params.get("-c"));
if (!commandMap.containsKey(action)) {
@ -200,31 +298,19 @@ public class SocketSrv {
command = command.replace("%SENDER", sender.toLowerCase());
String[] cmdArray = command.split(" ");
log("Executing: " + command);
//
// Map<String, String> sysEnv = System.getenv();
// Map<String, String> newEnv = new HashMap<String, String>();
// for (String key : sysEnv.keySet()) {
// newEnv.put(key, sysEnv.get(key));
// }
// newEnv.put("PATH", "/awips2/python/bin/:"+sysEnv.get("PATH"));
// newEnv.put("LD_PRELOAD", "/awips2/python/lib/libpython2.7.so");
// newEnv.put("LD_LIBRARY_PATH", "/awips2/python/lib");
// String[] envp = new String[newEnv.keySet().size()];
// int i = 0;
// for (String key : newEnv.keySet()) {
// envp[i] = key.trim() + "=" + newEnv.get(key).trim();
// i++;
// }
Process p = null;
try {
p = Runtime.getRuntime().exec(cmdArray);
p.waitFor();
} finally {
p.destroy();
if (p != null) {
p.destroy();
}
}
}
private byte[] getMessage(InputStream in) throws Exception {
private byte[] getMessage(InputStream in) throws IOException {
byte[] sizeBytes = new byte[4];
readBytes(in, sizeBytes);
int expectedSize = MhsUtil.byteArrayToInt(sizeBytes, 0);
@ -233,7 +319,7 @@ public class SocketSrv {
return message;
}
private void readBytes(InputStream in, byte[] bytes) throws Exception {
private void readBytes(InputStream in, byte[] bytes) throws IOException {
int expectedSize = bytes.length;
int bytesRead = 0;
int totalBytesRead = 0;
@ -245,13 +331,20 @@ public class SocketSrv {
}
private String writeToFile(String fileName, byte[] contents)
throws Exception {
throws IOException, InterruptedException {
String fileFQN = fileBase + fileName + "." + getFileIndex();
log("Writing file: " + fileFQN);
FileOutputStream fos = new FileOutputStream(new File(fileFQN));
fos.write(contents);
fos.flush();
fos.close();
BufferedOutputStream out = null;
try {
out = new BufferedOutputStream(new FileOutputStream(new File(
fileFQN)));
out.write(contents);
} finally {
if (out != null) {
out.close();
}
}
Process p = null;
try {
@ -259,7 +352,9 @@ public class SocketSrv {
new String[] { "/bin/chmod", "777", fileFQN });
p.waitFor();
} finally {
p.destroy();
if (p != null) {
p.destroy();
}
}
return fileFQN;
}
@ -269,40 +364,34 @@ public class SocketSrv {
if (fileIndex == 1000) {
fileIndex = 0;
}
String fileNumber = String.valueOf(fileIndex);
if (fileNumber.length() == 1) {
fileNumber = "00" + fileNumber;
} else if (fileNumber.length() == 2) {
fileNumber = "0" + fileNumber;
}
return fileNumber;
NumberFormat formatter = new DecimalFormat("000");
return formatter.format(fileIndex);
}
private void loadRcvHandlerTable() throws Exception {
private void loadRcvHandlerTable() throws IOException {
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader(configDir
in = new BufferedReader(new FileReader(configDir + File.separator
+ "rcv_handler.tbl"));
String str = null;
String[] tokens = null;
String str = null;
while ((str = in.readLine()) != null) {
String command = "";
tokens = str.split(" ");
StringBuilder commandBuilder = new StringBuilder();
String[] tokens = str.split(" ");
for (int i = 1; i < tokens.length; i++) {
String cmd = tokens[i].trim();
if (!cmd.isEmpty()) {
if (i != 1) {
command += " ";
commandBuilder.append(' ');
}
command += cmd;
commandBuilder.append(cmd);
}
}
command = command.trim();
commandMap.put(Integer.parseInt(tokens[0]), command);
String commandString = commandBuilder.toString().trim();
commandMap.put(Integer.parseInt(tokens[0]), commandString);
}
in.close();
} finally {
if (in != null) {
in.close();
@ -311,20 +400,19 @@ public class SocketSrv {
}
private String getMhsOfSender(InetSocketAddress address) {
String hostAddress = address.getAddress().getHostAddress();
for (Object key : serverProps.keySet()) {
String value = serverProps.getProperty((String) key);
for (String mhsId : serverProps.stringPropertyNames()) {
String value = serverProps.getProperty(mhsId);
if (value.contains(",")) {
String[] addrs = value.split(",");
for (String addr : addrs) {
if (addr.contains(hostAddress)) {
return (String) key;
return mhsId;
}
}
} else {
if (value.contains(hostAddress)) {
return (String) key;
return mhsId;
}
}
}

View file

@ -1,69 +0,0 @@
@echo OFF
REM Determine if we are running on a 32-bit or 64-bit OS.
IF NOT EXIST C:\Windows\SysWOW64\reg.exe (
SET REG_EXE=C:\Windows\System32\reg.exe
) ELSE (
SET REG_EXE=C:\Windows\SysWOW64\reg.exe
)
REM Determine where we are located.
SET CONTAINING_DIRECTORY=%~dp0
REM Prepare the environment.
REM Registry Query Variables.
SET A2_JAVA_REG="HKLM\Software\Raytheon\Runtime Environment\AWIPS II Java"
SET A2_PYTHON_REG="HKLM\Software\Raytheon\Runtime Environment\AWIPS II Python"
REM Determine where AWIPS II Java (the jre) is located.
%REG_EXE% QUERY %A2_JAVA_REG% /v JavaJreDirectory > NUL 2>&1
IF ERRORLEVEL 1 (echo ENVIRONMENT ERROR - Unable to find AWIPS II Java. && PAUSE && EXIT)
FOR /F "tokens=2* delims= " %%A IN (
'%REG_EXE% QUERY %A2_JAVA_REG% /v JavaJreDirectory') DO (
SET JavaJreDirectory=%%B)
REM Determine where AWIPS II Python is located.
%REG_EXE% QUERY %A2_PYTHON_REG% /v PythonInstallDirectory > NUL 2>&1
IF ERRORLEVEL 1 (echo ENVIRONMENT ERROR - Unable to find AWIPS II Python. && PAUSE && EXIT)
FOR /F "tokens=2* delims= " %%A IN (
'%REG_EXE% QUERY %A2_PYTHON_REG% /v PythonInstallDirectory') DO (
SET PythonInstallDirectory=%%B)
REM Add Java and Python to the path.
SET Path=%PythonInstallDirectory%;%PythonInstallDirectory%\DLLs;%Path%
SET Path=%JavaJreDirectory%\bin;%Path%
REM Define 'PythonPath'.
SET PythonPath=%PythonInstallDirectory%\Lib\lib-tk;%PythonPath%
SET PythonPath=%PythonInstallDirectory%\DLLs;%PythonPath%
SET PythonPath=%PythonInstallDirectory%\Lib;%PythonPath%
SET PythonPath=%PythonInstallDirectory%;%PythonPath%
REM Eliminate variables that will no longer be used.
SET PythonInstallDirectory=
SET JavaJreDirectory=
SET REG_EXE=
SET A2_JAVA_REG=
SET A2_PYTHON_REG=
REM Determine where we will be logging to.
SET HOME_DIRECTORY=%HOMEDRIVE%%HOMEPATH%
SET CAVEDATA_LOG_DIRECTORY=%HOMEDRIVE%%HOMEPATH%\caveData\logs
SET CONSOLE_LOG_DIRECTORY=%CAVEDATA_LOG_DIRECTORY%\consoleLogs\%COMPUTERNAME%
IF NOT EXIST "%CONSOLE_LOG_DIRECTORY%" (MKDIR "%CONSOLE_LOG_DIRECTORY%")
echo Starting ALERTVIZ; leave this CMD window open to enable AlertViz 'restart'.
REM Start AlertViz (and implement the alertviz restart capability).
:AlertVizLoopStart
SET RND=%random%
SET RND_DATETIME_FILE=%TMP%\awips2dt_%RND%.tmp
REM Python is used to retrieve the current date and time because the order
REM of the Windows date/time fields is not necessarily guaranteed and the
REM Windows date/time fields can only be extracted using substring operations
REM instead of -formatter- strings like Linux allows.
python -c "from datetime import datetime; print datetime.now().strftime('%%Y%%m%%d_%%H%%M%%S');" > %RND_DATETIME_FILE%
SET /p LOG_DATETIME= < %RND_DATETIME_FILE%
DEL %RND_DATETIME_FILE%
"%CONTAINING_DIRECTORY%alertviz.exe" %* > "%CONSOLE_LOG_DIRECTORY%\alertviz_%LOG_DATETIME%.log" 2>&1
IF %ERRORLEVEL% == 0 (EXIT)
echo Restarting AlertViz.
GOTO AlertVizLoopStart

View file

@ -1,72 +0,0 @@
@echo OFF
REM Determine if we are running on a 32-bit or 64-bit OS.
IF NOT EXIST C:\Windows\SysWOW64\reg.exe (
SET REG_EXE=C:\Windows\System32\reg.exe
) ELSE (
SET REG_EXE=C:\Windows\SysWOW64\reg.exe
)
REM Determine where we are located.
SET CONTAINING_DIRECTORY=%~dp0
REM Prepare the environment.
REM Registry Query Variables.
SET A2_JAVA_REG="HKLM\Software\Raytheon\Runtime Environment\AWIPS II Java"
SET A2_PYTHON_REG="HKLM\Software\Raytheon\Runtime Environment\AWIPS II Python"
REM Determine where AWIPS II Java (the jre) is located.
%REG_EXE% QUERY %A2_JAVA_REG% /v JavaJreDirectory > NUL 2>&1
IF ERRORLEVEL 1 (echo ENVIRONMENT ERROR - Unable to find AWIPS II Java. && PAUSE && EXIT)
FOR /F "tokens=2* delims= " %%A IN (
'%REG_EXE% QUERY %A2_JAVA_REG% /v JavaJreDirectory') DO (
SET JavaJreDirectory=%%B)
REM Determine where AWIPS II Python is located.
%REG_EXE% QUERY %A2_PYTHON_REG% /v PythonInstallDirectory > NUL 2>&1
IF ERRORLEVEL 1 (echo ENVIRONMENT ERROR - Unable to find AWIPS II Python. && PAUSE && EXIT)
FOR /F "tokens=2* delims= " %%A IN (
'%REG_EXE% QUERY %A2_PYTHON_REG% /v PythonInstallDirectory') DO (
SET PythonInstallDirectory=%%B)
REM Add Java and Python to the path.
SET Path=%PythonInstallDirectory%;%PythonInstallDirectory%\DLLs;%Path%
SET Path=%JavaJreDirectory%\bin;%Path%
REM Add the CAVE lib directory to the path.
SET Path=%CONTAINING_DIRECTORY%lib;%Path%
REM Define 'PythonPath'.
SET PythonPath=%CONTAINING_DIRECTORY%lib;%PythonPath%
SET PythonPath=%PythonInstallDirectory%\Lib\lib-tk;%PythonPath%
SET PythonPath=%PythonInstallDirectory%\DLLs;%PythonPath%
SET PythonPath=%PythonInstallDirectory%\Lib;%PythonPath%
SET PythonPath=%PythonInstallDirectory%;%PythonPath%
REM Eliminate variables that will no longer be used.
SET PythonInstallDirectory=
SET JavaJreDirectory=
SET REG_EXE=
SET A2_JAVA_REG=
SET A2_PYTHON_REG=
REM Determine where we will be logging to.
SET HOME_DIRECTORY=%HOMEDRIVE%%HOMEPATH%
SET CAVEDATA_LOG_DIRECTORY=%HOMEDRIVE%%HOMEPATH%\caveData\logs
SET CONSOLE_LOG_DIRECTORY=%CAVEDATA_LOG_DIRECTORY%\consoleLogs\%COMPUTERNAME%
IF NOT EXIST "%CONSOLE_LOG_DIRECTORY%" (MKDIR "%CONSOLE_LOG_DIRECTORY%")
SET RND=%random%
SET RND_DATETIME_FILE=%TMP%\awips2dt_%RND%.tmp
REM Python is used to retrieve the current date and time because the order
REM of the Windows date/time fields is not necessarily guaranteed and the
REM Windows date/time fields can only be extracted using substring operations
REM instead of -formatter- strings like Linux allows.
python -c "from datetime import datetime; print datetime.now().strftime('%%Y%%m%%d_%%H%%M%%S');" > %RND_DATETIME_FILE%
SET /p LOG_DATETIME= < %RND_DATETIME_FILE%
DEL %RND_DATETIME_FILE%
echo THIS CMD WINDOW CAN BE CLOSED AT ANY TIME!
cd %HOMEPATH%
REM Start CAVE.
"%CONTAINING_DIRECTORY%cave.exe" %* > "%CONSOLE_LOG_DIRECTORY%\cave_%LOG_DATETIME%.log" 2>&1
IF ERRORLEVEL 1 (echo CAVE ERROR - check the logs for additional information. && PAUSE)
EXIT

View file

@ -21,6 +21,7 @@ package com.raytheon.uf.viz.core;
import java.awt.geom.Rectangle2D;
import java.awt.image.RenderedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@ -41,6 +42,8 @@ import com.raytheon.uf.viz.core.data.resp.NumericImageData;
import com.raytheon.uf.viz.core.drawables.ColorMapLoader;
import com.raytheon.uf.viz.core.drawables.IDescriptor;
import com.raytheon.uf.viz.core.drawables.IFont;
import com.raytheon.uf.viz.core.drawables.IFont.FontType;
import com.raytheon.uf.viz.core.drawables.IFont.Style;
import com.raytheon.uf.viz.core.drawables.IImage;
import com.raytheon.uf.viz.core.drawables.IShadedShape;
import com.raytheon.uf.viz.core.drawables.IWireframeShape;
@ -62,6 +65,7 @@ import com.raytheon.uf.viz.core.exception.VizException;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 25, 2012 bsteffen Initial creation
* Jul 18, 2013 2189 mschenke Added ability to specify font type
*
* </pre>
*
@ -82,6 +86,11 @@ public abstract class AbstractGraphicsTarget implements IGraphicsTarget {
extensionManager = new GraphicsExtensionManager(this);
}
@Override
public IFont initializeFont(File fontFile, float size, Style[] styles) {
return initializeFont(fontFile, FontType.TRUETYPE, size, styles);
}
@Override
public boolean drawRasters(PaintProperties paintProps,
DrawableImage... images) throws VizException {

View file

@ -59,6 +59,7 @@ import com.raytheon.uf.viz.core.exception.VizException;
* track any needed updates to the Target extents.
* This functionality is primarily used by the
* Feature Following Zoom Tool at this time.
* 7/18/13 #2189 mschenke Added ability to specify font type
*
* </pre>
*
@ -234,8 +235,10 @@ public interface IGraphicsTarget extends IImagingExtension {
IFont.Style[] styles);
/**
* Create a font object from a truetype font
* Create a font object from a truetype font file
*
* @deprecated {@link #initializeFont(File, com.raytheon.uf.viz.core.drawables.IFont.FontType, float, com.raytheon.uf.viz.core.drawables.IFont.Style[])}
* should be used instead
*
* @param fontFile
* the truetype font
@ -245,9 +248,27 @@ public interface IGraphicsTarget extends IImagingExtension {
* the font styles
* @return a prepared font reference
*/
@Deprecated
public abstract IFont initializeFont(File fontFile, float size,
IFont.Style[] styles);
/**
* Create a font object from font file
*
*
* @param fontFile
* the font file
* @param type
* the type of the font file
* @param size
* the size in points
* @param styles
* the font styles
* @return a prepared font reference
*/
public abstract IFont initializeFont(File fontFile, IFont.FontType type,
float size, IFont.Style[] styles);
/**
* Draw a raster to a target, given an extent and an alpha (transparency)
* value. Assumes synchronous operation.

View file

@ -0,0 +1,165 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.core.drawables;
import java.awt.Font;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* Simple abstract base class for an AWT-based IFont implementations
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 24, 2013 2189 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public abstract class AbstractAWTFont implements IFont {
protected Font font;
protected boolean scaleFont;
protected boolean smoothing;
protected AbstractAWTFont(String fontName, float fontSize, Style[] styles) {
this(new Font(fontName, toAwtStyle(styles), (int) fontSize));
}
protected AbstractAWTFont(File fontFile, FontType fontType, float fontSize,
Style[] styles) {
this(createFont(fontFile, fontType, fontSize, styles));
}
protected AbstractAWTFont(Font font) {
this.font = font;
}
@Override
public final String getFontName() {
return font.getName();
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.core.drawables.IFont#getStyle()
*/
@Override
public final Style[] getStyle() {
return toVizStyles(font.getStyle());
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.core.drawables.IFont#setSmoothing(boolean)
*/
@Override
public final void setSmoothing(boolean smooth) {
this.smoothing = smooth;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.core.drawables.IFont#getSmoothing()
*/
@Override
public final boolean getSmoothing() {
return smoothing;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.core.drawables.IFont#isScaleFont()
*/
@Override
public final boolean isScaleFont() {
return scaleFont;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.core.drawables.IFont#setScaleFont(boolean)
*/
@Override
public final void setScaleFont(boolean scaleFont) {
this.scaleFont = scaleFont;
}
protected static Font createFont(File fontFile, FontType fontType,
float fontSize, Style[] styles) {
try {
return Font.createFont(toAwtFontType(fontType), fontFile)
.deriveFont(fontSize).deriveFont(toAwtStyle(styles));
} catch (Exception e) {
throw new IllegalArgumentException("Bad Font File", e);
}
}
protected static int toAwtFontType(FontType type) {
switch (type) {
case TYPE1:
return Font.TYPE1_FONT;
case TRUETYPE:
default:
return Font.TRUETYPE_FONT;
}
}
protected static int toAwtStyle(Style[] styles) {
int styleInt = Font.PLAIN;
if (styles == null || styles.length == 0) {
return styleInt;
}
for (Style style : styles) {
if (style == Style.BOLD) {
styleInt |= Font.BOLD;
} else if (style == Style.ITALIC) {
styleInt |= Font.ITALIC;
}
}
return styleInt;
}
protected static Style[] toVizStyles(int style) {
List<Style> styles = new ArrayList<Style>();
if ((style & Font.BOLD) != 0) {
styles.add(Style.BOLD);
}
if ((style & Font.ITALIC) != 0) {
styles.add(Style.ITALIC);
}
return styles.toArray(new Style[0]);
}
}

View file

@ -37,15 +37,12 @@ import org.geotools.coverage.grid.GeneralGridEnvelope;
import org.geotools.coverage.grid.GeneralGridGeometry;
import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.geometry.GeneralEnvelope;
import org.geotools.referencing.CRS;
import org.geotools.referencing.operation.DefaultMathTransformFactory;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.crs.GeneralDerivedCRS;
import org.opengis.referencing.datum.PixelInCell;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import com.raytheon.uf.common.geospatial.TransformFactory;
import com.raytheon.uf.common.serialization.adapters.GridGeometryAdapter;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
@ -78,8 +75,6 @@ import com.raytheon.uf.viz.core.time.TimeMatchingJob;
* Aug 15, 2007 chammack Initial Creation.
* Nov 30, 2007 461 bphillip Using VizTime now for time matching
* Oct 22, 2009 #3348 bsteffen added ability to limit number of frames
* July 20, 2013 NCEP #1015 Greg Hull check for rotated/derived CRS in getWorldToCRSTransform()
*
* </pre>
*
* @author chammack
@ -711,18 +706,9 @@ public abstract class AbstractDescriptor extends ResourceGroup implements
protected void setupTransforms() throws Exception {
GeneralGridGeometry gridGeometry = getGridGeometry();
MathTransform worldToCRS = getWorldToCRSTransform(gridGeometry);
if (worldToCRS != null) {
MathTransform crsToPixel = gridGeometry.getGridToCRS(
PixelInCell.CELL_CENTER).inverse();
worldToPixel = new DefaultMathTransformFactory()
.createConcatenatedTransform(worldToCRS, crsToPixel);
pixelToWorld = worldToPixel.inverse();
} else {
pixelToWorld = null;
worldToPixel = null;
}
worldToPixel = TransformFactory.worldToGrid(gridGeometry,
PixelInCell.CELL_CENTER);
pixelToWorld = (worldToPixel != null ? worldToPixel.inverse() : null);
}
/*
@ -862,35 +848,4 @@ public abstract class AbstractDescriptor extends ResourceGroup implements
false), envelope);
}
/**
* Get the world to CRS transform used for {@link #worldToPixel(double[])}
* and {@link #pixelToWorld(double[])}
*
* @param gridGeometry
* @return The world to gridGeometry CRS transform or null if there is none
*/
public static MathTransform getWorldToCRSTransform(
GeneralGridGeometry gridGeometry) {
CoordinateReferenceSystem crs = gridGeometry.getEnvelope()
.getCoordinateReferenceSystem();
if (crs instanceof GeneralDerivedCRS) {
GeneralDerivedCRS projCRS = (GeneralDerivedCRS) crs;
CoordinateReferenceSystem worldCRS = projCRS.getBaseCRS();
// NCEP #1015 : support of for ICAO-B PredefinedArea which
// has a FITTED_CS (ie rotated) CRS
if( worldCRS instanceof GeneralDerivedCRS ) {
worldCRS = ((GeneralDerivedCRS)worldCRS).getBaseCRS();
}
try {
return CRS.findMathTransform(worldCRS, crs);
} catch (FactoryException e) {
statusHandler.handle(Priority.PROBLEM,
"Error setting up Math Transforms,"
+ " this descriptor may not work properly", e);
}
}
return null;
}
}

View file

@ -29,7 +29,7 @@ package com.raytheon.uf.viz.core.drawables;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* May 7, 2007 chammack Initial Creation.
*
* Jul 18, 2013 2189 mschenke Added ability to specify font type
* </pre>
*
* @author chammack
@ -43,6 +43,11 @@ public interface IFont {
BOLD, ITALIC
};
/** Type of font */
public static enum FontType {
TRUETYPE, TYPE1
}
/**
* Return the name of the font
*

View file

@ -23,9 +23,8 @@ import java.awt.Font;
import java.awt.FontFormatException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.raytheon.uf.viz.core.drawables.AbstractAWTFont;
import com.raytheon.uf.viz.core.drawables.IFont;
/**
@ -39,25 +38,20 @@ import com.raytheon.uf.viz.core.drawables.IFont;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 1, 2012 bsteffen Initial creation
* Jun 1, 2012 bsteffen Initial creation
* Jul 24, 2013 2189 mschenke Refactored to share common awt font code
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class KmlFont implements IFont {
private Font font;
public class KmlFont extends AbstractAWTFont implements IFont {
private float magnification;
private boolean scaleFont;
private boolean smoothing;
public KmlFont(Font font) {
this.font = font;
super(font);
this.magnification = 1.0f;
}
@ -67,7 +61,6 @@ public class KmlFont implements IFont {
public KmlFont(String fontName) {
this(new Font(fontName, Font.PLAIN, 10));
}
public KmlFont(String fontName, float fontSize) {
@ -78,15 +71,10 @@ public class KmlFont implements IFont {
this(new Font(fontName, toAwtStyle(styles), (int) fontSize));
}
public KmlFont(File fontFile, float fontSize, Style[] styles)
throws FontFormatException, IOException {
this(Font.createFont(Font.TRUETYPE_FONT, fontFile).deriveFont(fontSize)
.deriveFont(toAwtStyle(styles)));
}
@Override
public String getFontName() {
return this.font.getFontName();
public KmlFont(File fontFile, FontType fontType, float fontSize,
Style[] styles) throws FontFormatException, IOException {
this(Font.createFont(toAwtFontType(fontType), fontFile)
.deriveFont(fontSize).deriveFont(toAwtStyle(styles)));
}
@Override
@ -94,11 +82,6 @@ public class KmlFont implements IFont {
return this.font.getSize2D();
}
@Override
public Style[] getStyle() {
return toVizStyles(font.getStyle());
}
@Override
public void dispose() {
@ -128,26 +111,6 @@ public class KmlFont implements IFont {
return magnification;
}
@Override
public void setSmoothing(boolean smooth) {
this.smoothing = smooth;
}
@Override
public boolean getSmoothing() {
return smoothing;
}
@Override
public boolean isScaleFont() {
return scaleFont;
}
@Override
public void setScaleFont(boolean scaleFont) {
this.scaleFont = scaleFont;
}
public Font getFont() {
return font;
}
@ -156,30 +119,4 @@ public class KmlFont implements IFont {
this.font = font;
}
private static int toAwtStyle(Style[] styles) {
int styleInt = Font.PLAIN;
if (styles == null || styles.length == 0) {
return styleInt;
}
for (Style style : styles) {
if (style == Style.BOLD) {
styleInt |= Font.BOLD;
} else if (style == Style.ITALIC) {
styleInt |= Font.ITALIC;
}
}
return styleInt;
}
private static Style[] toVizStyles(int style) {
List<Style> styles = new ArrayList<Style>();
if ((style & Font.BOLD) != 0) {
styles.add(Style.BOLD);
}
if ((style & Font.ITALIC) != 0) {
styles.add(Style.ITALIC);
}
return styles.toArray(new Style[0]);
}
}

View file

@ -48,6 +48,7 @@ import com.raytheon.uf.viz.core.IExtent;
import com.raytheon.uf.viz.core.IView;
import com.raytheon.uf.viz.core.data.IRenderedImageCallback;
import com.raytheon.uf.viz.core.drawables.IFont;
import com.raytheon.uf.viz.core.drawables.IFont.FontType;
import com.raytheon.uf.viz.core.drawables.IFont.Style;
import com.raytheon.uf.viz.core.drawables.IImage;
import com.raytheon.uf.viz.core.drawables.IShadedShape;
@ -134,9 +135,10 @@ public class KmlGraphicsTarget extends AbstractGraphicsTarget {
}
@Override
public KmlFont initializeFont(File fontFile, float size, Style[] styles) {
public IFont initializeFont(File fontFile, FontType type, float size,
Style[] styles) {
try {
return new KmlFont(fontFile, size, styles);
return new KmlFont(fontFile, type, size, styles);
} catch (FontFormatException e) {
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e);
} catch (IOException e) {

View file

@ -60,6 +60,7 @@ import com.raytheon.uf.viz.core.data.IRenderedImageCallback;
import com.raytheon.uf.viz.core.data.resp.NumericImageData;
import com.raytheon.uf.viz.core.drawables.IDescriptor;
import com.raytheon.uf.viz.core.drawables.IFont;
import com.raytheon.uf.viz.core.drawables.IFont.FontType;
import com.raytheon.uf.viz.core.drawables.IFont.Style;
import com.raytheon.uf.viz.core.drawables.IImage;
import com.raytheon.uf.viz.core.drawables.IShadedShape;
@ -246,8 +247,24 @@ public class DispatchGraphicsTarget extends DispatchingObject<IGraphicsTarget>
* float, com.raytheon.uf.viz.core.drawables.IFont.Style[])
*/
public IFont initializeFont(File fontFile, float size, Style[] styles) {
return new DispatchingFont(wrappedObject.initializeFont(fontFile, size,
styles), getDispatcher(), fontFile);
return initializeFont(fontFile, FontType.TRUETYPE, size, styles);
}
/**
* @param fontFile
* @param type
* @param size
* @param styles
* @return
* @see
* com.raytheon.uf.viz.core.IGraphicsTarget#initializeFont(java.io.File,
* com.raytheon.uf.viz.core.drawables.IFont.FontType float,
* com.raytheon.uf.viz.core.drawables.IFont.Style[])
*/
public IFont initializeFont(File fontFile, FontType type, float size,
Style[] styles) {
return new DispatchingFont(wrappedObject.initializeFont(fontFile, type,
size, styles), getDispatcher(), fontFile);
}
/**

View file

@ -20,9 +20,9 @@
package com.raytheon.viz.core.gl.internal;
import java.awt.Font;
import java.io.File;
import com.raytheon.uf.viz.core.drawables.AbstractAWTFont;
import com.raytheon.uf.viz.core.drawables.IFont;
import com.raytheon.viz.core.gl.IGLFont;
import com.sun.opengl.util.j2d.TextRenderer;
@ -36,6 +36,7 @@ import com.sun.opengl.util.j2d.TextRenderer;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* May 7, 2007 chammack Initial Creation.
* Jul 24, 2013 2189 mschenke Refactored to share common awt font code
*
* </pre>
*
@ -43,78 +44,33 @@ import com.sun.opengl.util.j2d.TextRenderer;
* @version 1.0
*/
public class GLFont implements IGLFont {
public class GLFont extends AbstractAWTFont implements IGLFont {
private boolean disposed = false;
private String fontName;
private float fontSize;
private float currentFontSize;
private Style[] styles;
private Font font;
private TextRenderer textRenderer;
private boolean smoothing = true;
private File fontFile;
private FontType fontType;
private float magnification = 1.0f;
private boolean scaleFont = true;
public GLFont() {
;
}
public GLFont(File font, float fontSize, Style[] styles) {
try {
this.fontName = font.getName();
this.font = Font.createFont(Font.TRUETYPE_FONT, font).deriveFont(
fontSize);
this.currentFontSize = this.fontSize = fontSize;
this.styles = styles;
if (styles != null && styles.length > 0) {
for (Style style : styles) {
if (style == Style.BOLD) {
this.font = this.font.deriveFont(Font.BOLD);
} else if (style == Style.ITALIC) {
this.font = this.font.deriveFont(Font.ITALIC);
}
}
}
} catch (Exception e) {
e.printStackTrace();
throw new IllegalArgumentException("Bad font file", e);
}
public GLFont(File font, FontType type, float fontSize, Style[] styles) {
super(font, type, fontSize, styles);
this.fontFile = font;
this.fontType = type;
this.currentFontSize = this.fontSize = fontSize;
this.textRenderer = TextRendererCache.getRenderer(this.font);
}
public GLFont(String fontName, float fontSize, Style[] styles) {
this.fontName = fontName;
super(fontName, fontSize, styles);
this.currentFontSize = this.fontSize = fontSize;
this.styles = styles;
int style = Font.PLAIN;
if (styles != null) {
for (Style s : styles) {
if (s == IFont.Style.BOLD) {
style = (Font.BOLD | style);
} else if (s == IFont.Style.ITALIC) {
style = (Font.ITALIC | style);
}
}
}
this.font = new Font(this.fontName, style, (int) fontSize);
this.textRenderer = TextRendererCache.getRenderer(this.font);
}
@ -127,15 +83,6 @@ public class GLFont implements IGLFont {
disposeInternal();
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.core.drawables.IFont#getFontName()
*/
public String getFontName() {
return this.fontName;
}
/*
* (non-Javadoc)
*
@ -145,15 +92,6 @@ public class GLFont implements IGLFont {
return currentFontSize;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.core.drawables.IFont#getStyle()
*/
public Style[] getStyle() {
return this.styles;
}
public TextRenderer getTextRenderer() {
return textRenderer;
}
@ -168,9 +106,9 @@ public class GLFont implements IGLFont {
GLFont newFont = null;
if (this.fontFile != null) {
// File based construction
newFont = new GLFont(this.fontFile, size, styles);
newFont = new GLFont(this.fontFile, fontType, size, getStyle());
} else {
newFont = new GLFont(this.fontName, size, styles);
newFont = new GLFont(getFontName(), size, getStyle());
}
return newFont;
@ -215,46 +153,6 @@ public class GLFont implements IGLFont {
return magnification;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.core.drawables.IFont#getSmoothing()
*/
@Override
public boolean getSmoothing() {
return smoothing;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.core.drawables.IFont#setSmoothing(boolean)
*/
@Override
public void setSmoothing(boolean smoothing) {
this.smoothing = smoothing;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.core.drawables.IFont#isScaleFont()
*/
@Override
public boolean isScaleFont() {
return scaleFont;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.core.drawables.IFont#setScaleFont(boolean)
*/
@Override
public void setScaleFont(boolean scaleFont) {
this.scaleFont = scaleFont;
}
/*
* (non-Javadoc)
*

View file

@ -71,6 +71,7 @@ import com.raytheon.uf.viz.core.data.IColorMapDataRetrievalCallback;
import com.raytheon.uf.viz.core.data.IRenderedImageCallback;
import com.raytheon.uf.viz.core.drawables.IDescriptor;
import com.raytheon.uf.viz.core.drawables.IFont;
import com.raytheon.uf.viz.core.drawables.IFont.FontType;
import com.raytheon.uf.viz.core.drawables.IFont.Style;
import com.raytheon.uf.viz.core.drawables.IImage;
import com.raytheon.uf.viz.core.drawables.IShadedShape;
@ -1224,15 +1225,10 @@ public class GLTarget extends AbstractGraphicsTarget implements IGLTarget {
return new GLImage(imageCallback, GLDefaultImagingExtension.class);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.core.IGraphicsTarget#initializeFont(java.io.File,
* float, com.raytheon.viz.core.drawables.IFont.Style[])
*/
@Override
public IFont initializeFont(File fontFile, float size, Style[] styles) {
return new GLFont(fontFile, size, styles);
public IFont initializeFont(File fontFile, FontType type, float size,
Style[] styles) {
return new GLFont(fontFile, type, size, styles);
}
/*

View file

@ -47,697 +47,123 @@ import com.raytheon.viz.mpe.util.DailyQcUtils.Station;
public class RenderPcp {
private static boolean first = true;
Pcp pcp = DailyQcUtils.pcp;
/*
* QC codes
*/
private static final int MISSING = -1;
private static final int STANDARD = 0;
private static final int FAILED = 1;
private static final int MANUAL = 2;
private static final int QUESTIONABLE = 3;
private static final int PARTIAL = 4;
private static final int ESTIMATED = 5;
private static final int TIMEDISTRIBUTED = 6;
private static final int VERIFIED = 8;
/**
* Converts point precipitation data in struct pdata to hrap grid. The 20
* closest stations are precalculated for each grid point - this speeds
* computations for data sets with many precipitation points. If there are
* no good precipitation points for a grid point, then a recalculation is
* made using all precipitation points. 1/R**2 interpolation is used. If
* requested, the final interpolation is scaled using seasonal isohyets. The
* grid is saved as a disk file and used later for a raster or vector (HRAP)
* plot.
*
* @param m
* @param k
* @param mk
* @param numPstations
* @param precip_stations
* @param hrap_grid
* @param pdata
* @param pcp_in_use
*/
public void render_pcp(int pcpn_day, int pcpn_time, int pcpn_time_step,
int numPstations, ArrayList<Station> precip_stations,
Hrap_Grid hrap_grid, Pdata[] pdata, int[] pcp_in_use) {
int isom = DailyQcUtils.isom;
int method = DailyQcUtils.method;
int mpe_dqc_max_precip_neighbors = DailyQcUtils.mpe_dqc_max_precip_neighbors;
int i, j, h, hh, time_pos, htotal;
double distance, dist1, dist2, dist, value;
double temp;
int totals[] = new int[5];
for (i = 0; i < 5; i++) {
totals[i] = 0;
}
/*
* pcpn_time_step is a function parameter. It specifies whether to
* interpolate 6hr or 24hr HRAP grid
*/
/*
* pcpn_time is a function parameter. It specifies which 6hr HRAP grid
* to generate. It takes 0,1,2,or 3 to represent different 6hr period of
* a day.
*/
/*
* time_pos is assigned a value of 0,1,2,or 3 (for 6hr data) or 4 (for
* 24hr data). This value is used in
* pdata[pcpn_day].stn[hh].frain[time_pos].data to control whether to
* retrieve 6hr data or 24hr data.
*/
if (pcpn_time_step == 0) {
time_pos = pcpn_time; // for 6 hour data: 0,1,2,3.
} else {
time_pos = 4; // for 24 hour data
/*
* in case the 24hr grid rendering is required, we check
* 24hr_grid_gen_method_token() to determine how to generate the
* grid. New Post OB9.2
*/
if (getTokenValue24hrGridGenMeth() == 1) {
render24hrPcpUsingFour6hr(pcpn_day, pcpn_time, numPstations,
precip_stations, hrap_grid, pdata, pcp_in_use);
return;
}
}
/* begin to interpolate value for each bin in the HRAP grid */
/*
* to interpolate, two quantities are needed first: value and distance.
* They are calculated by using the neighboring stations.
*/
for (i = 0; i < hrap_grid.maxi; i++) {
for (j = 0; j < hrap_grid.maxj; j++) {
/*
* Check if the grid cell is covered by an HSA. If not, then do
* not estimate precipitation for it.
*/
if (hrap_grid.owner[i][j] == -1) {
pcp.value[i][j] = 0;
continue;
}
value = 0.0;
distance = 0.0;
htotal = 0;
/*
* the following for loop is to calculate two quantities: value
* and distance, which later on, are used to interpret the HRAP
* grid.
*/
/*
* It uses neighbor stations of a HRAP grid bin to calculate
* value and distance.
*/
/* for each neighbor station of the grid bin, do the following */
/* For each of the closest stations. */
for (h = 0; h < mpe_dqc_max_precip_neighbors; h++) {
hh = hrap_grid.gage[i][j].index[h];
// hh is index of stations
if (pdata[pcpn_day].stn[hh].frain[time_pos].data < 0) {
/* No precip data. */
continue;
} // frain refers to level 2 data; rrain refers to level 1
if (method == 2 && precip_stations.get(hh).isoh[isom] <= 0) {
continue;
}
if (pdata[pcpn_day].stn[hh].frain[time_pos].qual != 0
&& pdata[pcpn_day].stn[hh].frain[time_pos].qual != 8
&& pdata[pcpn_day].stn[hh].frain[time_pos].qual != 6
&& pdata[pcpn_day].stn[hh].frain[time_pos].qual != 3
&& pdata[pcpn_day].stn[hh].frain[time_pos].qual != 4
&& pdata[pcpn_day].stn[hh].frain[time_pos].qual != 2) {
/* The station has a bad qc flag. Do not use it. */
continue;
}
/*
* Convert the coordinates of the grid and station in
* lat/lon into distance.
*/
dist1 = (i + (hrap_grid.hrap_minx - precip_stations.get(hh).hrap_x));
dist2 = (j + (hrap_grid.hrap_miny - precip_stations.get(hh).hrap_y));
dist = Math.pow(dist1, 2) + Math.pow(dist2, 2);
if (dist < .00001) {
dist = .00001;
}
dist = 1 / dist;
temp = pdata[pcpn_day].stn[hh].frain[time_pos].data * dist;
if (method == 2 && precip_stations.get(hh).isoh[isom] > 0) {
temp = temp * hrap_grid.isoh[isom][i][j]
/ (precip_stations.get(hh).isoh[isom] * 25.4);
}
value = value + temp;
distance = distance + dist;
htotal++;
if (htotal == 10) {
break;
}
}
/*
* end for loop (h = 0; h < mpe_dqc_max_precip_neighbors;h++)
* the above for loop is for each neighbor station.
*/
/*
* the above for loop is to calculate value and distance, which
* later on, are used to interpret the HRAP grid
*/
/*
* the resulting htotal is the valid number of neighbor stations
* that are used to calculate value and distance, which later
* on, are used to interpret the HRAP grid
*/
/*
* if there is not enough valid neighbor station, such as htotal
* <4, the code below handle this situation. Basically, the code
* recalculate the value and distance using all the stations --
* see the for (h = 0; h < max_stations; h++) loop below.
*/
if (htotal < 4) {
value = 0.0;
distance = 0.0;
htotal = 0;
for (h = 0; h < numPstations; h++) {
if (pdata[pcpn_day].stn[h].frain[time_pos].data < 0) {
continue;
}
if (pdata[pcpn_day].stn[h].frain[time_pos].qual != 0
&& pdata[pcpn_day].stn[h].frain[time_pos].qual != 8
&& pdata[pcpn_day].stn[h].frain[time_pos].qual != 6
&& pdata[pcpn_day].stn[h].frain[time_pos].qual != 3
&& pdata[pcpn_day].stn[h].frain[time_pos].qual != 4
&& pdata[pcpn_day].stn[h].frain[time_pos].qual != 2) {
continue;
}
if (method == 2
&& precip_stations.get(h).isoh[isom] <= 0) {
continue;
}
dist1 = (i + (hrap_grid.hrap_minx - precip_stations
.get(h).hrap_x));
dist2 = (j + (hrap_grid.hrap_miny - precip_stations
.get(h).hrap_y));
dist = Math.pow(dist1, 2) + Math.pow(dist2, 2);
/*
* if distance from grid box to station is >
* mpe_dqc_grid_max_distbins,
*/
/* then do not use station */
if (dist < .00001) {
dist = .00001;
}
else if (Math.sqrt(dist) > DailyQcUtils.mpe_dqc_grid_max_dist) {
continue;
}
dist = 1 / dist;
temp = pdata[pcpn_day].stn[h].frain[time_pos].data
* dist;
if (method == 2
&& precip_stations.get(h).isoh[isom] > 0) {
temp = temp
* hrap_grid.isoh[isom][i][j]
/ (precip_stations.get(h).isoh[isom] * 25.4);
}
value = value + temp;
distance = distance + dist;
htotal++;
}
}/* end the handling of special case : if (htotal < 4), */
/* which means there is no enough neighboring stations */
if (htotal == 0) {
pcp.value[i][j] = 0;
} else {
pcp.value[i][j] = (int) (value / distance * 100.0);
}
// if (htotal != 0) {
// pcp.value[i][j] += (int) (value / distance * 100);
// }
if (pcp.value[i][j] < .01) {
pcp.value[i][j] = 0;
}
}
} // end of the ( k = 0; k<4; k++) loop, which interpolates 4 6hr HRAP
// grid.
/* final adjustment of the pcp->value */
// for (i = 0; i < hrap_grid.maxi; i++) {
// hrap_grid comes from the function parameter
// for (j = 0; j < hrap_grid.maxj; j++) {
//
// if (pcp.value[i][j] < .01) {
// pcp.value[i][j] = 0;
// }
// }
// }
if (pcpn_time_step == 0) {
time_pos = pcpn_day * 4 + 3 - pcpn_time;
} else {
time_pos = 40 + pcpn_day;
}
// notice that time_pos is a variable defined inside the function, and
// its value do not need to be limited as 0,1,2,3,or 4. Here it is
// assigned with bigger numbers.
// time_pos = 40 + pcpn_day;
// pcp_in_use[i] = 1 -- grids rendered via Render button OR Save Level2
// option
// = -1 --grids for this time period not rendered (initialization value)
pcp_in_use[time_pos] = 1;
ReadQPFGrids rqp = new ReadQPFGrids();
rqp.write_file("pcp", time_pos, pcp);
}
/*
* get the token value of token mpe_24hr_grid_gen_method. This token will
* determine how we generate the 24hr grid. We can either use the 24hr gage
* values, which is the old way, or we can use four 6hr gage values and add
* them together.
*/
/* there is some problem with the static */
/**
* @param pcpn_day
* @param pcpn_time
* @param numPstations
* @param precip_stations
* @param hrap_grid
* @param pdata
* @param pcp_in_use
*/
private void render24hrPcpUsingFour6hr(int pcpn_day, int pcpn_time,
int numPstations, ArrayList<Station> precip_stations,
Hrap_Grid hrap_grid, Pdata[] pdata, int[] pcp_in_use) {
int i, j, k, h, hh, time_pos, htotal;
double distance, dist1, dist2, dist, value;
double temp;
int isom = DailyQcUtils.isom;
int method = DailyQcUtils.method;
int totals[] = new int[5];
int all_total = 0;
int neighbor_total = 0;
for (i = 0; i < 5; i++) {
totals[i] = 0;
}
/*
* pcpn_time_step is function parameter. It specifies whether to
* interpolate 6hr or 24hr HRAP grid
*/
/*
* pcpn_time is a function parameter. It specifies which 6hr HRAP grid
* to generate. It takes 0,1,2,or 3 to represent different 6hr period of
* a day.
*/
/*
* time_pos is assigned a value of 0,1,2,or 3 (for 6hr data) or 4 (for
* 24hr data). This value is used in
* pdata[pcpn_day].stn[hh].frain[time_pos].data to control whether to
* retrieve 6hr data or 24hr data.
*/
/* initialization of the pcp->value */
for (i = 0; i < hrap_grid.maxi; i++) { /*
* hrap_grid comes from the
* function parameter
*/
for (j = 0; j < hrap_grid.maxj; j++) {
pcp.value[i][j] = 0;
}
}
/*
* begin to interpolate 4 6hr grids. At the end of each iteration, the
* calculated interpolation value is added to pcp->value[i][j].
*/
/*
* time_pos is assigned a value of 0,1,2,or 3 (for four 6hr data). This
* value is used in pdata[pcpn_day].stn[hh].frain[time_pos].data to
* retrieve 6hr data.
*/
for (k = 0; k < 4; k++) {
time_pos = k; /* for 6 hour data: 0, 1,2,3. */
/* begin to interpolate value for each bin in the HRAP grid */
/*
* to interpolate, two quantities are needed first: value and
* distance. They are calculated by using the neighboring stations.
*/
for (i = 0; i < hrap_grid.maxi; i++) { /*
* hrap_grid comes from the
* function parameter
*/
for (j = 0; j < hrap_grid.maxj; j++) {
/*
* Check if the grid cell is covered by an HSA. If not, then
* do not estimate precipitation for it.
*/
if (hrap_grid.owner[i][j] == -1) {
pcp.value[i][j] = 0;
continue;
}
value = 0.0;
distance = 0.0;
htotal = 0;
/*
* the following for loop is to calculate two quantities:
* value and distance, which later on, are used to interpret
* the HRAP grid.
*/
/*
* It uses neighbor stations of a HRAP grid bin to calculate
* value and distance.
*/
/*
* for each neighbor station of the grid bin, do the
* following
*/
int mpe_dqc_max_precip_neighbors = DailyQcUtils.mpe_dqc_max_precip_neighbors;
for (h = 0; h < mpe_dqc_max_precip_neighbors; h++) {
hh = hrap_grid.gage[i][j].index[h];/*
* hh is index of
* stations
*/
if (pdata[pcpn_day].stn[hh].frain[time_pos].data < 0) {
/* No precip data. */
continue;
} /*
* frain refers to level 2 data; rain refers to level
* 1
*/
/*
* generate something for output later on if in debug
* mode
*/
// if (debug_level >= 1) {
// if (pdata[pcpn_day].stn[hh].frain[time_pos].qual
// == MISSING)
// {
// missing_total++;
// }
//
// if (pdata[pcpn_day].stn[hh].frain[time_pos].qual
// == ESTIMATED)
// {
// estimated_total++;
// }
//
// if (pdata[pcpn_day].stn[hh].frain[time_pos].qual
// == FAILED)
// {
// failed_total++;
// }
//
// if (method == 2 && station[hh].isoh[isom] <= 0)
// {
// climo_total++;
// }
// } /* end if (debug_level >= 1) */
if (DailyQcUtils.method == 2
&& precip_stations.get(hh).isoh[isom] <= 0) {
continue;
}
if (pdata[pcpn_day].stn[hh].frain[time_pos].qual != 0
&& pdata[pcpn_day].stn[hh].frain[time_pos].qual != 8
&& pdata[pcpn_day].stn[hh].frain[time_pos].qual != 6
&& pdata[pcpn_day].stn[hh].frain[time_pos].qual != 3
&& pdata[pcpn_day].stn[hh].frain[time_pos].qual != 4
&& pdata[pcpn_day].stn[hh].frain[time_pos].qual != 2) {
/* The station has a bad qc flag. Do not use it. */
continue;
}
/*
* Convert the coordinates of the grid and station in
* lat/lon into distance.
*/
dist1 = (i + hrap_grid.hrap_minx - precip_stations
.get(hh).hrap_x);
dist2 = (j + hrap_grid.hrap_miny - precip_stations
.get(hh).hrap_y);
dist = Math.pow(dist1, 2) + Math.pow(dist2, 2);
if (dist < .00001) {
dist = .00001;
}
dist = 1 / dist;
temp = pdata[pcpn_day].stn[hh].frain[time_pos].data
* dist;
if (method == 2
&& precip_stations.get(hh).isoh[isom] > 0) {
temp = temp
* hrap_grid.isoh[isom][i][j]
/ (precip_stations.get(hh).isoh[isom] * 25.4);
}
value = value + temp;
distance = distance + dist;
htotal++;
if (htotal == 10) {
break;
}
}
/*
* end for loop (h = 0; h <
* mpe_dqc_max_precip_neighbors;h++)
*/
/* the above for loop is for each neighbor station. */
/*
* the above for loop is to calculate value and distance,
* which later on, are used to interpret the HRAP grid
*/
/*
* the resulting htotal is the valid number of neighbor
* stations that are used to calculate value and distance,
* which later on, are used to interpret the HRAP grid
*/
/*
* if there is not enough valid neighbor station, such as
* htotal <4, the code below handle this situation.
* Basically, the code recalculate the value and distance
* using all the stations -- see the for (h = 0; h <
* max_stations; h++) loop below.
*/
if (htotal < 4) {
value = 0.0;
distance = 0.0;
htotal = 0;
for (h = 0; h < numPstations; h++) {
if (pdata[pcpn_day].stn[h].frain[time_pos].data < 0) {
continue;
}
if (pdata[pcpn_day].stn[h].frain[time_pos].qual != 0
&& pdata[pcpn_day].stn[h].frain[time_pos].qual != 8
&& pdata[pcpn_day].stn[h].frain[time_pos].qual != 6
&& pdata[pcpn_day].stn[h].frain[time_pos].qual != 3
&& pdata[pcpn_day].stn[h].frain[time_pos].qual != 4
&& pdata[pcpn_day].stn[h].frain[time_pos].qual != 2) {
continue;
}
if (method == 2
&& precip_stations.get(h).isoh[isom] <= 0) {
continue;
}
dist1 = (i + hrap_grid.hrap_minx - precip_stations
.get(h).hrap_x);
dist2 = (j + hrap_grid.hrap_miny - precip_stations
.get(h).hrap_y);
dist = Math.pow(dist1, 2) + Math.pow(dist2, 2);
if (dist < .00001) {
dist = .00001;
}
dist = 1 / dist;
temp = pdata[pcpn_day].stn[h].frain[time_pos].data
* dist;
if (method == 2
&& precip_stations.get(h).isoh[isom] > 0) {
temp = temp
* hrap_grid.isoh[isom][i][j]
/ (precip_stations.get(h).isoh[isom] * 25.4);
}
value = value + temp;
distance = distance + dist;
htotal++;
}
neighbor_total++;
} /* end the handling of special case : if (htotal < 4), */
/* which means there is no enough neighboring stations */
/*
* add the interpreted value for the bin of the HRAP_grid
*/
/*
* if (htotal == 0) { pcp->value[i][j] += 0; } else {
* pcp->value[i][j] += (int) (value / distance * 100); }
*/
if (htotal != 0) {
pcp.value[i][j] += (int) (value / distance * 100);
}
/*
* if (pcp->value[i][j] < .01) { pcp->value[i][j] = 0; }
*/
all_total++;
} /* end of for loop (j = 0; j < hrap_grid->maxj; j++) */
} /* end of for loop (i = 0; i < hrap_grid->maxi; i++) */
/* At this moment, the interpretation of HRAP grid is done */
}/*
* end of the ( k = 0; k<4; k++) loop, which interpolates 4 6hr HRAP
* grid.
*/
/* final adjustment of the pcp->value */
for (i = 0; i < hrap_grid.maxi; i++) { /*
* hrap_grid comes from the
* function parameter
*/
for (j = 0; j < hrap_grid.maxj; j++) {
if (pcp.value[i][j] < .01) {
pcp.value[i][j] = 0;
}
}
}
/* time_pos = pcpn_day * 4 + 3 - pcpn_time; */
time_pos = 40 + pcpn_day;
/*
* pcp_in_use[i] = 1 -- grids rendered via Render button OR Save Level2
* option = -1 --grids for this time period not rendered (initialization
* value)
*/
pcp_in_use[time_pos] = 1;
/*
* results of grid rendering routines (render_t, render_t6, render_pcp,
* render_z) are written to scratch files using the write_file routine.
* scratch file is stored in the scratch directory.
*/
ReadQPFGrids rqp = new ReadQPFGrids();
rqp.write_file("pcp", time_pos, pcp);
}
int getTokenValue24hrGridGenMeth() {
int token_of_24hr_grid_gen_method = 0;
/* int token_of_24hr_grid_gen_method = 0; */
if (first == true) {
String token_name_of_24hr_grid_gen_method_token = "mpe_dqc_24hr_precip_grid_meth";
/* char strTokenValue[50] = { '\0' }; */
String DQC24hrPrecipMeth;
// char message[GAGEQC_MESSAGE_LEN] = { '\0' };
AppsDefaults appsDefaults = AppsDefaults.getInstance();
DQC24hrPrecipMeth = appsDefaults
.getToken(token_name_of_24hr_grid_gen_method_token);
// sprintf(message, "\nSTATUS: token value of \"%s\" : %s\n",
// token_name_of_24hr_grid_gen_method_token, strTokenValue);
// logMessage(message);
if (DQC24hrPrecipMeth != null && DQC24hrPrecipMeth.length() > 0) {
/* we use the token ACCUM_6HR and USE_24HR */
if (DQC24hrPrecipMeth.equalsIgnoreCase("ACCUM_6HR")) {
token_of_24hr_grid_gen_method = 1;
}
}
first = false;
}
return token_of_24hr_grid_gen_method;
}
}
private static boolean first = true;
Pcp pcp = DailyQcUtils.pcp;
/*
* QC codes
*/
private static final int MISSING = -1;
private static final int STANDARD = 0;
private static final int SCREENED = 0;
private static final int FAILED = 1;
private static final int MANUAL = 2;
private static final int QUESTIONABLE = 3;
private static final int PARTIAL = 4;
private static final int ESTIMATED = 5;
private static final int TIMEDISTRIBUTED = 6;
private static final int VERIFIED = 8;
private static final String MPE_DQC_GRID_RENDERING_METHOD_TOKEN = "mpe_dqc_grid_render_method";
private static final int maxDistSquared = DailyQcUtils.mpe_dqc_grid_max_dist
* DailyQcUtils.mpe_dqc_grid_max_dist;
/**
* Converts point precipitation data in struct pdata to hrap grid. The 20
* closest stations are precalculated for each grid point - this speeds
* computations for data sets with many precipitation points. If there are
* no good precipitation points for a grid point, then a recalculation is
* made using all precipitation points. 1/R**2 interpolation is used. If
* requested, the final interpolation is scaled using seasonal isohyets. The
* grid is saved as a disk file and used later for a raster or vector (HRAP)
* plot.
*
* @param m
* @param k
* @param mk
* @param numPstations
* @param
* @param hrap_grid
* @param pdata
* @param pcp_in_use
*/
// mpe_dqc_grid_render_method
// ---------------------------------------------------------------------------------------
public void render_pcp(int pcpn_day, int pcpn_time, int pcpn_time_step,
int numPstations, ArrayList<Station> precip_stations,
Hrap_Grid hrap_grid, Pdata[] pdata, int[] pcp_in_use) {
String header = "RenderPcp.render_pcp(): ";
AppsDefaults appsDefaults = AppsDefaults.getInstance();
String tokenValue = appsDefaults
.getToken(MPE_DQC_GRID_RENDERING_METHOD_TOKEN);
// System.out.println(header + "tokenValue = " + tokenValue);
// tokenValue = "BLOCKING";
// tokenValue = "DISTANCE_SQUARED";
System.out.println(header + "now tokenValue = " + tokenValue);
if (tokenValue != null && tokenValue.equalsIgnoreCase("BLOCKING")) {
RenderPcpBlocking renderer = new RenderPcpBlocking();
renderer.render_pcp(pcpn_day, pcpn_time, pcpn_time_step,
numPstations, precip_stations, hrap_grid, pdata, pcp_in_use);
}
else {
RenderPcpStandard renderer = new RenderPcpStandard();
renderer.render_pcp(pcpn_day, pcpn_time, pcpn_time_step,
numPstations, precip_stations, hrap_grid, pdata, pcp_in_use);
}
determineMaxPrecip(hrap_grid);
}
private int determineMaxPrecip(Hrap_Grid hrap_grid) {
// TODO Auto-generated method stub
String header = "RenderPcp.determineMaxPrecip(): ";
int value = 0;
int maxValue = -1;
for (int col = 0; col < hrap_grid.maxi; col++) {
for (int row = 0; row < hrap_grid.maxj; row++) {
value = pcp.value[row][col];
if (value > maxValue) {
maxValue = value;
}
}
}
System.out.println(header + "maxValue = " + maxValue);
return maxValue;
} // end determineMaxPrecip()
// ---------------------------------------------------------------------------------------
} // end class RenderPcp

View file

@ -0,0 +1,957 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.mpe.util;
import java.util.ArrayList;
import com.raytheon.uf.common.ohd.AppsDefaults;
import com.raytheon.viz.mpe.util.DailyQcUtils.Hrap_Grid;
import com.raytheon.viz.mpe.util.DailyQcUtils.Pcp;
import com.raytheon.viz.mpe.util.DailyQcUtils.Pdata;
import com.raytheon.viz.mpe.util.DailyQcUtils.Station;
/**
* DESCRIPTION: Maps precipitation station values to an HRAP grid. Produces the
* DailyQC version of the GageOnly analysis.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 11, 2009 snaples Initial creation
* May 02, 2011 8962 snaples Added render24hrPcpUsingFour6hr() method
*
* </pre>
*
* @author snaples
* @version 1.0
*/
public class RenderPcpBlocking {
private static boolean first = true;
Pcp pcp = DailyQcUtils.pcp;
/*
* QC codes
*/
private static final int MISSING = -1;
private static final int STANDARD = 0;
private static final int SCREENED = 0;
private static final int FAILED = 1;
private static final int MANUAL = 2;
private static final int QUESTIONABLE = 3;
private static final int PARTIAL = 4;
private static final int ESTIMATED = 5;
private static final int TIMEDISTRIBUTED = 6;
private static final int VERIFIED = 8;
// private static final String MPE_DQC_GRID_RENDERING_METHOD_TOKEN =
// "mpe_dqc_grid_render_method";
private static final int maxDistSquared = DailyQcUtils.mpe_dqc_grid_max_dist
* DailyQcUtils.mpe_dqc_grid_max_dist;
// private static final int maxDistSquared = 400;
/**
* Converts point precipitation data in struct pdata to hrap grid. The 20
* closest stations are precalculated for each grid point - this speeds
* computations for data sets with many precipitation points. If there are
* no good precipitation points for a grid point, then a recalculation is
* made using all precipitation points. 1/R**2 interpolation is used. If
* requested, the final interpolation is scaled using seasonal isohyets. The
* grid is saved as a disk file and used later for a raster or vector (HRAP)
* plot.
*
* @param m
* @param k
* @param mk
* @param numPstations
* @param
* @param hrap_grid
* @param pdata
* @param pcp_in_use
*/
// mpe_dqc_grid_render_method
private boolean usingSingleDirectionCloseOutMode = true;
private static final int MIN_PREFERRED_USED_GRID_CELLS = 4;
private static final int MIN_REQUIRED_USED_GRID_CELLS = 1;
private SearchDirection north = new SearchDirection();
private SearchDirection south = new SearchDirection();
private SearchDirection east = new SearchDirection();
private SearchDirection west = new SearchDirection();
private int colMin;
private int colMax;
private int rowMin;
private int rowMax;
private int prevColMin;
private int prevColMax;
private int prevRowMin;
private int prevRowMax;
// weighting variables
private int usedGridCellCount = 0;
private double totalWeightedValue = 0;
private double totalDistanceWeight = 0;
// grid variables
private int binStationCount[][];
private int usableStationCount = 0;
private double valueGrid[][];
private double prismStationGrid[][];
private int isom = -1;
class SearchDirection {
private boolean isOpen;
private int level;
public SearchDirection() {
reset();
}
public void reset() {
setOpen(true);
setLevel(0);
}
public boolean isOpen() {
return isOpen;
}
public void setOpen(boolean isOpen) {
this.isOpen = isOpen;
}
public void close() {
setOpen(false);
}
void expandSearchIfAllowed() {
if (isOpen()) {
incrementLevel();
if (getLevel() > DailyQcUtils.mpe_dqc_grid_max_dist) {
setLevel(DailyQcUtils.mpe_dqc_grid_max_dist);
close();
}
}
}
public void incrementLevel() {
this.level++;
}
private void setLevel(int level) {
this.level = level;
}
public int getLevel() {
return level;
}
} // end inner class SearchDirection
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
int getTokenValue24hrGridGenMeth() {
int token_of_24hr_grid_gen_method = 0;
if (first == true) {
String tokenName = "mpe_dqc_24hr_precip_grid_meth";
String dqc24hrPrecipMeth;
// char message[GAGEQC_MESSAGE_LEN] = { '\0' };
AppsDefaults appsDefaults = AppsDefaults.getInstance();
dqc24hrPrecipMeth = appsDefaults.getToken(tokenName);
if (dqc24hrPrecipMeth != null) {
/* allowed token values: (ACCUM_6HR, USE_24HR) */
if (dqc24hrPrecipMeth.equalsIgnoreCase("ACCUM_6HR")) {
token_of_24hr_grid_gen_method = 1;
}
}
first = false;
}
return token_of_24hr_grid_gen_method;
}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
public void render_pcp(int pcpn_day, int pcpn_time, int pcpn_time_step,
int numPstations, ArrayList<Station> stationList,
Hrap_Grid hrap_grid, Pdata[] pdata, int[] pcp_in_use) {
isom = DailyQcUtils.isom;
int time_pos;
if (pcpn_time_step == 0) {
time_pos = pcpn_time; // for 6 hour data: 0,1,2,3.
boolean save_grids = true;
boolean accumulate_grids = false;
render_pcp_internal(pcpn_day, pcpn_time, pcpn_time_step,
numPstations, stationList, hrap_grid, pdata, pcp_in_use,
save_grids, accumulate_grids);
} else {
time_pos = 4; // for 24 hour data
/*
* in case the 24hr grid rendering is required, we check
* 24hr_grid_gen_method_token() to determine how to generate the
* grid. New Post OB9.2
*/
// debug
// first = true;
if (getTokenValue24hrGridGenMeth() == 1) {
render24hrPcpUsingFour6hr(pcpn_day, pcpn_time, numPstations,
stationList, hrap_grid, pdata, pcp_in_use);
return;
} else // calculate 24-hour grids the regular way
{
boolean save_grids = true;
boolean accumulate_grids = false;
render_pcp_internal(pcpn_day, pcpn_time, pcpn_time_step,
numPstations, stationList, hrap_grid, pdata,
pcp_in_use, save_grids, accumulate_grids);
}
}
}
private void render_pcp_internal(int pcpn_day, int pcpn_time,
int pcpn_time_step, int numPstations,
ArrayList<Station> stationList, Hrap_Grid hrap_grid, Pdata[] pdata,
int[] pcp_in_use, boolean save_grids, boolean should_accumulate) {
// String header = "RenderPcpBlocking.render_pcp_internal(): ";
int isom = DailyQcUtils.isom;
double resultingPrecipValue = 0.0;
/*-----------------------------------------------------*/
allocateGrids(hrap_grid);
initializeGrids(hrap_grid, should_accumulate);
placeStationsInGrid(pcpn_day, pcpn_time, pcpn_time_step, numPstations,
stationList, hrap_grid, pdata);
// for every grid location, determine its estimated value
for (int col = 0; col < hrap_grid.maxi; col++) {
for (int row = 0; row < hrap_grid.maxj; row++) {
/*
* Check if the grid cell is covered by an HSA. If not, then do
* not estimate precipitation for it.
*/
if (hrap_grid.owner[col][row] == -1) {
pcp.value[row][col] = 0;
continue;
}
if (binStationCount[col][row] > 0) // if any station is in this
// grid bin
{
resultingPrecipValue = valueGrid[col][row];
// adjust grid bin with actual gage by the prism factor
if (prismStationGrid[col][row] > 0) {
double prismStationValue = prismStationGrid[col][row] * 25.4;
double prismGridValue = hrap_grid.isoh[isom][col][row];
double prismFactor = (double) prismGridValue
/ prismStationValue;
resultingPrecipValue *= prismFactor;
} else {
resultingPrecipValue = 0.0;
}
// pcp.value[row][col] is the value of grid,
// so we don't need to estimate a value for [row][col]
}
else // this grid location requires an estimate to be generated
{
resultingPrecipValue = estimateValue(isom, col, row,
hrap_grid);
}
if (resultingPrecipValue >= 0.0) {
int precipInHundredthsOfMm = (int) Math
.floor((resultingPrecipValue * 100.0));
if (should_accumulate) { // for case where we want to make
// 24 = 4 6hr periods added
// together
pcp.value[col][row] += precipInHundredthsOfMm;
} else {
pcp.value[col][row] = precipInHundredthsOfMm;
}
}
} /* end for (col = 0 ... */
} /* end for (row = 0 ... */
// System.out.println(header + "maxPrecip in hundredths of mm = " +
// maxPrecip);
int time_pos;
/*
* notice that time_pos is a variable defined inside the function, and
* its value do not need to be limited as 0,1,2,3,or 4. Here it is
* assigned with bigger numbers.
*/
if (pcpn_time_step == 0) // one of the 6-hr periods
{
time_pos = pcpn_day * 4 + 3 - pcpn_time;
} else // 24 hr
{
time_pos = 40 + pcpn_day;
}
if (save_grids) {
/*
* pcp_in_use[i] = 1 -- grids rendered via Render button OR Save
* Level2 option = -1 --grids for this time period not rendered
* (initialization value)
*/
pcp_in_use[time_pos] = 1;
/*
* results of grid rendering routines (render_t, render_t6,
* render_pcp, render_z) are written to scratch files using the
* write_file routine. scratch file is stored in the scratch
* directory.
*/
ReadQPFGrids rqp = new ReadQPFGrids();
rqp.write_file("pcp", time_pos, pcp);
}
} // end render_pcp_internal()
private double estimateValue(int isom, int col, int row, Hrap_Grid hrap_grid) {
// String header = "RenderPcpBlocking.estimateValue(): ";
int r;
int c;
double estimatedPrecipValue = 0.0;
if (hrap_grid.isoh[isom][col][row] < 0.01) {
estimatedPrecipValue = 0;
return estimatedPrecipValue; // can't do anything more, quit
}
// look through surrounding grid bins only for
// values to be used in the distance-weighted interpolation
// set to open and level = 0
north.reset();
south.reset();
east.reset();
west.reset();
// initialize
totalWeightedValue = 0.0;
totalDistanceWeight = 0.0;
usedGridCellCount = 0;
rowMax = row;
rowMin = row;
colMax = col;
colMin = col;
prevRowMax = rowMax;
prevRowMin = rowMin;
prevColMax = colMax;
prevColMin = colMin;
while (north.isOpen() || south.isOpen() || east.isOpen()
|| west.isOpen()) {
// expand search levels as appropriate
// changes rowMin, rowMax, colMin, colMax
expandGridSearch(col, row, hrap_grid);
if (rowMin < prevRowMin) // grew the top side
{
r = rowMin;
for (c = colMin; c <= colMax; c++) {
processGriddedStationValues(col, row, c, r, hrap_grid);
}
} else // didn't grow the top side
{
if (colMin < prevColMin) // still need to check top left corner
{
c = colMin;
r = rowMin;
processGriddedStationValues(col, row, c, r, hrap_grid);
}
if (colMax > prevColMax) // still need to check top right corner
{
c = colMax;
r = rowMin;
processGriddedStationValues(col, row, c, r, hrap_grid);
}
}
if (rowMax > prevRowMax) // grew the bottom side
{
r = rowMax;
for (c = colMin; c <= colMax; c++) {
processGriddedStationValues(col, row, c, r, hrap_grid);
}
} else // didn't grow the bottom side
{
if (colMin < prevColMin) // still need to check bottom left
// corner
{
c = colMin;
r = rowMax;
processGriddedStationValues(col, row, c, r, hrap_grid);
}
if (colMax > prevColMax) // still need to check bottom right
// corner
{
c = colMax;
r = rowMax;
processGriddedStationValues(col, row, c, r, hrap_grid);
}
}
if (colMin < prevColMin) // grew left side
{
c = colMin;
for (r = rowMin + 1; r < rowMax; r++) {
processGriddedStationValues(col, row, c, r, hrap_grid);
}
}
if (colMax > prevColMax) // grew right side
{
c = colMax;
for (r = rowMin + 1; r < rowMax; r++) {
processGriddedStationValues(col, row, c, r, hrap_grid);
}
}
if (usedGridCellCount >= MIN_PREFERRED_USED_GRID_CELLS) // have
// enough
// cells to
// look at,
// can quit
// now
{
north.close();
south.close();
east.close();
west.close();
// System.out.println(header +
// "met minimum cell preference, resultingPrecipValue = " +
// resultingPrecipValue);
}
} /* end while (northLevelOpen ... */
// set weighted value to the cell or set value to 0.0 if there is not
// enough data
if (usedGridCellCount >= MIN_REQUIRED_USED_GRID_CELLS) {
estimatedPrecipValue = totalWeightedValue / totalDistanceWeight;
// System.out.println(header +
// "met minimum cell requirement, resultingPrecipValue = " +
// resultingPrecipValue);
} else // set to zero precip
{
estimatedPrecipValue = 0.0;
}
return estimatedPrecipValue;
} // end estimateValue()
// *--------------------------------------------------------------------------
void processGriddedStationValues(int renderingCol, int renderingRow,
int gridCol, int gridRow, Hrap_Grid hrap_grid) {
String header = "RenderPcpBlocking.processGriddedStationValues(): ";
int usedCells = 0;
// sprintf(message,
// "renderingCol = %d, renderingRow = %d, gridCol = %d, gridRow = %d \n",
// renderingCol, renderingRow, gridCol, gridRow);
// logMessage(message);
if ((gridCol < 0) || (gridCol > hrap_grid.maxi) || (gridRow < 0)
|| (gridRow > hrap_grid.maxj)) {
System.out.println(header + "OUT OF RANGE gridCol = " + gridCol
+ " gridRow = " + gridRow);
}
double gageValue = valueGrid[gridCol][gridRow];
if (gageValue >= 0.0) // there is a gage
// located at (gridCol,gridRow)
// with a valid precip value
{
usedCells = adjustWeights(gageValue, gridRow, gridCol,
renderingRow, renderingCol, hrap_grid, isom,
prismStationGrid);
usedGridCellCount += usedCells;
// if data was found, close off a direction, usually 2 directions,
// such as north and west
if (usedCells > 0) {
determineDirectionFoundAndCloseOff(renderingCol, renderingRow,
gridCol, gridRow);
}
}
return;
} // end processGriddedStationValues()
// *--------------------------------------------------------------------------
void expandGridSearch(int col, int row, Hrap_Grid hrap_grid) {
// expand search levels as appropriate
north.expandSearchIfAllowed();
south.expandSearchIfAllowed();
east.expandSearchIfAllowed();
west.expandSearchIfAllowed();
// save previous values of row and col min and max
prevRowMax = rowMax;
prevRowMin = rowMin;
prevColMax = colMax;
prevColMin = colMin;
// determine nested for loop ranges
rowMax = row + north.getLevel();
if (rowMax >= hrap_grid.maxj) {
rowMax = hrap_grid.maxj - 1;
north.close();
}
rowMin = row - south.getLevel(); // row
if (rowMin < 0) {
rowMin = 0;
south.close();
}
colMin = col - west.getLevel();
if (colMin < 0) {
colMin = 0;
west.close();
}
colMax = col + east.getLevel();
if (colMax >= hrap_grid.maxi) {
colMax = hrap_grid.maxi - 1;
east.close();
}
return;
} // end expandGridSearch()
/*--------------------------------------------------------------------------*/
void determineDirectionFoundAndCloseOffSimpleVersion(int renderingCol,
int renderingRow, int stationCol, int stationRow) {
if (stationRow < renderingRow) {
south.close();
} else if (stationRow > renderingRow) {
north.close();
}
if (stationCol < renderingCol) {
west.close();
} else if (stationCol > renderingCol) {
east.close();
}
}
/*--------------------------------------------------------------------------*/
void determineDirectionFoundAndCloseOff(int renderingCol, int renderingRow,
int stationCol, int stationRow) {
final int closeEnoughToBeEqual = 2;
// String header =
// "RenderPcpBlocking.determineDirectionFoundAndCloseOff(): ";
// consider taking a diff and a point is considered in a straightline if
// its difference is < 3 from the grid bin to render
int northSouthDifference = Math.abs(stationRow - renderingRow);
int eastWestDifference = Math.abs(stationCol - renderingCol);
boolean isNorthOrSouth = false;
boolean isEastOrWest = false;
if (northSouthDifference - eastWestDifference <= closeEnoughToBeEqual) {
isNorthOrSouth = true;
isEastOrWest = true;
} else if (northSouthDifference > eastWestDifference) {
isNorthOrSouth = true;
} else {
isEastOrWest = true;
}
if (usingSingleDirectionCloseOutMode) {
// System.out.println(header +
// "Using usingSingleDirectionCloseOutMode difference-based close off.");
if (isNorthOrSouth) {
// this point functions as the north-south representative, since
// it is primarily north or south
if (stationRow < renderingRow) {
south.close();
} else if (stationRow > renderingRow) {
north.close();
}
}
if (isEastOrWest) {
if (stationCol < renderingCol) {
west.close();
} else if (stationCol > renderingCol) {
east.close();
}
}
}
else // in mode in which points represent 2 directions (unless directly
// North-south or east-west)
{
// System.out.println(header +
// "Using traditional difference cutoff.");
if (stationRow < renderingRow) {
south.close();
} else if (stationRow > renderingRow) {
north.close();
}
if (stationCol < renderingCol) {
west.close();
} else if (stationCol > renderingCol) {
east.close();
}
}
return;
} // determineDirectionFoundAndCloseOff()
/*--------------------------------------------------------------------------*/
void allocateGrids(Hrap_Grid hrap_grid) {
int maxI = hrap_grid.maxi;
int maxJ = hrap_grid.maxj;
binStationCount = new int[maxI][maxJ];
valueGrid = new double[maxI][maxJ];
prismStationGrid = new double[maxI][maxJ];
return;
}
/*--------------------------------------------------------------------------*/
void initializeGrids(Hrap_Grid hrap_grid, boolean should_accumulate) {
int i = 0;
int j = 0;
/* initialize grids */
for (i = 0; i < hrap_grid.maxi; i++) {
for (j = 0; j < hrap_grid.maxj; j++) {
binStationCount[i][j] = 0;
valueGrid[i][j] = DailyQcUtils.MOSAIC_DEFAULT; // precip in
// inches
prismStationGrid[i][j] = DailyQcUtils.MOSAIC_DEFAULT; // prism
// station
// value
// mapped
// to
// grid
// (this
// algorithm
// only)
if (!should_accumulate) {
// in special 24hr = sum of 4 6hr periods mode,
// we accumulate in this grid, so we don't reinit every time
pcp.value[i][j] = (int) DailyQcUtils.MOSAIC_DEFAULT; // final
// precip
// in
// hundredths
// of
// mm
}
}
}
}
/*--------------------------------------------------------------------------*/
void placeStationsInGrid(int pcpn_day, int pcpn_time, int pcpn_time_step,
int max_stations, ArrayList<Station> stationList,
Hrap_Grid hrap_grid, Pdata pdata[]) {
int method = DailyQcUtils.method;
String header = "RenderPcpBlocking.placeStationsInGrid(): ";
int time_pos;
if (pcpn_time_step == 0) {
time_pos = pcpn_time; // for 6 hour data: 0,1,2,3.
} else {
time_pos = 4; // for 24 hour data
}
int hx, hy;
int h = 0;
int noPrismCount = 0;
// System.out.println("max_stations = " + max_stations);
int maxPrecip = 0;
for (h = 0; h < max_stations; h++) {
Station station = stationList.get(h);
hx = (int) (station.hrap_x - hrap_grid.hrap_minx);
hy = (int) (station.hrap_y - hrap_grid.hrap_miny);
/* check that station is within the site's area */
if (hx >= hrap_grid.maxi || hy >= hrap_grid.maxj || (hx < 0)
|| (hy < 0)) {
// This station cannot be used, because its coordinates are out
// of range
continue;
}
// debug only
int stationCount = binStationCount[hx][hy];
double precipValue = pdata[pcpn_day].stn[h].frain[time_pos].data;
short qualCode = pdata[pcpn_day].stn[h].frain[time_pos].qual;
// skip if not an acceptable quality code
if (qualCode != SCREENED && qualCode != VERIFIED
&& qualCode != TIMEDISTRIBUTED && qualCode != QUESTIONABLE
&& qualCode != PARTIAL && qualCode != MANUAL) {
continue;
}
if ((method == 2) && (station.isoh[isom] <= 0)) // no prism data for
// the station
{
noPrismCount++;
continue;
}
/* if station value is missing, ignore */
if (precipValue >= 0.0) {
int precipIn_h_mm = (int) Math.floor(precipValue * 100.0);
if (precipIn_h_mm > maxPrecip) {
maxPrecip = precipIn_h_mm;
}
// we have data and no other station has been assigned to this
// bin yet
if (binStationCount[hx][hy] == 0) {
binStationCount[hx][hy] = 1;
valueGrid[hx][hy] = precipValue;
prismStationGrid[hx][hy] = station.isoh[isom];
usableStationCount++;
}
else if (stationCount > 0) // we have at least 1 value for this
// grid location
{
double valueGridTotalValue = (valueGrid[hx][hy] * stationCount)
+ precipValue;
double prismGridTotalValue = (prismStationGrid[hx][hy] * stationCount)
+ station.isoh[isom];
binStationCount[hx][hy]++;
stationCount++;
double newGridAvgValue = valueGridTotalValue / stationCount;
double newPrismAvgValue = prismGridTotalValue
/ stationCount;
valueGrid[hx][hy] = newGridAvgValue;
prismStationGrid[hx][hy] = newPrismAvgValue;
usableStationCount++;
} // end else
} // end if
} // end for (h = 0; h < max_stations; h++)
System.out.println(header + " maxPrecip in hundredths of mm = "
+ maxPrecip);
// System.out.println(header +
// " number of stations missing PRISM data = " + noPrismCount);
// System.out.println(header + " usableStationCount = " +
// usableStationCount);
}
// ---------------------------------------------------------------------------------------
/*
* get the token value of token mpe_24hr_grid_gen_method. This token will
* determine how we generate the 24hr grid. We can either use the 24hr gage
* values, which is the old way, or we can use four 6hr gage values and add
* them together.
*/
/* there is some problem with the static */
private void render24hrPcpUsingFour6hr(int pcpn_day, int pcpn_time,
int numPstations, ArrayList<Station> stationList,
Hrap_Grid hrap_grid, Pdata[] pdata, int[] pcp_in_use) {
/* initialization of the pcp.value */
for (int i = 0; i < hrap_grid.maxi; i++) {
for (int j = 0; j < hrap_grid.maxj; j++) {
pcp.value[i][j] = 0;
}
}
boolean save_grids = false;
boolean should_accumulate = true;
for (int k = 0; k < 4; k++) {
int pcpn_time_internal = k;
int pcpn_time_step = 0; // means it is one of the 6-hr periods
render_pcp_internal(pcpn_day, pcpn_time_internal, pcpn_time_step,
numPstations, stationList, hrap_grid, pdata, pcp_in_use,
save_grids, should_accumulate);
}
} // end render24hrPcpUsingFour6hr()
// --------------------------------------------------------------------------
int adjustWeights(double originalValue, int otherRow, int otherColumn,
int renderingRow, int renderingColumn, Hrap_Grid hrap_grid,
int monthIndex, double[][] prismStationGrid) {
String header = "RenderPcpBlocking.adjustWeights(): ";
final double MIN_DISTANCE = 0.00001;
int usedCount = 0;
double distanceWeight = 0.0;
double weightedValue = 0.0;
int rowDiff = otherRow - renderingRow;
int colDiff = otherColumn - renderingColumn;
double distanceSquared = (rowDiff * rowDiff) + (colDiff * colDiff);
// int maxDistSquared = DailyQcUtils.mpe_dqc_grid_max_dist *
// DailyQcUtils.mpe_dqc_grid_max_dist;
if (distanceSquared < MIN_DISTANCE) {
distanceSquared = MIN_DISTANCE;
}
/*
* mpe_dqc_grid_max_dist = max distance of influence of a gage in units
* of grid bins
*/
if (distanceSquared <= maxDistSquared) {
distanceWeight = 1.0 / distanceSquared;
weightedValue = originalValue * distanceWeight;
// adjust by PRISM factor
if (prismStationGrid[renderingColumn][renderingRow] > 0) {
double prismFactor = (double) hrap_grid.isoh[monthIndex][renderingColumn][renderingRow]
/ (prismStationGrid[renderingColumn][renderingRow] * 25.4);
weightedValue *= prismFactor;
System.out.println(header + " prismFactor > 0 " + prismFactor);
}
totalWeightedValue += weightedValue;
totalDistanceWeight += distanceWeight;
usedCount++;
}
return usedCount;
}
// ---------------------------------------------------------------------------------------
}

View file

@ -0,0 +1,603 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.mpe.util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.raytheon.uf.common.ohd.AppsDefaults;
import com.raytheon.viz.mpe.util.DailyQcUtils.Hrap_Grid;
import com.raytheon.viz.mpe.util.DailyQcUtils.Pcp;
import com.raytheon.viz.mpe.util.DailyQcUtils.Pdata;
import com.raytheon.viz.mpe.util.DailyQcUtils.Station;
/**
* DESCRIPTION: Maps precipitation station values to an HRAP grid. Produces the
* DailyQC version of the GageOnly analysis.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 11, 2009 snaples Initial creation
* May 02, 2011 8962 snaples Added render24hrPcpUsingFour6hr() method
*
* </pre>
*
* @author snaples
* @version 1.0
*/
public class RenderPcpStandard {
private static final int MINIMUM_NEAREST_NEIGHBOR_GAGES = 4;
private static final int SUFFICIENT_NEAREST_NEIGHBOR_GAGES = 10;
private static boolean first = true;
Pcp pcp = DailyQcUtils.pcp;
/*
* QC codes
*/
private static final int MISSING = -1;
private static final int STANDARD = 0;
private static final int SCREENED = 0;
private static final int FAILED = 1;
private static final int MANUAL = 2;
private static final int QUESTIONABLE = 3;
private static final int PARTIAL = 4;
private static final int ESTIMATED = 5;
private static final int TIMEDISTRIBUTED = 6;
private static final int VERIFIED = 8;
private static final String MPE_DQC_GRID_RENDERING_METHOD_TOKEN = "mpe_dqc_grid_render_method";
private static final int maxDistSquared = DailyQcUtils.mpe_dqc_grid_max_dist
* DailyQcUtils.mpe_dqc_grid_max_dist;
private static final double BOGUS_ESTIMATED_GRID_VALUE = -1.0;
// weighting variables
// consider making these members of a local variable of an inner class
private double totalWeightedValue = 0;
private double totalDistanceWeight = 0;
/**
* Converts point precipitation data in struct pdata to hrap grid. The 20
* closest stations are precalculated for each grid point - this speeds
* computations for data sets with many precipitation points. If there are
* no good precipitation points for a grid point, then a recalculation is
* made using all precipitation points. 1/R**2 interpolation is used. If
* requested, the final interpolation is scaled using seasonal isohyets. The
* grid is saved as a disk file and used later for a raster or vector (HRAP)
* plot.
*
* @param m
* @param k
* @param mk
* @param numPstations
* @param
* @param hrap_grid
* @param pdata
* @param pcp_in_use
*/
// ---------------------------------------------------------------------------------------
public void render_pcp(int pcpn_day, int pcpn_time, int pcpn_time_step,
int numPstations, ArrayList<Station> precip_stations,
Hrap_Grid hrap_grid, Pdata[] pdata, int[] pcp_in_use) {
// String header = "RenderPcpStandard.render_pcp_original(): ";
int isom = DailyQcUtils.isom;
int method = DailyQcUtils.method;
int mpe_dqc_max_precip_neighbors = DailyQcUtils.mpe_dqc_max_precip_neighbors;
int i, j, h, hh, time_pos;
int usedStationCount = 0;
int totals[] = new int[5];
for (i = 0; i < 5; i++) {
totals[i] = 0;
}
/*
* pcpn_time_step is a function parameter. It specifies whether to
* interpolate 6hr or 24hr HRAP grid
*/
/*
* pcpn_time is a function parameter. It specifies which 6hr HRAP grid
* to generate. It takes 0,1,2,or 3 to represent different 6hr period of
* a day.
*/
/*
* time_pos is assigned a value of 0,1,2,or 3 (for 6hr data) or 4 (for
* 24hr data). This value is used in
* pdata[pcpn_day].stn[hh].frain[time_pos].data to control whether to
* retrieve 6hr data or 24hr data.
*/
if (pcpn_time_step == 0) {
time_pos = pcpn_time; // for 6 hour data: 0,1,2,3.
} else {
time_pos = 4; // for 24 hour data
/*
* in case the 24hr grid rendering is required, we check
* 24hr_grid_gen_method_token() to determine how to generate the
* grid. New Post OB9.2
*/
if (getTokenValue24hrGridGenMeth() == 1) {
render24hrPcpUsingFour6hr(pcpn_day, pcpn_time, numPstations,
precip_stations, hrap_grid, pdata, pcp_in_use);
return;
}
}
/* begin to interpolate value for each bin in the HRAP grid */
/*
* to interpolate, two quantities are needed first: value and distance.
* They are calculated by using the neighboring stations.
*/
for (i = 0; i < hrap_grid.maxi; i++) {
for (j = 0; j < hrap_grid.maxj; j++) {
/*
* Check if the grid cell is covered by an HSA. If not, then do
* not estimate precipitation for it.
*/
if (hrap_grid.owner[i][j] == -1) {
pcp.value[i][j] = 0;
continue;
}
totalDistanceWeight = 0.0;
totalWeightedValue = 0.0;
usedStationCount = 0;
boolean usedStation = false;
/*
* the following for loop is to calculate two quantities: value
* and distance, which later on, are used to interpret the HRAP
* grid.
*/
/*
* It uses neighbor stations of a HRAP grid bin to calculate
* value and distance.
*/
/* for each neighbor station of the grid bin, do the following */
/* For each of the closest stations. */
for (h = 0; h < mpe_dqc_max_precip_neighbors; h++) {
// hh is index of stations
hh = hrap_grid.gage[i][j].index[h];
int gageIndex = hh;
usedStation = processStation(gageIndex, isom, i, j,
pcpn_day, pcpn_time, time_pos, method,
precip_stations, hrap_grid, pdata, pcp_in_use,
false);
if (usedStation) {
usedStationCount++;
}
if (usedStationCount == SUFFICIENT_NEAREST_NEIGHBOR_GAGES) {
break;
}
}
/*
* end for loop (h = 0; h < mpe_dqc_max_precip_neighbors;h++)
* the above for loop is for each neighbor station.
*/
/*
* the above for loop is to calculate value and distance, which
* later on, are used to interpret the HRAP grid
*/
/*
* the resulting htotal is the valid number of neighbor stations
* that are used to calculate value and distance, which later
* on, are used to interpret the HRAP grid
*/
/*
* if there is not enough valid neighbor station, such as
* usedStationCount < MINIMUM_NEAREST_NEIGHBOR_GAGES the code
* below handle this situation. Basically, the code recalculate
* the value and distance using all the stations -- see the for
* (h = 0; h < max_stations; h++) loop below.
*/
if (usedStationCount < MINIMUM_NEAREST_NEIGHBOR_GAGES) {
totalWeightedValue = 0.0;
totalDistanceWeight = 0.0;
usedStationCount = 0;
for (h = 0; h < numPstations; h++) {
int gageIndex = h;
usedStation = processStation(gageIndex, isom, i, j,
pcpn_day, pcpn_time, time_pos, method,
precip_stations, hrap_grid, pdata, pcp_in_use,
true);
if (usedStation) {
usedStationCount++;
}
}
}/*
* end the handling of special case : if (usedStationCount <
* MINIMUM_NEAREST_NEIGHBOR_GAGES),
*/
/* which means there are not enough neighboring stations */
// found no usable gages
if (usedStationCount == 0) {
pcp.value[i][j] = 0;
}
else {
pcp.value[i][j] = (int) (totalWeightedValue
/ totalDistanceWeight * 100.0);
}
if (pcp.value[i][j] < .01) {
pcp.value[i][j] = 0;
}
} // end for (j = 0; j < hrap_grid.maxj; j++) {
} // end for (i = 0; i < hrap_grid.maxi; i++) {
if (pcpn_time_step == 0) {
time_pos = pcpn_day * 4 + 3 - pcpn_time;
} else {
time_pos = 40 + pcpn_day;
}
// notice that time_pos is a variable defined inside the function, and
// its value do not need to be limited as 0,1,2,3,or 4. Here it is
// assigned with bigger numbers.
// time_pos = 40 + pcpn_day;
// pcp_in_use[i] = 1 -- grids rendered via Render button OR Save Level2
// option
// = -1 --grids for this time period not rendered (initialization value)
pcp_in_use[time_pos] = 1;
ReadQPFGrids rqp = new ReadQPFGrids();
rqp.write_file("pcp", time_pos, pcp);
}
private boolean processStation(int gageIndex, int isom, int col, int row,
int pcpn_day, int pcpn_time, int time_pos, int method,
ArrayList<Station> stationList, Hrap_Grid hrap_grid, Pdata[] pdata,
int[] pcp_in_use, boolean checkDistance) {
boolean usedStation = false;
Station station = stationList.get(gageIndex);
float value = pdata[pcpn_day].stn[gageIndex].frain[time_pos].data;
if (value < 0) {
return usedStation;// false
}
int qualityCode = pdata[pcpn_day].stn[gageIndex].frain[time_pos].qual;
if (qualityCode != 0 && qualityCode != 8 && qualityCode != 6
&& qualityCode != 3 && qualityCode != 4 && qualityCode != 2) {
return usedStation; // false
}
if (method == 2 && station.isoh[isom] <= 0) {
return usedStation; // false
}
/*
* determine distance between grid bin and the station in question of
* the grid and station in question
*/
double distanceX = (col + (hrap_grid.hrap_minx - station.hrap_x));
double distanceY = (row + (hrap_grid.hrap_miny - station.hrap_y));
double distanceSquared = (distanceX * distanceX)
+ (distanceY * distanceY);
if (distanceSquared < .00001) {
distanceSquared = .00001;
}
if (checkDistance) {
if (distanceSquared > maxDistSquared) // too far away, don't use the
// station
{
return usedStation; // false, bail out, don't adjust weight with
// this reading
}
}
double distanceWeight = 1 / distanceSquared;
double weightedValue = value * distanceWeight;
float prismValue = station.isoh[isom];
if (method == 2 && prismValue > 0) {
weightedValue = weightedValue * hrap_grid.isoh[isom][col][row]
/ (prismValue * 25.4);
}
totalWeightedValue += weightedValue;
totalDistanceWeight += distanceWeight;
usedStation = true;
return usedStation;
}
// ---------------------------------------------------------------------------------------
/*
* get the token value of token mpe_24hr_grid_gen_method. This token will
* determine how we generate the 24hr grid. We can either use the 24hr gage
* values, which is the old way, or we can use four 6hr gage values and add
* them together.
*/
/* there is some problem with the static */
/**
* @param pcpn_day
* @param pcpn_time
* @param numPstations
* @param precip_stations
* @param hrap_grid
* @param pdata
* @param pcp_in_use
*/
private void render24hrPcpUsingFour6hr(int pcpn_day, int pcpn_time,
int numPstations, ArrayList<Station> precip_stations,
Hrap_Grid hrap_grid, Pdata[] pdata, int[] pcp_in_use) {
int i, j, k, h, hh, time_pos;
boolean usedStation = false;
int isom = DailyQcUtils.isom;
int method = DailyQcUtils.method;
int totals[] = new int[5];
int all_total = 0;
int neighbor_total = 0;
int usedStationCount;
for (i = 0; i < 5; i++) {
totals[i] = 0;
}
/*
* pcpn_time_step is function parameter. It specifies whether to
* interpolate 6hr or 24hr HRAP grid
*/
/*
* pcpn_time is a function parameter. It specifies which 6hr HRAP grid
* to generate. It takes 0,1,2,or 3 to represent different 6hr period of
* a day.
*/
/*
* time_pos is assigned a value of 0,1,2,or 3 (for 6hr data) or 4 (for
* 24hr data). This value is used in
* pdata[pcpn_day].stn[hh].frain[time_pos].data to control whether to
* retrieve 6hr data or 24hr data.
*/
/* initialization of the pcp.value */
for (i = 0; i < hrap_grid.maxi; i++) {
for (j = 0; j < hrap_grid.maxj; j++) {
pcp.value[i][j] = 0;
}
}
/*
* begin to interpolate 4 6hr grids. At the end of each iteration, the
* calculated interpolation value is added to pcp.value[i][j].
*/
/*
* time_pos is assigned a value of 0,1,2,or 3 (for four 6hr data). This
* value is used in pdata[pcpn_day].stn[hh].frain[time_pos].data to
* retrieve 6hr data.
*/
for (k = 0; k < 4; k++) {
time_pos = k; /* for 6 hour data: 0, 1,2,3. */
/* begin to interpolate value for each bin in the HRAP grid */
/*
* to interpolate, two quantities are needed first: value and
* distance. They are calculated by using the neighboring stations.
*/
for (i = 0; i < hrap_grid.maxi; i++) {
for (j = 0; j < hrap_grid.maxj; j++) {
/*
* Check if the grid cell is covered by an HSA. If not, then
* do not estimate precipitation for it.
*/
if (hrap_grid.owner[i][j] == -1) {
pcp.value[i][j] = 0;
continue;
}
totalDistanceWeight = 0.0;
totalWeightedValue = 0.0;
usedStationCount = 0;
/*
* for each neighbor station of the grid bin, do the
* following
*/
int mpe_dqc_max_precip_neighbors = DailyQcUtils.mpe_dqc_max_precip_neighbors;
for (h = 0; h < mpe_dqc_max_precip_neighbors; h++) {
hh = hrap_grid.gage[i][j].index[h];/*
* hh is index of
* stations
*/
int gageIndex = hh;
usedStation = processStation(gageIndex, isom, i, j,
pcpn_day, pcpn_time, time_pos, method,
precip_stations, hrap_grid, pdata, pcp_in_use,
false);
if (usedStation) {
usedStationCount++;
}
if (usedStationCount == SUFFICIENT_NEAREST_NEIGHBOR_GAGES) {
break;
}
}
if (usedStationCount < MINIMUM_NEAREST_NEIGHBOR_GAGES) {
// not enough gages, so extend search to all gages
totalWeightedValue = 0.0;
totalDistanceWeight = 0.0;
usedStationCount = 0;
for (h = 0; h < numPstations; h++) {
int gageIndex = h;
usedStation = processStation(gageIndex, isom, i, j,
pcpn_day, pcpn_time, time_pos, method,
precip_stations, hrap_grid, pdata,
pcp_in_use, false);
if (usedStation) {
usedStationCount++;
}
}
neighbor_total++;
}
if (usedStationCount != 0) {
pcp.value[i][j] += (int) ((totalWeightedValue / totalDistanceWeight) * 100);
}
/*
* if (pcp.value[i][j] < .01) { pcp.value[i][j] = 0; }
*/
all_total++;
} /* end of for loop (j = 0; j < hrap_grid.maxj; j++) */
} /* end of for loop (i = 0; i < hrap_grid.maxi; i++) */
/* At this moment, the interpretation of HRAP grid is done */
}/*
* end of the ( k = 0; k<4; k++) loop, which interpolates 4 6hr HRAP
* grid.
*/
/* final adjustment of the pcp.value */
for (i = 0; i < hrap_grid.maxi; i++) {
for (j = 0; j < hrap_grid.maxj; j++) {
if (pcp.value[i][j] < .01) { // this doesn't really make sense,
// since this is an integer
pcp.value[i][j] = 0;
}
}
}
/* time_pos = pcpn_day * 4 + 3 - pcpn_time; */
time_pos = 40 + pcpn_day;
/*
* pcp_in_use[i] = 1 -- grids rendered via Render button OR Save Level2
* option = -1 --grids for this time period not rendered (initialization
* value)
*/
pcp_in_use[time_pos] = 1;
/*
* results of grid rendering routines (render_t, render_t6, render_pcp,
* render_z) are written to scratch files using the write_file routine.
* scratch file is stored in the scratch directory.
*/
ReadQPFGrids rqp = new ReadQPFGrids();
rqp.write_file("pcp", time_pos, pcp);
} // end render24hrPcpUsingFour6hr()
// ---------------------------------------------------------------------------------------
int getTokenValue24hrGridGenMeth() {
int token_of_24hr_grid_gen_method = 0;
if (first == true) {
String tokenName = "mpe_dqc_24hr_precip_grid_meth";
String dqc24hrPrecipMeth;
// char message[GAGEQC_MESSAGE_LEN] = { '\0' };
AppsDefaults appsDefaults = AppsDefaults.getInstance();
dqc24hrPrecipMeth = appsDefaults.getToken(tokenName);
if (dqc24hrPrecipMeth != null) {
/* allowed token values: (ACCUM_6HR, USE_24HR) */
if (dqc24hrPrecipMeth.equalsIgnoreCase("ACCUM_6HR")) {
token_of_24hr_grid_gen_method = 1;
}
}
first = false;
}
return token_of_24hr_grid_gen_method;
}
// -----------------------------------------------------------------------------------
}

View file

@ -25,7 +25,8 @@ Require-Bundle: org.eclipse.ui,
com.raytheon.uf.common.dataplugin.radar;bundle-version="1.0.0",
org.apache.commons.logging,
com.raytheon.uf.viz.localization,
com.raytheon.uf.common.auth;bundle-version="1.12.1174"
com.raytheon.uf.common.auth;bundle-version="1.12.1174",
com.raytheon.uf.common.dataplugin.warning;bundle-version="1.12.1174"
Bundle-ActivationPolicy: lazy
Export-Package: com.raytheon.viz.texteditor,
com.raytheon.viz.texteditor.alarmalert.dialogs,

View file

@ -0,0 +1,196 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.texteditor.dialogs;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import com.raytheon.uf.common.activetable.ActiveTableMode;
import com.raytheon.uf.common.activetable.ActiveTableRecord;
import com.raytheon.uf.common.activetable.GetActiveTableRequest;
import com.raytheon.uf.common.activetable.GetActiveTableResponse;
import com.raytheon.uf.common.dataplugin.warning.WarningRecord.WarningAction;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.requests.ThriftClient;
import com.raytheon.viz.core.mode.CAVEMode;
import com.raytheon.viz.texteditor.util.VtecObject;
import com.raytheon.viz.texteditor.util.VtecUtil;
/**
* Produces the product message and mode message for the warngen confirmation
* dialog for emergency warnings.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 23, 2013 2176 jsanchez Initial creation
*
* </pre>
*
* @author jsanchez
* @version 1.0
*/
public class EmergencyConfirmationMsg implements IWarnGenConfirmationable {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(EmergencyConfirmationMsg.class);
private String productMessage;
private static class EmergencyType {
private static final EmergencyType TORNADO = new EmergencyType(
"TORNADO EMERGENCY", "TO.W");
private static final EmergencyType FLASH_FLOOD = new EmergencyType(
"FLASH FLOOD EMERGENCY", "FF.W");
private final String value;
private final String phensig;
private final static EmergencyType[] values = new EmergencyType[] {
TORNADO, FLASH_FLOOD };
private EmergencyType(String type, String phensig) {
this.value = type;
this.phensig = phensig;
}
public static EmergencyType valueOf(String phensig) {
EmergencyType type = null;
for (EmergencyType t : values) {
if (t.phensig.equals(phensig)) {
type = t;
break;
}
}
return type;
}
};
/**
* Orders the ActiveTableRecord based on the issue time (ascending)
*/
private class ActiveTableRecordComparator implements
Comparator<ActiveTableRecord> {
@Override
public int compare(ActiveTableRecord o1, ActiveTableRecord o2) {
return o1.getIssueTime().compareTo(o2.getIssueTime());
}
}
@Override
public boolean checkWarningInfo(String header, String body, String nnn) {
VtecObject vtec = VtecUtil.parseMessage(body);
EmergencyType type = null;
WarningAction action = null;
if (vtec != null) {
type = EmergencyType.valueOf(vtec.getPhensig());
action = WarningAction.valueOf(vtec.getAction());
if (action == WarningAction.CAN && body.split("\\$\\$").length > 2) {
// It is possible for a warning products to have two segments: a
// CAN and a CON.'$$' denotes the end of one segment. VtecUtil
// only grabs the first VTEC. If there are multiple segments CAN
// should always be the first VTEC
action = WarningAction.CANCON;
}
}
// Check if the warning product is a valid EmergencyType.
if (type != null) {
boolean currentEmergency = body.contains("EMERGENCY");
if (action == WarningAction.NEW && currentEmergency) {
// Only occurs when the warning is first issued and not any
// other action
productMessage = "This is a " + type.value;
} else if (action == WarningAction.CON
|| action == WarningAction.EXT
|| action == WarningAction.CANCON) {
// Check if the warning was an upgrade or downgrade in the
// emergency warning for continuation, extension (FFW), or a
// cancel
// and continuation.
GetActiveTableRequest request = new GetActiveTableRequest();
if (CAVEMode.getMode().equals(CAVEMode.PRACTICE)) {
request.setMode(ActiveTableMode.PRACTICE);
} else {
request.setMode(ActiveTableMode.OPERATIONAL);
}
request.setSiteID(vtec.getOffice());
request.setPhensigList(vtec.getPhensig());
request.setEtn(String.format("%04d", vtec.getSequence()));
try {
GetActiveTableResponse response = (GetActiveTableResponse) ThriftClient
.sendRequest(request);
List<ActiveTableRecord> records = response.getActiveTable();
// There should be existing records since this is for follow
// ups. This is just a precaution
if (records != null && !records.isEmpty()) {
// Get latest active table record
Collections.sort(records,
new ActiveTableRecordComparator());
ActiveTableRecord record = records
.get(records.size() - 1);
boolean wasEmergency = record.getRawmessage().contains(
"EMERGENCY");
if (!wasEmergency && currentEmergency) {
productMessage = "This is an upgrade of a "
+ type.value;
} else if (wasEmergency && !currentEmergency) {
productMessage = "This is a downgrade of a "
+ type.value;
}
}
} catch (VizException e) {
statusHandler.handle(Priority.ERROR,
"Error making request to active table.");
}
}
}
return productMessage == null;
}
@Override
public String getTitle() {
return "Severe Weather Product";
}
@Override
public String getProductMessage() {
return productMessage;
}
@Override
public String getModeMessage() {
return "Should we proceed?\n";
}
}

View file

@ -0,0 +1,67 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.texteditor.dialogs;
/**
* Interface to retrieve the WarnGen Confirmation Dialog message values.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 23, 2013 2176 jsanchez Initial creation
*
* </pre>
*
* @author jsanchez
* @version 1.0
*/
public interface IWarnGenConfirmationable {
/**
* Returns true if the WarnGen Confirmation Dialog needs to pop-up.
*
* @param header
* @param body
* @param nnn
* @return
*/
public boolean checkWarningInfo(String header, String body, String nnn);
/**
*
* @return the title for the WarnGen Confirmation Dialog
*/
public String getTitle();
/**
*
* @return the product message in the WarnGen Confirmation Dialog
*/
public String getProductMessage();
/**
*
* @return the mode message in the WarnGen Confirmation Dialog
*/
public String getModeMessage();
}

View file

@ -0,0 +1,66 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.texteditor.dialogs;
import com.raytheon.viz.texteditor.qc.QualityControl;
/**
* Produces the product message and mode message for the warngen confirmation
* dialog for warnings failing QC.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 23, 2013 2176 jsanchez Initial creation
*
* </pre>
*
* @author jsanchez
* @version 1.0
*/
public class QCConfirmationMsg implements IWarnGenConfirmationable {
private QualityControl qcCheck = new QualityControl();
@Override
public boolean checkWarningInfo(String header, String body, String nnn) {
return qcCheck.checkWarningInfo(header, body, nnn);
}
@Override
public String getTitle() {
return "Problem Detected by QC";
}
@Override
public String getProductMessage() {
return qcCheck.getErrorMessage();
}
@Override
public String getModeMessage() {
return "Do you really want to Send?\n";
}
}

View file

@ -0,0 +1,102 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.texteditor.dialogs;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.raytheon.viz.core.mode.CAVEMode;
import com.raytheon.viz.texteditor.qc.QualityControl;
/**
* Produces the product message and mode message for the warngen confirmation
* dialog for sending a warning.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 23, 2013 2176 jsanchez Initial creation
*
* </pre>
*
* @author jsanchez
* @version 1.0
*/
public class SendConfirmationMsg implements IWarnGenConfirmationable {
private String title;
private boolean resend;
private String afosId;
public SendConfirmationMsg(boolean resend, String afosId, String nnn) {
this.resend = resend;
this.afosId = afosId;
title = QualityControl.getProductWarningType(nnn);
}
@Override
public boolean checkWarningInfo(String header, String body, String nnn) {
return true;
}
@Override
public String getTitle() {
return title;
}
@Override
public String getProductMessage() {
StringBuilder productMessage = new StringBuilder();
if (resend) {
productMessage.append("You are about to RESEND a " + afosId + "\n");
productMessage.append(title).append(".\n");
} else {
productMessage.append("You are about to SEND a " + afosId + "\n");
productMessage.append(title).append(".\n");
}
return productMessage.toString();
}
@Override
public String getModeMessage() {
CAVEMode mode = CAVEMode.getMode();
StringBuilder modeMessage = new StringBuilder();
modeMessage.append("The workstation is in ").append(mode)
.append(" mode.");
if (resend) {
modeMessage.append("\nThere is no QC check for resend product.");
}
Pattern p = Pattern.compile(".\\%[s].");
Matcher m = p.matcher(TextEditorDialog.STORED_SENT_MSG);
boolean result = (CAVEMode.OPERATIONAL.equals(mode) || CAVEMode.TEST
.equals(mode));
modeMessage.append(result ? m.replaceAll(" ") : m.replaceAll(" not "));
return modeMessage.toString();
}
}

View file

@ -85,8 +85,8 @@ import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.FontMetrics;
@ -100,7 +100,6 @@ import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
@ -142,7 +141,6 @@ import com.raytheon.uf.common.time.SimulatedTime;
import com.raytheon.uf.edex.decodertools.time.TimeTools;
import com.raytheon.uf.edex.services.textdbsrv.IQueryTransport;
import com.raytheon.uf.edex.wmo.message.WMOHeader;
// import com.raytheon.uf.viz.core.RGBColors;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.uf.viz.core.auth.UserController;
import com.raytheon.uf.viz.core.exception.VizException;
@ -176,7 +174,6 @@ import com.raytheon.viz.texteditor.msgs.ITextEditorCallback;
import com.raytheon.viz.texteditor.msgs.IWmoBrowserCallback;
import com.raytheon.viz.texteditor.notify.NotifyExpiration;
import com.raytheon.viz.texteditor.print.PrintDisplay;
import com.raytheon.viz.texteditor.qc.QualityControl;
import com.raytheon.viz.texteditor.scripting.dialogs.IScriptEditor;
import com.raytheon.viz.texteditor.scripting.dialogs.IScriptEditorObserver;
import com.raytheon.viz.texteditor.scripting.dialogs.ScriptEditorDialog;
@ -191,6 +188,8 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
import com.raytheon.viz.ui.dialogs.ICloseCallback;
import com.raytheon.viz.ui.dialogs.SWTMessageBox;
// import com.raytheon.uf.viz.core.RGBColors;
/**
* Main Text Editor dialog.
*
@ -328,6 +327,7 @@ import com.raytheon.viz.ui.dialogs.SWTMessageBox;
* *.xml files in localization;
* add selection listener to catch the highlight words and
* set the highlight colors.
* 23Jul2013 2176 jsanchez Added a new confirmation message for emergency warnings.
* 25July2013 15733 GHull Read font and color prefs from TextEditorCfg.
* 23Aug2013 DR 16514 D. Friedman Fix handling of completed product requests. Do not change
* command history or close browser window for "update obs".
@ -378,9 +378,9 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
* System colro to use for foreground color when an obs is updated.
*/
private static final int UPDATE_FG = SWT.COLOR_WHITE;
private final int HIGHLIGHT_BG = SWT.COLOR_RED;
/**
* The length of BEGIN_ELEMENT_TAG.
*/
@ -791,19 +791,19 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
/**
* Small font menu item.
*/
// private MenuItem smallFontItem;
// private MenuItem smallFontItem;
/**
* Medium font menu item.
*/
// private MenuItem mediumFontItem;
// private MenuItem mediumFontItem;
/**
* Large font menu item.
*/
// private MenuItem largeFontItem;
// private MenuItem largeFontItem;
/**
/**
* Overstrike (overwrite) menu item.
*/
private MenuItem overStrikeItem;
@ -1017,12 +1017,12 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
* Styled text editor.
*/
private StyledText textEditor;
/**
* default font
*/
private Font dftFont;
/**
* Composite containing the editor buttons.
*/
@ -1289,12 +1289,12 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
*/
private static final String[] popupItems = { "Select All", "Cut", "Copy",
"Paste" };
/**
* Currently active popupItems.
*/
private static final boolean[] isPopItemDefault = { true, false, true,
false };
false };
/**
* Indictes this instance of dialog if for a warnGen.
@ -1372,14 +1372,16 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
* needs to be done.
*/
private boolean isPreviousLineWrapped;
private Color textForeground;
private Color textBackground;
private Color highlightForeground;
private Color highlightBackground;
// protected Color color;
// protected Color color;
/**
* Constructor with additional cave style rules
@ -2041,7 +2043,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
Menu fontSizeSubMenu = new Menu(shell, SWT.DROP_DOWN);
fontSizeMenuItem.setMenu(fontSizeSubMenu);
createFontSizeSubMenu(fontSizeSubMenu);
// ------------------------------
// Create overstrike menu item
// ------------------------------
@ -2862,7 +2864,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
private void createAutoWrapSubMenu(Menu autoWrapSubMenu) {
AutoWrapCfg autoWrapcfg = getAutoWrapCfg();
for (WrapButtonCfg buttonCfg : autoWrapcfg.getButtons()) {
MenuItem item = new MenuItem(autoWrapSubMenu, SWT.RADIO);
MenuItem item = new MenuItem(autoWrapSubMenu, SWT.RADIO);
item.setText(buttonCfg.getLabelName());
item.setSelection(buttonCfg.isSelected());
item.setData(buttonCfg);
@ -2950,11 +2952,11 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
* The font size sub menu.
*/
private void createFontSizeSubMenu(Menu fontSizeSubMenu) {
FontSizeCfg fontSizeCfg = TextEditorCfg.getTextEditorCfg().getFontSizeCfg();
SizeButtonCfg seldFontBtn = TextEditorCfg.getTextEditorCfg().getSelectedFontButton();
for (SizeButtonCfg buttonCfg : fontSizeCfg.getButtons()) {
FontSizeCfg fontSizeCfg = TextEditorCfg.getTextEditorCfg().getFontSizeCfg();
SizeButtonCfg seldFontBtn = TextEditorCfg.getTextEditorCfg().getSelectedFontButton();
for (SizeButtonCfg buttonCfg : fontSizeCfg.getButtons()) {
MenuItem item = new MenuItem(fontSizeSubMenu, SWT.RADIO);
item.setText(buttonCfg.getLabelName());
item.setSelection( false );
@ -2962,33 +2964,33 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
// if this button is the initial selection.
if( seldFontBtn.getLabelName().equals( buttonCfg.getLabelName() ) ) {
item.setSelection(true);
item.setSelection(true);
setDefaultFont( seldFontBtn.getFontSize(), seldFontBtn.getFontName() );
}
item.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
MenuItem item = (MenuItem) event.getSource();
if (item.getSelection()) {
int selectFontSize = ( (SizeButtonCfg) item.getData()).getFontSize();
MenuItem item = (MenuItem) event.getSource();
if (item.getSelection()) {
int selectFontSize = ( (SizeButtonCfg) item.getData()).getFontSize();
String seldFontName = ((SizeButtonCfg) item.getData()).getFontName();
setDefaultFont( selectFontSize, seldFontName );
textEditor.setFont(dftFont);
headerTF.setFont(dftFont);
}
textEditor.setFont(dftFont);
headerTF.setFont(dftFont);
}
}
});
}
}
public void setDefaultFont( int fontSize, String fontName ) {
dftFont = new Font( getDisplay(), fontName, fontSize, SWT.NORMAL);
}
/**
* Initialize the components and put them on the display.
*/
@ -3029,7 +3031,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
displayAfosBrowser();
}
});
// Add the Load History button.
rd = new RowData(BUTTON_WIDTH, BUTTON_HEIGHT);
loadHistoryBtn = new Button(topBtnRowComp, SWT.PUSH);
@ -3554,7 +3556,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
headerTF = new Text(headerTFComp, SWT.BORDER | SWT.MULTI
| SWT.READ_ONLY);
headerTF.setLayoutData(gd);
headerTF.setFont(dftFont);
headerTF.setEditable(false);
@ -3722,7 +3724,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
textEditorComp = new Composite(shell, SWT.NONE);
GridLayout gridLayout = new GridLayout(1, false);
// TextColorsCfg textColorCfg = null;
textEditorComp.setLayout(gridLayout);
textEditorComp.setLayoutData(gd);
@ -3742,31 +3744,32 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
textEditor.setEditable(false);
airportToolTip = new DefaultToolTip(textEditor, SWT.DEFAULT, true);
textEditor.setKeyBinding(SWT.INSERT, SWT.NULL); // DR 7826
// textColorCfg = getTextColorCfg();
setDefaultTextColor( TextEditorCfg.getTextEditorCfg() );
textEditor.setForeground(textForeground);
textEditor.setBackground(textBackground);
textEditor.addSelectionListener(new SelectionListener() {
@Override
public void widgetDefaultSelected(SelectionEvent e) {
System.out.println("\ntextEditor default selection event --" + e.toString());
System.out.println("\ntextEditor default selection event --"
+ e.toString());
}
@Override
public void widgetSelected(SelectionEvent e) {
StyledText stylText = (StyledText) e.getSource();
// String slctText = stylText.getSelectionText();
// int length = slctText.length();
stylText.setSelectionBackground(highlightBackground);
stylText.setSelectionForeground(highlightForeground);
public void widgetSelected(SelectionEvent e) {
StyledText stylText = (StyledText) e.getSource();
// String slctText = stylText.getSelectionText();
// int length = slctText.length();
stylText.setSelectionBackground(highlightBackground);
stylText.setSelectionForeground(highlightForeground);
}
});
});
textEditor.addKeyListener(new KeyAdapter() {
@Override
@ -3832,8 +3835,8 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
public void verifyKey(VerifyEvent event) {
// Ignore edit keys when not in edit mode.
if (textEditor.getEditable() == false) {
return;
}
return;
}
if (event.keyCode == SWT.DEL || event.keyCode == SWT.BS
|| event.keyCode == SWT.SHIFT) {
// Do nothing...
@ -3933,7 +3936,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
}
if (e.button == 3) {
processPopup();
processPopup();
}
}
@ -3973,6 +3976,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
//
// return textColorsCfg;
// }
private void setDefaultTextColor(TextEditorCfg txtClrCfg ) {
@ -3981,52 +3985,52 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
highlightBackground = new Color(shell.getDisplay(), txtClrCfg.getHighlightTextBackgroundColor() );
highlightForeground = new Color(shell.getDisplay(), txtClrCfg.getHighlightTextForegroundColor() );
}
/**
* Process the user choice from the popup list. DR14842 - re-written
*/
private void processPopup() {
Menu menu = new Menu(shell, SWT.POP_UP);
List<String> items = Arrays.asList(popupItems);
for (String pi : popupItems) {
MenuItem mi = new MenuItem(menu, SWT.PUSH);
mi.setText(pi);
if (isEditMode()) {
mi.setEnabled(true);
} else {
mi.setEnabled(isPopItemDefault[items.indexOf(pi)]);
}
mi.addListener(SWT.Selection, new Listener() {
private void processPopup() {
Menu menu = new Menu(shell, SWT.POP_UP);
List<String> items = Arrays.asList(popupItems);
for (String pi : popupItems) {
MenuItem mi = new MenuItem(menu, SWT.PUSH);
mi.setText(pi);
if (isEditMode()) {
mi.setEnabled(true);
} else {
mi.setEnabled(isPopItemDefault[items.indexOf(pi)]);
}
mi.addListener(SWT.Selection, new Listener() {
@Override
public void handleEvent(Event event) {
handleSelection(event);
}
});
}
menu.setVisible(true);
}
public void handleEvent(Event event) {
handleSelection(event);
}
});
}
menu.setVisible(true);
}
/**
* Handle the selection from the popup menu
* Handle the selection from the popup menu
*
* @param event
*/
protected void handleSelection(Event event) {
MenuItem item = (MenuItem) event.widget;
String choice = item.getText();
if (choice != null) {
if (popupItems[0].equals(choice)) {
textEditor.selectAll();
} else if (popupItems[1].equals(choice)) {
cutText();
} else if (popupItems[2].equals(choice)) {
copyText();
} else if (popupItems[3].equals(choice)) {
pasteText();
}
textEditor.update();
}
}
protected void handleSelection(Event event) {
MenuItem item = (MenuItem) event.widget;
String choice = item.getText();
if (choice != null) {
if (popupItems[0].equals(choice)) {
textEditor.selectAll();
} else if (popupItems[1].equals(choice)) {
cutText();
} else if (popupItems[2].equals(choice)) {
copyText();
} else if (popupItems[3].equals(choice)) {
pasteText();
}
textEditor.update();
}
}
/**
* creates the bar containing the script runner controls.
@ -4841,47 +4845,31 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
* true if product is to be resent
*/
synchronized private void sendProduct(final boolean resend) {
final CAVEMode mode = CAVEMode.getMode();
StdTextProduct prod = getStdTextProduct();
String afosId = prod.getCccid() + prod.getNnnid() + prod.getXxxid();
final String title = QualityControl.getProductWarningType(prod
.getNnnid());
final StringBuilder productMessage = new StringBuilder();
final StringBuilder modeMessage = new StringBuilder();
modeMessage.append("The workstation is in ").append(mode)
.append(" mode.");
if (resend) {
productMessage.append("You are about to RESEND a " + afosId + "\n");
productMessage.append(title).append(".\n");
modeMessage.append("\nThere is no QC check for resend product.");
} else if (warnGenFlag) {
productMessage.append("You are about to SEND a " + afosId + "\n");
productMessage.append(title).append(".\n");
QualityControl qcCheck = new QualityControl();
if (qcCheck.checkWarningInfo(headerTF.getText().toUpperCase(),
textEditor.getText().toUpperCase(), prod.getNnnid()) == false) {
if (warnGenFlag) {
QCConfirmationMsg qcMsg = new QCConfirmationMsg();
if (!qcMsg.checkWarningInfo(headerTF.getText().toUpperCase(),
textEditor.getText().toUpperCase(), prod.getNnnid())) {
WarnGenConfirmationDlg wgcd = new WarnGenConfirmationDlg(shell,
"Problem Detected by QC", qcCheck.getErrorMessage(),
"Do you really want to Send?\n", mode);
qcMsg.getTitle(), qcMsg.getProductMessage(),
qcMsg.getModeMessage());
wgcd.setCloseCallback(new ICloseCallback() {
@Override
public void dialogClosed(Object returnValue) {
if (Boolean.TRUE.equals(returnValue))
finishSendProduct(resend, title, mode,
productMessage, modeMessage);
if (Boolean.TRUE.equals(returnValue)) {
checkEmergencyProduct(resend);
}
}
});
wgcd.open();
return;
} else {
checkEmergencyProduct(resend);
}
} else {
finishSendProduct(resend);
}
finishSendProduct(resend, title, mode, productMessage, modeMessage);
}
/**
@ -4890,21 +4878,8 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
* the WarnGen being sent.
*
* @param resend
* @param title
* @param mode
* @param productMessage
* @param modeMessage
*/
private void finishSendProduct(final boolean resend, String title,
CAVEMode mode, StringBuilder productMessage,
StringBuilder modeMessage) {
Pattern p = Pattern.compile(".\\%[s].");
Matcher m = p.matcher(STORED_SENT_MSG);
final boolean result = (CAVEMode.OPERATIONAL.equals(mode) || CAVEMode.TEST
.equals(mode));
modeMessage.append(result ? m.replaceAll(" ") : m.replaceAll(" not "));
private void finishSendProduct(final boolean resend) {
if (statusBarLabel.getText().startsWith("Attachment:")) {
StringBuilder sb = new StringBuilder("An Attachment file (");
int startIndex = "Attachment:".length() + 1;
@ -4927,21 +4902,58 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
if (!verifyRequiredFields()) {
return;
}
StdTextProduct prod = getStdTextProduct();
String afosId = prod.getCccid() + prod.getNnnid() + prod.getXxxid();
SendConfirmationMsg sendMsg = new SendConfirmationMsg(resend, afosId,
prod.getNnnid());
WarnGenConfirmationDlg wgcd = new WarnGenConfirmationDlg(shell, title,
productMessage.toString(), modeMessage.toString(), mode);
WarnGenConfirmationDlg wgcd = new WarnGenConfirmationDlg(shell,
sendMsg.getTitle(), sendMsg.getProductMessage(),
sendMsg.getModeMessage());
wgcd.setCloseCallback(new ICloseCallback() {
@Override
public void dialogClosed(Object returnValue) {
if (Boolean.TRUE.equals(returnValue)) {
warngenCloseCallback(resend, result);
warngenCloseCallback(resend);
}
}
});
wgcd.open();
}
/**
* Checks if the product is a emergency warning product and opens up the
* WarnGen Confirmation Dialog if necessary.
*
* @param resend
* true if product is to be resent
*/
private void checkEmergencyProduct(final boolean resend) {
StdTextProduct prod = getStdTextProduct();
EmergencyConfirmationMsg emergencyMsg = new EmergencyConfirmationMsg();
if (emergencyMsg.checkWarningInfo(headerTF.getText().toUpperCase(),
textEditor.getText().toUpperCase(), prod.getNnnid()) == false) {
WarnGenConfirmationDlg wgcd = new WarnGenConfirmationDlg(shell,
emergencyMsg.getTitle(), emergencyMsg.getProductMessage(),
emergencyMsg.getModeMessage());
wgcd.setCloseCallback(new ICloseCallback() {
@Override
public void dialogClosed(Object returnValue) {
if (Boolean.TRUE.equals(returnValue)) {
finishSendProduct(resend);
}
}
});
wgcd.open();
} else {
finishSendProduct(resend);
}
}
/**
* This is used by finishedSendProduct as the call back to the warnGen
* confirmaiton Dialog.
@ -4949,10 +4961,13 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
* @param resend
* @param result
*/
private void warngenCloseCallback(boolean resend, boolean isOperational) {
private void warngenCloseCallback(boolean resend) {
// DR14553 (make upper case in product)
String body = textEditor.getText().toUpperCase();
CAVEMode mode = CAVEMode.getMode();
boolean isOperational = (CAVEMode.OPERATIONAL.equals(mode) || CAVEMode.TEST
.equals(mode));
if (isOperational) {
removeOptionalFields();
@ -5605,93 +5620,94 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
textEditor.setText("");
}
} else {
// TODO FIX PARSING
// TODO FIX PARSING
// First, set the current header by assuming that it usually
// consists of the first two lines of text in the text product,
// though there will be exceptions to that "rule" as handled below.
// So, obtain the AFOS NNNxxx. If it's where it is supposed to be
// in the new format, then the existing header is already an AWIPS
// First, set the current header by assuming that it usually
// consists of the first two lines of text in the text product,
// though there will be exceptions to that "rule" as handled below.
// So, obtain the AFOS NNNxxx. If it's where it is supposed to be
// in the new format, then the existing header is already an AWIPS
// text product identifier. Otherwise it is a legacy AFOS
// identifier.
if (TextDisplayModel.getInstance().hasStdTextProduct(token)) {
StdTextProduct textProd = TextDisplayModel.getInstance()
.getStdTextProduct(token);
StdTextProductId prodId = textProd.getProdId();
try {
// start of second line of text
start = textEditor.getOffsetAtLine(thisLine + 1);
if ((textEditor.getText(start, start + afosNnnLimit)
.equals(prodId.getNnnid()))
if (TextDisplayModel.getInstance().hasStdTextProduct(token)) {
StdTextProduct textProd = TextDisplayModel.getInstance()
.getStdTextProduct(token);
StdTextProductId prodId = textProd.getProdId();
try {
// start of second line of text
start = textEditor.getOffsetAtLine(thisLine + 1);
if ((textEditor.getText(start, start + afosNnnLimit)
.equals(prodId.getNnnid()))
&& (textEditor.getText(start + afosNnnLimit + 1,
start + afosXxxLimit).equals(prodId
.getXxxid()))) {
// Text matches the products nnnid and xxxid
numberOfLinesOfHeaderText = 2;
// Text matches the products nnnid and xxxid
numberOfLinesOfHeaderText = 2;
} else if (textEditor.getText(start,
start + afosNnnLimit + 2).equals(
AFOSParser.DRAFT_PIL)
|| textEditor.getText(start,
start + afosNnnLimit + 2).equals("TTAA0")) {
// Text matches temporary WRKWG#
numberOfLinesOfHeaderText = 2;
} else {
// Text matches temporary WRKWG#
numberOfLinesOfHeaderText = 2;
} else {
// Assume this header block is a legacy AFOS identifier.
numberOfLinesOfHeaderText = 1;
}
} catch (IllegalArgumentException e) {
// Assume this header block is a legacy AFOS identifier.
numberOfLinesOfHeaderText = 1;
}
} catch (IllegalArgumentException e) {
// Assume this header block is a legacy AFOS identifier.
numberOfLinesOfHeaderText = 1;
}
}
try {
start = 0;
finish = textEditor.getOffsetAtLine(thisLine
+ numberOfLinesOfHeaderText) - 1;
} catch (IllegalArgumentException e) {
// The text does not span enough lines so use the full extent
// of the product.
finish = textEditor.getCharCount() - 1;
}
try {
start = 0;
finish = textEditor.getOffsetAtLine(thisLine
+ numberOfLinesOfHeaderText) - 1;
} catch (IllegalArgumentException e) {
// The text does not span enough lines so use the full extent
// of the product.
finish = textEditor.getCharCount() - 1;
}
// Set the content of the header block to consist of just the header of
// the text product... it will get reunited with the body when it is
// saved.
if (finish > start) {
headerTF.setText(textEditor.getText(start, finish));
} else {
headerTF.setText("");
}
// Set the content of the header block to consist of just the header
// of
// the text product... it will get reunited with the body when it is
// saved.
if (finish > start) {
headerTF.setText(textEditor.getText(start, finish));
} else {
headerTF.setText("");
}
// Next, set the current body by assuming that it always
// consists of the rest of the text product beyond the line(s)
// of text in the header.
try {
int numberOfBlankLines = -1;
String line = null;
do {
numberOfBlankLines++;
// Next, set the current body by assuming that it always
// consists of the rest of the text product beyond the line(s)
// of text in the header.
try {
int numberOfBlankLines = -1;
String line = null;
do {
numberOfBlankLines++;
line = textEditor.getLine(thisLine
+ numberOfLinesOfHeaderText + numberOfBlankLines);
} while (line.length() == 0 || line.equals(""));
// Note: 'st' is a reference to 'textEditor'...
// delelete the header from the text in 'textEditor'
finish = textEditor.getOffsetAtLine(thisLine
+ numberOfLinesOfHeaderText + numberOfBlankLines);
textEditor.setSelection(start, finish);
textEditor.setEditable(true);
textEditor.invokeAction(SWT.DEL);
textEditor.setEditable(false);
} catch (IllegalArgumentException e) {
// There is no text product body, so set it to the empty string.
textEditor.setText("");
}
} while (line.length() == 0 || line.equals(""));
// Note: 'st' is a reference to 'textEditor'...
// delelete the header from the text in 'textEditor'
finish = textEditor.getOffsetAtLine(thisLine
+ numberOfLinesOfHeaderText + numberOfBlankLines);
textEditor.setSelection(start, finish);
textEditor.setEditable(true);
textEditor.invokeAction(SWT.DEL);
textEditor.setEditable(false);
} catch (IllegalArgumentException e) {
// There is no text product body, so set it to the empty string.
textEditor.setText("");
}
}
// set editor status flags
dirty = false;
}
/**
* Update the editor's header text field.
*
@ -5901,9 +5917,9 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
statusBarLabel.update();
setBusy(true);
if (queryTransport == null) {
queryTransport = TextEditorUtil.getTextDbsrvTransport();
}
if (queryTransport == null) {
queryTransport = TextEditorUtil.getTextDbsrvTransport();
}
productQueryJob.addRequest(command, isObsUpdated,
accumChkBtn.getSelection());
}
@ -7588,9 +7604,9 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
protected void disposed() {
textEditor.setFont(shell.getFont());
headerTF.setFont(shell.getFont());
if (dftFont != null) {
dftFont.dispose();
dftFont.dispose();
}
if (clipboard != null) {
@ -8182,7 +8198,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
private void displayAirportTooltip(Point location) {
String word = parseProduct(textEditor, location.y);
if (word != null) {
String result = AfosBrowserModel.getInstance().getNodeHelp(word);
String result = AfosBrowserModel.getInstance().getNodeHelp(word);
if (result != null) {
// dispaly below and to the right of location.
location.x += 5;
@ -8208,29 +8224,29 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
String result = new String("");
try {
char c = lineText.charAt(0);
if ((c == 'M') || (c == 'S') || (c == 'T')) {
char c = lineText.charAt(0);
if ((c == 'M') || (c == 'S') || (c == 'T')) {
// # Most obs start with METAR, SPECI, TESTM, or TESTS. Skip
// over
// that tag,
// # a space, and the K or P, to get to the 3-char station ID.
if (lineText.length() > 10) {
result = lineText.substring(7, 10);
} else {
result = lineText.substring(lineText.length() - 3);
}
} else if ((c == 'W') || (c == 'Y')) {
// that tag,
// # a space, and the K or P, to get to the 3-char station ID.
if (lineText.length() > 10) {
result = lineText.substring(7, 10);
} else {
result = lineText.substring(lineText.length() - 3);
}
} else if ((c == 'W') || (c == 'Y')) {
// # Canadian SAOs have 3-character IDs, starting with W or Y.
// Grab
// 'em.
result = lineText.substring(0, 3);
} else {
// 'em.
result = lineText.substring(0, 3);
} else {
// # Some military obs don't get tagged. Skip the K or P and get
// 3
// chars.
int wordLineStart = 1;
result = lineText.substring(wordLineStart, wordLineStart + 4);
}
// chars.
int wordLineStart = 1;
result = lineText.substring(wordLineStart, wordLineStart + 4);
}
} catch (StringIndexOutOfBoundsException ex) {
// User has non METAR/SAO products and the parsing failed.
result = null;

View file

@ -71,7 +71,7 @@ public class WarnGenConfirmationDlg extends CaveSWTDialog {
private String IMAGE_PRACTICE = "res/images/twsPractice.gif";
protected WarnGenConfirmationDlg(Shell parentShell, String title,
String productMessage, String modeMessage, CAVEMode mode) {
String productMessage, String modeMessage) {
super(parentShell, SWT.DIALOG_TRIM | SWT.PRIMARY_MODAL, CAVE.NONE
| CAVE.DO_NOT_BLOCK);
@ -79,7 +79,7 @@ public class WarnGenConfirmationDlg extends CaveSWTDialog {
this.productMessage = productMessage;
this.modeMessage = modeMessage;
this.mode = mode;
this.mode = CAVEMode.getMode();
setReturnValue(Boolean.FALSE);
}

View file

@ -32,6 +32,7 @@ import java.util.List;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Dec 11, 2007 #601 chammack Initial Creation.
* Aug 19, 2013 2177 jsanchez Removed suppress attribute.
*
* </pre>
*
@ -49,11 +50,6 @@ public class AffectedAreas {
*/
protected List<String> partOfArea;
/**
* The partOfArea to suppress (e.g. "ns")
*/
protected String suppress;
/** The notation of the area affected (e.g. "COUNTY") */
protected String areaNotation;
@ -89,17 +85,15 @@ public class AffectedAreas {
public String getName() {
return name;
}
/**
* @param name
* the name to set
* @param name
* the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the areaNotation
*/

View file

@ -46,7 +46,6 @@ import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.viz.warngen.gui.WarngenLayer;
import com.raytheon.viz.warngen.suppress.SuppressMap;
import com.raytheon.viz.warngen.util.Abbreviation;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
@ -74,6 +73,7 @@ import com.vividsolutions.jts.geom.prep.PreparedGeometry;
* Nov 9, 2012 DR 15430 D. Friedman Extracted method converFeAreaToPartList.
* Apr 29, 2013 1955 jsanchez Ignored comparing the geometry's user data when finding intersected areas.
* May 2, 2013 1963 jsanchez Updated method to determine partOfArea.
* Aug 19, 2013 2177 jsanchez Used portionsUtil to calculate area portion descriptions.
* </pre>
*
* @author chammack
@ -89,13 +89,15 @@ public class Area {
*/
public static final double DEFAULT_PORTION_TOLERANCE = 0.60;
private Area() {
private PortionsUtil portionsUtil;
public Area(PortionsUtil portionsUtil) {
this.portionsUtil = portionsUtil;
}
public static AffectedAreas[] findAffectedAreas(
WarngenConfiguration config, Geometry polygon,
Geometry warningArea, String localizedSite) throws VizException {
public AffectedAreas[] findAffectedAreas(WarngenConfiguration config,
Geometry polygon, Geometry warningArea, String localizedSite)
throws VizException {
// --- Begin argument checking ---
Validate.notNull(config.getGeospatialConfig().getAreaSource(),
@ -113,7 +115,7 @@ public class Area {
localizedSite, geoms);
}
private static AffectedAreas[] findAffectedAreas(
private AffectedAreas[] findAffectedAreas(
AreaSourceConfiguration areaConfig,
GeospatialConfiguration geospatialConfig, Geometry polygon,
String localizedSite, List<Geometry> geoms) throws VizException {
@ -183,7 +185,6 @@ public class Area {
area.stateabbr = regionFeature.attributes.get(areaNotationField)
.toString();
area.size = regionGeom.getArea();
area.suppress = suppressType(areaSource, area.stateabbr, area.fips);
Object tzData = regionFeature.attributes.get(timezonePathcastField);
@ -219,9 +220,16 @@ public class Area {
double tolerCheck = regionGeom.getArea()
* DEFAULT_PORTION_TOLERANCE;
if (areaIntersection < tolerCheck) {
area.partOfArea = GisUtil
.asStringList(GisUtil.calculatePortion(regionGeom,
intersection, true, true));
try {
String entityID = area.stateabbr + areaSource.charAt(0)
+ area.fips.substring(2);
area.partOfArea = GisUtil.asStringList(portionsUtil
.getPortions(entityID, regionGeom, intersection,
true));
} catch (Exception e) {
statusHandler.error("Unable to calculate part of area for "
+ area.name, e);
}
}
// Search the parent region
@ -277,10 +285,9 @@ public class Area {
* @return
* @throws VizException
*/
public static Map<String, Object> findInsectingAreas(
WarngenConfiguration config, Geometry warnPolygon,
Geometry warnArea, String localizedSite, WarngenLayer warngenLayer)
throws VizException {
public Map<String, Object> findInsectingAreas(WarngenConfiguration config,
Geometry warnPolygon, Geometry warnArea, String localizedSite,
WarngenLayer warngenLayer) throws VizException {
Map<String, Object> areasMap = new HashMap<String, Object>();
String hatchedAreaSource = config.getHatchedAreaSource()
@ -311,18 +318,6 @@ public class Area {
}
private static String suppressType(String areaSource, String state,
String fips) {
String retVal = SuppressMap.NONE;
String type = areaSource.equalsIgnoreCase("zone") ? "Z" : "C";
if (state != null && fips != null) {
String key = state + type + fips.substring(2);
retVal = SuppressMap.getInstance().getType(key);
}
return retVal;
}
public static List<String> converFeAreaToPartList(String feArea) {
final List<String> partList = new ArrayList<String>();
if (feArea == null) {

View file

@ -0,0 +1,178 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.warngen.gis;
/**
* Port of A1 constants applied to a grid to determine county or zone portions.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 5, 2013 2177 jsanchez Initial creation
*
* </pre>
*
* @author jsanchez
* @version 1.0
*/
public class CoverageConstants {
public static final int XSOUTH = 0x0001;
public static final int SOUTH = 0x0002;
public static final int NORTH = 0x0040;
public static final int XNORTH = 0x0080;
public static final int CENTER_NS = 0x0018;
public static final int CENTRAL_NS = 0x0024;
public static final int XWEST = 0x0100;
public static final int WEST = 0x0200;
public static final int EAST = 0x4000;
public static final int XEAST = 0x8000;
public static final int CENTER_EW = 0x1800;
public static final int CENTRAL_EW = 0x2400;
public static final int SOUTHERN = 0x0003;
public static final int NORTHERN = 0x00C0;
public static final int WESTERN = 0x0300;
public static final int EASTERN = 0xC000;
public static final int SOUTHSIDE = 0x000F;
public static final int NORTHSIDE = 0x00F0;
public static final int WESTSIDE = 0x0F00;
public static final int EASTSIDE = 0xF000;
public static final int EXTREME = 0x8181;
public static final int NOT_EXTREME = 0x7E7E;
public static final int EXTREME_NS = 0x0081;
public static final int EXTREME_EW = 0x8100;
public static final int CENTRAL = 0x2424;
public static final int CENTER = 0x1818;
public static final int NOT_CENTRAL = 0xC3C3;
public static final int NORTH_SOUTH = 0x00FF;
public static final int EAST_WEST = 0xFF00;
public static final int NNE = 0x0001;
public static final int ENE = 0x0002;
public static final int ESE = 0x0004;
public static final int SSE = 0x0008;
public static final int SSW = 0x0010;
public static final int WSW = 0x0020;
public static final int WNW = 0x0040;
public static final int NNW = 0x0080;
public static final int EXTREME_YES = 0xFFFF00;
public static final int EXTREME_NO = 0x00FF;
public static final int EXTREME_CORNER = 0xFF0000;
public static int[] NS_MASK = new int[256];
public static int[] EW_MASK = new int[256];
static {
int i;
NS_MASK[0] = 0;
for (i = 1; i < 256; i++) {
if (i < 87) {
NS_MASK[i] = XSOUTH | SOUTH;
} else if (i > 167) {
NS_MASK[i] = XNORTH | NORTH;
} else if (i < 106) {
NS_MASK[i] = SOUTH;
} else if (i > 148) {
NS_MASK[i] = NORTH;
} else if (i < 118) {
NS_MASK[i] = CENTRAL_NS | SOUTH;
} else if (i > 138) {
NS_MASK[i] = CENTRAL_NS | NORTH;
} else if (i < 127) {
NS_MASK[i] = CENTER_NS | CENTRAL_NS | SOUTH;
} else if (i > 127) {
NS_MASK[i] = CENTER_NS | CENTRAL_NS | NORTH;
} else {
NS_MASK[i] = CENTER_NS | CENTRAL_NS;
}
}
EW_MASK[0] = 0;
for (i = 1; i < 256; i++) {
if (i < 87) {
EW_MASK[i] = XWEST | WEST;
} else if (i > 167) {
EW_MASK[i] = XEAST | EAST;
} else if (i < 106) {
EW_MASK[i] = WEST;
} else if (i > 145) {
EW_MASK[i] = EAST;
} else if (i < 118) {
EW_MASK[i] = CENTRAL_EW | WEST;
} else if (i > 138) {
EW_MASK[i] = CENTRAL_EW | EAST;
} else if (i < 127) {
EW_MASK[i] = CENTER_EW | CENTRAL_EW | WEST;
} else if (i > 127) {
EW_MASK[i] = CENTER_EW | CENTRAL_EW | EAST;
} else {
EW_MASK[i] = CENTER_EW | CENTRAL_EW;
}
}
}
private CoverageConstants() {
}
}

View file

@ -0,0 +1,65 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.warngen.gis;
/**
* Simple port of an A1 struct created by GridUtil and used by PortionsUtil.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 5, 2013 2177 jsanchez Initial creation
*
* </pre>
*
* @author jsanchez
* @version 1.0
*/
public class EntityData {
private int meanMask = 0;
private int coverageMask = 0;
private int octants = 0;
public EntityData(int meanMask, int coverageMask, int octants) {
this.meanMask = meanMask;
this.coverageMask = coverageMask;
this.octants = octants;
}
public int getMeanMask() {
return meanMask;
}
public int getCoverageMask() {
return coverageMask;
}
public int getOctants() {
return octants;
}
}

View file

@ -0,0 +1,616 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.warngen.gis;
import java.util.ArrayList;
import java.util.List;
import org.geotools.coverage.grid.GeneralGridGeometry;
import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.referencing.operation.DefaultMathTransformFactory;
import org.opengis.coverage.grid.GridEnvelope;
import org.opengis.metadata.spatial.PixelOrientation;
import org.opengis.referencing.operation.MathTransform;
import com.raytheon.uf.common.dataplugin.warning.util.GeometryUtil;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.viz.warngen.gui.WarngenLayer;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.CoordinateSequence;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory;
/**
* Converts the county or zone and the intersecting warning area to grids. The
* county or zone is also weighted to determine the northern, southern, eastern,
* and western parts of the county or zone. Most of the code is ported from A1
* to create an EntityData object that will be used by PortionsUtil to determine
* the applicable impacted portions of a county or zone.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 5, 2013 jsanchez Initial creation
*
* </pre>
*
* @author jsanchez
* @version 1.0
*/
public class GridUtil {
private int ny = 0;
private int nx = 0;
private int[] ewGrid;
private int[] nsGrid;
private byte[] warnedAreaGrid;
private byte[] countyOrZoneGrid;
private WarngenLayer layer;
private MathTransform latLonToContour, contourToLatLon;
public GridUtil(WarngenLayer layer, GeneralGridGeometry localGridGeometry,
MathTransform localToLatLon) throws Exception {
this.layer = layer;
GridEnvelope range = localGridGeometry.getGridRange();
this.nx = range.getHigh(0);
this.ny = range.getHigh(1);
org.opengis.geometry.Envelope ge = localGridGeometry.getEnvelope();
contourToLatLon = new DefaultMathTransformFactory()
.createConcatenatedTransform(new GridGeometry2D(range, ge)
.getGridToCRS(PixelOrientation.CENTER), localToLatLon);
latLonToContour = contourToLatLon.inverse();
ewGrid = new int[nx * ny];
nsGrid = new int[nx * ny];
}
/**
* Converts the countyOrZone geometry and the warnedArea into grids and sets
* the appropriate data in an EntityData object.
*
* @param countyOrZone
* @param warnedArea
* @return
* @throws Exception
*/
public EntityData calculateGrids(Geometry countyOrZone, Geometry warnedArea)
throws Exception {
countyOrZoneGrid = toByteArray(countyOrZone);
warnedAreaGrid = toByteArray(warnedArea);
int[] bounds = awips1FinishAreaEntity();
EntityData entityData = finishDefineArea(bounds);
return entityData;
}
/**
* Converts the geometry into a byte array that is expected by ported A1
* code.
*
* @param geometry
* @return
* @throws VizException
*/
private byte[] toByteArray(Geometry geometry) throws VizException {
byte[] bytes = new byte[nx * ny];
float[][] floatData = toFloatData(geometry);
// Rotates grid
int k = 0;
for (int j = ny - 1; j >= 0; j--) {
for (int i = 0; i < nx; i++) {
if (floatData[i][j] == 1) {
bytes[k] = 1;
}
k++;
}
}
return bytes;
}
/**
* Converts the geometry into a 2-D float array.
*
* @param geometry
* @return
* @throws VizException
*/
private float[][] toFloatData(Geometry geometry) throws VizException {
Geometry contoured = layer.convertGeom(geometry, latLonToContour);
List<Geometry> geomList = new ArrayList<Geometry>(
contoured.getNumGeometries());
GeometryUtil.buildGeometryList(geomList, contoured);
List<PreparedGeometry> prepped = new ArrayList<PreparedGeometry>(
geomList.size());
for (Geometry g : geomList) {
prepped.add(PreparedGeometryFactory.prepare(g));
}
GeometryFactory gf = geometry.getFactory();
Point point = gf.createPoint(new Coordinate(0, 0));
CoordinateSequence pointCS = point.getCoordinateSequence();
float[][] contourAreaData = new float[nx][ny];
for (PreparedGeometry geom : prepped) {
Envelope env = geom.getGeometry().getEnvelopeInternal();
int startX = (int) env.getMinX();
int startY = (int) env.getMinY();
int width = (int) env.getMaxX();
int height = (int) env.getMaxY();
if (startX < 0 || width > nx || startY < 0 || height > ny) {
continue;
}
startX = Math.max(0, startX - 1);
startY = Math.max(0, startY - 1);
width = Math.min(nx, width + 1);
height = Math.min(ny, height + 1);
for (int x = startX; x < width; ++x) {
for (int y = startY; y < height; ++y) {
pointCS.setOrdinate(0, 0, x);
pointCS.setOrdinate(0, 1, y);
point.geometryChanged();
if (contourAreaData[x][y] == 0.0f && geom.intersects(point)) {
contourAreaData[x][y] = 1.0f;
}
}
}
}
return contourAreaData;
}
/**
* Ported only the logic from A1 code
* GeoEntityLookupTable::finishDefineArea() that calculates the meanMask,
* coverageMask,and octants for an entity (i.e. county or zone).
*
* @param countyOrZone
* @param warnedArea
* @return
*/
private EntityData finishDefineArea(int[] bounds) {
int meanMask = 0;
int coverageMask = 0;
int octants = 0;
int ewCount = 0;
int nsCount = 0;
int ewTotal = 0;
int nsTotal = 0;
int k = 0;
int min_i = bounds[0];
int max_i = bounds[1];
int min_j = bounds[2];
int max_j = bounds[3];
for (int j = min_j; j < max_j; j++) {
k = nx * j + min_i;
for (int i = min_i; i < max_i; i++, k++) {
if (warnedAreaGrid[k] == 1) {
int e = countyOrZoneGrid[k];
int ii = ewGrid[k];
int jj = nsGrid[k];
if (ii == 0 && jj == 0) {
continue;
}
ewTotal += ii;
if (ii > 0) {
ewCount++;
}
nsTotal += jj;
if (jj > 0) {
nsCount++;
}
int m = CoverageConstants.EW_MASK[ii]
| CoverageConstants.NS_MASK[jj];
coverageMask |= m;
if ((m & CoverageConstants.CENTRAL) == CoverageConstants.CENTRAL) {
continue;
}
if (ii == 0) {
ii = 127;
}
if (jj == 0) {
jj = 127;
}
if (ii < 127) {
if (jj < 127) {
e = (ii > jj ? CoverageConstants.SSW
: CoverageConstants.WSW);
} else {
e = (ii > 254 - jj ? CoverageConstants.NNW
: CoverageConstants.WNW);
}
} else {
if (jj < 127) {
e = (ii < 254 - jj ? CoverageConstants.SSE
: CoverageConstants.ESE);
} else {
e = (ii < jj ? CoverageConstants.NNE
: CoverageConstants.ENE);
}
}
if ((m & CoverageConstants.EXTREME_NS) > 0) {
e <<= 8;
}
if ((m & CoverageConstants.EXTREME_EW) > 0) {
e <<= 8;
}
octants |= e;
} else {
warnedAreaGrid[k] = 0;
}
}
}
if (ewCount > 0) {
ewTotal = (ewTotal + ewCount / 2) / ewCount;
}
if (nsCount > 0) {
nsTotal = (nsTotal + nsCount / 2) / nsCount;
}
meanMask = CoverageConstants.NS_MASK[nsTotal]
| CoverageConstants.EW_MASK[ewTotal];
return new EntityData(meanMask, coverageMask, octants);
}
/**
* Calculates the _ewGrid and _nsGrid via A1 ~~ mAgIc ~~
*/
private int[] awips1FinishAreaEntity() {
final double EXTREME_FRAC = 0.1;
final double MIN_EXTREME = 87;
final double MAX_EXTREME = 167;
int k = 0;
int ii, jj;
/*
* identify those points on the boundary of the entity so we can shrink
* from there
*/
int i_mean = 0;
int j_mean = 0;
int new_tot = 0;
int ii_mean = 0;
int jj_mean = 0;
int min_i = Integer.MAX_VALUE;
int min_j = Integer.MAX_VALUE;
int max_i = Integer.MIN_VALUE;
int max_j = Integer.MIN_VALUE;
for (jj = 0; jj < ny; jj++) {
k = nx * jj;
for (ii = 0; ii < nx; ii++, k++) {
// If the entity is not 1 then it's not part of the county or
// zone area.
if (countyOrZoneGrid[k] != 1) {
continue;
}
if (ii > max_i) {
max_i = ii;
}
if (ii < min_i) {
min_i = ii;
}
if (jj > max_j) {
max_j = jj;
}
if (jj < min_j) {
min_j = jj;
}
++new_tot;
ii_mean += ii;
jj_mean += jj;
}
}
/*
* restablish some things that might have changed since the first time
* they were calculated.
*/
// if (!outside) {
ii_mean /= new_tot;
jj_mean /= new_tot;
i_mean = ii_mean;
j_mean = jj_mean;
// }/*endif*/
/* assign correct base for directional computation */
// I changed this from ii_mean to this
double i_base = (min_i + max_i) / 2;
// I changed this from jj_mean to this
double j_base = (min_j + max_j) / 2;
/*
* calculate needed rotation factors for computation of amount each
* point is north and east of centroid
*/
double x_intcpg = 0.5;
double y_intcpg = 0.5;
double dx = 1, dy = 1;
double x = (i_base - x_intcpg);
double y = (j_base - y_intcpg);
// Below is some code from the original A1 code. I assumed that x_intcpg
// to be 0.5 to avoid porting all the methods in gelt_maker.c.
// xy_to_ll(&x,&y,&lat,&lon,&my_proj);
// lat01=lat+0.1;
// ll_to_xy(&lat01,&lon,&dx,&dy,&my_proj);
// dx -= x;
dy -= y;
double mag = Math.sqrt(dx * dx + dy * dy);
dx /= mag;
dy /= mag;
double erot_i = -dy;
double erot_j = -dx;
double nrot_i = dx;
double nrot_j = dy;
int[] ew_hist = new int[nx * ny];
int[] ns_hist = new int[nx * ny];
/* Calculate north/south & east/west offsets, create histogram of these. */
// TODO I did not fully implement the histograms as used in a1. Using
// the histograms created index out of bounds errors. If the field is
// unhappy with the portions, then porting the histograms needs to be
// re-investigated.
int ns1 = 0, ns2 = 0, ew1 = 0, ew2 = 0;
int np_n = 0, np_s = 0, np_e = 0, np_w = 0;
ns_hist[0] = 0;
ew_hist[0] = 0;
for (jj = min_j; jj < max_j; jj++) {
k = nx * jj + min_i;
for (ii = min_i; ii < max_i; ii++, k++) {
// If the entity is not 1 then it's not part of the county or
// zone area.
if (countyOrZoneGrid[k] != 1) {
continue;
}
double di = ii - i_base;
double dj = jj - j_base;
double dns = (int) (nrot_i * di + nrot_j * dj);
while (ns1 > dns) {
// ns_hist[--ns1] = 0;
--ns1;
}
while (ns2 < dns) {
// ns_hist[++ns2] = 0;
++ns2;
}
// ns_hist[(int) dns]++;
double dew = (int) (erot_i * di + erot_j * dj);
while (ew1 > dew) {
// ew_hist[--ew1] = 0;
--ew1;
}
while (ew2 < dew) {
// ew_hist[++ew2] = 0;
++ew2;
}
// ew_hist[(int) dew]++;
if (dew < 0) {
np_w++;
}
if (dew > 0) {
np_e++;
}
if (dns < 0) {
np_s++;
}
if (dns > 0) {
np_n++;
}
}/* end for */
}/* end for */
/*
* Transform n-s & e-w offsets into normalized distances north and
* south. This is done based on a preferred fraction of each area that
* is "extreme".
*/
// a lot of assumptions were made here. therefore, not everything in
// this part was fully ported.
double target = np_w * EXTREME_FRAC;
// for (ii = 0, k = ew1; k < -1 && ii < target; k++) {
// ii += ew_hist[k];
// }
// if (ii / target > 1.5) {
// k--;
// }
// if (k < ew1) {
// k = ew1;
// }
k = ew1;
double mu_w = (MIN_EXTREME - 127) / (k + 0.5);
target = np_e * EXTREME_FRAC;
// for (ii = 0, k = ew2; k > 1 && ii < target; k--) {
// ii += ew_hist[k];
// }
// if (ii / target > 1.5) {
// k++;
// }
// if (k > ew2) {
// k = ew2;
// }
k = ew2;
double mu_e = (MAX_EXTREME - 127) / (k - 0.5);
target = np_s * EXTREME_FRAC;
// for (ii = 0, k = ns1; k < -1 && ii < target; k++) {
// ii += ns_hist[k];
// }
// if (ii / target > 1.5) {
// k--;
// }
// if (k < ns1) {
// k = ns1;
// }
k = ns1;// TODO - REPLACE WITH ABOVE
double mu_s = (MIN_EXTREME - 127) / (k + 0.5);
target = np_n * EXTREME_FRAC;
// for (ii = 0, k = ns2; k > 1 && ii < target; k--) {
// ii += ns_hist[k];
// }
// if (ii / target > 1.5) {
// k++;
// }
// if (k > ns2) {
// k = ns2;
// }
k = ns2;
double mu_n = (MAX_EXTREME - 127) / (k - 0.5);
for (jj = min_j; jj < max_j; jj++) {
k = nx * jj + min_i;
for (ii = min_i; ii < max_i; ii++, k++) {
// If the entity is not 1 then it's not part of the county or
// zone area.
if (countyOrZoneGrid[k] != 1) {
ewGrid[k] = 0;
nsGrid[k] = 0;
continue;
}
double di = ii - i_base;
double dj = jj - j_base;
double dns = (int) (nrot_i * di + nrot_j * dj);
double dew = (int) (erot_i * di + erot_j * dj);
int c_ns2 = (int) (dns);
int c_ew2 = (int) (dew);
if (c_ew2 < 0) {
dx = c_ew2 * mu_w;
} else {
dx = c_ew2 * mu_e;
}
if (dx > 127) {
dx = 127;
}
if (dx < -127) {
dx = -127;
}
ewGrid[k] = (int) (127 + (int) (dx));
if (c_ns2 < 0) {
dy = c_ns2 * mu_s;
} else {
dy = c_ns2 * mu_n;
}
if (dy > 127) {
dy = 127;
}
if (dy < -127) {
dy = -127;
}
nsGrid[k] = (int) (127 + (int) (dy));
}
}
// System.out.println("-----------------------------------");
// printGrids(countyOrZoneGrid, min_i, max_i, min_j, max_j);
// System.out.println("-----------------------------------");
// printGrids(_currentArea, min_i, max_i, min_j, max_j);
// System.out.println("-------------- EAST WEST ---------------------");
// printGrids(ewGrid, min_i, max_i, min_j, max_j);
// System.out.println("-------------- NORTH SOUTH ---------------------");
// printGrids(nsGrid, min_i, max_i, min_j, max_j);
// System.out.println("north/south - east/west done");
return new int[] { min_i, max_i, min_j, max_j };
}
// For debugging and view the grid in ascii format.
private void printGrids(int[] grid, int min_i, int max_i, int min_j,
int max_j) {
int k = 0;
for (int jj = min_j; jj < max_j; jj++) {
k = nx * jj + min_i;
for (int ii = min_i; ii < max_i; ii++) {
System.out.print((int) grid[k]);
k++;
}
System.out.println("-");
}
}
// For debugging and view the grid in ascii format.
private void printGrids(byte[] grid, int min_i, int max_i, int min_j,
int max_j) {
int k = 0;
for (int jj = min_j; jj < max_j; jj++) {
k = nx * jj + min_i;
for (int ii = min_i; ii < max_i; ii++) {
System.out.print((int) grid[k]);
k++;
}
System.out.println("-");
}
}
}

View file

@ -0,0 +1,471 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.warngen.gis;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import com.raytheon.viz.warngen.gis.GisUtil.Direction;
import com.raytheon.viz.warngen.gui.WarngenLayer;
import com.vividsolutions.jts.geom.Geometry;
/**
* Port of A1 code that determines the portions of the county or zone
* descriptions, such as NORTHWEST.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 5, 2013 2177 jsanchez Initial creation
*
* </pre>
*
* @author jsanchez
* @version 1.0
*/
public class PortionsUtil {
private GridUtil gridUtil;
public PortionsUtil(WarngenLayer layer) throws Exception {
gridUtil = new GridUtil(layer, layer.getLocalGridGeometry(),
layer.getlocalToLatLon());
}
/**
* Determines the the appropriate portion description for the warnedArea
* intersecting the countyOrZone.
*
* @param entityID
* @param countyOrZone
* @param warnedArea
* @param useExtreme
* @return
* @throws Exception
*/
public EnumSet<Direction> getPortions(String entityID,
Geometry countyOrZone, Geometry warnedArea, boolean useExtreme)
throws Exception {
countyOrZone.getUserData();
EntityData entityData = gridUtil.calculateGrids(countyOrZone,
warnedArea);
EnumSet<Direction> portions = getAreaDesc(entityData.getMeanMask(),
entityData.getCoverageMask(), entityData.getOctants(),
useExtreme);
return suppressPortions(entityID, portions);
}
/**
* Looks up if the designated entity ID has an suppressed directions. For
* example, a county or zone may not need to include the north and sound
* direction description if it was included in the area.suppress file.
*
* @param entityID
* @param portions
* @return
*/
private EnumSet<Direction> suppressPortions(String entityID,
EnumSet<Direction> portions) {
Map<String, List<Direction>> suppressedCounties = SuppressMap
.getInstance().getAreas();
if (entityID != null && suppressedCounties != null
&& !suppressedCounties.isEmpty()) {
List<Direction> suppressedDirections = suppressedCounties
.get(entityID.toUpperCase());
if (suppressedDirections != null && !suppressedDirections.isEmpty()) {
portions.removeAll(suppressedDirections);
}
}
return portions;
}
/**
* Port from A1 code of GeoEntityLookupTable::getAreaDesc.
*
* @param meanMask
* @param areaMask
* @param octants
* @param exYes
*/
private static EnumSet<Direction> getAreaDesc(int meanMask, int areaMask,
int octants, boolean exYes) {
EnumSet<Direction> portions = EnumSet.noneOf(Direction.class);
// Test for case where we cannot do portions
if (meanMask == 0 || areaMask == 0) {
return portions;
}
// The next block of code is the original port of A1 code but prevented
// producing the correct result:
// Test for case where area is completely within one subsection.
// if (meanMask == areaMask) {
// return getPointDesc(meanMask, exYes);
// }
// Test for central by not being near adjacent borders.
if (octants == 0
|| ((octants & CoverageConstants.EXTREME_YES) == 0)
&& (meanMask & CoverageConstants.CENTER) == CoverageConstants.CENTER) {
portions.add(Direction.CENTRAL);
return portions;
}
if ((octants & 0xFFFF) == 0xFFFF) {
return portions;
}
// Identify quadrants in use, q is typical, qq is diagonal.
int xoctant = octants >> 8;
int xxoctant = octants >> 16;
int nn, ss, ee, ww, ne, nw, se, sw;
nn = ss = ee = ww = ne = nw = se = sw = 0;
int omerge = xxoctant | xoctant | octants;
if ((omerge & (CoverageConstants.NNE | CoverageConstants.ENE)) > 0) {
ne = 1;
}
if ((omerge & (CoverageConstants.SSE | CoverageConstants.ESE)) > 0) {
se = 1;
}
if ((omerge & (CoverageConstants.NNW | CoverageConstants.WNW)) > 0) {
nw = 1;
}
if ((omerge & (CoverageConstants.SSW | CoverageConstants.WSW)) > 0) {
sw = 1;
}
if ((omerge & (CoverageConstants.NNE | CoverageConstants.NNW)) > 0) {
nn = 1;
}
if ((omerge & (CoverageConstants.SSE | CoverageConstants.SSW)) > 0) {
ss = 1;
}
if ((omerge & (CoverageConstants.WNW | CoverageConstants.WSW)) > 0) {
ww = 1;
}
if ((omerge & (CoverageConstants.ENE | CoverageConstants.ESE)) > 0) {
ee = 1;
}
if ((areaMask & CoverageConstants.NORTH_SOUTH) == 0) {
nn = ss = ne = nw = se = sw = 0;
}
if ((areaMask & CoverageConstants.EAST_WEST) == 0) {
ee = ww = ne = nw = se = sw = 0;
}
int q = ne + nw + se + sw;
int qq = nn + ss + ee + ww;
// Identify extremes in use.
int nnx, ssx, eex, wwx;
nnx = ssx = eex = wwx = 0;
if ((areaMask & CoverageConstants.XNORTH) > 0) {
nnx = 1;
}
if ((areaMask & CoverageConstants.XSOUTH) > 0) {
ssx = 1;
}
if ((areaMask & CoverageConstants.XWEST) > 0) {
wwx = 1;
}
if ((areaMask & CoverageConstants.XEAST) > 0) {
eex = 1;
}
int xxx = nnx + ssx + eex + wwx;
// Modify masks based on whether we can use extreme.
if ((octants & CoverageConstants.EXTREME_NO) > 0
&& (areaMask & CoverageConstants.EXTREME) > 0) {
areaMask &= CoverageConstants.NOT_EXTREME;
meanMask &= CoverageConstants.NOT_EXTREME;
}
// Possible case of a stripe across the middle
if (q == 0) {
;// Only one direction encoded
} else if (q == 2 && nw == se || q == 2 && ne == sw || qq == 2
&& nn == ss || qq == 2 && ee == ww) {
if ((meanMask & CoverageConstants.CENTRAL) == CoverageConstants.CENTRAL
|| nnx == ssx && wwx == eex) {
portions.add(Direction.CENTRAL);
return portions;
}
return getPointDesc2(meanMask, exYes, nn, ss, ee, ww);
}
// Modify masks based on whether we can use central.
if (xxx > 2 || nnx != ssx && wwx != eex) {
areaMask &= CoverageConstants.NOT_CENTRAL;
meanMask &= CoverageConstants.NOT_CENTRAL;
}
// Another possible case of a stripe across the middle.
if (q == 4 && (meanMask & CoverageConstants.CENTER) > 0) {
portions.add(Direction.CENTRAL);
return portions;
}
// All quadrants in use.
if (q == 4 && qq == 4) {
return EnumSet.noneOf(Direction.class);
}
// Only one typical quadrant in use.
if (q == 1) {
// if (ne == 1) {
// portions.add(Direction.NORTH);
// portions.add(Direction.EAST);
// } else if (nw == 1) {
// portions.add(Direction.NORTH);
// portions.add(Direction.WEST);
// } else if (se == 1) {
// portions.add(Direction.SOUTH);
// portions.add(Direction.EAST);
// } else if (sw == 1) {
// portions.add(Direction.SOUTH);
// portions.add(Direction.WEST);
// }
// return portions;
return getPointDesc2(meanMask, exYes, nn, ss, ee, ww);
}
// Further modify masks based on whether we can use central.
if (xxx >= 2) {
areaMask &= CoverageConstants.NOT_CENTRAL;
meanMask &= CoverageConstants.NOT_CENTRAL;
}
// No more than two quadrants of any kind in use, or all quadrants.
if (q < 3 && qq < 3) {
if (nnx != ssx && wwx != eex
|| (meanMask & CoverageConstants.CENTRAL) > 0) {
return getPointDesc2(meanMask, exYes, nn, ss, ee, ww);
} else {
return getPointDesc2(areaMask, exYes, nn, ss, ee, ww);
}
}
// Three typical quadrants in use.
if (q == 3 && qq != 3) {
if (ne == 0) {
// The next line is the original port of A1 code but prevented
// producing the correct result:
// if (ne == 0 && (xxoctant & (SSW | WSW)) > 0) {
portions.add(Direction.SOUTH);
portions.add(Direction.WEST);
} else if (se == 0) {
// The next line is the original port of A1 code but prevented
// producing the correct result:
// } else if (se == 0 && (xxoctant & (NNW | WNW)) > 0) {
portions.add(Direction.NORTH);
portions.add(Direction.WEST);
} else if (nw == 0) {
// The next line is the original port of A1 code but prevented
// producing the correct result:
// } else if (nw == 0 && (xxoctant & (SSE | ESE)) > 0) {
portions.add(Direction.SOUTH);
portions.add(Direction.EAST);
} else if (sw == 0) {
// The next line is the original port of A1 code but prevented
// producing the correct result:
// } else if (sw == 0 && (xxoctant & (NNE | ENE)) > 0) {
portions.add(Direction.NORTH);
portions.add(Direction.EAST);
}
// The next line is the original port of A1 code but prevented
// producing the correct result:
// return getPointDesc(meanMask, exYes);
}
// Three diagonal quadrants in use.
if (qq == 3 && portions.isEmpty()) {
if (nn == 0) {
portions.add(Direction.SOUTH);
} else if (ss == 0) {
portions.add(Direction.NORTH);
} else if (ww == 0) {
portions.add(Direction.EAST);
} else if (ee == 0) {
portions.add(Direction.WEST);
}
}
// add extreme for three quadrant case.
if (!portions.isEmpty()) {
if (exYes && ((areaMask & CoverageConstants.EXTREME)) > 0) {
portions.add(Direction.EXTREME);
}
return portions;
}
// All of either type of quadrant in use.
if (q == 4 || qq == 4) {
return EnumSet.noneOf(Direction.class);
}
// Case of a pure simple direction.
nn = areaMask & CoverageConstants.NORTHERN;
ss = areaMask & CoverageConstants.SOUTHERN;
ee = areaMask & CoverageConstants.EASTERN;
ww = areaMask & CoverageConstants.WESTERN;
if (ss > 0 && nn > 0 || q == 0) {
if (ee == 0 && ww > 0) {
portions.add(Direction.WEST);
}
if (ww == 0 && ee > 0) {
portions.add(Direction.EAST);
}
} else if (ee > 0 && ww > 0 || q == 0) {
if (nn == 0 && ss > 0) {
portions.add(Direction.SOUTH);
}
if (ss == 0 && nn > 0) {
portions.add(Direction.NORTH);
}
}
// add extreme for simple direction case.
if (!portions.isEmpty()) {
if (exYes && ((areaMask & CoverageConstants.EXTREME)) > 0) {
portions.add(Direction.EXTREME);
}
return portions;
}
// Catch with the point descriptor one last time
return getPointDesc2(meanMask, exYes, nn, ss, ee, ww);
}
/**
* Port from A1 code of GeoEntityLookupTable::getPointDesc.
*
* @param mask
* @param exYes
* @return
*/
private static EnumSet<Direction> getPointDesc(int mask, boolean exYes) {
EnumSet<Direction> portions = EnumSet.noneOf(Direction.class);
if (mask == 0) {
return portions;
}
int cc = mask & CoverageConstants.CENTRAL;
if (cc == CoverageConstants.CENTRAL) {
portions.add(Direction.CENTRAL);
return portions;
}
if ((mask & CoverageConstants.NORTH_SOUTH) == 0) {
;
} else if ((mask & CoverageConstants.SOUTHERN) == (mask & CoverageConstants.NORTH_SOUTH)) {
portions.add(Direction.SOUTH);
} else if ((mask & CoverageConstants.NORTHERN) == (mask & CoverageConstants.NORTH_SOUTH)) {
portions.add(Direction.NORTH);
}
if ((mask & CoverageConstants.EAST_WEST) == 0) {
;
} else if ((mask & CoverageConstants.WESTERN) == (mask & CoverageConstants.EAST_WEST)) {
portions.add(Direction.WEST);
} else if ((mask & CoverageConstants.EASTERN) == (mask & CoverageConstants.EAST_WEST)) {
portions.add(Direction.EAST);
}
if (portions.isEmpty()) {
return portions;
}
if (cc != 0) {
portions.add(Direction.CENTRAL);
}
if (exYes && ((int) (mask & CoverageConstants.EXTREME) > 0)) {
portions.add(Direction.EXTREME);
}
return portions;
}
/**
* This method is not a direct port from A1. The original getPointDesc did
* not produce the expected results. This method is a modified version of
* getPointDesct that uses the calculated qq values instead of just the
* meanMask.
*
* @param mask
* @param exYes
* @return
*/
private static EnumSet<Direction> getPointDesc2(int mask, boolean exYes,
int nn, int ss, int ee, int ww) {
EnumSet<Direction> portions = EnumSet.noneOf(Direction.class);
if (mask == 0) {
return portions;
}
int counter = 0;
if (nn > 0 && ss > 0) {
;
} else if (ss > 0) {
portions.add(Direction.SOUTH);
counter++;
} else if (nn > 0) {
portions.add(Direction.NORTH);
counter++;
}
if (ee > 0 && ww > 0) {
;
} else if (ww > 0) {
portions.add(Direction.WEST);
counter++;
} else if (ee > 0) {
portions.add(Direction.EAST);
counter++;
}
if (portions.isEmpty()) {
return portions;
}
int cc = mask & CoverageConstants.CENTRAL;
boolean useCentral = counter < 2;
if (useCentral && cc != 0) {
portions.add(Direction.CENTRAL);
}
if (exYes && ((int) (mask & CoverageConstants.EXTREME) > 0)) {
portions.add(Direction.EXTREME);
}
return portions;
}
}

View file

@ -17,7 +17,7 @@
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.warngen.suppress;
package com.raytheon.viz.warngen.gis;
import java.io.BufferedReader;
import java.io.File;
@ -25,7 +25,10 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -38,9 +41,11 @@ import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.localization.LocalizationManager;
import com.raytheon.viz.warngen.gis.GisUtil.Direction;
/**
* TODO Add Description
* Creates a map of all the site's area suppress files.
*
* <pre>
*
@ -48,6 +53,7 @@ import com.raytheon.uf.common.status.UFStatus.Priority;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 2, 2010 jsanchez Initial creation
* Aug 15,2013 2177 jsanchez Refactored.
*
* </pre>
*
@ -66,16 +72,26 @@ public class SuppressMap {
private static final Pattern ugcPattern = Pattern
.compile("[A-Z]{2}[CZ][0-9]{3}");
public static final String NORTH_SOUTH = "NS";
private static final List<Direction> NORTH_SOUTH = Arrays.asList(
Direction.NORTH, Direction.SOUTH);
public static final String EAST_WEST = "EW";
private static final List<Direction> EAST_WEST = Arrays.asList(
Direction.EAST, Direction.WEST);
public static final String NONE = "NONE";
private static final List<Direction> ALL = Arrays.asList(Direction.NORTH,
Direction.SOUTH, Direction.EAST, Direction.WEST, Direction.CENTRAL,
Direction.EXTREME);
public static final String ALL = "ALL";
private static Map<String, Map<String, List<Direction>>> suppressMap = new HashMap<String, Map<String, List<Direction>>>();
private Map<String, String> suppressMap = new HashMap<String, String>();
private SuppressMap() {
}
/**
*
* @return an instance of the SuppressMap object.
*/
public static SuppressMap getInstance() {
if (instance == null) {
instance = new SuppressMap();
@ -83,64 +99,82 @@ public class SuppressMap {
return instance;
}
private SuppressMap() {
readFile();
/**
* Returns the suppressed area map for the current localized site.
*
* @return
*/
public Map<String, List<Direction>> getAreas() {
String threeLetterSiteID = LocalizationManager.getInstance()
.getCurrentSite();
Map<String, List<Direction>> areas = suppressMap.get(threeLetterSiteID);
if (areas == null) {
areas = new HashMap<String, List<Direction>>();
IPathManager pm = PathManagerFactory.getPathManager();
LocalizationContext lc = pm.getContext(
LocalizationType.COMMON_STATIC, LocalizationLevel.SITE);
File file = pm.getFile(lc, AREA_SUPPRESS_FILENAME);
loadFile(file, areas);
}
return areas;
}
private void readFile() {
// load site
IPathManager pathMgr = PathManagerFactory.getPathManager();
LocalizationContext lc = pathMgr.getContext(
LocalizationType.COMMON_STATIC, LocalizationLevel.SITE);
File file = pathMgr.getFile(lc, AREA_SUPPRESS_FILENAME);
loadFile(file, suppressMap);
}
private void loadFile(File file, Map<String, String> aliasMap) {
/**
* Loads the areas map with the suppress information in the file
*
* @param file
* @param areas
*/
private void loadFile(File file, Map<String, List<Direction>> areas) {
if ((file != null) && file.exists()) {
Matcher m = null;
BufferedReader fis = null;
try {
BufferedReader fis = new BufferedReader(new InputStreamReader(
fis = new BufferedReader(new InputStreamReader(
new FileInputStream(file)));
String line = null;
try {
while ((line = fis.readLine()) != null) {
m = ugcPattern.matcher(line);
if (m.find()) {
String dataKey = m.group();
String data = ALL;
List<Direction> suppressedDirections = new ArrayList<Direction>();
String ugc = m.group();
if (line.indexOf("ns") > 5) {
data = NORTH_SOUTH;
suppressedDirections = NORTH_SOUTH;
} else if (line.indexOf("ew") > 5) {
data = EAST_WEST;
suppressedDirections = EAST_WEST;
} else {
suppressedDirections = ALL;
}
aliasMap.put(dataKey, data);
areas.put(ugc, suppressedDirections);
}
}
} catch (IOException e) {
// TODO Auto-generated catch block. Please revise as
// appropriate.
statusHandler.handle(Priority.PROBLEM,
"Could not read counties file: "
+ AREA_SUPPRESS_FILENAME, e);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block. Please revise as
// appropriate.
statusHandler.handle(Priority.PROBLEM,
"Failed to find counties file: "
+ AREA_SUPPRESS_FILENAME, e);
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
statusHandler.handle(Priority.PROBLEM,
"Error trying to close buffered reader ", e);
}
}
}
}
}
public String getType(String key) {
if (suppressMap.containsKey(key)) {
return suppressMap.get(key);
} else {
return NONE;
}
}
}

View file

@ -35,8 +35,10 @@ import com.raytheon.uf.common.time.util.TimeUtil;
* ------------ ---------- ----------- --------------------------
* Initial creation
* May 7, 2013 1973 rferrel Changes to properly display Issue Time.
* Jul 22, 2013 2176 jsanchez Added EMER to the display string in the update list.
* Aug 7, 2013 2243 jsanchez Set all the attributes of an AbstractWarningRecord and added an expiration string. Removed calendar object.
* Aug 15,2013 2243 jsanchez Improved the expiration string off by one minute. Fixed for practice mode.
* Aug 15,2013 2243 jsanchez Improved the expiration string off by one minute.
* </pre>
*
* @author rferrel
@ -94,6 +96,9 @@ public class FollowupData extends AbstractWarningRecord {
rval.append(buildExpStr(status, record));
}
if (record.getRawmessage().contains("EMERGENCY")) {
rval.append(" EMER");
}
equvialentString = rval.substring(0,
record.getProductClass().equals("T") ? 20 : 18);

View file

@ -49,6 +49,9 @@ import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.ui.PlatformUI;
import org.geotools.coverage.grid.GeneralGridEnvelope;
import org.geotools.coverage.grid.GeneralGridGeometry;
import org.geotools.geometry.GeneralEnvelope;
import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.GeodeticCalculator;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
@ -57,7 +60,6 @@ import org.opengis.referencing.operation.MathTransform;
import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord;
import com.raytheon.uf.common.dataplugin.warning.WarningRecord.WarningAction;
import com.raytheon.uf.common.dataplugin.warning.config.AreaSourceConfiguration;
import com.raytheon.uf.common.dataplugin.warning.config.AreaSourceConfiguration.AreaType;
import com.raytheon.uf.common.dataplugin.warning.config.BulletActionGroup;
import com.raytheon.uf.common.dataplugin.warning.config.DialogConfiguration;
import com.raytheon.uf.common.dataplugin.warning.config.GridSpacing;
@ -185,6 +187,7 @@ import com.vividsolutions.jts.io.WKTReader;
* 07/26/2013 DR 16376 Qinglu Lin Moved adjustVertex() and computeSlope() to PolygonUtil; removed calculateDistance();
* updated AreaHatcher's run().
* 07/26/2013 DR 16450 D. Friedman Fix logic errors when frame count is one.
* 08/19/2013 2177 jsanchez Set a GeneralGridGeometry object in the GeospatialDataList.
* </pre>
*
* @author mschenke
@ -212,24 +215,28 @@ public class WarngenLayer extends AbstractStormTrackResource {
IExtent localExtent;
int nx, ny;
GeneralGridGeometry localGridGeometry;
}
private static class GeospatialDataAccessor {
GeospatialDataList geoData;
AreaSourceConfiguration areaConfig;
public GeospatialDataAccessor(GeospatialDataList geoData,
AreaSourceConfiguration areaConfig) {
if (geoData == null || areaConfig == null) {
throw new IllegalArgumentException("GeospatialDataAccessor must not be null");
throw new IllegalArgumentException(
"GeospatialDataAccessor must not be null");
}
this.geoData = geoData;
this.areaConfig = areaConfig;
}
/**
* Build the geometry area that intersects the cwa filter for the polygon in
* local projection space
* Build the geometry area that intersects the cwa filter for the
* polygon in local projection space
*
* @param polygon
* polygon to intersect with in lat/lon space
@ -243,8 +250,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
PreparedGeometry prepGeom = (PreparedGeometry) r.attributes
.get(GeospatialDataList.LOCAL_PREP_GEOM);
try {
Geometry intersection = GeometryUtil.intersection(polygon,
prepGeom);
Geometry intersection = GeometryUtil.intersection(
polygon, prepGeom);
if (intersection.isEmpty()) {
continue;
}
@ -407,7 +414,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
}
try {
warningPolygon = PolygonUtil.removeDuplicateCoordinate(warningPolygon);
warningPolygon = PolygonUtil
.removeDuplicateCoordinate(warningPolygon);
Polygon hatched = polygonUtil.hatchWarningArea(
warningPolygon,
removeCounties(warningArea,
@ -425,27 +433,37 @@ public class WarngenLayer extends AbstractStormTrackResource {
LinearRing lr = gf.createLinearRing(coords);
hatchedArea = gf.createPolygon(lr, null);
int adjustPolygon_counter = 0;
while (!hatchedArea.isValid() && adjustPolygon_counter < 1) {
System.out.println("Calling adjustPolygon #" + adjustPolygon_counter);
while (!hatchedArea.isValid()
&& adjustPolygon_counter < 1) {
System.out.println("Calling adjustPolygon #"
+ adjustPolygon_counter);
PolygonUtil.adjustPolygon(coords);
PolygonUtil.round(coords, 2);
coords = PolygonUtil.removeDuplicateCoordinate(coords);
coords = PolygonUtil.removeOverlaidLinesegments(coords);
coords = PolygonUtil
.removeDuplicateCoordinate(coords);
coords = PolygonUtil
.removeOverlaidLinesegments(coords);
lr = gf.createLinearRing(coords);
hatchedArea = gf.createPolygon(lr, null);
adjustPolygon_counter += 1;
}
int counter = 0;
if (!hatchedArea.isValid() && counter < 2) {
System.out.println("calling adjustVertex & alterVertexes: loop #" + counter);
System.out
.println("calling adjustVertex & alterVertexes: loop #"
+ counter);
int adjustVertex_counter = 0;
lr = gf.createLinearRing(coords);
hatchedArea = gf.createPolygon(lr, null);
while (!hatchedArea.isValid() && adjustVertex_counter < 5) {
System.out.println(" Calling adjustVertex #" + adjustVertex_counter);
while (!hatchedArea.isValid()
&& adjustVertex_counter < 5) {
System.out.println(" Calling adjustVertex #"
+ adjustVertex_counter);
coords = PolygonUtil.adjustVertex(coords);
coords = PolygonUtil.removeDuplicateCoordinate(coords);
coords = PolygonUtil.removeOverlaidLinesegments(coords);
coords = PolygonUtil
.removeDuplicateCoordinate(coords);
coords = PolygonUtil
.removeOverlaidLinesegments(coords);
lr = gf.createLinearRing(coords);
hatchedArea = gf.createPolygon(lr, null);
adjustVertex_counter += 1;
@ -453,10 +471,14 @@ public class WarngenLayer extends AbstractStormTrackResource {
int inner_counter = 0;
System.out.println("");
while (!hatchedArea.isValid() && inner_counter < 5) {
System.out.println(" Calling alterVertexes #" + inner_counter);
System.out
.println(" Calling alterVertexes #"
+ inner_counter);
coords = PolygonUtil.alterVertexes(coords);
coords = PolygonUtil.removeDuplicateCoordinate(coords);
coords = PolygonUtil.removeOverlaidLinesegments(coords);
coords = PolygonUtil
.removeDuplicateCoordinate(coords);
coords = PolygonUtil
.removeOverlaidLinesegments(coords);
lr = gf.createLinearRing(coords);
hatchedArea = gf.createPolygon(lr, null);
inner_counter += 1;
@ -674,8 +696,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
displayState.angle = 0;
displayState.speed = 0;
} else if (checkStormTrackData(data = ToolsDataManager
.getInstance()
.getStormTrackData())) {
.getInstance().getStormTrackData())) {
displayState.angle = adjustAngle(data.getMotionDirection());
displayState.speed = knotToMeterPerSec.convert(data
.getMotionSpeed());
@ -995,8 +1016,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
}
if (config != null) {
init(config);
displayState.setInitiallyMotionless(
this.configuration.isTrackEnabled() == false
displayState.setInitiallyMotionless(this.configuration
.isTrackEnabled() == false
|| this.configuration.getPathcastConfig() == null);
}
}
@ -1044,9 +1065,11 @@ public class WarngenLayer extends AbstractStormTrackResource {
+ (System.currentTimeMillis() - t0) + "ms");
}
/** Adds geospatial data to siteMap and timezoneMap for the given
* template configuration. This must not have any site effects on the
* currently loaded template or the current product being edited.
/**
* Adds geospatial data to siteMap and timezoneMap for the given template
* configuration. This must not have any site effects on the currently
* loaded template or the current product being edited.
*
* @param config
*/
private void loadGeodataForConfiguration(WarngenConfiguration config) {
@ -1083,7 +1106,6 @@ public class WarngenLayer extends AbstractStormTrackResource {
Coordinate c = new GeometryFactory()
.buildGeometry(geoms).getCentroid()
.getCoordinate();
gData.latLonToLocal = MapUtil
.getTransformFromLatLon(MapUtil
.constructStereographic(
@ -1146,6 +1168,18 @@ public class WarngenLayer extends AbstractStormTrackResource {
gData.nx = nx;
gData.ny = ny;
GeneralGridEnvelope range = new GeneralGridEnvelope(
new int[] { 0, 0 }, new int[] { gData.nx,
gData.ny }, false);
GeneralEnvelope ge = new GeneralEnvelope(new double[] {
gData.localExtent.getMinX(),
gData.localExtent.getMaxY() }, new double[] {
gData.localExtent.getMaxX(),
gData.localExtent.getMinY() });
gData.localGridGeometry = new GeneralGridGeometry(
range, ge);
System.out.println("Time to lookup geospatial data "
+ (System.currentTimeMillis() - tq0));
siteMap.put(currKey, gData);
@ -1188,6 +1222,14 @@ public class WarngenLayer extends AbstractStormTrackResource {
return new GeospatialData[0];
}
public GeneralGridGeometry getLocalGridGeometry() {
return geoData.localGridGeometry;
}
public MathTransform getlocalToLatLon() {
return geoData.localToLatLon;
}
private GeospatialDataList getGeodataList(String areaSource,
String localizedSite) {
String key = areaSource + "." + localizedSite;
@ -1303,7 +1345,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
* Returns a set of UGCs for each area in the CWA that intersects the given
* polygon.
*/
public Set<String> getUgcsForCountyWatches(Polygon polygon) throws Exception {
public Set<String> getUgcsForCountyWatches(Polygon polygon)
throws Exception {
GeospatialDataAccessor gda = getCountyGeospatialDataAcessor();
Set<String> ugcs = new HashSet<String>();
for (String fips : gda.getAllFipsInArea(gda.buildArea(polygon))) {
@ -1321,17 +1364,20 @@ public class WarngenLayer extends AbstractStormTrackResource {
return ugcs;
}
private GeospatialDataAccessor getCountyGeospatialDataAcessor() throws Exception {
private GeospatialDataAccessor getCountyGeospatialDataAcessor()
throws Exception {
GeospatialDataList gdl = searchCountyGeospatialDataAccessor();
if (gdl == null) {
// Cause county geospatial data to be loaded
// TODO: Should not be referencing tornadoWarning.
WarngenConfiguration torConfig = WarngenConfiguration.loadConfig("tornadoWarning", getLocalizedSite());
WarngenConfiguration torConfig = WarngenConfiguration.loadConfig(
"tornadoWarning", getLocalizedSite());
loadGeodataForConfiguration(torConfig);
gdl = searchCountyGeospatialDataAccessor();
}
// TODO: There should be some way to get the "county" configuration by name
// TODO: There should be some way to get the "county" configuration by
// name
// independent of a template
AreaSourceConfiguration areaConfig = new AreaSourceConfiguration();
areaConfig.setFipsField("FIPS");
@ -1341,7 +1387,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
private GeospatialDataList searchCountyGeospatialDataAccessor() {
synchronized (siteMap) {
for (Map.Entry<String, GeospatialDataList> entry : siteMap.entrySet()) {
for (Map.Entry<String, GeospatialDataList> entry : siteMap
.entrySet()) {
String[] keyParts = entry.getKey().split("\\.");
if (keyParts.length == 2
&& "county".equalsIgnoreCase(keyParts[0])
@ -1938,8 +1985,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
return;
}
if (warningAction == null || warningAction == WarningAction.NEW) {
if ((configuration.isTrackEnabled() == false ||
configuration.getPathcastConfig() == null)
if ((configuration.isTrackEnabled() == false || configuration
.getPathcastConfig() == null)
&& !this.displayState.isNonstationary()
&& this.displayState.displayType != DisplayType.POLY) {
createSquare();
@ -2271,8 +2318,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
}
Point point = displayState.dragMePoint;
if (motdir != null && motspd != null &&
(motspd != 0 || configuration.isTrackEnabled())) {
if (motdir != null && motspd != null
&& (motspd != 0 || configuration.isTrackEnabled())) {
displayState.setInitiallyMotionless(false);
displayState.angle = adjustAngle(motdir);
displayState.speed = knotToMeterPerSec.convert(motspd);
@ -2325,10 +2372,9 @@ public class WarngenLayer extends AbstractStormTrackResource {
if (m.find()) {
int hour = Integer.parseInt(m.group(1));
int minute = Integer.parseInt(m.group(2));
frameTime = TimeUtil.timeOfDayToAbsoluteTime(
hour * TimeUtil.SECONDS_PER_HOUR +
minute * TimeUtil.SECONDS_PER_MINUTE,
warnRecord.getIssueTime());
frameTime = TimeUtil.timeOfDayToAbsoluteTime(hour
* TimeUtil.SECONDS_PER_HOUR + minute
* TimeUtil.SECONDS_PER_MINUTE, warnRecord.getIssueTime());
} else {
frameTime = warnRecord.getIssueTime();
}
@ -2376,8 +2422,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
FramesInfo info = descriptor.getFramesInfo();
int currentFrame = trackUtil.getCurrentFrame(info);
int frameCount = trackUtil.getFrameCount(info);
if (currentFrame == frameCount - 1
|| ! displayState.isNonstationary()) {
if (currentFrame == frameCount - 1 || !displayState.isNonstationary()) {
return coordinate;
}
DataTime[] datatimes = trackUtil.getDataTimes(info);
@ -2686,7 +2731,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
getFips(f));
if (tmp.isEmpty()) {
String fip = getFips(f);
if (fip != null && uniqueFip != null && fip.equals(uniqueFip)) {
if (fip != null && uniqueFip != null
&& fip.equals(uniqueFip)) {
updateWarnedAreas(true);
}
break;
@ -2769,8 +2815,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
if (areaHatcher != null) {
Polygon polygon = state.getWarningPolygon();
polygon = tryToIntersectWithOriginalPolygon(polygon);
areaHatcher.hatchArea(polygon,
state.getWarningArea(),
areaHatcher.hatchArea(polygon, state.getWarningArea(),
state.getOldWarningPolygon());
}
}

View file

@ -98,6 +98,7 @@ import com.raytheon.viz.warngen.gis.Area;
import com.raytheon.viz.warngen.gis.ClosestPointComparator;
import com.raytheon.viz.warngen.gis.GisUtil;
import com.raytheon.viz.warngen.gis.PathCast;
import com.raytheon.viz.warngen.gis.PortionsUtil;
import com.raytheon.viz.warngen.gis.Wx;
import com.raytheon.viz.warngen.gui.BackupData;
import com.raytheon.viz.warngen.gui.FollowupData;
@ -154,6 +155,7 @@ import com.vividsolutions.jts.io.WKTReader;
* May 10, 2013 1951 rjpeter Updated ugcZones references
* May 30, 2013 DR 16237 D. Friedman Fix watch query.
* Jun 18, 2013 2118 njensen Only calculate pathcast if it's actually used
* Aug 19, 2013 2177 jsanchez Passed PortionsUtil to Area class.
* </pre>
*
* @author njensen
@ -301,17 +303,18 @@ public class TemplateRunner {
AffectedAreas[] cancelareas = null;
Map<String, Object> intersectAreas = null;
Wx wx = null;
Area area = new Area(new PortionsUtil(warngenLayer));
long wwaMNDTime = 0l;
try {
t0 = System.currentTimeMillis();
areas = Area.findAffectedAreas(config, warnPolygon, warningArea,
areas = area.findAffectedAreas(config, warnPolygon, warningArea,
threeLetterSiteId);
System.out.println("Time to get areas = "
+ (System.currentTimeMillis() - t0));
context.put(config.getHatchedAreaSource().getVariable(), areas);
t0 = System.currentTimeMillis();
intersectAreas = Area.findInsectingAreas(config, warnPolygon,
intersectAreas = area.findInsectingAreas(config, warnPolygon,
warningArea, threeLetterSiteId, warngenLayer);
System.out.println("Time to get intersecting areas = "
+ (System.currentTimeMillis() - t0));
@ -324,10 +327,11 @@ public class TemplateRunner {
double minSize = 1.0E-3d;
if ((areas != null) && (areas.length > 0)) {
Set<String> timeZones = new HashSet<String>();
for (AffectedAreas area : areas) {
if (area.getTimezone() != null) {
for (AffectedAreas affectedAreas : areas) {
if (affectedAreas.getTimezone() != null) {
// Handles counties that span two time zones
String oneLetterTimeZones = area.getTimezone().trim();
String oneLetterTimeZones = affectedAreas.getTimezone()
.trim();
oneLetterTZ = new String[oneLetterTimeZones.length()];
if (oneLetterTimeZones.length() == 1) {
timeZones.add(String.valueOf(oneLetterTimeZones
@ -799,14 +803,14 @@ public class TemplateRunner {
Geometry removedAreas = warngenLayer.getWarningAreaForGids(
oldGids, oldWarningArea);
if (removedAreas.isEmpty() == false) {
cancelareas = Area.findAffectedAreas(config,
cancelareas = area.findAffectedAreas(config,
oldWarn.getGeometry(), removedAreas,
threeLetterSiteId);
for (int i = 0; i < cancelareas.length; i++) {
for (AffectedAreas area : areas) {
for (AffectedAreas affectedAreas : areas) {
if ((cancelareas[i] != null)
&& cancelareas[i].getFips().equals(
area.getFips())) {
affectedAreas.getFips())) {
cancelareas[i] = null;
}
}
@ -824,7 +828,7 @@ public class TemplateRunner {
// This may not be efficient enough. Is it possible that
// a removed intersected county be in the affected
// intersected county. Need an example to fully test.
Map<String, Object> intersectRemovedAreas = Area
Map<String, Object> intersectRemovedAreas = area
.findInsectingAreas(config, warnPolygon,
removedAreas, threeLetterSiteId,
warngenLayer);

View file

@ -73,6 +73,7 @@ import com.vividsolutions.jts.geom.Geometry;
* May 10, 2013 1951 rjpeter Updated ugcZones references
* May 31, 2013 DR 16264 D. Friedman Fix query in prepare method.
* Jun 05, 2013 DR 16279 D. Friedman Fix updating of issuance time for followups.
* Jul 22, 2013 2176 jsanchez Set the raw message for an EXT.
* Aug 14, 2013 DR 16483 Qinglu Lin Fixed no option issue in WarnGen dropdown menu after
* issuance of an CANCON and restart of CAVE.
* </pre>
@ -314,6 +315,7 @@ public class CurrentWarnings {
if (rval != null) {
rval.setEndTime(warning.getEndTime());
rval.setIssueTime(warning.getIssueTime());
rval.setRawmessage(warning.getRawmessage());
}
}
}

View file

@ -79,6 +79,7 @@ import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory;
* Apr 18, 2013 1877 jsanchez Had the child classes set the comparator. Fixed a null pointer.
* Remove frameAltered condition in matchesFrame. It prevented entries from being displayed.
* Check if geometry is null when inspecting.
* Jul 22, 2013 2176 jsanchez Updated the wire frame and text for EMERGENCY warnings.
* </pre>
*
* @author jsanchez
@ -358,14 +359,23 @@ public abstract class AbstractWWAResource extends
}
if (entry != null && entry.wireframeShape != null) {
LineStyle lineStyle = (record.getProductClass() != null && record
.getProductClass().equals("T")) ? LineStyle.DASHED
: LineStyle.SOLID;
LineStyle lineStyle = LineStyle.SOLID;
if (record.getProductClass() != null
&& record.getProductClass().equals("T")) {
lineStyle = LineStyle.DASHED;
}
int outlineWidth = getCapability(OutlineCapability.class)
.getOutlineWidth();
// Make wire frame outline thicker for EMERGENCY warnings
if (record.getRawmessage().contains("EMERGENCY")) {
outlineWidth *= 2;
}
target.drawWireframeShape(
entry.wireframeShape,
getCapability(ColorableCapability.class).getColor(),
getCapability(OutlineCapability.class)
.getOutlineWidth(), lineStyle);
outlineWidth, lineStyle);
} else if (entry != null && entry.shadedShape != null) {
target.drawShadedShape(entry.shadedShape, 1);
}
@ -409,6 +419,14 @@ public abstract class AbstractWWAResource extends
params.magnification = getCapability(
MagnificationCapability.class).getMagnification();
target.drawStrings(params);
// Draws the string again to have it appear bolder
if (textToPrintReversed[2].endsWith("EMER")) {
params.setText(new String[] { "", "", "EMER", "" },
color);
target.drawStrings(params);
}
}
}
}
@ -581,7 +599,11 @@ public abstract class AbstractWWAResource extends
}
textToPrint[0] += "." + record.getEtn();
textToPrint[1] = record.getPil();
if (record.getRawmessage().contains("EMERGENCY")) {
textToPrint[1] = record.getPil() + " EMER";
} else {
textToPrint[1] = record.getPil();
}
SimpleDateFormat startFormat = DEFAULT_FORMAT;
SimpleDateFormat endFormat = DEFAULT_FORMAT;

View file

@ -0,0 +1,22 @@
#!/bin/bash
# DR #2275 - this script is needd to add the dataURI column back into the
# bufrmosavn and bufrmoshpc tables.
PSQL="/awips2/psql/bin/psql"
${PSQL} -U awips -d metadata -c "ALTER TABLE bufrmosavn ADD COLUMN datauri character varying(255);"
if [ $? -ne 0 ]; then
echo "ERROR: Failed to drop dataURI column for bufrmosavn"
echo "FATAL: The update has failed."
exit 1
fi
${PSQL} -U awips -d metadata -c "ALTER TABLE bufrmoshpc ADD COLUMN datauri character varying(255);"
if [ $? -ne 0 ]; then
echo "ERROR: Failed to add dataURI column for bufrmoshpc"
echo "FATAL: The update has failed."
exit 1
fi
${PSQL} -U awips -d metadata -c "VACUUM FULL ANALYZE bufrmosavn"
${PSQL} -U awips -d metadata -c "VACUUM FULL ANALYZE bufrmoshpc"
echo "INFO: dataURI columns added successfully"

View file

@ -28,6 +28,10 @@
<mkdir dir="${gfesuite.directory}/products/ISC" />
<mkdir dir="${gfesuite.directory}/products/ATBL" />
<!-- Create directories used by Service Backup export_grids script -->
<mkdir dir="${gfesuite.directory}/exportgrids/primary" />
<mkdir dir="${gfesuite.directory}/exportgrids/backup" />
<!-- Adjust GFESuite permissions -->
<chmod perm="ugo+rx">
<fileset dir="${gfesuite.directory}/bin">

View file

@ -19,6 +19,9 @@
**/
package com.raytheon.edex.plugin.bufrmos.common;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
@ -48,6 +51,8 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
* May 07, 2013 1869 bsteffen Remove dataURI column from
* PluginDataObject.
* May 14, 2013 1869 bsteffen Remove DataURI column from bufrmos.
* Aug 19, 2013 2275 bsteffen Add dataURI column back into bufrmos
* types.
*
* </pre>
*
@ -77,4 +82,11 @@ public class BufrMosAvnData extends BufrMosData {
return MOSType.AVN;
}
@Override
@Column
@Access(AccessType.PROPERTY)
public String getDataURI() {
return super.getDataURI();
}
}

View file

@ -19,6 +19,9 @@
**/
package com.raytheon.edex.plugin.bufrmos.common;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
@ -48,6 +51,8 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
* May 07, 2013 1869 bsteffen Remove dataURI column from
* PluginDataObject.
* May 14, 2013 1869 bsteffen Remove DataURI column from bufrmos.
* Aug 19, 2013 2275 bsteffen Add dataURI column back into bufrmos
* types.
*
* </pre>
*
@ -77,4 +82,11 @@ public class BufrMosHpcData extends BufrMosData {
return MOSType.HPC;
}
@Override
@Column
@Access(AccessType.PROPERTY)
public String getDataURI() {
return super.getDataURI();
}
}

View file

@ -58,7 +58,8 @@ import com.raytheon.uf.edex.database.cluster.ClusterTask;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 10/15/10 6644 bphillip Initial Creation
* Oct 15, 2010 6644 bphillip Initial Creation
* Jul 18, 2013 2194 bsteffen Fix site override.
*
* </pre>
*
@ -191,9 +192,8 @@ public class GribLargeFileChecker implements Processor {
File siteModelFile = new File(sitePath);
if (siteModelFile.exists()) {
sitePatterns = loadPatterns(siteModelFile);
} else {
basePatterns = loadPatterns(modelFile);
}
basePatterns = loadPatterns(modelFile);
}

View file

@ -20,6 +20,7 @@
package com.raytheon.uf.common.geospatial;
import org.geotools.coverage.grid.GeneralGridGeometry;
import org.geotools.referencing.CRS;
import org.geotools.referencing.operation.DefaultMathTransformFactory;
import org.geotools.referencing.operation.transform.IdentityTransform;
import org.opengis.referencing.FactoryException;
@ -166,6 +167,27 @@ public class TransformFactory {
return factory.createConcatenatedTransform(mt1, mt2);
}
/**
* Constructs a transform from the "world" CRS of the crs passed in. null
* will be returned if no "world" crs exists.
*
* @param crs
* @return
* @throws FactoryException
*/
public static MathTransform worldToCRS(CoordinateReferenceSystem crs)
throws FactoryException {
CoordinateReferenceSystem worldCRS = crs;
while (worldCRS instanceof GeneralDerivedCRS) {
GeneralDerivedCRS derivedCRS = (GeneralDerivedCRS) worldCRS;
worldCRS = derivedCRS.getBaseCRS();
}
if (worldCRS != crs) {
return CRS.findMathTransform(worldCRS, crs);
}
return null;
}
/**
* Constructs a transform from the "world" CRS of the target geometry to the
* grid of the targetGeometry. Will return crsToGrid if no "world" CRS
@ -178,23 +200,19 @@ public class TransformFactory {
*/
public static MathTransform worldToGrid(GeneralGridGeometry targetGeometry,
PixelInCell cellType) throws FactoryException {
CoordinateReferenceSystem crs = targetGeometry.getEnvelope()
.getCoordinateReferenceSystem();
try {
if (crs instanceof GeneralDerivedCRS) {
GeneralDerivedCRS projCRS = (GeneralDerivedCRS) crs;
CoordinateReferenceSystem worldCRS = projCRS.getBaseCRS();
MathTransform worldToCRS = CRSCache.getInstance()
.findMathTransform(worldCRS, crs);
MathTransform crsToPixel = targetGeometry
.getGridToCRS(cellType).inverse();
return factory.createConcatenatedTransform(worldToCRS,
crsToPixel);
} else {
// No associated "world" CRS, go straight crs to grid
return targetGeometry.getGridToCRS(cellType).inverse();
CoordinateReferenceSystem crs = targetGeometry.getEnvelope()
.getCoordinateReferenceSystem();
MathTransform worldToCRS = worldToCRS(crs);
MathTransform worldToGrid = targetGeometry.getGridToCRS(cellType)
.inverse();
if (worldToCRS != null) {
worldToGrid = factory.createConcatenatedTransform(worldToCRS,
worldToGrid);
}
return worldToGrid;
} catch (FactoryException e) {
throw e;
} catch (Exception e) {
throw new FactoryException(e);
}

View file

@ -45,6 +45,7 @@ import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.JAXBContextBuilder;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Sep 12, 2011 mschenke Initial creation
* June 24, 2013 #2126 bkowal Update for Java 7 compatibility
*
* </pre>
*
@ -54,6 +55,7 @@ import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.JAXBContextBuilder;
public class SerializationContextFactory {
@SuppressWarnings("rawtypes")
public static JAXBContext createContext(Class[] classes, Map props) {
// Construct delegate implementation
System.setProperty(JAXBContextImpl.class.getName() + ".fastBoot",
@ -68,7 +70,7 @@ public class SerializationContextFactory {
// TODO: Can we override/extend some part of the context
// implementation to allow for ignoring of xsi:type fields that we
// don't have classes for?
return new CustomJAXBContext(new JAXBContextImpl(builder));
return new CustomJAXBContext(builder.build());
} catch (JAXBException e) {
throw new RuntimeException(e);
}

View file

@ -10,6 +10,9 @@
# 04/29/13 #1761 dgilling Remove use of NATIONAL_CENTER,
# script caller will determine
# which sites to export.
# 05/16/13 #2009 dgilling New backup structure:
# PRIMARY_SITES go to exportgrids/primary/
# and all other go to exportgrids/backup/.
##############################################################################
if [ ${#AWIPS_HOME} = 0 ]
@ -114,9 +117,30 @@ else
fi
$LOGGER ${DB_NAME}
# use PRIMARY_SITES setting to determine NETCDF_PATH
IFS=',' read -ra PRI_SITES <<< "${PRIMARY_SITES}"
if [ ${#PRI_SITES[@]} -eq 0 ]
then
declare -a PRI_SITES=( "${AW_SITE_IDENTIFIER}" )
fi
EXPORT_FOR_PRIMARY=0
for primary_site in "${PRI_SITES[@]}"
do
primary_site=`echo $primary_site | tr [a-z] [A-Z]`
if [ "$primary_site" = "${CAPS_SITE}" ]
then
EXPORT_FOR_PRIMARY=1
break
fi
done
NETCDF_PATH=${GFESUITE_HOME}/exportgrids/primary
export NETCDF_TMP_PATH=/tmp/exportgrids
if [ $EXPORT_FOR_PRIMARY = 0 ]
then
NETCDF_PATH=${GFESUITE_HOME}/exportgrids/backup
fi
NETCDF_PATH=${GFESUITE_HOME}/exportgrids
export NETCDF_TMP_PATH=${NETCDF_PATH}/tmp
if [ ! -d ${NETCDF_TMP_PATH} ]; then
mkdir ${NETCDF_TMP_PATH}
chmod 777 ${NETCDF_TMP_PATH}

Binary file not shown.

View file

@ -24,30 +24,14 @@
<Directory Id="ProgramFilesFolder" Name="PFiles">
<Directory Id="INSTALLDIR" Name="Raytheon">
<Directory Id="AwipsII" Name="AWIPS II">
<Directory Id="CaveDir" Name="CAVE">
<Component Id="caveBatch" Guid="8924277C-5B6A-4EEB-AE9F-5471481F92A6">
<File Id="caveBAT" Name="cave.bat"
DiskId="1" Source="SourceDir\CAVE\cave.bat" />
<Shortcut Id="caveDesktopShortcut" Directory="DesktopFolder" Name="CAVE"
WorkingDirectory="CaveDir" Advertise="yes" Icon="cave.exe" IconIndex="0"
Arguments="-component thinclient" />
<Shortcut Id="caveStartMenu" Directory="ProgramMenuDir" Name="CAVE"
WorkingDirectory="CaveDir" Advertise="yes" Icon="cave.exe" IconIndex="0"
Arguments="-component thinclient" />
<Component Id="VizLauncherExe" Guid="8924277C-5B6A-4EEB-AE9F-5471481F92A6">
<File Id="VizLauncherExe" Name="VizLauncher.exe"
DiskId="1" Source="SourceDir\VizLauncher.exe" />
<Shortcut Id="vizLauncherDesktopShortcut" Directory="DesktopFolder" Name="Viz Launcher"
WorkingDirectory="SourceDir" Advertise="yes" Icon="cave.exe" IconIndex="0" />
<Shortcut Id="vizLauncherStartMenu" Directory="ProgramMenuDir" Name="Viz Launcher"
WorkingDirectory="SourceDir" Advertise="yes" Icon="cave.exe" IconIndex="0" />
</Component>
</Directory>
<Directory Id="AlertvizDir" Name="AlertViz">
<Component Id="alertvizBatch" Guid="8924277C-5B6A-4EEB-AE9F-5471481F92B4">
<File Id="alertvizBAT" Name="alertviz.bat"
DiskId="1" Source="SourceDir\AlertViz\alertviz.bat" />
<Shortcut Id="alertvizDesktopShortcut" Directory="DesktopFolder" Name="AlertViz"
WorkingDirectory="AlertvizDir" Advertise="yes" Icon="alertviz.exe" IconIndex="0"
Arguments="-component thinalertviz" />
<Shortcut Id="alertvizStartMenu" Directory="ProgramMenuDir" Name="AlertViz"
WorkingDirectory="AlertvizDir" Advertise="yes" Icon="alertviz.exe" IconIndex="0"
Arguments="-component thinalertviz" />
</Component>
</Directory>
</Directory>
</Directory>
@ -71,7 +55,6 @@
<Feature Id="AWIPS_II_CAVE" Title="AWIPS II CAVE" Level="1"
Display="expand" Description="AWIPS II Common AWIPS Visualization Environment (CAVE)"
ConfigurableDirectory="INSTALLDIR">
<ComponentRef Id="caveBatch" />
<ComponentRef Id="ProgramMenuDir" />
<ComponentGroupRef Id="AWIPSII_CAVE" />
@ -80,16 +63,20 @@
<Feature Id="AWIPS_II_ALERTVIZ" Title="AWIPS II AlertViz" Level="1"
Display="expand" Description="AWIPS II AlertViz"
ConfigurableDirectory="INSTALLDIR">
<ComponentRef Id="alertvizBatch" />
<ComponentGroupRef Id="AWIPSII_ALERTVIZ" />
</Feature>
<Feature Id="AWIPS_II_LAUNCHER" Title="AWIPS II Viz Launcher" Level="1"
Display="expand" Description="Viz Launcher - Starts both AlertViz and CAVE"
ConfigurableDirectory="INSTALLDIR">
<ComponentRef Id="VizLauncherExe" />
</Feature>
<UIRef Id="WixUI_FeatureTree" />
<UIRef Id="WixUI_ErrorProgressText" />
<Icon Id="cave.exe" SourceFile="SourceDir\CAVE\cave.exe" />
<Icon Id="alertviz.exe" SourceFile="SourceDir\AlertViz\alertviz.exe" />
</Product>
</Wix>

View file

@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual C# Express 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VizLauncher", "VizLauncher\VizLauncher.csproj", "{45B15612-0725-479C-8E1B-9B63F2FB45A3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{45B15612-0725-479C-8E1B-9B63F2FB45A3}.Debug|x86.ActiveCfg = Debug|x86
{45B15612-0725-479C-8E1B-9B63F2FB45A3}.Debug|x86.Build.0 = Debug|x86
{45B15612-0725-479C-8E1B-9B63F2FB45A3}.Release|x86.ActiveCfg = Release|x86
{45B15612-0725-479C-8E1B-9B63F2FB45A3}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

Binary file not shown.

View file

@ -0,0 +1,79 @@
namespace VizLauncher
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.lblFailureDetail = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// label1
//
this.label1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(128)))), ((int)(((byte)(128)))));
this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 18F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label1.Location = new System.Drawing.Point(12, 0);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(337, 50);
this.label1.TabIndex = 0;
this.label1.Text = "Failed to Start AWIPS II Viz!";
this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// lblFailureDetail
//
this.lblFailureDetail.BackColor = System.Drawing.Color.White;
this.lblFailureDetail.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.lblFailureDetail.Location = new System.Drawing.Point(14, 59);
this.lblFailureDetail.Name = "lblFailureDetail";
this.lblFailureDetail.Size = new System.Drawing.Size(335, 119);
this.lblFailureDetail.TabIndex = 1;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(361, 187);
this.Controls.Add(this.lblFailureDetail);
this.Controls.Add(this.label1);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "Form1";
this.ShowInTaskbar = false;
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Viz Launcher";
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label lblFailureDetail;
}
}

View file

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace VizLauncher
{
public partial class Form1 : Form
{
public Form1(String errorText)
{
InitializeComponent();
this.lblFailureDetail.Text = errorText;
}
}
}

View file

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View file

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using VizLauncher.com.raytheon.viz.launcher;
namespace VizLauncher
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
VizLauncher.com.raytheon.viz.launcher.VizLauncher vizLauncher =
new VizLauncher.com.raytheon.viz.launcher.VizLauncher();
bool success = vizLauncher.run(Application.StartupPath);
if (success == false)
{
// Display the "Failure" dialog.
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1(vizLauncher.getErrorDetail()));
}
Application.Exit();
}
}
}

View file

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("VizLauncher")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("VizLauncher")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("7f929b46-b56e-47eb-b6e6-ff79e54f6572")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View file

@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.17929
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace VizLauncher.Properties
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("VizLauncher.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

View file

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View file

@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.17929
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace VizLauncher.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
return defaultInstance;
}
}
}
}

View file

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View file

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{45B15612-0725-479C-8E1B-9B63F2FB45A3}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>VizLauncher</RootNamespace>
<AssemblyName>VizLauncher</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="com\raytheon\viz\launcher\environment\EnvironmentProperties.cs" />
<Compile Include="com\raytheon\viz\launcher\environment\VizEnvironment.cs" />
<Compile Include="com\raytheon\viz\launcher\process\AbstractProcessLauncher.cs" />
<Compile Include="com\raytheon\viz\launcher\process\impl\AlertvizProcessLauncher.cs" />
<Compile Include="com\raytheon\viz\launcher\process\impl\CaveProcessLauncher.cs" />
<Compile Include="com\raytheon\viz\launcher\process\IProcessLauncher.cs" />
<Compile Include="com\raytheon\viz\launcher\VizLauncher.cs" />
<Compile Include="Form1.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form1.Designer.cs">
<DependentUpon>Form1.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="Form1.resx">
<DependentUpon>Form1.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View file

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
</Project>

View file

@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using VizLauncher.com.raytheon.viz.launcher.environment;
using VizLauncher.com.raytheon.viz.launcher.process;
using VizLauncher.com.raytheon.viz.launcher.process.impl;
namespace VizLauncher.com.raytheon.viz.launcher
{
public class VizLauncher
{
private String errorDetail;
public bool run(String location)
{
VizEnvironment vizEnvironment = new VizEnvironment(location);
if (vizEnvironment.isReady() == false)
{
this.errorDetail = vizEnvironment.getExceptionText();
return false;
}
/* Alternatively, we would be able to construct both process launchers using Spring and inject them. */
// Construct the AlertViz Process Launcher.
IProcessLauncher alertvizProcessLauncher = new AlertvizProcessLauncher(vizEnvironment);
if (alertvizProcessLauncher.isReady() == false)
{
this.errorDetail = alertvizProcessLauncher.getExceptionText();
return false;
}
Thread alertvizThread = new Thread(alertvizProcessLauncher.launchProcess);
// Construct the CAVE Process Launcher.
IProcessLauncher caveProcessLauncher = new CaveProcessLauncher(vizEnvironment);
if (caveProcessLauncher.isReady() == false)
{
this.errorDetail = caveProcessLauncher.getExceptionText();
return false;
}
Thread caveThread = new Thread(caveProcessLauncher.launchProcess);
// Start AlertViz.
alertvizThread.Start();
// Delay - Give Alertviz Time To Start.
Thread.Sleep(1000);
// Start CAVE.
caveThread.Start();
// Wait for CAVE.
caveThread.Join();
// Wait for AlertViz.
alertvizThread.Join();
return true;
}
public String getErrorDetail()
{
return this.errorDetail;
}
}
}

View file

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace VizLauncher.com.raytheon.viz.launcher.environment
{
public abstract class EnvironmentProperties
{
/* Environment Properties */
public static readonly String USER_HOME_ENV_PROPERTY = "%HOMEDRIVE%%HOMEPATH%";
public static readonly String COMPUTER_NAME_ENV_PROPERTY = "%COMPUTERNAME%";
/* Registry Constants */
public static readonly String A2_JAVA_REG = @"Software\Raytheon\Runtime Environment\AWIPS II Java";
public static readonly String A2_PYTHON_REG = @"Software\Raytheon\Runtime Environment\AWIPS II Python";
public static readonly String JAVA_JRE_VALUE_NAME = "JavaJreDirectory";
public static readonly String PYTHON_INSTALL_NAME = "PythonInstallDirectory";
/* Environment Additions */
public static readonly String ENVIRONMENT_VARIABLE_PATH = "Path";
public static readonly String ENVIRONMENT_VARIABLE_PYTHON_PATH = "PythonPath";
public static readonly String PATH_PYTHON_DLLS = Path.DirectorySeparatorChar + "DLLs";
public static readonly String PATH_JAVA_BIN = Path.DirectorySeparatorChar + "bin";
public static readonly String PYTHON_PATH_PYTHON_LIBTK =
Path.DirectorySeparatorChar + "Lib" + Path.DirectorySeparatorChar + "lib-tk";
public static readonly String PYTHON_PATH_PYTHON_DLLS = Path.DirectorySeparatorChar + "DLLs";
public static readonly String PYTHON_PATH_PYTHON_LIB = Path.DirectorySeparatorChar + "Lib";
}
}

View file

@ -0,0 +1,137 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Microsoft.Win32;
namespace VizLauncher.com.raytheon.viz.launcher.environment
{
public class VizEnvironment
{
private static readonly String CONSOLE_LOGS_DIRECTORY =
Path.DirectorySeparatorChar + "caveData" + Path.DirectorySeparatorChar +
"logs" + Path.DirectorySeparatorChar + "consoleLogs";
private String location;
private String logDirectory = null;
private String path = null;
private String pythonPath = null;
// did an error occur while initializing this object?
private bool ready;
// details about the error that has occurred.
private String exceptionText;
public VizEnvironment(String location)
{
this.location = location;
this.init();
}
private void init()
{
/* For now we will assume that the environment properties will be available */
// determine the location of the user's "home" directory.
String homeDirectory =
this.resolveEnvironmentProperty(EnvironmentProperties.USER_HOME_ENV_PROPERTY);
// determine the computer name.
String computerName =
this.resolveEnvironmentProperty(EnvironmentProperties.COMPUTER_NAME_ENV_PROPERTY);
// construct the path to the log directory.
this.logDirectory = homeDirectory + CONSOLE_LOGS_DIRECTORY +
Path.DirectorySeparatorChar + computerName;
// retrieve the jdk directory from the registry.
String jdkDirectory =
this.retrieveRegistryProperty(EnvironmentProperties.A2_JAVA_REG,
EnvironmentProperties.JAVA_JRE_VALUE_NAME);
if (jdkDirectory == null)
{
this.notReady("Unable to retrieve the Java JDK Path from the registry!");
return;
}
// retrieve the python location from the registry.
String pythonLocation =
this.retrieveRegistryProperty(EnvironmentProperties.A2_PYTHON_REG,
EnvironmentProperties.PYTHON_INSTALL_NAME);
if (pythonLocation == null)
{
this.notReady("Unable to retrieve the Python Install Location from the registry!");
return;
}
// Construct the PATH.
this.path = pythonLocation + Path.PathSeparator;
this.path += pythonLocation + EnvironmentProperties.PATH_PYTHON_DLLS + Path.PathSeparator;
this.path += jdkDirectory + EnvironmentProperties.PATH_JAVA_BIN;
// Construct the PYTHON_PATH.
this.pythonPath = pythonLocation + EnvironmentProperties.PYTHON_PATH_PYTHON_LIBTK + Path.PathSeparator;
this.pythonPath += pythonLocation + EnvironmentProperties.PYTHON_PATH_PYTHON_DLLS + Path.PathSeparator;
this.pythonPath += pythonLocation + EnvironmentProperties.PYTHON_PATH_PYTHON_LIB + Path.PathSeparator;
this.pythonPath += pythonLocation;
this.ready = true;
}
private String resolveEnvironmentProperty(String property)
{
return Environment.ExpandEnvironmentVariables(property);
}
private String retrieveRegistryProperty(String registryKeyName, String valueName)
{
RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(registryKeyName);
if (registryKey == null)
{
return null;
}
Object registryValue = registryKey.GetValue(valueName, null);
if (registryValue == null)
{
return null;
}
return registryValue.ToString();
}
private void notReady(String reason)
{
this.ready = false;
this.exceptionText = reason;
}
public String getLocation()
{
return this.location;
}
public String getLogDirectory()
{
return this.logDirectory;
}
public String getPath()
{
return this.path;
}
public String getPythonPath()
{
return this.pythonPath;
}
public bool isReady()
{
return this.ready;
}
public String getExceptionText()
{
return this.exceptionText;
}
}
}

View file

@ -0,0 +1,129 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using VizLauncher.com.raytheon.viz.launcher.environment;
namespace VizLauncher.com.raytheon.viz.launcher.process
{
public abstract class AbstractProcessLauncher : IProcessLauncher
{
private static readonly String LOG_DATE_FORMAT = "yyyyMMdd_HHmmss";
protected static readonly String LOG_SUFFIX = ".log";
protected Process process = null;
private StreamWriter logFileWriter;
private bool ready = false;
private String exceptionText = null;
public AbstractProcessLauncher(VizEnvironment vizEnvironment)
{
// Prepare the log file.
if (Directory.Exists(vizEnvironment.getLogDirectory()) == false)
{
Directory.CreateDirectory(vizEnvironment.getLogDirectory());
}
String logName = vizEnvironment.getLogDirectory() +
Path.DirectorySeparatorChar + this.constructLogName(this.determineLogDate());
// Prepare the process.
this.process = new Process();
this.process.StartInfo = this.constructProcessStartInfo(vizEnvironment);
this.process.OutputDataReceived += new DataReceivedEventHandler(processOutputHandler);
this.validate();
if (this.ready == false)
{
return;
}
/*
* Access the log file for write access; other processes will have read-only access to
* the log file until it is closed.
**/
this.logFileWriter =
new StreamWriter(File.Open(logName, FileMode.Append,
FileAccess.Write, FileShare.Read));
}
private String determineLogDate()
{
return DateTime.Now.ToString(LOG_DATE_FORMAT);
}
private ProcessStartInfo constructProcessStartInfo(VizEnvironment vizEnvironment)
{
ProcessStartInfo processStartInfo =
new ProcessStartInfo(this.constructProcessName(vizEnvironment.getLocation()));
processStartInfo.EnvironmentVariables.Remove(EnvironmentProperties.ENVIRONMENT_VARIABLE_PATH);
processStartInfo.EnvironmentVariables.Add(
EnvironmentProperties.ENVIRONMENT_VARIABLE_PATH, vizEnvironment.getPath());
processStartInfo.EnvironmentVariables.Add(
EnvironmentProperties.ENVIRONMENT_VARIABLE_PYTHON_PATH, vizEnvironment.getPythonPath());
processStartInfo.UseShellExecute = false;
processStartInfo.Arguments = this.getCommandLineArguments();
processStartInfo.RedirectStandardOutput = true;
return processStartInfo;
}
protected void validate()
{
String application = this.process.StartInfo.FileName;
/* ensure that the specified application exists. */
if (File.Exists(application) == false)
{
this.ready = false;
this.exceptionText = "Unable to find the specified Viz application: " + application;
return;
}
this.ready = true;
}
public virtual void launchProcess()
{
this.runProcess();
this.closeLog();
}
protected void runProcess()
{
this.process.Start();
this.process.BeginOutputReadLine();
this.process.WaitForExit();
this.process.CancelOutputRead();
}
protected void closeLog()
{
this.logFileWriter.Close();
}
private void processOutputHandler(Object sendingProcess, DataReceivedEventArgs outline)
{
if (String.IsNullOrEmpty(outline.Data))
{
return;
}
this.logFileWriter.WriteLine(outline.Data);
}
public bool isReady()
{
return this.ready;
}
public String getExceptionText()
{
return this.exceptionText;
}
protected abstract String constructProcessName(String location);
protected abstract String constructLogName(String logDate);
protected abstract String getCommandLineArguments();
}
}

View file

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace VizLauncher.com.raytheon.viz.launcher.process
{
public interface IProcessLauncher
{
void launchProcess();
bool isReady();
String getExceptionText();
}
}

View file

@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO;
using VizLauncher.com.raytheon.viz.launcher.process;
using VizLauncher.com.raytheon.viz.launcher.environment;
namespace VizLauncher.com.raytheon.viz.launcher.process.impl
{
public class AlertvizProcessLauncher : AbstractProcessLauncher
{
private static readonly String LOG_PREFIX = "alertviz_";
private static readonly String COMMAND_LINE_ARGUMENTS = "-component thinalertviz";
private static readonly String ALERTVIZ_PROCESS_NAME = "alertviz";
private static readonly String ALERTVIZ_EXECUTABLE =
Path.DirectorySeparatorChar + "AlertViz" +
Path.DirectorySeparatorChar + "alertviz.exe";
public AlertvizProcessLauncher(VizEnvironment vizEnvironment) : base(vizEnvironment)
{
}
public override void launchProcess()
{
// need to verify that another AlertViz process is not already running.
if (this.isAlertVizAlreadyRunning())
{
// do not start a new AlertViz process.
return;
}
this.runProcess();
while (this.process.ExitCode != 0)
{
this.runProcess();
}
this.closeLog();
}
private Boolean isAlertVizAlreadyRunning()
{
return (Process.GetProcessesByName(ALERTVIZ_PROCESS_NAME).Length > 0);
}
protected override String constructProcessName(String location)
{
return location + ALERTVIZ_EXECUTABLE;
}
protected override String constructLogName(String logDate)
{
return LOG_PREFIX + logDate + AbstractProcessLauncher.LOG_SUFFIX;
}
protected override String getCommandLineArguments()
{
return COMMAND_LINE_ARGUMENTS;
}
}
}

View file

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using VizLauncher.com.raytheon.viz.launcher.process;
using VizLauncher.com.raytheon.viz.launcher.environment;
namespace VizLauncher.com.raytheon.viz.launcher.process.impl
{
public class CaveProcessLauncher : AbstractProcessLauncher
{
private static readonly String LOG_PREFIX = "cave_";
private static readonly String COMMAND_LINE_ARGUMENTS = "-component thinclient";
private static readonly String CAVE_EXECUTABLE =
Path.DirectorySeparatorChar + "CAVE" + Path.DirectorySeparatorChar + "cave.exe";
public CaveProcessLauncher(VizEnvironment vizEnvironment)
: base(vizEnvironment)
{
}
protected override String constructProcessName(String location)
{
return location + CAVE_EXECUTABLE;
}
protected override String constructLogName(String logDate)
{
return LOG_PREFIX + logDate + AbstractProcessLauncher.LOG_SUFFIX;
}
protected override String getCommandLineArguments()
{
return COMMAND_LINE_ARGUMENTS;
}
}
}

Binary file not shown.

View file

@ -24,7 +24,6 @@ Export-Package: gov.noaa.nws.ncep.viz.common,
gov.noaa.nws.ncep.viz.common.customprojection,
gov.noaa.nws.ncep.viz.common.dbQuery,
gov.noaa.nws.ncep.viz.common.display,
gov.noaa.nws.ncep.viz.common.gpdQuery,
gov.noaa.nws.ncep.viz.common.graphicUtil,
gov.noaa.nws.ncep.viz.common.preferences,
gov.noaa.nws.ncep.viz.common.soundingQuery,
@ -35,7 +34,5 @@ Import-Package: com.raytheon.uf.common.comm,
com.raytheon.uf.common.parameter,
com.raytheon.viz.pointdata,
com.vividsolutions.jts.geom,
gov.noaa.nws.ncep.common.dataplugin.gpd.product,
gov.noaa.nws.ncep.common.dataplugin.gpd.query,
javax.measure.unit

View file

@ -58,11 +58,11 @@ if [ ${RC} -ne 0 ]; then
fi
# Create additional directories that are required.
mkdir -p ${RPM_BUILD_ROOT}/awips2/GFESuite/exportgrids/tmp
mkdir -p ${RPM_BUILD_ROOT}/awips2/GFESuite/exportgrids/primary
if [ $? -ne 0 ]; then
exit 1
fi
mkdir -p ${RPM_BUILD_ROOT}/awips2/GFESuite/exportgrids2
mkdir -p ${RPM_BUILD_ROOT}/awips2/GFESuite/exportgrids/backup
if [ $? -ne 0 ]; then
exit 1
fi
@ -97,7 +97,6 @@ rm -rf ${RPM_BUILD_ROOT}
/awips2/GFESuite/bin/src/*
%dir /awips2/GFESuite/exportgrids
/awips2/GFESuite/exportgrids/*
%dir /awips2/GFESuite/exportgrids2
%defattr(644,awips,fxalpha,775)
%dir /awips2/GFESuite/products
/awips2/GFESuite/products/*

View file

@ -58,11 +58,11 @@ if [ ${RC} -ne 0 ]; then
fi
# Create additional directories that are required.
mkdir -p ${RPM_BUILD_ROOT}/awips2/GFESuite/exportgrids/tmp
mkdir -p ${RPM_BUILD_ROOT}/awips2/GFESuite/exportgrids/primary
if [ $? -ne 0 ]; then
exit 1
fi
mkdir -p ${RPM_BUILD_ROOT}/awips2/GFESuite/exportgrids2
mkdir -p ${RPM_BUILD_ROOT}/awips2/GFESuite/exportgrids/backup
if [ $? -ne 0 ]; then
exit 1
fi
@ -97,7 +97,6 @@ rm -rf ${RPM_BUILD_ROOT}
/awips2/GFESuite/bin/src/*
%dir /awips2/GFESuite/exportgrids
/awips2/GFESuite/exportgrids/*
%dir /awips2/GFESuite/exportgrids2
%defattr(755,awips,fxalpha,777)
%dir /awips2/GFESuite/ServiceBackup/scripts
/awips2/GFESuite/ServiceBackup/scripts/*

View file

@ -348,7 +348,7 @@ fi
if [ "${1}" = "-viz" ]; then
buildRPM "awips2"
# buildRPM "awips2-common-base"
buildRPM "awips2-common-base"
# buildRPM "awips2-rcm"
# buildRPM "awips2-hydroapps-shared"
# buildRPM "awips2-notification"
@ -366,11 +366,11 @@ if [ "${1}" = "-edex" ]; then
#buildRPM "awips2-common-base"
# buildRPM "awips2-adapt-native"
#buildRPM "awips2-python-qpid"
buildRPM "awips2-cli"
# buildRPM "awips2-gfesuite-client"
# buildRPM "awips2-gfesuite-server"
buildRPM "awips2-ncep-database"
buildRPM "awips2-python-dynamicserialize"
# buildRPM "awips2-cli"
buildRPM "awips2-gfesuite-client"
buildRPM "awips2-gfesuite-server"
# buildRPM "awips2-ncep-database"
# buildRPM "awips2-python-dynamicserialize"
buildEDEX
if [ $? -ne 0 ]; then
exit 1