From 57393984d300532ab07dff3238575e91d0fd1d60 Mon Sep 17 00:00:00 2001 From: Stephen Gilbert Date: Mon, 1 Dec 2014 17:17:39 -0500 Subject: [PATCH] VLab Issue #4003 - Mostly PGEN bug fixes minor updates to nsharp, lat/lon overlay, ntrans, and plotdata resource Change-Id: I2a1718ed7674edb786bceec13bcb20c29cc5d616 Former-commit-id: 8bdc663629050457b23d06c19bd7a925597c1288 --- .../parameters/core/contourinterval/CINT.java | 49 +- .../display/rsc/NsharpResourceHandler.java | 7 +- .../ui/nsharp/view/NsharpPaletteWindow.java | 51 +- .../localization/ncep/pgen/settings_tbl.xml | 2 +- .../pgen/settings_tbl_Surface_Analysis.xml | 2 +- .../pgen/xslt/airmet/get_attention_line.xsl | 5 +- .../ncep/pgen/xslt/airmet/get_status.xsl | 17 +- .../ncep/pgen/xslt/airmet/output_outlook.xsl | 7 +- .../nws/ncep/ui/pgen/attrdialog/AttrDlg.java | 22 +- .../ui/pgen/attrdialog/ContoursAttrDlg.java | 124 +- .../ui/pgen/attrdialog/GfaFormatAttrDlg.java | 16 +- .../ncep/ui/pgen/attrdialog/TrackAttrDlg.java | 2241 ++++++------ .../pgen/display/DefaultElementContainer.java | 21 +- .../pgen/display/DisplayElementFactory.java | 35 +- .../noaa/nws/ncep/ui/pgen/display/ITrack.java | 218 +- .../pgen/display/RasterElementContainer.java | 118 +- .../ui/pgen/display/TextDisplayElement.java | 35 +- .../noaa/nws/ncep/ui/pgen/elements/Track.java | 2300 ++++++------ .../ncep/ui/pgen/file/ProductConverter.java | 13 +- .../gov/noaa/nws/ncep/ui/pgen/file/Track.java | 311 +- .../nws/ncep/ui/pgen/file/TrackConverter.java | 691 ++-- .../noaa/nws/ncep/ui/pgen/file/product.xsd | 49 +- .../nws/ncep/ui/pgen/gfa/GfaGenerate.java | 812 ++--- .../noaa/nws/ncep/ui/pgen/gfa/GfaInfo.java | 715 ++-- .../noaa/nws/ncep/ui/pgen/gfa/GfaRules.java | 3156 +++++++++-------- .../layering/PgenLayeringControlDialog.java | 1218 +++---- .../productmanage/ProductManageDialog.java | 41 +- .../pgen/productmanage/ProductNameDialog.java | 883 ++--- .../nws/ncep/ui/pgen/rsc/PgenResource.java | 11 +- .../ncep/ui/pgen/rsc/PgenResourceGhost.java | 61 +- .../ncep/ui/pgen/tools/PgenContoursTool.java | 1 + .../resources/LatLonOverlayResource.java | 388 +- .../ui/createRbd/NtransSelectionControl.java | 18 + .../attributes/ResourceExtPointMngr.java | 663 ++-- .../ncep/viz/rsc/ncgrid/dgdriv/Dgdriv.java | 94 +- .../nws/ncep/viz/rsc/ntrans/ncgm/README.txt | 28 + .../NcPlotModelHdf5DataRequestor.java | 2 +- 37 files changed, 7515 insertions(+), 6910 deletions(-) create mode 100644 ncep/gov.noaa.nws.ncep.viz.rsc.ntrans/src/gov/noaa/nws/ncep/viz/rsc/ntrans/ncgm/README.txt diff --git a/ncep/gov.noaa.nws.ncep.gempak.parameters.core/src/gov/noaa/nws/ncep/gempak/parameters/core/contourinterval/CINT.java b/ncep/gov.noaa.nws.ncep.gempak.parameters.core/src/gov/noaa/nws/ncep/gempak/parameters/core/contourinterval/CINT.java index 25e950d299..7472b4e3d8 100644 --- a/ncep/gov.noaa.nws.ncep.gempak.parameters.core/src/gov/noaa/nws/ncep/gempak/parameters/core/contourinterval/CINT.java +++ b/ncep/gov.noaa.nws.ncep.gempak.parameters.core/src/gov/noaa/nws/ncep/gempak/parameters/core/contourinterval/CINT.java @@ -47,7 +47,7 @@ import java.util.Set; * 17-May-2011 M. Li Created a parseCINT to simplify CINT parsing. * 07-Apr-2014 TTR-938 D.Sushon Added check for null string to constructor, fixing NullPointerException * thrown when attempting to initialize with null String. - * + * 09-Sep-2014 TTR-852 A.Yuk remove restriction of contour lines =50 and make it unlimited contour lines. * * * @@ -56,7 +56,7 @@ import java.util.Set; * @see $GEMPAK/help/hlx/cint.hl2 */ public class CINT { - + /** The object responsible for parsing the CINT string */ private ContourStringParser cintParser; @@ -396,20 +396,44 @@ public class CINT { if (interval == null || interval.isNaN()) { interval = (cmax - cmin) / 10.0; } - - // Only allow less than 50 contour levels - if ((cmax - cmin) / interval > 50) - interval = (cmax - cmin) / 50; - - // System.out.println(" cmax=="+cmax); + +// Only allow less than 50 contour levels : +// comment out contour restriction. : IT WAs BAD Code to generate decimal point on contour labels. + /* if ((cmax - cmin) / interval > 50) { + interval = (cmax - cmin) / 50; + interval =(double) (int) ((cmax - cmin)/50) ; } + */ contourInfo = new CINT(interval.toString() + "/" + cmin.toString() + "/" + cmax.toString()); cvalues = contourInfo - .getUniqueSortedContourValuesFromAllZoomLevels(); + .getUniqueSortedContourValuesFromAllZoomLevels(); + } + } + +/******************************** + int csize=cvalues.size(); + System.out.println(" ................."); + System.out.println(" ................."); + System.out.println(" Contour level range is from "+cvalues.get(0)+" to "+cvalues.get(csize-1)+"."); + System.out.println(" Contour interval "+interval+"."); + System.out.println(" ................."); + System.out.println(" ................."); +// * capped contour lines to 50 + if (csize > 50) { + System.out.println(" !!! Pay attention to CONTOUR INTERVAL."); + System.out.println(" Contour lines from "+cvalues.get(0)+" to "+cvalues.get(csize-1)+" are eliminated due to maximum contour allowance." ); + while (cvalues.size()>50){cvalues.remove(50);} + System.out.println(" !!! Contours are being plotted to the first 50th lines."); + System.out.println(" Range of contour lines drawn is from "+cvalues.get(0)+" to "+cvalues.get(49)+"."); + System.out.println(" !!! Contour lines are capped due to allowance of maximum contour lines of 50. "); } - } - - return cvalues; + System.out.println(" Contour level = "+cvalues.toString()+"."); +***************************/ + while (cvalues.size()>50){cvalues.remove(50);} + int csize=cvalues.size(); + System.out.println(" Contour lines("+csize+ ") from "+cvalues.get(0)+" to "+cvalues.get(csize-1)); + + return cvalues; } /** @return boolean isCINTStringParsed */ @@ -652,3 +676,4 @@ public class CINT { } } + diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpResourceHandler.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpResourceHandler.java index 1b1b867fe4..f9f861282f 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpResourceHandler.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/display/rsc/NsharpResourceHandler.java @@ -1940,9 +1940,10 @@ public class NsharpResourceHandler { return; } if (!fromArchive) { - // start FixMark:nearByStnCompSnd d2dlite - if (!(sndType.contentEquals("NCUAIR") || sndType - .contentEquals("BUFRUA"))) { + // For those sounding report with forecast time, e.g. model/pfc sounding + if (timeLine.contains("V")) { //fix D2D loading issue. 10/8/2014 + // if (!(sndType.contentEquals("NCUAIR") || sndType + // .contentEquals("BUFRUA"))) { // Chin's NOTE: // Can Not use reference time directly from the stnInfo, // Timestamp refTime = stnInfo.getReftime() diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/view/NsharpPaletteWindow.java b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/view/NsharpPaletteWindow.java index 390883ca95..be2d25a49b 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/view/NsharpPaletteWindow.java +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/src/gov/noaa/nws/ncep/ui/nsharp/view/NsharpPaletteWindow.java @@ -16,7 +16,7 @@ * 01/08/2014 Chin Chen Only initializing inventory when in NCP * 01/13/2014 Chin Chen TTR829- when interpolation, edit graph is allowed * 01/22/2014 Chin Chen DR17003 issue: NSHARP sounding display throws errors when swapping into main pane when show text is turned on. - * + * 10/20/2014 Chin Chen DR16864, D2D does not use unload button. Check to make sure not D2D instance before access unload button. * * * @author Chin Chen @@ -150,7 +150,7 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, private boolean spcGpCreated = false; - private boolean awcGpCreated = false; + private boolean imD2d = false; // fixMark:NcInventory public static NsharpPaletteWindow getInstance() { if (VizPerspectiveListener.getCurrentPerspectiveManager() != null) { @@ -220,7 +220,8 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, interpBtn.setEnabled(false); graphModeBtnIcing.setEnabled(false); graphModeBtnTurb.setEnabled(false); - unloadBtn.setEnabled(false); // FixMark:nearByStnCompSnd + if (!imD2d) + unloadBtn.setEnabled(false); // FixMark:nearByStnCompSnd } else if (compareStnIsOn) { compareStnBtn.setText(COMP_STN_ON); graphEditBtn.setEnabled(false); @@ -231,7 +232,8 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, interpBtn.setEnabled(false); graphModeBtnIcing.setEnabled(false); graphModeBtnTurb.setEnabled(false); - unloadBtn.setEnabled(false); // FixMark:nearByStnCompSnd + if (!imD2d) + unloadBtn.setEnabled(false); // FixMark:nearByStnCompSnd } else if (compareSndIsOn) { compareSndBtn.setText(COMP_SND_ON); graphEditBtn.setEnabled(false); @@ -242,7 +244,8 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, interpBtn.setEnabled(false); graphModeBtnIcing.setEnabled(false); graphModeBtnTurb.setEnabled(false); - unloadBtn.setEnabled(false); // FixMark:nearByStnCompSnd + if (!imD2d) + unloadBtn.setEnabled(false); // FixMark:nearByStnCompSnd } else if (compareTmIsOn) { compareTmBtn.setText(COMP_TM_ON); compareSndBtn.setEnabled(false); @@ -253,7 +256,8 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, interpBtn.setEnabled(false); graphModeBtnIcing.setEnabled(false); graphModeBtnTurb.setEnabled(false); - unloadBtn.setEnabled(false); // FixMark:nearByStnCompSnd + if (!imD2d) + unloadBtn.setEnabled(false); // FixMark:nearByStnCompSnd } else if (editGraphOn) { graphEditBtn.setText(EDIT_GRAPH_ON); dataEditBtn.setEnabled(false); @@ -264,7 +268,8 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, interpBtn.setEnabled(false); graphModeBtnIcing.setEnabled(false); graphModeBtnTurb.setEnabled(false); - unloadBtn.setEnabled(false); // FixMark:nearByStnCompSnd + if (!imD2d) + unloadBtn.setEnabled(false); // FixMark:nearByStnCompSnd } } else if (currentGraphMode == NsharpConstants.GRAPH_TURB) { @@ -377,7 +382,7 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, public NsharpPaletteWindow() { super(); instance = this; - boolean imD2d = false; // fixMark:NcInventory + //boolean imD2d = false; // fixMark:NcInventory if (VizPerspectiveListener.getCurrentPerspectiveManager() != null) { if (VizPerspectiveListener.getCurrentPerspectiveManager() .getPerspectiveId().equals(D2D5Pane.ID_PERSPECTIVE)) { @@ -945,7 +950,8 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, graphModeBtnIcing.setEnabled(false); interpBtn.setEnabled(false); cfgBtn.setEnabled(false); - unloadBtn.setEnabled(false);// FixMark:nearByStnCompSnd + if (!imD2d) + unloadBtn.setEnabled(false);// FixMark:nearByStnCompSnd } else { overlayIsOn = false; overlayBtn.setText(OVLY_OFF); @@ -958,7 +964,8 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, graphModeBtnIcing.setEnabled(true); interpBtn.setEnabled(true); cfgBtn.setEnabled(true); - unloadBtn.setEnabled(true);// FixMark:nearByStnCompSnd + if (!imD2d) + unloadBtn.setEnabled(true);// FixMark:nearByStnCompSnd } NsharpResourceHandler rsc = getRscHandler(); if (rsc != null) { @@ -1001,7 +1008,8 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, graphModeBtnIcing.setEnabled(false); interpBtn.setEnabled(false); cfgBtn.setEnabled(false); - unloadBtn.setEnabled(false);// FixMark:nearByStnCompSnd + if (!imD2d) + unloadBtn.setEnabled(false);// FixMark:nearByStnCompSnd } else { compareStnIsOn = false; compareStnBtn.setText(COMP_STN_OFF); @@ -1014,7 +1022,8 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, graphModeBtnIcing.setEnabled(true); interpBtn.setEnabled(true); cfgBtn.setEnabled(true); - unloadBtn.setEnabled(true);// FixMark:nearByStnCompSnd + if (!imD2d) + unloadBtn.setEnabled(true);// FixMark:nearByStnCompSnd } NsharpResourceHandler rsc = getRscHandler(); if (rsc != null) { @@ -1059,7 +1068,8 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, graphModeBtnIcing.setEnabled(false); interpBtn.setEnabled(false); cfgBtn.setEnabled(false); - unloadBtn.setEnabled(false);// FixMark:nearByStnCompSnd + if (!imD2d) + unloadBtn.setEnabled(false);// FixMark:nearByStnCompSnd } else { compareTmIsOn = false; compareTmBtn.setText(COMP_TM_OFF); @@ -1072,7 +1082,8 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, graphModeBtnIcing.setEnabled(true); interpBtn.setEnabled(true); cfgBtn.setEnabled(true); - unloadBtn.setEnabled(true);// FixMark:nearByStnCompSnd + if (!imD2d) + unloadBtn.setEnabled(true);// FixMark:nearByStnCompSnd } NsharpResourceHandler rsc = getRscHandler(); if (rsc != null) { @@ -1115,7 +1126,8 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, graphModeBtnIcing.setEnabled(false); interpBtn.setEnabled(false); cfgBtn.setEnabled(false); - unloadBtn.setEnabled(false);// FixMark:nearByStnCompSnd + if (!imD2d) + unloadBtn.setEnabled(false);// FixMark:nearByStnCompSnd } else { compareSndIsOn = false; compareSndBtn.setText(COMP_SND_OFF); @@ -1128,7 +1140,8 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, graphModeBtnIcing.setEnabled(true); interpBtn.setEnabled(true); cfgBtn.setEnabled(true); - unloadBtn.setEnabled(true);// FixMark:nearByStnCompSnd + if (!imD2d) + unloadBtn.setEnabled(true);// FixMark:nearByStnCompSnd } NsharpResourceHandler rsc = getRscHandler(); if (rsc != null) { @@ -1187,7 +1200,8 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, compareSndBtn.setEnabled(true); compareStnBtn.setEnabled(true); overlayBtn.setEnabled(true); - unloadBtn.setEnabled(true);// FixMark:nearByStnCompSnd + if (!imD2d) + unloadBtn.setEnabled(true);// FixMark:nearByStnCompSnd } } else { editGraphOn = true; @@ -1200,7 +1214,8 @@ public class NsharpPaletteWindow extends ViewPart implements SelectionListener, compareSndBtn.setEnabled(false); compareStnBtn.setEnabled(false); overlayBtn.setEnabled(false); - unloadBtn.setEnabled(false);// FixMark:nearByStnCompSnd + if (!imD2d) + unloadBtn.setEnabled(false);// FixMark:nearByStnCompSnd } NsharpResourceHandler rsc = getRscHandler(); if (rsc != null) { diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/settings_tbl.xml b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/settings_tbl.xml index d208e7a0c7..691ee0e477 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/settings_tbl.xml +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/settings_tbl.xml @@ -840,7 +840,7 @@ - + diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/settings_tbl_Surface_Analysis.xml b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/settings_tbl_Surface_Analysis.xml index 87b170cdab..6bf8fcd9fb 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/settings_tbl_Surface_Analysis.xml +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/settings_tbl_Surface_Analysis.xml @@ -803,7 +803,7 @@ - + diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/airmet/get_attention_line.xsl b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/airmet/get_attention_line.xsl index e2066390b8..1921311f21 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/airmet/get_attention_line.xsl +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/airmet/get_attention_line.xsl @@ -18,6 +18,7 @@ E. Safford/SAIC 06/07 rm "...UPDT TO CANCEL..." B. Yin/SAIC 02/08 add tag number after cancellation B. Yin 12/11 added new line for 'New' or 'Cor' + J. Wu 09/14 added new line for 'CAN' --> @@ -25,14 +26,16 @@ - + 0 + CANCEL AIRMET. CONDS HV ENDED. + CANCEL OUTLOOK. diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/airmet/get_status.xsl b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/airmet/get_status.xsl index 8b34b9c8d3..4c3756067f 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/airmet/get_status.xsl +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/airmet/get_status.xsl @@ -20,15 +20,19 @@ B. Yin/SAIC 08/06 distinguish smear and outlook B. Yin/Chugach 12/11 changed 'Status' to 'issueType' changed for-each condition for smears - + J. Wu/SGT 10/14 TTR 714 - go through all smears (airmets & outlooks) in + one loop since the input XML format is different from + those in NMAP2 + --> NO HAZARD1 NO HAZARD2 NO HAZARD3 - - + + @@ -46,8 +50,9 @@ - - + + - +--> diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/AttrDlg.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/AttrDlg.java index 2e3a9c4962..d961f7f897 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/AttrDlg.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/AttrDlg.java @@ -78,6 +78,7 @@ public abstract class AttrDlg extends Dialog implements IAttribute { public static int ctrlBtnHeight = 28; // public static int ctrlBtnWidth = 90; + // public static int ctrlBtnHeight = 30; /** @@ -128,11 +129,24 @@ public abstract class AttrDlg extends Dialog implements IAttribute { this.getButton(IDialogConstants.CANCEL_ID).setEnabled(false); this.getButton(IDialogConstants.OK_ID).setEnabled(false); - this.getButton(IDialogConstants.CANCEL_ID).setLayoutData( - new GridData(ctrlBtnWidth, ctrlBtnHeight)); - this.getButton(IDialogConstants.OK_ID).setLayoutData( - new GridData(ctrlBtnWidth, ctrlBtnHeight)); + setDefaultControlButtonSize(); + } + /** + * Set default size for control buttons. + */ + public void setDefaultControlButtonSize() { + setButtonSize(ctrlBtnWidth, ctrlBtnHeight); + } + + /** + * Set size for control buttons. + */ + public void setButtonSize(int width, int height) { + this.getButton(IDialogConstants.CANCEL_ID).setLayoutData( + new GridData(width, height)); + this.getButton(IDialogConstants.OK_ID).setLayoutData( + new GridData(width, height)); } @Override diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/ContoursAttrDlg.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/ContoursAttrDlg.java index ebd338f1d9..18e7a06ccd 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/ContoursAttrDlg.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/ContoursAttrDlg.java @@ -3169,6 +3169,10 @@ public class ContoursAttrDlg extends AttrDlg implements IContours, private PgenContoursTool tool = null; + private Contours prevCont = null; + + private Contours nowCont = null; + private ContourMinmaxAttrDlg(Shell parShell) throws VizException { super(parShell); @@ -3238,11 +3242,54 @@ public class ContoursAttrDlg extends AttrDlg implements IContours, if (apt instanceof PgenContoursTool) { tool = (PgenContoursTool) apt; } + if (tool != null) { tool.resetUndoRedoCount(); PgenSession.getInstance().getCommandManager() .addStackListener(tool); } + + // set the lat/lon from the current symbol. + DrawableElement de = drawingLayer.getSelectedDE(); + if (de != null && de.getParent() instanceof ContourMinmax + && de instanceof Symbol) { + super.setLatitude(((Symbol) de).getLocation().y); + super.setLongitude(((Symbol) de).getLocation().x); + } + + /* + * Reset the listenser. + */ + for (Listener ls : undoBtn.getListeners(SWT.MouseDown)) { + undoBtn.removeListener(SWT.MouseDown, ls); + } + + undoBtn.addListener(SWT.MouseDown, new Listener() { + + @Override + public void handleEvent(Event event) { + + if (undoBtn.getText().equalsIgnoreCase(UNDO_SYMBOL)) { + undoBtn.setText(REDO_SYMBOL); + drawingLayer.getCommandMgr().undo(); + + } else if (undoBtn.getText().equalsIgnoreCase(REDO_SYMBOL)) { + undoBtn.setText(UNDO_SYMBOL); + drawingLayer.getCommandMgr().redo(); + } + + /* + * Reset the currentContours for the ContoursAttrDlg. + */ + currentContours = prevCont; + prevCont = nowCont; + nowCont = currentContours; + + mapEditor.refresh(); + + } + + }); } @Override @@ -3252,6 +3299,10 @@ public class ContoursAttrDlg extends AttrDlg implements IContours, PgenSession.getInstance().getCommandManager() .removeStackListener(tool); } + + prevCont = null; + nowCont = null; + return super.close(); } @@ -3262,15 +3313,34 @@ public class ContoursAttrDlg extends AttrDlg implements IContours, protected void placeSymbol() { if (tool != null) { + if (tool.getMouseHandler() instanceof PgenContoursHandler) { + /* + * Keep a copy of currentConoturs for "Undo". It chnages + * after call the "tool". + */ + prevCont = currentContours; + ((PgenContoursHandler) tool.getMouseHandler()) + .drawContourMinmax(new Coordinate(Double + .parseDouble(longitudeText.getText()), + Double.parseDouble(latitudeText.getText()))); + placeBtn.setEnabled(false); + nowCont = currentContours; // Keep a copy for "Redo" + undoBtn.setEnabled(true); + undoBtn.setText("Undo Symbol"); - ((PgenContoursHandler) tool.getMouseHandler()) - .drawContourMinmax(new Coordinate(Double - .parseDouble(longitudeText.getText()), Double - .parseDouble(latitudeText.getText()))); - placeBtn.setEnabled(false); - undoBtn.setEnabled(true); - undoBtn.setText("Undo Symbol"); + } else if (tool.getMouseHandler() instanceof PgenSelectHandler) { + minmaxTemplate = (gov.noaa.nws.ncep.ui.pgen.elements.Symbol) new DrawableElementFactory() + .create(DrawableType.SYMBOL, (IAttribute) this, + "Symbol", getActiveSymbolObjType(), + (Coordinate) null, null); + contoursAttrSettings.put(getActiveSymbolObjType(), + minmaxTemplate); + updateMinmaxAttributes(); + + placeBtn.setEnabled(false); + + } } } } @@ -3330,7 +3400,34 @@ public class ContoursAttrDlg extends AttrDlg implements IContours, if (newEl != null && oldAdc.equals(de.getParent())) { newEl.setParent(newAdc); + if (newEl instanceof Symbol) { + + if (minmaxAttrDlg != null + && minmaxAttrDlg.getShell() != null) { + if (minmaxAttrDlg.latitudeText.isEnabled() + && minmaxAttrDlg.longitudeText + .isEnabled()) { + ArrayList loc = new ArrayList(); + double lat = ((Symbol) newEl).getLocation().y; + double lon = ((Symbol) newEl).getLocation().x; + try { + lon = Double + .valueOf(minmaxAttrDlg.longitudeText + .getText()); + lat = Double + .valueOf(minmaxAttrDlg.latitudeText + .getText()); + } catch (Exception e) { + lon = ((Symbol) newEl).getLocation().x; + lat = ((Symbol) newEl).getLocation().y; + } + + loc.add(new Coordinate(lon, lat)); + newEl.setPoints(loc); + } + } + ((DECollection) newAdc) .replace(((ContourMinmax) newAdc) .getSymbol(), newEl); @@ -3338,6 +3435,8 @@ public class ContoursAttrDlg extends AttrDlg implements IContours, ((ContourMinmax) newAdc).getSymbol().update( minmaxTemplate); + + ((ContourMinmax) newAdc).getLabel().setAuto(true); } } @@ -3926,4 +4025,15 @@ public class ContoursAttrDlg extends AttrDlg implements IContours, return typeChanged; } + /** + * Update lat/lon and Undo button on SymbolAttrDlg. + */ + public void updateSymbolAttrOnGUI(Coordinate loc) { + if (minmaxAttrDlg != null && minmaxAttrDlg.getShell() != null) { + minmaxAttrDlg.setLatitude(loc.y); + minmaxAttrDlg.setLongitude(loc.x); + minmaxAttrDlg.enableUndoBtn(true); + } + } + } \ No newline at end of file diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/GfaFormatAttrDlg.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/GfaFormatAttrDlg.java index 1baeca0350..1befb3e618 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/GfaFormatAttrDlg.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/GfaFormatAttrDlg.java @@ -68,9 +68,6 @@ import com.raytheon.uf.viz.core.exception.VizException; */ public class GfaFormatAttrDlg extends AttrDlg { - // private final static Logger logger = - // Logger.getLogger(GfaFormatAttrDlg.class); - private static final String ZULU = "ZULU"; private static final String TANGO = "TANGO"; @@ -151,7 +148,6 @@ public class GfaFormatAttrDlg extends AttrDlg { instance = new GfaFormatAttrDlg(parShell); } catch (VizException e) { - // logger.error(e); e.printStackTrace(); } } @@ -306,12 +302,14 @@ public class GfaFormatAttrDlg extends AttrDlg { @Override public void createButtonsForButtonBar(Composite parent) { - super.createButtonsForButtonBar(parent); - this.getButton( OK_ID ).setText( SAVE_LABEL ); - this.getButton( CANCEL_ID).setText( CANCEL_LABEL ); + super.createButtonsForButtonBar(parent); + this.getButton(OK_ID).setText(SAVE_LABEL); + this.getButton(CANCEL_ID).setText(CANCEL_LABEL); + } - // createButton(parent, OK_ID, SAVE_LABEL, true); - // createButton(parent, CANCEL_ID, CANCEL_LABEL, false); + @Override + public void setDefaultControlButtonSize() { + setButtonSize(ctrlBtnWidth + 50, ctrlBtnHeight); } @Override diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/TrackAttrDlg.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/TrackAttrDlg.java index 6134338ed8..24e5633982 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/TrackAttrDlg.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/attrdialog/TrackAttrDlg.java @@ -8,39 +8,39 @@ package gov.noaa.nws.ncep.ui.pgen.attrdialog; +import gov.noaa.nws.ncep.ui.pgen.display.FillPatternList.FillPattern; +import gov.noaa.nws.ncep.ui.pgen.display.IAttribute; +import gov.noaa.nws.ncep.ui.pgen.display.IText.FontStyle; +import gov.noaa.nws.ncep.ui.pgen.display.ITrack; +import gov.noaa.nws.ncep.ui.pgen.display.TrackPoint; +import gov.noaa.nws.ncep.ui.pgen.elements.AbstractDrawableComponent; +import gov.noaa.nws.ncep.ui.pgen.elements.Track; +import gov.noaa.nws.ncep.viz.common.ui.color.ColorButtonSelector; + +import java.awt.Color; import java.util.ArrayList; import java.util.Calendar; -import java.awt.Color; import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.Combo; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Label; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import com.raytheon.uf.viz.core.exception.VizException; import com.vividsolutions.jts.geom.Coordinate; -import gov.noaa.nws.ncep.ui.pgen.display.ITrack; -import gov.noaa.nws.ncep.ui.pgen.display.IText.FontStyle; -import gov.noaa.nws.ncep.ui.pgen.display.TrackPoint; -import gov.noaa.nws.ncep.ui.pgen.display.FillPatternList.FillPattern; -import gov.noaa.nws.ncep.ui.pgen.elements.AbstractDrawableComponent; -import gov.noaa.nws.ncep.ui.pgen.display.IAttribute; -import gov.noaa.nws.ncep.ui.pgen.elements.Track; -import gov.noaa.nws.ncep.viz.common.ui.color.ColorButtonSelector; - /** * Singleton attribute dialog for Track. * @@ -61,1319 +61,1306 @@ import gov.noaa.nws.ncep.viz.common.ui.color.ColorButtonSelector; * Added isNewTrack flag to make the FirstTime(/SecondTime) current time when create a Track * 03/13 #928 B. Yin Added a separator above the button bar. * 08/13 #1020 B. Yin Fixed the 'Other' interval problem. + * 09/14 TTR750 J. Wu Use fontStyle for track labels. * * - * @author M. Gao + * @author M. Gao */ -public class TrackAttrDlg extends AttrDlg implements ITrack{ - -// private final static org.apache.log4j.Logger log = -// org.apache.log4j.Logger.getLogger(TrackAttrDlg.class); - - public static enum FontSizeName { TINY, SMALL, MEDIUM, LARGE, HUGE, GIANT }; - public static int[] FontSizeValue = { 10, 12, 14, 18, 24, 34 }; - //public static String[] FontName = new String[]{ "Courier", "Helvetica", "Times" }; - public static String[] FontName = new String[]{ "Courier", "Nimbus Sans L", "Liberation Serif" }; +public class TrackAttrDlg extends AttrDlg implements ITrack { - public static String[] BoxName = new String[]{ "Normal", "Boxed", "Blanked", "Outline" }; - - private final int DEFAULT_NUMBER_OF_TIMES = 5; - private final int DEFAULT_HOUR_SHIFT_FOR_FIRST_TIME = 4; - private final int DEFAULT_HOUR_SHIFT_BEYOND_FIRST_TIME = 1; - - private static String[] IntervalTimeValues = {"00:15", "00:30", "01:00", "02:00", "06:00", - "12:00", "Other"}; - private String previousIntervalTimeValue = ""; + public static enum FontSizeName { + TINY, SMALL, MEDIUM, LARGE, HUGE, GIANT + }; - private static String[] UnitValues = {"kts", "kph", "mph"}; - private static String[] RoundTo = {" ", "5", "10"}; - private static String[] RoundDirTo = {" ", "1", "5"}; - - private Text firstTimeText; - private Text secondTimeText; - private boolean setTimeButtonSelected; - private Button frameTimeButton; - private Button setTimeButton; - - private Text numberOfTimesText; - private Text intervalText; + public static int[] FontSizeValue = { 10, 12, 14, 18, 24, 34 }; - private Text skipFactorText; - private ExtraPointTimeDisplayOption extraPointTimeDisplayOption; - - // private Composite top = null; + public static String[] FontName = new String[] { "Courier", + "Nimbus Sans L", "Liberation Serif" }; + + public static String[] BoxName = new String[] { "Normal", "Boxed", + "Blanked", "Outline" }; + + private final int DEFAULT_NUMBER_OF_TIMES = 5; + + private final int DEFAULT_HOUR_SHIFT_FOR_FIRST_TIME = 4; + + private final int DEFAULT_HOUR_SHIFT_BEYOND_FIRST_TIME = 1; + + private static String[] IntervalTimeValues = { "00:15", "00:30", "01:00", + "02:00", "06:00", "12:00", "Other" }; + + private String previousIntervalTimeValue = ""; + + private static String[] UnitValues = { "kts", "kph", "mph" }; + + private static String[] RoundTo = { " ", "5", "10" }; + + private static String[] RoundDirTo = { " ", "1", "5" }; + + private Text firstTimeText; + + private Text secondTimeText; + + private boolean setTimeButtonSelected; + + private Button frameTimeButton; + + private Button setTimeButton; + + private Text numberOfTimesText; + + private Text intervalText; + + private Text skipFactorText; + + private ExtraPointTimeDisplayOption extraPointTimeDisplayOption; + + // private Composite top = null; private ColorButtonSelector initialCS; + private ColorButtonSelector extrapCS; - + private Text text = null; - private Combo intervalCombo; - - private Combo unitCombo; - private int unitComboSelectedIndex; - private Button roundButton; - private Combo roundCombo; - private int roundComboSelectedIndex; - private Button roundDirButton; - private Combo roundDirCombo; - private int roundDirComboSelectedIndex; - - private Combo fontSizeCombo; - private int fontSizeComboSelectedIndex; - private Combo fontNameCombo; - private int fontNameComboSelectedIndex; - private Combo fontStyleCombo; - private int fontStyleComboSelectedIndex; + private Combo intervalCombo; + + private Combo unitCombo; + + private int unitComboSelectedIndex; + + private Button roundButton; + + private Combo roundCombo; + + private int roundComboSelectedIndex; + + private Button roundDirButton; + + private Combo roundDirCombo; + + private int roundDirComboSelectedIndex; + + private Combo fontSizeCombo; + + private int fontSizeComboSelectedIndex; + + private Combo fontNameCombo; + + private int fontNameComboSelectedIndex; + + private Combo fontStyleCombo; + + private int fontStyleComboSelectedIndex; + + private Button skipFactorButton; + + private Button showFirstLastButton; + + private Button onHourButton; + + private Button onHalfHourButton; + + private Calendar firstTimeCalendar; + + private Calendar secondTimeCalendar; + + private int numberOfTimes = DEFAULT_NUMBER_OF_TIMES; // set the default to 5 + + TrackExtrapPointInfoDlg trackExtrapPointInfoDlg; + + private static TrackAttrDlg INSTANCE = null; + + public boolean isNewTrack = false; - private Button skipFactorButton; - private Button showFirstLastButton; - private Button onHourButton; - private Button onHalfHourButton; - - private Calendar firstTimeCalendar; - private Calendar secondTimeCalendar; - - private int numberOfTimes = DEFAULT_NUMBER_OF_TIMES; //set the default to 5 - - TrackExtrapPointInfoDlg trackExtrapPointInfoDlg; - - private static TrackAttrDlg INSTANCE = null; - - public boolean isNewTrack = false; - /** - * Private constructor - * @param parShell - * @throws VizException - */ - private TrackAttrDlg(Shell parShell) throws VizException { + * Private constructor + * + * @param parShell + * @throws VizException + */ + private TrackAttrDlg(Shell parShell) throws VizException { super(parShell); } - - /** - * Creates a track attribute dialog if the dialog does not exist - * and returns the instance. If the dialog exists, return the instance. - * - * @param parShell - * @return - */ - public static TrackAttrDlg getInstance( Shell parShell){ - if ( INSTANCE == null ){ - try { - INSTANCE = new TrackAttrDlg( parShell ); - } catch (VizException e) { - e.printStackTrace(); - } - } - return INSTANCE; - } - - public void okPressed() { - - ArrayList adcList = null; - ArrayList newList = new ArrayList() ; - //get the list of selected tracks - if ( drawingLayer != null ) { - adcList = (ArrayList) drawingLayer.getAllSelected(); - } - - if ( adcList != null && !adcList.isEmpty() ){ - - Track newEl = null; - //loop through the list and update attributes - for ( AbstractDrawableComponent adc : adcList){ + /** + * Creates a track attribute dialog if the dialog does not exist and returns + * the instance. If the dialog exists, return the instance. + * + * @param parShell + * @return + */ + public static TrackAttrDlg getInstance(Shell parShell) { + if (INSTANCE == null) { + try { + INSTANCE = new TrackAttrDlg(parShell); + } catch (VizException e) { + e.printStackTrace(); + } + } + return INSTANCE; + } - Track el = (Track)adc.getPrimaryDE(); + public void okPressed() { - if ( el != null ){ - // Create a copy of the currently selected element - newEl = (Track)el.copy(); - // Update the new Element with these current attributes - newEl.update(this); - /* - * populate the TrackExtrapPointInofDlg object - */ - populateTrackExtrapPointInfoDlgWithNewTrackData(getTrackExtrapPointInfoDlg(), newEl, - unitComboSelectedIndex, roundComboSelectedIndex, roundDirComboSelectedIndex); - - newList.add(newEl); + ArrayList adcList = null; + ArrayList newList = new ArrayList(); - } - } - - if ( newEl != null ){ - AttrSettings.getInstance().setSettings( newEl ); - } - - ArrayList oldList = new ArrayList(adcList); - drawingLayer.replaceElements(oldList, newList); - } - - // set the new elements as selected. - drawingLayer.removeSelected(); - for ( AbstractDrawableComponent adc : newList ){ - drawingLayer.addSelected(adc); - } - - if ( mapEditor != null ) { - mapEditor.refresh(); - } - } + // get the list of selected tracks + if (drawingLayer != null) { + adcList = (ArrayList) drawingLayer + .getAllSelected(); + } - public void cancelPressed(){ - - if(trackExtrapPointInfoDlg != null) { - trackExtrapPointInfoDlg.close(); - trackExtrapPointInfoDlg = null; - } - super.cancelPressed(); - - } - - /** - * Creates the dialog area - */ - @Override - public Control createDialogArea(Composite parent) { - - Composite top = (Composite) super.createDialogArea(parent); + if (adcList != null && !adcList.isEmpty()) { - // Create the main layout for the shell. - GridLayout mainLayout = new GridLayout(2, false); - mainLayout.marginHeight = 3; - mainLayout.marginWidth = 3; - top.setLayout(mainLayout); + Track newEl = null; + // loop through the list and update attributes + for (AbstractDrawableComponent adc : adcList) { - // Initialize all of the menus, controls, and layouts - initializeComponents(top); + Track el = (Track) adc.getPrimaryDE(); - return top; - - } - - public void initializeTrackAttrDlg(Track track) { - if(track == null) - return; - /* - * 1. restore frameTimeButton and setTimeButton status - */ - if(track.isSetTimeButtonSelected()) { - getSetTimeButton().setSelection(true); - getFrameTimeButton().setSelection(false); - } else { - getFrameTimeButton().setSelection(true); - getSetTimeButton().setSelection(false); - } - /* - * 2. restore first time and second time text values - */ - if (isNewTrack == true) { - String[] firstSecondTimeValueArray = getFirstSecondTimeInitialTimeValueForSetTimeButton(); - getFirstTimeText().setText(firstSecondTimeValueArray[0]); - getSecondTimeText().setText(firstSecondTimeValueArray[1]); - } - else { - - getFirstTimeText().setText(getFirstOrSecondTimeStringValue(track.getFirstTimeCalendar(), true, track.getInitialPoints())); - getSecondTimeText().setText(getFirstOrSecondTimeStringValue(track.getSecondTimeCalendar(), false, track.getInitialPoints())); - } - - //isNewTrack = false; - /* - * 3. restore Number of times value - */ - if(track.getExtrapPoints() != null) - numberOfTimesText.setText(String.valueOf(track.getExtrapPoints().length)); - - /* - * 4. restore interval time settings - */ -// intervalCombo.select(track.getIntervalComboSelectedIndex()); -// int intervalComboItemCount = intervalCombo.getItemCount(); -// if ( (intervalComboItemCount - 1) == track.getIntervalComboSelectedIndex() ) -// intervalText.setText(track.getIntervalTimeString()); - - setIntervalTimeString( track.getIntervalTimeString() ); - -// restoreIntervalTimeSettingByTrack(this, track); - - /* - * 5. restore initial and extrap colors - */ - java.awt.Color initColor = track.getInitialColor(); - initialCS.setColorValue(new RGB(initColor.getRed(), initColor.getGreen(), initColor.getBlue())); - java.awt.Color extrapColor = track.getExtrapColor(); - extrapCS.setColorValue(new RGB(extrapColor.getRed(), extrapColor.getGreen(), extrapColor.getBlue())); - - /* - * 6. restore label option settings - */ - setExtraPointTimeDisplayOption(track.getExtraPointTimeDisplayOption()); - makeTimeDisplayOptionSelected(track.getExtraPointTimeDisplayOption(), track.getSkipFactorTextString()); - - /* - * 7. restore Font, Size, Style combo values - */ - getFontNameCombo().select(track.getFontNameComboSelectedIndex()); - getFontSizeCombo().select(track.getFontSizeComboSelectedIndex()); - getFontStyleCombo().select(track.getFontStyleComboSelectedIndex()); - - /* - * 7. restore Unit combo values - */ - unitComboSelectedIndex = track.getUnitComboSelectedIndex(); - getUnitCombo().select(unitComboSelectedIndex); - - roundComboSelectedIndex = track.getRoundComboSelectedIndex(); - getRoundCombo().select(roundComboSelectedIndex); - if (roundComboSelectedIndex >0) - roundButton.setSelection(true); - else - roundButton.setSelection(false); - - roundDirComboSelectedIndex = track.getRoundDirComboSelectedIndex(); - getRoundDirCombo().select(roundDirComboSelectedIndex); - if (roundDirComboSelectedIndex >0) - roundDirButton.setSelection(true); - else - roundDirButton.setSelection(false); - } - - private void populateTrackExtrapPointInfoDlgWithNewTrackData(TrackExtrapPointInfoDlg trackExtrapPointInfoDlgObject, - Track newTrackObject, int unitComboSelectedIndex, int roundComboSelectedIndex, int roundDirComboSelectedIndex) { - if(trackExtrapPointInfoDlgObject != null && newTrackObject != null) { - trackExtrapPointInfoDlgObject.close(); - - trackExtrapPointInfoDlgObject.setBlockOnOpen( false ); - trackExtrapPointInfoDlgObject.open(); - - trackExtrapPointInfoDlgObject.setTrack(newTrackObject, unitComboSelectedIndex, roundComboSelectedIndex, roundDirComboSelectedIndex); + if (el != null) { + // Create a copy of the currently selected element + newEl = (Track) el.copy(); + // Update the new Element with these current attributes + newEl.update(this); + /* + * populate the TrackExtrapPointInofDlg object + */ + populateTrackExtrapPointInfoDlgWithNewTrackData( + getTrackExtrapPointInfoDlg(), newEl, + unitComboSelectedIndex, roundComboSelectedIndex, + roundDirComboSelectedIndex); - trackExtrapPointInfoDlgObject.setBlockOnOpen( true ); - } - } - -// private void restoreIntervalTimeSettingByTrack(TrackAttrDlg targetTrackAttrDlg, Track track) { -// if(targetTrackAttrDlg == null || track == null) -// return; -// -// targetTrackAttrDlg.getIntervalCombo().select(track.getIntervalComboSelectedIndex()); -// int intervalComboItemCount = targetTrackAttrDlg.getIntervalCombo().getItemCount(); -// if((intervalComboItemCount - 1) == track.getIntervalComboSelectedIndex()) { -// if(track.getIntervalTimeString() != null) -// targetTrackAttrDlg.getIntervalText().setText(track.getIntervalTimeString()); -// } else { -//// targetTrackAttrDlg.getIntervalText().setText(targetTrackAttrDlg.getIntervalCombo().getText()); -// track.setIntervalTimeString(targetTrackAttrDlg.getIntervalCombo().getText()); -// } -// } - - private void makeTimeDisplayOptionSelected(ExtraPointTimeDisplayOption extraPointTimeDisplayOption, String skipFactorTextString) { - getSkipFactorButton().setSelection(false); - skipFactorText.setText(""); - if(extraPointTimeDisplayOption == ITrack.ExtraPointTimeDisplayOption.ON_HALF_HOUR) - getOnHalfHourButton().setSelection(true); - else if(extraPointTimeDisplayOption == ITrack.ExtraPointTimeDisplayOption.ON_ONE_HOUR) - getOnHourButton().setSelection(true); - else if(extraPointTimeDisplayOption == ITrack.ExtraPointTimeDisplayOption.SHOW_FIRST_LAST) - getShowFirstLastButton().setSelection(true); - else { - getSkipFactorButton().setSelection(true); - skipFactorText.setText(skipFactorTextString); - } - } - - /** - * Creates buttons, menus, and other controls in the dialog area - * @param listener - */ - private void initializeComponents(Composite topComposite) { - isNewTrack = true; - - int textWidth = 120; //160; - int textHeight = 15; //40; + newList.add(newEl); - GridLayout childGridLayout = new GridLayout( 2, false ); + } + } + + if (newEl != null) { + AttrSettings.getInstance().setSettings(newEl); + } + + ArrayList oldList = new ArrayList( + adcList); + drawingLayer.replaceElements(oldList, newList); + } + + // set the new elements as selected. + drawingLayer.removeSelected(); + for (AbstractDrawableComponent adc : newList) { + drawingLayer.addSelected(adc); + } + + if (mapEditor != null) { + mapEditor.refresh(); + } + } + + public void cancelPressed() { + + if (trackExtrapPointInfoDlg != null) { + trackExtrapPointInfoDlg.close(); + trackExtrapPointInfoDlg = null; + } + super.cancelPressed(); + + } + + /** + * Creates the dialog area + */ + @Override + public Control createDialogArea(Composite parent) { + + Composite top = (Composite) super.createDialogArea(parent); + + // Create the main layout for the shell. + GridLayout mainLayout = new GridLayout(2, false); + mainLayout.marginHeight = 3; + mainLayout.marginWidth = 3; + top.setLayout(mainLayout); + + // Initialize all of the menus, controls, and layouts + initializeComponents(top); + + return top; + + } + + public void initializeTrackAttrDlg(Track track) { + if (track == null) + return; + /* + * 1. restore frameTimeButton and setTimeButton status + */ + if (track.isSetTimeButtonSelected()) { + getSetTimeButton().setSelection(true); + getFrameTimeButton().setSelection(false); + } else { + getFrameTimeButton().setSelection(true); + getSetTimeButton().setSelection(false); + } + /* + * 2. restore first time and second time text values + */ + if (isNewTrack == true) { + String[] firstSecondTimeValueArray = getFirstSecondTimeInitialTimeValueForSetTimeButton(); + getFirstTimeText().setText(firstSecondTimeValueArray[0]); + getSecondTimeText().setText(firstSecondTimeValueArray[1]); + } else { + + getFirstTimeText().setText( + getFirstOrSecondTimeStringValue( + track.getFirstTimeCalendar(), true, + track.getInitialPoints())); + getSecondTimeText().setText( + getFirstOrSecondTimeStringValue( + track.getSecondTimeCalendar(), false, + track.getInitialPoints())); + } + + // isNewTrack = false; + /* + * 3. restore Number of times value + */ + if (track.getExtrapPoints() != null) + numberOfTimesText + .setText(String.valueOf(track.getExtrapPoints().length)); + + /* + * 4. restore interval time settings + */ + setIntervalTimeString(track.getIntervalTimeString()); + + /* + * 5. restore initial and extrap colors + */ + java.awt.Color initColor = track.getInitialColor(); + initialCS.setColorValue(new RGB(initColor.getRed(), initColor + .getGreen(), initColor.getBlue())); + java.awt.Color extrapColor = track.getExtrapColor(); + extrapCS.setColorValue(new RGB(extrapColor.getRed(), extrapColor + .getGreen(), extrapColor.getBlue())); + + /* + * 6. restore label option settings + */ + setExtraPointTimeDisplayOption(track.getExtraPointTimeDisplayOption()); + makeTimeDisplayOptionSelected(track.getExtraPointTimeDisplayOption(), + track.getSkipFactorTextString()); + + /* + * 7. restore Font, Size, Style combo values + */ + getFontNameCombo().select(track.getFontNameComboSelectedIndex()); + getFontSizeCombo().select(track.getFontSizeComboSelectedIndex()); + getFontStyleCombo().select(track.getFontStyleComboSelectedIndex()); + + /* + * 7. restore Unit combo values + */ + unitComboSelectedIndex = track.getUnitComboSelectedIndex(); + getUnitCombo().select(unitComboSelectedIndex); + + roundComboSelectedIndex = track.getRoundComboSelectedIndex(); + getRoundCombo().select(roundComboSelectedIndex); + if (roundComboSelectedIndex > 0) + roundButton.setSelection(true); + else + roundButton.setSelection(false); + + roundDirComboSelectedIndex = track.getRoundDirComboSelectedIndex(); + getRoundDirCombo().select(roundDirComboSelectedIndex); + if (roundDirComboSelectedIndex > 0) + roundDirButton.setSelection(true); + else + roundDirButton.setSelection(false); + } + + private void populateTrackExtrapPointInfoDlgWithNewTrackData( + TrackExtrapPointInfoDlg trackExtrapPointInfoDlgObject, + Track newTrackObject, int unitComboSelectedIndex, + int roundComboSelectedIndex, int roundDirComboSelectedIndex) { + if (trackExtrapPointInfoDlgObject != null && newTrackObject != null) { + trackExtrapPointInfoDlgObject.close(); + + trackExtrapPointInfoDlgObject.setBlockOnOpen(false); + trackExtrapPointInfoDlgObject.open(); + + trackExtrapPointInfoDlgObject.setTrack(newTrackObject, + unitComboSelectedIndex, roundComboSelectedIndex, + roundDirComboSelectedIndex); + + trackExtrapPointInfoDlgObject.setBlockOnOpen(true); + } + } + + private void makeTimeDisplayOptionSelected( + ExtraPointTimeDisplayOption extraPointTimeDisplayOption, + String skipFactorTextString) { + getSkipFactorButton().setSelection(false); + skipFactorText.setText(""); + if (extraPointTimeDisplayOption == ITrack.ExtraPointTimeDisplayOption.ON_HALF_HOUR) + getOnHalfHourButton().setSelection(true); + else if (extraPointTimeDisplayOption == ITrack.ExtraPointTimeDisplayOption.ON_ONE_HOUR) + getOnHourButton().setSelection(true); + else if (extraPointTimeDisplayOption == ITrack.ExtraPointTimeDisplayOption.SHOW_FIRST_LAST) + getShowFirstLastButton().setSelection(true); + else { + getSkipFactorButton().setSelection(true); + skipFactorText.setText(skipFactorTextString); + } + } + + /** + * Creates buttons, menus, and other controls in the dialog area + * + * @param listener + */ + private void initializeComponents(Composite topComposite) { + isNewTrack = true; + + int textWidth = 120; // 160; + int textHeight = 15; // 40; + + GridLayout childGridLayout = new GridLayout(2, false); this.getShell().setText("Track Attributes"); -// log.info("===now it is inside initializeComponents(...)"); /** - * Draw Frame/Set time buttons + * Draw Frame/Set time buttons */ Group timeRadioButtonGroup = new Group(topComposite, SWT.NONE); timeRadioButtonGroup.setLayout(childGridLayout); - - frameTimeButton = new Button(timeRadioButtonGroup, SWT.RADIO); -// Button frameTimeButton = new Button(topComposite, SWT.RADIO); + + frameTimeButton = new Button(timeRadioButtonGroup, SWT.RADIO); frameTimeButton.setText("Frame time"); - -// Button setTimeButton = new Button(topComposite, SWT.RADIO); + setTimeButton = new Button(timeRadioButtonGroup, SWT.RADIO); - setTimeButton.setText( "Set Time" ); -// setTimeButton.setSelection(true); -// timeRadioButtonGroup.h - Label emptyLabel = new Label( topComposite, SWT.LEFT ); + setTimeButton.setText("Set Time"); + Label emptyLabel = new Label(topComposite, SWT.LEFT); emptyLabel.setText(" "); /* * Draw First and Second Time text rows */ - String[] firstSecondTimeValueArray = getFirstSecondTimeInitialTimeValueForSetTimeButton(); - setFirstTimeText(createTextfieldWithLabel(topComposite, "First time:", - SWT.SINGLE | SWT.BORDER, textWidth, textHeight, true)); + String[] firstSecondTimeValueArray = getFirstSecondTimeInitialTimeValueForSetTimeButton(); + setFirstTimeText(createTextfieldWithLabel(topComposite, "First time:", + SWT.SINGLE | SWT.BORDER, textWidth, textHeight, true)); getFirstTimeText().setText(firstSecondTimeValueArray[0]); - getFirstTimeText().addModifyListener( new ModifyListener(){ - public void modifyText(ModifyEvent e) { - Text txt = (Text)e.widget; - Calendar cal = gempakTM2Calendar(txt.getText()); - if ( cal != null ) firstTimeCalendar = cal; - - } + getFirstTimeText().addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + Text txt = (Text) e.widget; + Calendar cal = gempakTM2Calendar(txt.getText()); + if (cal != null) + firstTimeCalendar = cal; + + } }); - - setSecondTimeText(createTextfieldWithLabel(topComposite, "Second time:", - SWT.SINGLE | SWT.BORDER, textWidth, textHeight, true)); + setSecondTimeText(createTextfieldWithLabel(topComposite, + "Second time:", SWT.SINGLE | SWT.BORDER, textWidth, textHeight, + true)); getSecondTimeText().setText(firstSecondTimeValueArray[1]); - - getSecondTimeText().addModifyListener( new ModifyListener(){ - public void modifyText(ModifyEvent e) { - Text txt = (Text)e.widget; - Calendar cal = gempakTM2Calendar(txt.getText()); - if ( cal != null ) secondTimeCalendar = cal; - - } + + getSecondTimeText().addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + Text txt = (Text) e.widget; + Calendar cal = gempakTM2Calendar(txt.getText()); + if (cal != null) + secondTimeCalendar = cal; + + } }); - + setTimeButton.setSelection(true); - setSetTimeButtonSelected(true); - frameAndSetTimeButtonSelectionListenerAction(frameTimeButton, getFirstTimeText(), - getSecondTimeText()); - frameAndSetTimeButtonSelectionListenerAction(setTimeButton, getFirstTimeText(), - getSecondTimeText()); - + setSetTimeButtonSelected(true); + frameAndSetTimeButtonSelectionListenerAction(frameTimeButton, + getFirstTimeText(), getSecondTimeText()); + frameAndSetTimeButtonSelectionListenerAction(setTimeButton, + getFirstTimeText(), getSecondTimeText()); + /* - * Played with NMAP2, it seems directly change first/second time texts do not have any - * impact on the first/second starting points. Thus, now set both text fields are not - * editable + * Played with NMAP2, it seems directly change first/second time texts + * do not have any impact on the first/second starting points. Thus, now + * set both text fields are not editable */ - getFirstTimeText().setEditable(true); - getSecondTimeText().setEditable(true); - + getFirstTimeText().setEditable(true); + getSecondTimeText().setEditable(true); + /* * Draw Number of times text row */ - setNumberOfTimesText(createTextfieldWithLabel(topComposite, "Number of times:", - SWT.SINGLE | SWT.BORDER, textWidth/3, textHeight, true)); + setNumberOfTimesText(createTextfieldWithLabel(topComposite, + "Number of times:", SWT.SINGLE | SWT.BORDER, textWidth / 3, + textHeight, true)); numberOfTimesText.setText(String.valueOf(numberOfTimes)); numberOfTimesText.addModifyListener(new ModifyListener() { - public void modifyText(ModifyEvent e) { - try { - numberOfTimes = Integer.parseInt(numberOfTimesText.getText()); - } catch(NumberFormatException nfe) { - numberOfTimes = DEFAULT_NUMBER_OF_TIMES; //use the default value - // log.error("The text value of number of times is invalid, input text=" - // +getNumberOfTimesText().getText()); - } - } - }); - + public void modifyText(ModifyEvent e) { + try { + numberOfTimes = Integer.parseInt(numberOfTimesText + .getText()); + } catch (NumberFormatException nfe) { + numberOfTimes = DEFAULT_NUMBER_OF_TIMES; // use the default + // value + } + } + }); + /* * Draw Interval combo box row */ - Label intervalLabel = new Label(topComposite, SWT.LEFT); - intervalLabel.setText("Interval:"); + Label intervalLabel = new Label(topComposite, SWT.LEFT); + intervalLabel.setText("Interval:"); Group intervalRowGroup = new Group(topComposite, SWT.NONE); intervalRowGroup.setLayout(childGridLayout); - - intervalCombo = new Combo(intervalRowGroup, SWT.DROP_DOWN | SWT.READ_ONLY); - for ( String currentString : IntervalTimeValues ) { - intervalCombo.add(currentString); + + intervalCombo = new Combo(intervalRowGroup, SWT.DROP_DOWN + | SWT.READ_ONLY); + for (String currentString : IntervalTimeValues) { + intervalCombo.add(currentString); } - intervalCombo.select(2); //set default to 01:00 - setPreviousIntervalTimeValue(intervalCombo.getText()); - intervalText = new Text(intervalRowGroup, SWT.SINGLE | SWT.BORDER); + intervalCombo.select(2); // set default to 01:00 + setPreviousIntervalTimeValue(intervalCombo.getText()); + intervalText = new Text(intervalRowGroup, SWT.SINGLE | SWT.BORDER); intervalCombo.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - if(intervalCombo.getText().equalsIgnoreCase("Other")) { - intervalText.setEditable(true); - intervalText.setText(getPreviousIntervalTimeValue()); - } else { - intervalText.setEditable(false); - intervalText.setText(""); - setPreviousIntervalTimeValue(intervalCombo.getText()); - // setIntervalTimeString(intervalCombo.getText()); - } - } - }); + public void widgetSelected(SelectionEvent e) { + if (intervalCombo.getText().equalsIgnoreCase("Other")) { + intervalText.setEditable(true); + intervalText.setText(getPreviousIntervalTimeValue()); + } else { + intervalText.setEditable(false); + intervalText.setText(""); + setPreviousIntervalTimeValue(intervalCombo.getText()); + } + } + }); intervalText.addModifyListener(new ModifyListener() { - public void modifyText(ModifyEvent e) { - if ( !((Text)e.widget).getText().isEmpty()) - ;// setIntervalTimeString(intervalText.getText()); - } - }); - + public void modifyText(ModifyEvent e) { + if (!((Text) e.widget).getText().isEmpty()) + ;// setIntervalTimeString(intervalText.getText()); + } + }); + /* * Draw two color choice options */ - Label colorLabel = new Label(topComposite, SWT.LEFT); - colorLabel.setText("Initial Color:"); - initialCS = new ColorButtonSelector ( topComposite ); - initialCS.setColorValue( new RGB( 0,0,255 ) ); // Blue??? - - colorLabel = new Label(topComposite, SWT.LEFT); - colorLabel.setText("Extra Color:"); - extrapCS = new ColorButtonSelector( topComposite ); - extrapCS.setColorValue( new RGB( 0,192,0 ) ); // Green??? - + Label colorLabel = new Label(topComposite, SWT.LEFT); + colorLabel.setText("Initial Color:"); + initialCS = new ColorButtonSelector(topComposite); + initialCS.setColorValue(new RGB(0, 0, 255)); // Blue??? + + colorLabel = new Label(topComposite, SWT.LEFT); + colorLabel.setText("Extra Color:"); + extrapCS = new ColorButtonSelector(topComposite); + extrapCS.setColorValue(new RGB(0, 192, 0)); // Green??? + /* - * Draw speed unit selection label, checkbox and combo + * Draw speed unit selection label, checkbox and combo */ - Label speedUnitLabel = new Label(topComposite, SWT.LEFT); - speedUnitLabel.setText("Speed Unit:"); - - unitCombo = new Combo(topComposite, SWT.DROP_DOWN | SWT.READ_ONLY); + Label speedUnitLabel = new Label(topComposite, SWT.LEFT); + speedUnitLabel.setText("Speed Unit:"); + + unitCombo = new Combo(topComposite, SWT.DROP_DOWN | SWT.READ_ONLY); for (String unit : UnitValues) { - unitCombo.add(unit); + unitCombo.add(unit); } - - unitCombo.select(0); // default to the 1st item of the list. the value is Courier - setUnitComboSelectedIndex(0); + + unitCombo.select(0); // default to the 1st item of the list. the value + // is Courier + setUnitComboSelectedIndex(0); unitCombo.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - setUnitComboSelectedIndex(unitCombo.getSelectionIndex()); - } + public void widgetSelected(SelectionEvent e) { + setUnitComboSelectedIndex(unitCombo.getSelectionIndex()); + } }); /* - * Draw speed Round To selection - */ - roundButton = new Button(topComposite, SWT.CHECK); - String roundTo = "Round speed To:"; - roundButton.setText(roundTo); - roundButton.setSelection(false); + * Draw speed Round To selection + */ + roundButton = new Button(topComposite, SWT.CHECK); + String roundTo = "Round speed To:"; + roundButton.setText(roundTo); + roundButton.setSelection(false); roundButton.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - if (!roundButton.getSelection()) - setRoundComboSelectedIndex(-1); - } + public void widgetSelected(SelectionEvent e) { + if (!roundButton.getSelection()) + setRoundComboSelectedIndex(-1); + } }); - - roundCombo = new Combo(topComposite, SWT.DROP_DOWN | SWT.READ_ONLY); + + roundCombo = new Combo(topComposite, SWT.DROP_DOWN | SWT.READ_ONLY); for (String round : RoundTo) { - roundCombo.add(round); - } - roundCombo.select(0); + roundCombo.add(round); + } + roundCombo.select(0); setRoundComboSelectedIndex(0); roundCombo.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - if (roundButton.getSelection()) - setRoundComboSelectedIndex(roundCombo.getSelectionIndex()); - else - setRoundComboSelectedIndex(-1); - } + public void widgetSelected(SelectionEvent e) { + if (roundButton.getSelection()) + setRoundComboSelectedIndex(roundCombo.getSelectionIndex()); + else + setRoundComboSelectedIndex(-1); + } }); - + /* * Draw Direction Round To selection */ - roundDirButton = new Button(topComposite, SWT.CHECK); - String roundDirTo = "Round Direction To:"; - roundDirButton.setText(roundDirTo); - roundDirButton.setSelection(false); - roundDirButton.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - if (!roundDirButton.getSelection()) - setRoundDirComboSelectedIndex(-1); - } - }); - - roundDirCombo = new Combo(topComposite, SWT.DROP_DOWN | SWT.READ_ONLY); - for (String round : RoundDirTo) { - roundDirCombo.add(round); - } - roundDirCombo.select(0); - setRoundDirComboSelectedIndex(0); - roundDirCombo.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - if (roundDirButton.getSelection()) - setRoundDirComboSelectedIndex(roundDirCombo.getSelectionIndex()); - else - setRoundDirComboSelectedIndex(-1); - } - }); - + roundDirButton = new Button(topComposite, SWT.CHECK); + String roundDirTo = "Round Direction To:"; + roundDirButton.setText(roundDirTo); + roundDirButton.setSelection(false); + roundDirButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + if (!roundDirButton.getSelection()) + setRoundDirComboSelectedIndex(-1); + } + }); + + roundDirCombo = new Combo(topComposite, SWT.DROP_DOWN | SWT.READ_ONLY); + for (String round : RoundDirTo) { + roundDirCombo.add(round); + } + roundDirCombo.select(0); + setRoundDirComboSelectedIndex(0); + roundDirCombo.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + if (roundDirButton.getSelection()) + setRoundDirComboSelectedIndex(roundDirCombo + .getSelectionIndex()); + else + setRoundDirComboSelectedIndex(-1); + } + }); + /* * Draw a single line Label */ - Label optionLabel = new Label(topComposite, SWT.LEFT); - optionLabel.setText("Label Options:"); - //make the label to fill the two columns - GridData gridData = new GridData(); - gridData.horizontalSpan = 2; - optionLabel.setLayoutData(gridData); + Label optionLabel = new Label(topComposite, SWT.LEFT); + optionLabel.setText("Label Options:"); + + // make the label to fill the two columns + GridData gridData = new GridData(); + gridData.horizontalSpan = 2; + optionLabel.setLayoutData(gridData); /* * Draw the four Buttons of Label Options */ - skipFactorButton = new Button(topComposite, SWT.RADIO); - String skipFactorButtonText = "Skip factor"; - skipFactorButton.setText(skipFactorButtonText); - skipFactorButton.setSelection(true); - skipFactorText = new Text(topComposite, SWT.SINGLE | SWT.BORDER); - skipFactorText.setLayoutData( new GridData( textWidth/4, textHeight ) ); + skipFactorButton = new Button(topComposite, SWT.RADIO); + String skipFactorButtonText = "Skip factor"; + skipFactorButton.setText(skipFactorButtonText); + skipFactorButton.setSelection(true); + skipFactorText = new Text(topComposite, SWT.SINGLE | SWT.BORDER); + skipFactorText.setLayoutData(new GridData(textWidth / 4, textHeight)); - skipFactorText.setText("0"); - labelOptionButtonSelectionListenerAction(skipFactorButton, skipFactorText, true, - skipFactorButtonText, 0); - - showFirstLastButton = createButton(topComposite, "Show first&&last", true, 2); - labelOptionButtonSelectionListenerAction(showFirstLastButton, skipFactorText, false, - skipFactorButtonText, 0); + skipFactorText.setText("0"); + labelOptionButtonSelectionListenerAction(skipFactorButton, + skipFactorText, true, skipFactorButtonText, 0); - onHourButton = createButton(topComposite, "On hour", true, 2); - labelOptionButtonSelectionListenerAction(onHourButton, skipFactorText, false, - skipFactorButtonText, 0); + showFirstLastButton = createButton(topComposite, "Show first&&last", + true, 2); + labelOptionButtonSelectionListenerAction(showFirstLastButton, + skipFactorText, false, skipFactorButtonText, 0); - onHalfHourButton = createButton(topComposite, "On half-hour", true, 2); - labelOptionButtonSelectionListenerAction(onHalfHourButton, skipFactorText, false, - skipFactorButtonText, 0); + onHourButton = createButton(topComposite, "On hour", true, 2); + labelOptionButtonSelectionListenerAction(onHourButton, skipFactorText, + false, skipFactorButtonText, 0); + + onHalfHourButton = createButton(topComposite, "On half-hour", true, 2); + labelOptionButtonSelectionListenerAction(onHalfHourButton, + skipFactorText, false, skipFactorButtonText, 0); /* * Initialize the extra point display option as SKIP_FACTOR */ - setExtraPointTimeDisplayOption(ITrack.ExtraPointTimeDisplayOption.SKIP_FACTOR); + setExtraPointTimeDisplayOption(ITrack.ExtraPointTimeDisplayOption.SKIP_FACTOR); /* * Draw some Combo drop down lists */ - Label fontLabel = new Label(topComposite, SWT.LEFT); - fontLabel.setText("Font:"); - fontNameCombo = new Combo(topComposite, SWT.DROP_DOWN | SWT.READ_ONLY); + Label fontLabel = new Label(topComposite, SWT.LEFT); + fontLabel.setText("Font:"); + fontNameCombo = new Combo(topComposite, SWT.DROP_DOWN | SWT.READ_ONLY); for (String fontName : FontName) { - fontNameCombo.add(fontName); + fontNameCombo.add(fontName); } - fontNameCombo.select(0); // default to the 1st item of the list. the value is Courier - setFontNameComboSelectedIndex(0); + fontNameCombo.select(0); // default to the 1st item of the list. the + // value is Courier + setFontNameComboSelectedIndex(0); fontNameCombo.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - setFontNameComboSelectedIndex(fontNameCombo.getSelectionIndex()); - } - }); - - Label fontSizeLabel = new Label(topComposite, SWT.LEFT); - fontSizeLabel.setText("Size:"); - fontSizeCombo = new Combo(topComposite, SWT.DROP_DOWN | SWT.READ_ONLY); - for ( FontSizeName fontSizeName : FontSizeName.values() ) { - fontSizeCombo.add(fontSizeName.name()); + public void widgetSelected(SelectionEvent e) { + setFontNameComboSelectedIndex(fontNameCombo.getSelectionIndex()); + } + }); + + Label fontSizeLabel = new Label(topComposite, SWT.LEFT); + fontSizeLabel.setText("Size:"); + fontSizeCombo = new Combo(topComposite, SWT.DROP_DOWN | SWT.READ_ONLY); + for (FontSizeName fontSizeName : FontSizeName.values()) { + fontSizeCombo.add(fontSizeName.name()); } - fontSizeCombo.select(2); // default to the 3rd item of the list. The value is Medium - setFontSizeComboSelectedIndex(2); + fontSizeCombo.select(2); // default to the 3rd item of the list. The + // value is Medium + setFontSizeComboSelectedIndex(2); fontSizeCombo.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - setFontSizeComboSelectedIndex(fontSizeCombo.getSelectionIndex()); - } - }); - - Label fontStyleLabel = new Label(topComposite, SWT.LEFT); - fontStyleLabel.setText("Style:"); - fontStyleCombo = new Combo(topComposite, SWT.DROP_DOWN | SWT.READ_ONLY); - for ( FontStyle fontStyle : FontStyle.values() ) { - fontStyleCombo.add(fontStyle.name()); + public void widgetSelected(SelectionEvent e) { + setFontSizeComboSelectedIndex(fontSizeCombo.getSelectionIndex()); + } + }); + + Label fontStyleLabel = new Label(topComposite, SWT.LEFT); + fontStyleLabel.setText("Style:"); + fontStyleCombo = new Combo(topComposite, SWT.DROP_DOWN | SWT.READ_ONLY); + for (FontStyle fontStyle : FontStyle.values()) { + fontStyleCombo.add(fontStyle.name()); } - fontStyleCombo.select(2); // default to the 3rd item of the list. The value is Bold - setFontStyleComboSelectedIndex(2); + fontStyleCombo.select(2); // default to the 3rd item of the list. The + // value is Bold + setFontStyleComboSelectedIndex(2); fontStyleCombo.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - setFontStyleComboSelectedIndex(fontStyleCombo.getSelectionIndex()); - } - }); - + public void widgetSelected(SelectionEvent e) { + setFontStyleComboSelectedIndex(fontStyleCombo + .getSelectionIndex()); + } + }); + addSeparator(topComposite.getParent()); - } - - private void frameAndSetTimeButtonSelectionListenerAction(final Button button, - final Text firstTimeText, final Text secondTimeText) { - button.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - String[] firstAndSecondTimeValueArray = null; - String buttonText = button.getText(); - if(buttonText.indexOf("Frame") < 0) { - firstAndSecondTimeValueArray = getFirstSecondTimeInitialTimeValueForSetTimeButton(); - setSetTimeButtonSelected(true); - } else { - firstAndSecondTimeValueArray = getFirstSecondTimeInitialTimeValueForFrameTimeButton(); - setSetTimeButtonSelected(false); - } - firstTimeText.setText(firstAndSecondTimeValueArray[0]); - secondTimeText.setText(firstAndSecondTimeValueArray[1]); - } - }); - } - - private String[] getFirstSecondTimeInitialTimeValueForFrameTimeButton() { - return getFirstSecondTimeInitialTimeValueForSetTimeButton(); - } - - private String[] getFirstSecondTimeInitialTimeValueForSetTimeButton() { - String[] timeValueResult = new String[2]; - Calendar calendar = Calendar.getInstance(); - - calendar.add(Calendar.HOUR_OF_DAY, DEFAULT_HOUR_SHIFT_FOR_FIRST_TIME); - setFirstTimeCalendar(calendar); - timeValueResult[0] = getDateTimeStringValue(calendar); - calendar.add(Calendar.HOUR_OF_DAY, DEFAULT_HOUR_SHIFT_BEYOND_FIRST_TIME); - setSecondTimeCalendar(calendar); - timeValueResult[1] = getDateTimeStringValue(calendar); - -// Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT")); -// //calendar.add(Calendar.HOUR_OF_DAY, DEFAULT_HOUR_SHIFT_FOR_FIRST_TIME); -// setFirstTimeCalendar(calendar); -// timeValueResult[0] = getDateTimeStringValue(calendar); -// -// String intervalStr = getPreviousIntervalTimeValue(); //intervalTimeValue; -// System.out.println("intervalStr "+intervalStr); -// -// if (intervalStr == null || intervalStr.equalsIgnoreCase("")) -// intervalStr = "1:00"; -// String[] intervalString = intervalStr.split(":"); -// -// int day = 0; -// int hr = 0; -// int min = 0; -// if (intervalString.length == 1){ -// try { -// hr = Integer.parseInt(intervalString[0]); -// } -// catch (NumberFormatException e) { -// } -// } -// else if (intervalString.length == 2){ -// try { -// hr = Integer.parseInt(intervalString[0]); -// min = Integer.parseInt(intervalString[1]); -// } -// catch (NumberFormatException e) { -// } -// } -// -// calendar.add(Calendar.HOUR_OF_DAY, hr); -// calendar.add(Calendar.MINUTE, min); -// setSecondTimeCalendar(calendar); -// timeValueResult[1] = getDateTimeStringValue(calendar); - - return timeValueResult; - } + } - private String getFirstOrSecondTimeStringValue(Calendar timeCalendar, boolean isFirstTimeCalendar, TrackPoint[] initTrackPoints) { - String timeStringValue = ""; - if(timeCalendar != null) { - timeStringValue = getDateTimeStringValue(timeCalendar); - } else { - if(initTrackPoints != null && initTrackPoints.length >= 2) { - int trackPointArrayIndex = initTrackPoints.length - 1; - if(isFirstTimeCalendar) - trackPointArrayIndex--; - timeStringValue = getInitialPointsTimeStringValue(initTrackPoints, trackPointArrayIndex); - } - } - return timeStringValue; - } - - private String getInitialPointsTimeStringValue(TrackPoint[] trackPointArray, int pointArrayIndex) { - String timeStringValue = ""; - if(pointArrayIndex < trackPointArray.length) { - TrackPoint targetTrackPoint = trackPointArray[pointArrayIndex]; - if(targetTrackPoint != null && targetTrackPoint.getTime() != null) - timeStringValue = getDateTimeStringValue(targetTrackPoint.getTime()); - } - return timeStringValue; - } - - - private String getDateTimeStringValue(Calendar calendar) { - StringBuilder stringBuilder = new StringBuilder(11); - int year = calendar.get(Calendar.YEAR); - int month = calendar.get(Calendar.MONTH); - int day = calendar.get(Calendar.DAY_OF_MONTH); - int hour = calendar.get(Calendar.HOUR_OF_DAY); - int minute = calendar.get(Calendar.MINUTE); - - String yearString = String.valueOf(year); - stringBuilder.append(yearString.substring(2)); - if((month+1) < 10) - stringBuilder.append(0); - stringBuilder.append((month+1)); - if(day < 10) - stringBuilder.append(0); - stringBuilder.append(day); - stringBuilder.append("/"); - if(hour < 10) - stringBuilder.append(0); - stringBuilder.append(hour); - if(minute < 10) - stringBuilder.append(0); - stringBuilder.append(minute); - - return stringBuilder.toString(); - } - -// private Calendar getCalendarByParsingString(String dateString, String dateFormatPattern) { -// SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormatPattern); //a pattern is something like "yyMMdd/HHmm" -// Calendar cal = null; -// if(dateString == null) -// return cal; -// try { -// Date date = simpleDateFormat.parse(dateString); -// cal = Calendar.getInstance(); -// cal.setTime(date); -// } catch(ParseException pe) { -// log.error("The input of dateString is invalid, parse fails, dateString="+dateString); -// } -// return cal; -// } - - - /** - * a helper method to create an editable text with a text label - * @parentComposite, a parent Composite the text and label are built on - * @textLabel, the value of the labe ltext - * @textStyle, text style value - * @textWidth, text width - * @textHeight, text height - * @isEditable, a boolean to indicate if the text is editable - * @return Text - */ - private Text createTextfieldWithLabel(Composite parentComposite, String textLabel, - int textStyle, int textWidth, int textHeight, boolean isEditable) { + private void frameAndSetTimeButtonSelectionListenerAction( + final Button button, final Text firstTimeText, + final Text secondTimeText) { + button.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + String[] firstAndSecondTimeValueArray = null; + String buttonText = button.getText(); + if (buttonText.indexOf("Frame") < 0) { + firstAndSecondTimeValueArray = getFirstSecondTimeInitialTimeValueForSetTimeButton(); + setSetTimeButtonSelected(true); + } else { + firstAndSecondTimeValueArray = getFirstSecondTimeInitialTimeValueForFrameTimeButton(); + setSetTimeButtonSelected(false); + } + firstTimeText.setText(firstAndSecondTimeValueArray[0]); + secondTimeText.setText(firstAndSecondTimeValueArray[1]); + } + }); + } + + private String[] getFirstSecondTimeInitialTimeValueForFrameTimeButton() { + return getFirstSecondTimeInitialTimeValueForSetTimeButton(); + } + + private String[] getFirstSecondTimeInitialTimeValueForSetTimeButton() { + String[] timeValueResult = new String[2]; + Calendar calendar = Calendar.getInstance(); + + calendar.add(Calendar.HOUR_OF_DAY, DEFAULT_HOUR_SHIFT_FOR_FIRST_TIME); + setFirstTimeCalendar(calendar); + timeValueResult[0] = getDateTimeStringValue(calendar); + calendar.add(Calendar.HOUR_OF_DAY, DEFAULT_HOUR_SHIFT_BEYOND_FIRST_TIME); + setSecondTimeCalendar(calendar); + timeValueResult[1] = getDateTimeStringValue(calendar); + + return timeValueResult; + } + + private String getFirstOrSecondTimeStringValue(Calendar timeCalendar, + boolean isFirstTimeCalendar, TrackPoint[] initTrackPoints) { + String timeStringValue = ""; + if (timeCalendar != null) { + timeStringValue = getDateTimeStringValue(timeCalendar); + } else { + if (initTrackPoints != null && initTrackPoints.length >= 2) { + int trackPointArrayIndex = initTrackPoints.length - 1; + if (isFirstTimeCalendar) + trackPointArrayIndex--; + timeStringValue = getInitialPointsTimeStringValue( + initTrackPoints, trackPointArrayIndex); + } + } + return timeStringValue; + } + + private String getInitialPointsTimeStringValue( + TrackPoint[] trackPointArray, int pointArrayIndex) { + String timeStringValue = ""; + if (pointArrayIndex < trackPointArray.length) { + TrackPoint targetTrackPoint = trackPointArray[pointArrayIndex]; + if (targetTrackPoint != null && targetTrackPoint.getTime() != null) + timeStringValue = getDateTimeStringValue(targetTrackPoint + .getTime()); + } + return timeStringValue; + } + + private String getDateTimeStringValue(Calendar calendar) { + StringBuilder stringBuilder = new StringBuilder(11); + int year = calendar.get(Calendar.YEAR); + int month = calendar.get(Calendar.MONTH); + int day = calendar.get(Calendar.DAY_OF_MONTH); + int hour = calendar.get(Calendar.HOUR_OF_DAY); + int minute = calendar.get(Calendar.MINUTE); + + String yearString = String.valueOf(year); + stringBuilder.append(yearString.substring(2)); + if ((month + 1) < 10) + stringBuilder.append(0); + stringBuilder.append((month + 1)); + if (day < 10) + stringBuilder.append(0); + stringBuilder.append(day); + stringBuilder.append("/"); + if (hour < 10) + stringBuilder.append(0); + stringBuilder.append(hour); + if (minute < 10) + stringBuilder.append(0); + stringBuilder.append(minute); + + return stringBuilder.toString(); + } + + /** + * a helper method to create an editable text with a text label + * + * @parentComposite, a parent Composite the text and label are built on + * @textLabel, the value of the labe ltext + * @textStyle, text style value + * @textWidth, text width + * @textHeight, text height + * @isEditable, a boolean to indicate if the text is editable + * @return Text + */ + private Text createTextfieldWithLabel(Composite parentComposite, + String textLabel, int textStyle, int textWidth, int textHeight, + boolean isEditable) { Label firstTimeLabel = new Label(parentComposite, SWT.NONE); firstTimeLabel.setText(textLabel); - - Text text = new Text(parentComposite, textStyle); - text.setLayoutData( new GridData( textWidth, textHeight ) ); - text.setEditable(isEditable); - return text; - } - - /** - * a helper method to create a button - * @parentComposite, a parent Composite the button is built on - * @buttonText, text value associated with the button - * @isHorizontalSpan, a boolean to indicate if the button should do a span - * @spanValue, this value decides how many columns are spaned - * @return Button - */ - private Button createButton(Composite parentComposite, String buttonText, - boolean isHorizontalSpan, int spanValue) { - Button button = new Button(parentComposite, SWT.RADIO); - button.setText(buttonText); + + Text text = new Text(parentComposite, textStyle); + text.setLayoutData(new GridData(textWidth, textHeight)); + text.setEditable(isEditable); + return text; + } + + /** + * a helper method to create a button + * + * @parentComposite, a parent Composite the button is built on + * @buttonText, text value associated with the button + * @isHorizontalSpan, a boolean to indicate if the button should do a span + * @spanValue, this value decides how many columns are spaned + * @return Button + */ + private Button createButton(Composite parentComposite, String buttonText, + boolean isHorizontalSpan, int spanValue) { + Button button = new Button(parentComposite, SWT.RADIO); + button.setText(buttonText); /* * check to see if the button needs to do horizontal span */ - if(isHorizontalSpan) { - GridData gridData = new GridData(); - gridData.horizontalSpan = spanValue; - button.setLayoutData(gridData); + if (isHorizontalSpan) { + GridData gridData = new GridData(); + gridData.horizontalSpan = spanValue; + button.setLayoutData(gridData); } - return button; - } - - private void labelOptionButtonSelectionListenerAction(final Button button, - final Text targetText, final boolean isTargetTextEditable, - final String skipFactorButtonText, final int defaultSkipFactorValue) { - button.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - targetText.setEditable(isTargetTextEditable); - if(isTargetTextEditable) - targetText.setText(String.valueOf(defaultSkipFactorValue)); - else - targetText.setText(""); - String buttonTextString = button.getText(); - ExtraPointTimeDisplayOption extraPointTimeDisplayOption = - decideExtraPointTimeDisplayOptionByButtonText(buttonTextString); - setExtraPointTimeDisplayOption(extraPointTimeDisplayOption); - } - }); - } - // "Skip factor" "Show first&&last" "On hour" "On half-hour" - private ExtraPointTimeDisplayOption decideExtraPointTimeDisplayOptionByButtonText(String buttonTextString) { -// ITrack.ExtraPointTimeDisplayOption[] testOptions = ITrack.ExtraPointTimeDisplayOption.values(); - - if(buttonTextString.equalsIgnoreCase("Show first&&last")) - return ITrack.ExtraPointTimeDisplayOption.SHOW_FIRST_LAST; - else if(buttonTextString.equalsIgnoreCase("On hour")) - return ITrack.ExtraPointTimeDisplayOption.ON_ONE_HOUR; - else if(buttonTextString.equalsIgnoreCase("On half-hour")) - return ITrack.ExtraPointTimeDisplayOption.ON_HALF_HOUR; - else - return ITrack.ExtraPointTimeDisplayOption.SKIP_FACTOR; - - } - - /** - * Gets the text - */ - public String[] getString(){ + return button; + } - return text.getText().split( "\n" ); + private void labelOptionButtonSelectionListenerAction(final Button button, + final Text targetText, final boolean isTargetTextEditable, + final String skipFactorButtonText, final int defaultSkipFactorValue) { + button.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + targetText.setEditable(isTargetTextEditable); + if (isTargetTextEditable) + targetText.setText(String.valueOf(defaultSkipFactorValue)); + else + targetText.setText(""); + String buttonTextString = button.getText(); + ExtraPointTimeDisplayOption extraPointTimeDisplayOption = decideExtraPointTimeDisplayOptionByButtonText(buttonTextString); + setExtraPointTimeDisplayOption(extraPointTimeDisplayOption); + } + }); + } - } + // "Skip factor" "Show first&&last" "On hour" "On half-hour" + private ExtraPointTimeDisplayOption decideExtraPointTimeDisplayOptionByButtonText( + String buttonTextString) { - /** - * Return font size from the font size combo - */ - public float getFontSize(){ - return ( FontSizeValue[ fontSizeCombo.getSelectionIndex() ] ); - } + if (buttonTextString.equalsIgnoreCase("Show first&&last")) + return ITrack.ExtraPointTimeDisplayOption.SHOW_FIRST_LAST; + else if (buttonTextString.equalsIgnoreCase("On hour")) + return ITrack.ExtraPointTimeDisplayOption.ON_ONE_HOUR; + else if (buttonTextString.equalsIgnoreCase("On half-hour")) + return ITrack.ExtraPointTimeDisplayOption.ON_HALF_HOUR; + else + return ITrack.ExtraPointTimeDisplayOption.SKIP_FACTOR; - /** - * Return font name from the font combo - */ - public String getFontName(){ - return FontName[fontNameCombo.getSelectionIndex()]; - } - - /** - * Return font style from the style combo - */ - public FontStyle getStyle(){ - return FontStyle.values()[ fontStyleCombo.getSelectionIndex() ]; - } - - /** - * Set font size - */ - public void setFontSize( float size ){ - - int index = 0; - for ( int ii = 0; ii < FontSizeValue.length; ii++ ) { - if ( (int)size == FontSizeValue[ ii ] ) { - index = ii; - break; - } - } + } - fontSizeCombo.select( index ); + /** + * Gets the text + */ + public String[] getString() { - } + return text.getText().split("\n"); - /** - * Set font name - */ - public void setFontName( String name ){ - for ( String st:FontName ) { - if ( st.equalsIgnoreCase( name ) ) { - fontNameCombo.setText( st ); - break; - } - } - } - - /** - * set font style - */ - public void setStyle( FontStyle style ){ - for ( FontStyle fs : FontStyle.values() ) { - if ( fs == style ) { - fontStyleCombo.setText( fs.name() ); - break; + } + + /** + * Return font size from the font size combo + */ + public float getFontSize() { + return (FontSizeValue[fontSizeCombo.getSelectionIndex()]); + } + + /** + * Return font name from the font combo + */ + public String getFontName() { + return FontName[fontNameCombo.getSelectionIndex()]; + } + + /** + * Return font style from the style combo + */ + @Override + public FontStyle getFontStyle() { + return FontStyle.values()[fontStyleCombo.getSelectionIndex()]; + } + + /** + * Set font size + */ + public void setFontSize(float size) { + + int index = 0; + for (int ii = 0; ii < FontSizeValue.length; ii++) { + if ((int) size == FontSizeValue[ii]) { + index = ii; + break; } } - } - - /** - * Sets values of all attributes of the dialog. - */ - public void setAttrForDlg( IAttribute attr ){ - } - @Override - public void setAttr(AbstractDrawableComponent adc){ - if ( adc instanceof Track){ - initializeTrackAttrDlg((Track)adc); - } - } - - /* - * All setters and getters start here - */ + fontSizeCombo.select(index); + + } + + /** + * Set font name + */ + public void setFontName(String name) { + for (String st : FontName) { + if (st.equalsIgnoreCase(name)) { + fontNameCombo.setText(st); + break; + } + } + } + + /** + * set font style + */ + public void setFontStyle(FontStyle style) { + for (FontStyle fs : FontStyle.values()) { + if (fs == style) { + fontStyleCombo.setText(fs.name()); + break; + } + } + } + + /** + * Sets values of all attributes of the dialog. + */ + public void setAttrForDlg(IAttribute attr) { + } + + @Override + public void setAttr(AbstractDrawableComponent adc) { + if (adc instanceof Track) { + initializeTrackAttrDlg((Track) adc); + } + } + + /* + * All setters and getters start here + */ public TrackExtrapPointInfoDlg getTrackExtrapPointInfoDlg() { - return trackExtrapPointInfoDlg; - } + return trackExtrapPointInfoDlg; + } - public void setTrackExtrapPointInfoDlg( - TrackExtrapPointInfoDlg trackExtrapPointInfoDlg) { - this.trackExtrapPointInfoDlg = trackExtrapPointInfoDlg; - } + public void setTrackExtrapPointInfoDlg( + TrackExtrapPointInfoDlg trackExtrapPointInfoDlg) { + this.trackExtrapPointInfoDlg = trackExtrapPointInfoDlg; + } public Button getSkipFactorButton() { - return skipFactorButton; - } + return skipFactorButton; + } - public Button getShowFirstLastButton() { - return showFirstLastButton; - } + public Button getShowFirstLastButton() { + return showFirstLastButton; + } - public Button getOnHourButton() { - return onHourButton; - } + public Button getOnHourButton() { + return onHourButton; + } - public Button getOnHalfHourButton() { - return onHalfHourButton; - } + public Button getOnHalfHourButton() { + return onHalfHourButton; + } - public Combo getFontSizeCombo() { - return fontSizeCombo; - } + public Combo getFontSizeCombo() { + return fontSizeCombo; + } - public Combo getFontNameCombo() { - return fontNameCombo; - } + public Combo getFontNameCombo() { + return fontNameCombo; + } - public Combo getFontStyleCombo() { - return fontStyleCombo; - } + public Combo getFontStyleCombo() { + return fontStyleCombo; + } + public int getFontSizeComboSelectedIndex() { + return fontSizeComboSelectedIndex; + } - public int getFontSizeComboSelectedIndex() { - return fontSizeComboSelectedIndex; - } + public void setFontSizeComboSelectedIndex(int fontSizeComboSelectedIndex) { + this.fontSizeComboSelectedIndex = fontSizeComboSelectedIndex; + } - public void setFontSizeComboSelectedIndex(int fontSizeComboSelectedIndex) { - this.fontSizeComboSelectedIndex = fontSizeComboSelectedIndex; - } + public int getFontNameComboSelectedIndex() { + return fontNameComboSelectedIndex; + } - public int getFontNameComboSelectedIndex() { - return fontNameComboSelectedIndex; - } + public void setFontNameComboSelectedIndex(int fontNameComboSelectedIndex) { + this.fontNameComboSelectedIndex = fontNameComboSelectedIndex; + } - public void setFontNameComboSelectedIndex(int fontNameComboSelectedIndex) { - this.fontNameComboSelectedIndex = fontNameComboSelectedIndex; - } + public int getFontStyleComboSelectedIndex() { + return fontStyleComboSelectedIndex; + } - public int getFontStyleComboSelectedIndex() { - return fontStyleComboSelectedIndex; - } + public void setFontStyleComboSelectedIndex(int fontStyleComboSelectedIndex) { + this.fontStyleComboSelectedIndex = fontStyleComboSelectedIndex; + } - public void setFontStyleComboSelectedIndex(int fontStyleComboSelectedIndex) { - this.fontStyleComboSelectedIndex = fontStyleComboSelectedIndex; - } + public Combo getUnitCombo() { + return unitCombo; + } - public Combo getUnitCombo() { - return unitCombo; - } - - public int getUnitComboSelectedIndex() { - return unitComboSelectedIndex; - } + public int getUnitComboSelectedIndex() { + return unitComboSelectedIndex; + } - public void setUnitComboSelectedIndex(int unitComboSelectedIndex) { - this.unitComboSelectedIndex = unitComboSelectedIndex; - } + public void setUnitComboSelectedIndex(int unitComboSelectedIndex) { + this.unitComboSelectedIndex = unitComboSelectedIndex; + } - public Combo getRoundCombo() { - return roundCombo; - } - - public int getRoundComboSelectedIndex() { - return roundComboSelectedIndex; - } + public Combo getRoundCombo() { + return roundCombo; + } - public void setRoundComboSelectedIndex(int roundComboSelectedIndex) { - this.roundComboSelectedIndex = roundComboSelectedIndex; - } + public int getRoundComboSelectedIndex() { + return roundComboSelectedIndex; + } - public Combo getRoundDirCombo() { - return roundDirCombo; - } - - public int getRoundDirComboSelectedIndex() { - return roundDirComboSelectedIndex; - } + public void setRoundComboSelectedIndex(int roundComboSelectedIndex) { + this.roundComboSelectedIndex = roundComboSelectedIndex; + } - public void setRoundDirComboSelectedIndex(int roundDirComboSelectedIndex) { - this.roundDirComboSelectedIndex = roundDirComboSelectedIndex; - } + public Combo getRoundDirCombo() { + return roundDirCombo; + } + public int getRoundDirComboSelectedIndex() { + return roundDirComboSelectedIndex; + } - public boolean isSetTimeButtonSelected() { - return setTimeButtonSelected; - } + public void setRoundDirComboSelectedIndex(int roundDirComboSelectedIndex) { + this.roundDirComboSelectedIndex = roundDirComboSelectedIndex; + } - public void setSetTimeButtonSelected(boolean setTimeButtonSelected) { - this.setTimeButtonSelected = setTimeButtonSelected; - } - public Button getFrameTimeButton() { - return frameTimeButton; - } + public boolean isSetTimeButtonSelected() { + return setTimeButtonSelected; + } - public void setFrameTimeButton(Button frameTimeButton) { - this.frameTimeButton = frameTimeButton; - } + public void setSetTimeButtonSelected(boolean setTimeButtonSelected) { + this.setTimeButtonSelected = setTimeButtonSelected; + } - public Button getSetTimeButton() { - return setTimeButton; - } + public Button getFrameTimeButton() { + return frameTimeButton; + } - public void setSetTimeButton(Button setTimeButton) { - this.setTimeButton = setTimeButton; - } + public void setFrameTimeButton(Button frameTimeButton) { + this.frameTimeButton = frameTimeButton; + } + public Button getSetTimeButton() { + return setTimeButton; + } - public ExtraPointTimeDisplayOption getExtraPointTimeDisplayOption() { - return extraPointTimeDisplayOption; - } + public void setSetTimeButton(Button setTimeButton) { + this.setTimeButton = setTimeButton; + } - public void setExtraPointTimeDisplayOption(ExtraPointTimeDisplayOption extraPointTimeDisplayOption) { - this.extraPointTimeDisplayOption = extraPointTimeDisplayOption; - } + public ExtraPointTimeDisplayOption getExtraPointTimeDisplayOption() { + return extraPointTimeDisplayOption; + } - public String getSkipFactorText() { - return skipFactorText.getText(); - } + public void setExtraPointTimeDisplayOption( + ExtraPointTimeDisplayOption extraPointTimeDisplayOption) { + this.extraPointTimeDisplayOption = extraPointTimeDisplayOption; + } - public void setSkipFactorText(String skipFactorText) { - this.skipFactorText.setText(skipFactorText); - } + public String getSkipFactorText() { + return skipFactorText.getText(); + } - public Text getFirstTimeText() { - return firstTimeText; - } + public void setSkipFactorText(String skipFactorText) { + this.skipFactorText.setText(skipFactorText); + } - public void setFirstTimeText(Text firstTimeText) { - this.firstTimeText = firstTimeText; - } + public Text getFirstTimeText() { + return firstTimeText; + } - public Text getSecondTimeText() { - return secondTimeText; - } + public void setFirstTimeText(Text firstTimeText) { + this.firstTimeText = firstTimeText; + } - public void setSecondTimeText(Text secondTimeText) { - this.secondTimeText = secondTimeText; - } + public Text getSecondTimeText() { + return secondTimeText; + } - public int getExtraDrawingPointNumber() { - int ret = 0; - try { - ret = Integer.parseInt(numberOfTimesText.getText()); - } - catch ( Exception e ){ - ret = 0; - } - - return ret ; - } + public void setSecondTimeText(Text secondTimeText) { + this.secondTimeText = secondTimeText; + } - public void setNumberOfTimesText(Text numberOfTimesText) { - this.numberOfTimesText = numberOfTimesText; - } + public int getExtraDrawingPointNumber() { + int ret = 0; + try { + ret = Integer.parseInt(numberOfTimesText.getText()); + } catch (Exception e) { + ret = 0; + } - public String getPreviousIntervalTimeValue() { - return previousIntervalTimeValue; - } + return ret; + } - public void setPreviousIntervalTimeValue(String previousIntervalTimeValue) { - this.previousIntervalTimeValue = previousIntervalTimeValue; - } + public void setNumberOfTimesText(Text numberOfTimesText) { + this.numberOfTimesText = numberOfTimesText; + } + + public String getPreviousIntervalTimeValue() { + return previousIntervalTimeValue; + } + + public void setPreviousIntervalTimeValue(String previousIntervalTimeValue) { + this.previousIntervalTimeValue = previousIntervalTimeValue; + } public Calendar getFirstTimeCalendar() { - return firstTimeCalendar; - } + return firstTimeCalendar; + } - public String getIntervalTimeString() { - if(intervalCombo.getSelectionIndex() == intervalCombo.getItemCount() - 1) { - return intervalText.getText(); - } - else - return intervalCombo.getText(); - } + public String getIntervalTimeString() { + if (intervalCombo.getSelectionIndex() == intervalCombo.getItemCount() - 1) { + return intervalText.getText(); + } else + return intervalCombo.getText(); + } - private void setIntervalTimeString(String intervalTimeString) { - for ( int ii = 0; ii < intervalCombo.getItemCount(); ii++ ){ - if (intervalTimeString.equalsIgnoreCase( intervalCombo.getItem(ii) )){ - intervalCombo.select(ii); - return; - } - } - - //set for 'Other' - intervalCombo.select( intervalCombo.getItemCount() - 1 ); - intervalText.setText(intervalTimeString); + private void setIntervalTimeString(String intervalTimeString) { + for (int ii = 0; ii < intervalCombo.getItemCount(); ii++) { + if (intervalTimeString.equalsIgnoreCase(intervalCombo.getItem(ii))) { + intervalCombo.select(ii); + return; + } + } - } - - public void setFirstTimeCalendar(Calendar firstTimeCalendar) { - Calendar cal = Calendar.getInstance(); - cal.set(Calendar.YEAR, firstTimeCalendar.get(Calendar.YEAR)); - cal.set(Calendar.MONTH, firstTimeCalendar.get(Calendar.MONTH)); - cal.set(Calendar.DAY_OF_MONTH, firstTimeCalendar.get(Calendar.DAY_OF_MONTH)); - cal.set(Calendar.HOUR_OF_DAY, firstTimeCalendar.get(Calendar.HOUR_OF_DAY)); - cal.set(Calendar.MINUTE, firstTimeCalendar.get(Calendar.MINUTE)); - this.firstTimeCalendar = cal; - } + // set for 'Other' + intervalCombo.select(intervalCombo.getItemCount() - 1); + intervalText.setText(intervalTimeString); - public Calendar getSecondTimeCalendar() { - return secondTimeCalendar; - } + } - public void setSecondTimeCalendar(Calendar secondTimeCalendar) { - Calendar cal = Calendar.getInstance(); - cal.set(Calendar.YEAR, secondTimeCalendar.get(Calendar.YEAR)); - cal.set(Calendar.MONTH, secondTimeCalendar.get(Calendar.MONTH)); - cal.set(Calendar.DAY_OF_MONTH, secondTimeCalendar.get(Calendar.DAY_OF_MONTH)); - cal.set(Calendar.HOUR_OF_DAY, secondTimeCalendar.get(Calendar.HOUR_OF_DAY)); - cal.set(Calendar.MINUTE, secondTimeCalendar.get(Calendar.MINUTE)); - this.secondTimeCalendar = cal; - } + public void setFirstTimeCalendar(Calendar firstTimeCalendar) { + Calendar cal = Calendar.getInstance(); + cal.set(Calendar.YEAR, firstTimeCalendar.get(Calendar.YEAR)); + cal.set(Calendar.MONTH, firstTimeCalendar.get(Calendar.MONTH)); + cal.set(Calendar.DAY_OF_MONTH, + firstTimeCalendar.get(Calendar.DAY_OF_MONTH)); + cal.set(Calendar.HOUR_OF_DAY, + firstTimeCalendar.get(Calendar.HOUR_OF_DAY)); + cal.set(Calendar.MINUTE, firstTimeCalendar.get(Calendar.MINUTE)); + this.firstTimeCalendar = cal; + } - @Override - public Color getExtrapColor() { - Color color =new java.awt.Color( extrapCS.getColorValue().red, - extrapCS.getColorValue().green, extrapCS.getColorValue().blue ); + public Calendar getSecondTimeCalendar() { + return secondTimeCalendar; + } + + public void setSecondTimeCalendar(Calendar secondTimeCalendar) { + Calendar cal = Calendar.getInstance(); + cal.set(Calendar.YEAR, secondTimeCalendar.get(Calendar.YEAR)); + cal.set(Calendar.MONTH, secondTimeCalendar.get(Calendar.MONTH)); + cal.set(Calendar.DAY_OF_MONTH, + secondTimeCalendar.get(Calendar.DAY_OF_MONTH)); + cal.set(Calendar.HOUR_OF_DAY, + secondTimeCalendar.get(Calendar.HOUR_OF_DAY)); + cal.set(Calendar.MINUTE, secondTimeCalendar.get(Calendar.MINUTE)); + this.secondTimeCalendar = cal; + } + + @Override + public Color getExtrapColor() { + Color color = new java.awt.Color(extrapCS.getColorValue().red, + extrapCS.getColorValue().green, extrapCS.getColorValue().blue); return color; - } + } - @Override - public String getExtrapLinePattern() { - // TODO Auto-generated method stub - return null; - } + @Override + public String getExtrapLinePattern() { + // TODO Auto-generated method stub + return null; + } - @Override - public String getExtrapMarker() { - // TODO Auto-generated method stub - return null; - } + @Override + public String getExtrapMarker() { + // TODO Auto-generated method stub + return null; + } - @Override - public TrackPoint[] getExtrapPoints() { - // TODO Auto-generated method stub - return null; - } + @Override + public TrackPoint[] getExtrapPoints() { + // TODO Auto-generated method stub + return null; + } - @Override - public Color getInitialColor(){ - Color color =new java.awt.Color( initialCS.getColorValue().red, - initialCS.getColorValue().green, initialCS.getColorValue().blue ); + @Override + public Color getInitialColor() { + Color color = new java.awt.Color(initialCS.getColorValue().red, + initialCS.getColorValue().green, initialCS.getColorValue().blue); return color; - } + } - @Override - public String getInitialLinePattern() { - // TODO Auto-generated method stub - return null; - } + @Override + public String getInitialLinePattern() { + // TODO Auto-generated method stub + return null; + } - @Override - public String getInitialMarker() { - // TODO Auto-generated method stub - return null; - } + @Override + public String getInitialMarker() { + // TODO Auto-generated method stub + return null; + } - @Override - public TrackPoint[] getInitialPoints() { - // TODO Auto-generated method stub - return null; - } + @Override + public TrackPoint[] getInitialPoints() { + // TODO Auto-generated method stub + return null; + } - /** - * The following methods are used in DrawableElementFactory class to set up all - * necessary attributes for drawing a line. Since Track element dialogue GUI does - * not supply all of those attributes needed by a line. The methods below provide - * some default values for the attributes - */ - /** - * Update the attributes - */ + /** + * The following methods are used in DrawableElementFactory class to set up + * all necessary attributes for drawing a line. Since Track element dialogue + * GUI does not supply all of those attributes needed by a line. The methods + * below provide some default values for the attributes + */ + /** + * Update the attributes + */ public int getSmoothFactor() { - return 0; + return 0; } - + public String getLinePattern() { - return "Solid Line"; + return "Solid Line"; } - + public FillPattern getFillPattern() { - return FillPattern.FILL_PATTERN_0; + return FillPattern.FILL_PATTERN_0; } - + public Boolean isClosedLine() { - return false; + return false; } - + public Boolean isFilled() { - return false; + return false; } - - public Color[] getColors() { - Color[] colors = new Color[1]; - colors[0] = getInitialColor(); - return colors; - } - + + public Color[] getColors() { + Color[] colors = new Color[1]; + colors[0] = getInitialColor(); + return colors; + } + public float getLineWidth() { - return (float)1.0; + return (float) 1.0; } - + public double getSizeScale() { - return 2; + return 2; } - @Override - public FontStyle getFontStyle() { - // TODO Auto-generated method stub - return null; - } + @Override + public boolean[] getExtraPointTimeTextDisplayIndicator() { + // TODO Auto-generated method stub + return null; + } - @Override - public boolean[] getExtraPointTimeTextDisplayIndicator() { - // TODO Auto-generated method stub - return null; - } + @Override + public Coordinate[] getLinePoints() { + // TODO Auto-generated method stub + return null; + } - @Override - public Coordinate[] getLinePoints() { - // TODO Auto-generated method stub - return null; - } + @Override + public String getPatternName() { + // TODO Auto-generated method stub + return null; + } - @Override - public String getPatternName() { - // TODO Auto-generated method stub - return null; - } + /** + * Convert a String in gempak time format to a calendar. + * + * @param gempakTm + * - String in GEMPAK time format + * @return - Calendar + */ + private Calendar gempakTM2Calendar(String gempakTm) { + Calendar cal = null; + try { + cal = Calendar.getInstance(); + int year = 2000 + Integer.valueOf(gempakTm.substring(0, 2)); + int month = Integer.valueOf(gempakTm.substring(2, 4)) - 1; + int day = Integer.valueOf(gempakTm.substring(4, 6)); + int hour = Integer.valueOf(gempakTm.substring(7, 9)); + int min = Integer.valueOf(gempakTm.substring(9)); + cal.set(Calendar.YEAR, year); + cal.set(Calendar.MONTH, month); + cal.set(Calendar.DAY_OF_MONTH, day); + cal.set(Calendar.HOUR_OF_DAY, hour); + cal.set(Calendar.MINUTE, min); + } catch (Exception e) { + cal = null; + } - - /** - * Convert a String in gempak time format to a calendar. - * @param gempakTm - String in GEMPAK time format - * @return - Calendar - */ - private Calendar gempakTM2Calendar( String gempakTm ){ - Calendar cal = null; - try { - cal = Calendar.getInstance(); - int year = 2000 + Integer.valueOf(gempakTm.substring(0, 2)); - int month = Integer.valueOf(gempakTm.substring(2, 4)) - 1; - int day = Integer.valueOf(gempakTm.substring(4, 6)); - int hour = Integer.valueOf(gempakTm.substring(7, 9)); - int min = Integer.valueOf(gempakTm.substring(9)); - cal.set(Calendar.YEAR, year); - cal.set(Calendar.MONTH, month); - cal.set(Calendar.DAY_OF_MONTH, day); - cal.set(Calendar.HOUR_OF_DAY, hour); - cal.set(Calendar.MINUTE, min); - } - catch (Exception e){ - cal = null; - } - - return cal; - } + return cal; + } } diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/display/DefaultElementContainer.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/display/DefaultElementContainer.java index efcc35ab85..893c94e71b 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/display/DefaultElementContainer.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/display/DefaultElementContainer.java @@ -69,9 +69,27 @@ public class DefaultElementContainer extends AbstractElementContainer { public void draw(IGraphicsTarget target, PaintProperties paintProps, DisplayProperties dprops, boolean needsCreate) { - if ((displayEls == null) || paintProps.isZooming()) + /* + * For ghost drawing - "needsCreate && dprops == null" - It is always on + * the active layer so DiaplayProperties' "filled" should be true while + * "monoColor" should be false (using the element's color). + */ + if (needsCreate && dprops == null) { + dprops = new DisplayProperties(false, null, true); + } + + // For normal drawing........ + if ((displayEls == null) || paintProps.isZooming()) { needsCreate = true; + /* + * TTR971 - needs to set display properties, otherwise the layer + * color may not take effect (e.g., after switching projection) + */ + def.setLayerDisplayAttr(dprops.getLayerMonoColor(), + dprops.getLayerColor(), dprops.getLayerFilled()); + } + if (paintProps.getZoomLevel() != zoomLevel) { needsCreate = true; zoomLevel = paintProps.getZoomLevel(); @@ -102,5 +120,4 @@ public class DefaultElementContainer extends AbstractElementContainer { } } - } diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/display/DisplayElementFactory.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/display/DisplayElementFactory.java index eb752cd01b..07d6b64145 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/display/DisplayElementFactory.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/display/DisplayElementFactory.java @@ -143,6 +143,9 @@ import com.vividsolutions.jts.operation.distance.DistanceOp; * 05/14 TTR 995 J. Wu Make contour label auto-placement an option. * 07/14 ? B. Yin Added support for dashed-line circle for TCM 12 feet sea. * 08/14 ? B. Yin Fixed world wrap for TCM track and zero circle issues. + * 08/14 TTR972 J. Wu Draw filled object as filled only if either its layer's "filled" flag + * "true" or they are on the active layer, . + * 09/14 TTR750 J. Wu Draw track label with specified font styles. * * * @author sgilbert @@ -524,6 +527,7 @@ public class DisplayElementFactory { if (isFilled) { list.add(createFill(pts)); } + /* * Compile each IWireframeShape, create its LineDisplayElement, and add * to IDisplayable return list @@ -1814,7 +1818,8 @@ public class DisplayElementFactory { double major = Math.sqrt((diff[0] * diff[0]) + (diff[1] * diff[1])); double minor = major * arc.getAxisRatio(); - if (major / this.screenToExtent < 0.000001) { // ignore circles with major = 0 + if (major / this.screenToExtent < 0.000001) { // ignore circles with + // major = 0 return slist; } @@ -2035,8 +2040,9 @@ public class DisplayElementFactory { Text txt = new Text(null, track.getFontName(), track.getFontSize(), TextJustification.LEFT_JUSTIFY, pt.getLocation(), 0.0, TextRotation.SCREEN_RELATIVE, - new String[] { dtime }, FontStyle.BOLD, iniDspClr, 0, - 3, false, DisplayType.NORMAL, "Text", "General Text"); + new String[] { dtime }, track.getFontStyle(), + iniDspClr, 0, 3, false, DisplayType.NORMAL, "Text", + "General Text"); temps = createDisplayElements((IText) txt, paintProps); slist.addAll(temps); } @@ -2093,8 +2099,9 @@ public class DisplayElementFactory { Text txt = new Text(null, track.getFontName(), track.getFontSize(), TextJustification.LEFT_JUSTIFY, pt.getLocation(), 0.0, TextRotation.SCREEN_RELATIVE, - new String[] { dtime }, FontStyle.BOLD, expDspClr, 0, - 3, false, DisplayType.NORMAL, "Text", "General Text"); + new String[] { dtime }, track.getFontStyle(), + expDspClr, 0, 3, false, DisplayType.NORMAL, "Text", + "General Text"); temps = createDisplayElements((IText) txt, paintProps); slist.addAll(temps); } @@ -4814,10 +4821,22 @@ public class DisplayElementFactory { */ private boolean getDisplayFillMode(Boolean filled) { - if (layerFilled) { - return layerFilled; + /* + * if (layerFilled) { return layerFilled; } else { return filled; } + */ + + /* + * TTR 972 - to match NMAP2 behavior, non-filled elements will always be + * drawn as non-filled. Filled objects should be drawn as filled only + * when the "filled" flag for its layer is set to "true" or they are on + * the active layer, so it is necessary to set the "layerFilled" flag to + * true before generating displayables for such objects (see + * PgenResource.drawFilledElement()). + */ + if (filled && layerFilled) { + return true; } else { - return filled; + return false; } } diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/display/ITrack.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/display/ITrack.java index e82f758c52..e195ede396 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/display/ITrack.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/display/ITrack.java @@ -7,118 +7,134 @@ */ package gov.noaa.nws.ncep.ui.pgen.display; +import gov.noaa.nws.ncep.ui.pgen.display.IText.FontStyle; + import java.awt.Color; import java.util.Calendar; -import gov.noaa.nws.ncep.ui.pgen.display.IText.FontStyle; - /** * Interface used to get specific attributes of a PGEN Storm track object. + * * @author sgilbert - * + * */ -public interface ITrack extends ILine{ +public interface ITrack extends ILine { - /** - * this enum stores the time display options for extra points - */ - public static enum ExtraPointTimeDisplayOption { SKIP_FACTOR, SHOW_FIRST_LAST, ON_ONE_HOUR, ON_HALF_HOUR }; + /** + * this enum stores the time display options for extra points + */ + public static enum ExtraPointTimeDisplayOption { + SKIP_FACTOR, SHOW_FIRST_LAST, ON_ONE_HOUR, ON_HALF_HOUR + }; -// /** -// * Defines available font styles -// * @return font style -// */ -// public static enum FontStyle { -// REGULAR, BOLD, ITALIC, BOLD_ITALIC -// } - /** * Gets a font style for text of track points */ - public FontStyle getFontStyle() ; - - /** - * Fets a boolean array that indicates if a time text of a extra point should be skipped - */ - public boolean[] getExtraPointTimeTextDisplayIndicator(); + public FontStyle getFontStyle(); - /** - * Gets extra point time display option - */ - public ExtraPointTimeDisplayOption getExtraPointTimeDisplayOption(); - - /** - * Gets color to plot the initial storm points - * @return color - */ - public Color getInitialColor(); - - /** - * Gets the line pattern used to display the initial storm points - * @return line pattern - */ - public String getInitialLinePattern(); - - /** - * Gets the marker used to display the initial storm points - * @return marker type - */ - public String getInitialMarker(); - - /** - * Gets the initial storm points and associated date/times - * @return track points - */ - public TrackPoint[] getInitialPoints(); - - /** - * Gets color to plot the extrapolated storm points - * @return color - */ - public Color getExtrapColor(); - - /** - * Gets the line pattern used to display the extrapolated storm points - * @return line pattern - */ - public String getExtrapLinePattern(); - - /** - * Gets the marker used to display the extrapolated storm points - * @return marker type - */ - public String getExtrapMarker(); - - /** - * Gets the extrapolated storm points and associated date/times - * @return track points - */ - public TrackPoint[] getExtrapPoints(); - - /** - * Gets the font used to display the location times - * @return font name - */ - public String getFontName(); - - /** - * Gets the size of the font - * @return font size - */ - public float getFontSize(); - - public Calendar getFirstTimeCalendar(); - public Calendar getSecondTimeCalendar(); - public boolean isSetTimeButtonSelected(); - public int getExtraDrawingPointNumber(); - public FontStyle getStyle(); - public String getSkipFactorText(); - public int getFontNameComboSelectedIndex(); - public int getFontSizeComboSelectedIndex(); - public int getFontStyleComboSelectedIndex(); - public int getUnitComboSelectedIndex(); - public int getRoundComboSelectedIndex(); - public int getRoundDirComboSelectedIndex(); - public String getIntervalTimeString(); + /** + * Fets a boolean array that indicates if a time text of a extra point + * should be skipped + */ + public boolean[] getExtraPointTimeTextDisplayIndicator(); - } + /** + * Gets extra point time display option + */ + public ExtraPointTimeDisplayOption getExtraPointTimeDisplayOption(); + + /** + * Gets color to plot the initial storm points + * + * @return color + */ + public Color getInitialColor(); + + /** + * Gets the line pattern used to display the initial storm points + * + * @return line pattern + */ + public String getInitialLinePattern(); + + /** + * Gets the marker used to display the initial storm points + * + * @return marker type + */ + public String getInitialMarker(); + + /** + * Gets the initial storm points and associated date/times + * + * @return track points + */ + public TrackPoint[] getInitialPoints(); + + /** + * Gets color to plot the extrapolated storm points + * + * @return color + */ + public Color getExtrapColor(); + + /** + * Gets the line pattern used to display the extrapolated storm points + * + * @return line pattern + */ + public String getExtrapLinePattern(); + + /** + * Gets the marker used to display the extrapolated storm points + * + * @return marker type + */ + public String getExtrapMarker(); + + /** + * Gets the extrapolated storm points and associated date/times + * + * @return track points + */ + public TrackPoint[] getExtrapPoints(); + + /** + * Gets the font used to display the location times + * + * @return font name + */ + public String getFontName(); + + /** + * Gets the size of the font + * + * @return font size + */ + public float getFontSize(); + + public Calendar getFirstTimeCalendar(); + + public Calendar getSecondTimeCalendar(); + + public boolean isSetTimeButtonSelected(); + + public int getExtraDrawingPointNumber(); + + public String getSkipFactorText(); + + public int getFontNameComboSelectedIndex(); + + public int getFontSizeComboSelectedIndex(); + + public int getFontStyleComboSelectedIndex(); + + public int getUnitComboSelectedIndex(); + + public int getRoundComboSelectedIndex(); + + public int getRoundDirComboSelectedIndex(); + + public String getIntervalTimeString(); + +} diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/display/RasterElementContainer.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/display/RasterElementContainer.java index f441262a09..ba197bf19c 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/display/RasterElementContainer.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/display/RasterElementContainer.java @@ -15,59 +15,81 @@ import com.raytheon.uf.viz.core.map.IMapDescriptor; /** * An Element Container that can be used for most Symbol/Marker Elements. - * Recreation of the IDisplayable objects is only done if the layer DisplayProperties change. - * The raster images do not need to be recreated when panning or zooming. + * Recreation of the IDisplayable objects is only done if the layer + * DisplayProperties change. The raster images do not need to be recreated when + * panning or zooming. + * * @author sgilbert - * + * */ public class RasterElementContainer extends AbstractElementContainer { - private DisplayProperties saveProps = null; - - /** - * @param element - * @param mapDescriptor - * @param target - */ - public RasterElementContainer(DrawableElement element, - IMapDescriptor mapDescriptor, IGraphicsTarget target) { - super(element, mapDescriptor, target); - // - } + private DisplayProperties saveProps = null; - /* - * Draws to the given graphics target. Recreates the IDisplayable objects - * if the Layer properties change. - * @see gov.noaa.nws.ncep.ui.pgen.display.AbstractTBNL#draw(com.raytheon.uf.viz.core.IGraphicsTarget, com.raytheon.uf.viz.core.drawables.PaintProperties) - */ - @Override - public void draw(IGraphicsTarget target, PaintProperties paintProps, - DisplayProperties dprops) { - draw(target, paintProps, dprops, false); - } + /** + * @param element + * @param mapDescriptor + * @param target + */ + public RasterElementContainer(DrawableElement element, + IMapDescriptor mapDescriptor, IGraphicsTarget target) { + super(element, mapDescriptor, target); + // + } - /* - * Draws to the given graphics target. Recreates the IDisplayable objects - * if the Layer properties change. - * @see gov.noaa.nws.ncep.ui.pgen.display.AbstractTBNL#draw(com.raytheon.uf.viz.core.IGraphicsTarget, com.raytheon.uf.viz.core.drawables.PaintProperties, boolean) - */ - @Override - public void draw(IGraphicsTarget target, PaintProperties paintProps, - DisplayProperties dprops, boolean needsCreate) { - - if ( displayEls == null ) needsCreate = true; - - if ( (dprops != null) && ! dprops.equals(saveProps) ) { - def.setLayerDisplayAttr(dprops.getLayerMonoColor(), dprops.getLayerColor(), dprops.getLayerFilled()); - needsCreate = true; - } - - if ( needsCreate ) createDisplayables(paintProps); - saveProps = dprops; - - for ( IDisplayable each : displayEls ) { - each.draw(target, paintProps); - } - } + /* + * Draws to the given graphics target. Recreates the IDisplayable objects if + * the Layer properties change. + * + * @see + * gov.noaa.nws.ncep.ui.pgen.display.AbstractTBNL#draw(com.raytheon.uf.viz + * .core.IGraphicsTarget, + * com.raytheon.uf.viz.core.drawables.PaintProperties) + */ + @Override + public void draw(IGraphicsTarget target, PaintProperties paintProps, + DisplayProperties dprops) { + draw(target, paintProps, dprops, false); + } + + /* + * Draws to the given graphics target. Recreates the IDisplayable objects if + * the Layer properties change. + * + * @see + * gov.noaa.nws.ncep.ui.pgen.display.AbstractTBNL#draw(com.raytheon.uf.viz + * .core.IGraphicsTarget, + * com.raytheon.uf.viz.core.drawables.PaintProperties, boolean) + */ + @Override + public void draw(IGraphicsTarget target, PaintProperties paintProps, + DisplayProperties dprops, boolean needsCreate) { + + if (displayEls == null) { + needsCreate = true; + + /* + * TTR971 - needs to set display properties, otherwise the layer + * color may not take effect (e.g., after switching projection) + */ + def.setLayerDisplayAttr(dprops.getLayerMonoColor(), + dprops.getLayerColor(), dprops.getLayerFilled()); + } + + if ((dprops != null) && !dprops.equals(saveProps)) { + def.setLayerDisplayAttr(dprops.getLayerMonoColor(), + dprops.getLayerColor(), dprops.getLayerFilled()); + needsCreate = true; + } + + if (needsCreate) + createDisplayables(paintProps); + + saveProps = dprops; + + for (IDisplayable each : displayEls) { + each.draw(target, paintProps); + } + } } diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/display/TextDisplayElement.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/display/TextDisplayElement.java index b25ed35510..0fa6ec7103 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/display/TextDisplayElement.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/display/TextDisplayElement.java @@ -154,6 +154,14 @@ public class TextDisplayElement implements IDisplayable { target.drawShadedRect(box, bg, 1.0, null); } + /* + * TTR 741 (10/2014) - Note, for single-line text, we could match it + * to Raytheon's text style. For multi-line text, we cannot match it + * to Raytheon's since it may add box, overline, underline to each + * line of text, not one single box, overline, or underline - so we + * may need to develop a new drawing method or ask Raytheon to + * provide support in GlTarget. + */ switch (displayType) { case NORMAL: @@ -161,19 +169,40 @@ public class TextDisplayElement implements IDisplayable { break; case BOX: - dstring.textStyle = TextStyle.BOXED; + // dstring.textStyle = TextStyle.BOXED; + if (dstring.getText().length > 1) { + target.drawRect(box, dstring.getColors()[0], 1.0f, 1.0); + } else { + dstring.textStyle = TextStyle.BOXED; + } // target.drawRect(box, dstring.getColors()[0], 1.0f, 1.0); break; case OVERLINE: - dstring.textStyle = TextStyle.OVERLINE; + // dstring.textStyle = TextStyle.OVERLINE; + if (dstring.getText().length > 1) { + target.drawLine(box.getMinX(), box.getMinY(), 0.0, + box.getMaxX(), box.getMinY(), 0.0, + dstring.getColors()[0], 1.0f); + } else { + + dstring.textStyle = TextStyle.OVERLINE; + } // target.drawLine(box.getMinX(), box.getMinY(), 0.0, // box.getMaxX(), box.getMinY(), 0.0, // dstring.getColors()[0], 1.0f); break; case UNDERLINE: - dstring.textStyle = TextStyle.UNDERLINE; + // dstring.textStyle = TextStyle.UNDERLINE; + if (dstring.getText().length > 1) { + target.drawLine(box.getMinX(), box.getMaxY(), 0.0, + box.getMaxX(), box.getMaxY(), 0.0, + dstring.getColors()[0], 1.0f); + + } else { + dstring.textStyle = TextStyle.UNDERLINE; + } // target.drawLine(box.getMinX(), box.getMaxY(), 0.0, // box.getMaxX(), box.getMaxY(), 0.0, // dstring.getColors()[0], 1.0f); diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/elements/Track.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/elements/Track.java index 1e67621d07..dd9f624e75 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/elements/Track.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/elements/Track.java @@ -38,1133 +38,1185 @@ import com.vividsolutions.jts.geom.Coordinate; * 02/12 TTR456 Q.Zhou Added speed knot, mph. Added combos and roundTo indices for speed & dir . * Modified setSpeed * 06/12 #777 Q.Zhou Modified DEFAULT_EXTRA_POINT_NUMBER. - * 08/13 #1020 B. Yin Added a method to get direction 'FROM'. + * 08/13 #1020 B. Yin Added a method to get direction 'FROM'. * * - * @author M. Gao - * @version 0.0.1 + * @author M. Gao + * @version 0.0.1 */ -@ElementOperations ( {Operation.COPY_MOVE, Operation.EXTRAPOLATE} ) +@ElementOperations({ Operation.COPY_MOVE, Operation.EXTRAPOLATE }) public class Track extends Line implements ITrack { -//public class Track extends MultiPointElement implements ITrack { - -// private final static org.apache.log4j.Logger log = -// org.apache.log4j.Logger.getLogger(Track.class); - - - private final static float DEFAULT_FONT_SIZE = 14.0f; - private final static float DEFAULT_LINE_WIDTH = 0.1f; - private final static int DEFAULT_EXTRA_POINT_NUMBER = 5; -// private final static int DEFAULT_INTERVAL_HOUR = 1; - private final static String INTERVAL_TIME_FORMAT_PATTERN = "HH:mm"; - public void setExtrapMarker(String extrapMarker) { - this.extrapMarker = extrapMarker; - } - - public void setExtrapLinePattern(String extrapLinePattern) { - this.extrapLinePattern = extrapLinePattern; - } - - private final static String INITIAL_MARKER = "FILLED_DIAMOND"; - private final static String EXTRAP_MARKER = "FILLED_TRIANGLE"; - private final static String INITIAL_LINE_PATTERN = "LINE_SOLID"; - private final static String EXTRAP_LINE_PATTERN = "LINE_SOLID"; - /* - * This value of DEFAULT_LINE_PATTERN is a temporary solution - * Eventually a decision needs to be done for what a value - * should be used - */ - public final static String TRACK_PGEN_CATEGORY = "Track"; - public final static String TRACK_INFO_DLG_CATEGORY_NAME = "TRACK_EXTRA_POINTS_INFO"; - public final static String TRACK_PGEN_TYPE = "STORM_TRACK"; - - private Color initialColor; - private Color extrapColor; - private String initialMarker; - private String initialLinePattern; - private String extrapMarker; - private String extrapLinePattern; - - private TrackPoint[] initTrackPoints; - private TrackPoint[] extrapPoints; - private String fontName; - private float fontSize; - private FontStyle fontStyle; - - private float lineWidth; - private int extraDrawingPointNumber; - - private boolean setTimeButtonSelected; - - private Calendar firstTimeCalendar; - private Calendar secondTimeCalendar; - private String intervalTimeString; - private int intervalComboSelectedIndex; - - private int fontSizeComboSelectedIndex; - private int fontNameComboSelectedIndex; - private int fontStyleComboSelectedIndex; - - private int elapsedHourForExtraPoint; - private int elapsedMinuteForExtraPoint; - - private ExtraPointTimeDisplayOption extraPointTimeDisplayOption; - private String skipFactorTextString; - private boolean[] extraPointTimeTextDisplayIndicator; - - // direction, speed and unit are not saved to a file - private double directionForExtraPoints; - private boolean roundDirBtnSelected; - private int roundDirComboSelectedIndex; - - private double speed; // speed in meter/millisecond - private double speedInKnotOverHour; - private double speedInKilometerOverHour; - private double speedInMileOverHour; - private boolean roundBtnSelected; - private int unitComboSelectedIndex; - private int roundComboSelectedIndex; - - public Track() {} - - public Track(ArrayList _locations, Calendar _firstTimeCalendar, - Calendar _secondTimeCalendar) { - initializeInitTrackPoints(_locations, - _firstTimeCalendar, _secondTimeCalendar); - } - - - public void initializeInitTrackPoints(ArrayList locations, - Calendar firstTimeCalendar, Calendar secondTimeCalendar) { - initializeInitTrackPoints(locations); - initializeInitFirstTimeCalendar(firstTimeCalendar); - initializeInitSecondTimeCalendar(secondTimeCalendar); - } - - public void initializeTrackByTrackAttrDlgAndLocationList(ITrack trackAttrDlgObject, ArrayList locations) { - initializeInitTrackPoints(locations); - initializeInitFirstTimeCalendar(trackAttrDlgObject.getFirstTimeCalendar()); - initializeInitSecondTimeCalendar(trackAttrDlgObject.getSecondTimeCalendar()); - - this.setInitialMarker(""); - this.setSetTimeButtonSelected(trackAttrDlgObject.isSetTimeButtonSelected()); - this.setExtraDrawingPointNumber(trackAttrDlgObject.getExtraDrawingPointNumber()); - - this.setIntervalTimeString(getIntervalTimeTextStringValue(trackAttrDlgObject)); - - this.setFontName(trackAttrDlgObject.getFontName()); - this.setFontStyle(trackAttrDlgObject.getStyle()); - this.setFontSize(trackAttrDlgObject.getFontSize()); - this.setInitialColor(trackAttrDlgObject.getInitialColor()); - this.setExtrapColor(trackAttrDlgObject.getExtrapColor()); - this.setExtraPointTimeDisplayOption(trackAttrDlgObject.getExtraPointTimeDisplayOption()); - this.setSkipFactorTextString(trackAttrDlgObject.getSkipFactorText()); - this.setFontNameComboSelectedIndex(trackAttrDlgObject.getFontNameComboSelectedIndex()); - this.setFontSizeComboSelectedIndex(trackAttrDlgObject.getFontSizeComboSelectedIndex()); - this.setFontStyleComboSelectedIndex(trackAttrDlgObject.getFontStyleComboSelectedIndex()); - this.setUnitComboSelectedIndex(trackAttrDlgObject.getUnitComboSelectedIndex()); - this.setRoundComboSelectedIndex(trackAttrDlgObject.getRoundComboSelectedIndex()); - if (trackAttrDlgObject.getRoundComboSelectedIndex() >0) - this.setRoundBtnSelected(true); - else - this.setRoundBtnSelected(false); - - this.setRoundDirComboSelectedIndex(trackAttrDlgObject.getRoundDirComboSelectedIndex()); - if (trackAttrDlgObject.getRoundDirComboSelectedIndex() >0) - this.setRoundDirBtnSelected(true); - else - this.setRoundDirBtnSelected(false); - - //This method can be called only after all of the above settings are completed! - this.calculateExtrapTrackPoints(); - /** - * For now, the type is the name of a LinePattern defined in - * "gov.noaa.nws.ncep.ui.pgen.display.LinePatternList" - * However, there is no type has been decided for Track element - * yet. Thus, it is now hard coded. - */ -// this.setType("Solid Lines"); - this.setPgenCategory(Track.TRACK_PGEN_CATEGORY); - this.setPgenType(Track.TRACK_PGEN_TYPE); - } - - public void initializeInitTrackPoints(ArrayList locations) { - TrackPoint[] initTrackPointArray = new TrackPoint[locations.size()]; - int arrayIndex = 0; -// log.info("inside Track.initializeInitTrackPoints, points Number="+locations.size()); - for(Coordinate currentCoordinate : locations) { - TrackPoint eachTrackPoint = new TrackPoint(currentCoordinate, null); - initTrackPointArray[arrayIndex++] = eachTrackPoint; - } - setInitTrackPoints(initTrackPointArray); - } - - public void initializeInitFirstTimeCalendar(Calendar firstCalendar) { - setFirstTimeCalendar(firstCalendar); - if(getInitTrackPoints() != null) { - int initTrackPointLength = getInitTrackPoints().length; - if(initTrackPointLength >= 2) { - getInitTrackPoints()[initTrackPointLength - 2].setTime(firstCalendar); - } - } - } - - public void initializeInitSecondTimeCalendar(Calendar secondCalendar) { - setSecondTimeCalendar(secondCalendar); - if(getInitTrackPoints() != null) { - int initTrackPointLength = getInitTrackPoints().length; - if(initTrackPointLength >= 2) { - getInitTrackPoints()[initTrackPointLength - 1].setTime(secondCalendar); - } - } - } - - public void calculateExtrapTrackPoints() { - extrapPoints = calculateExtrapTrackPoints(getInitialPoints(), getFirstTimeCalendar(), - getSecondTimeCalendar(), getExtraDrawingPointNumber(), - getElapsedHourForExtraPoint(), getElapsedMinuteForExtraPoint(), - getExtraPointTimeDisplayOption(), getSkipFactorTextString()); - - /* - * it is important to override the variable "ArrayList linePoints" with - * initTrackPoints and extrapPoints arrays - */ - setLinePointsValue(getInitialPoints(), getExtrapPoints()); - - /* - * a linePattern needs to be set for PgenSelectingTool to pick up - * the correct dialogue window to popup - */ - setPgenCategory(Track.TRACK_PGEN_CATEGORY); - setPgenType(Track.TRACK_PGEN_TYPE); - } - - public void setLinePointsValue(TrackPoint[] initTrackPoints, TrackPoint[] extrapPoints) { - int listSize = 1; - if(initTrackPoints != null) - listSize += initTrackPoints.length; - if(extrapPoints != null) - listSize += extrapPoints.length; - ArrayList coordinatePointList = new ArrayList(listSize); - addArrayToArrayList(coordinatePointList, initTrackPoints); - addArrayToArrayList(coordinatePointList, extrapPoints); - - /* - * Now use the inherited method setLinePoints to set the linPoints value - */ - setLinePoints(coordinatePointList); - } - - /** - * Creates a copy of this object. This is a deep copy and new objects are - * created so that we are not just copying references of objects - */ -// @Override -// public DrawableElement copy() { - public Track copy() { - - /* - * create a new Track object and initially set its attributes to this one's - */ - Track newTrack = new Track(); - Calendar newFirstTimeCalendar = Calendar.getInstance(); - newFirstTimeCalendar.setTimeInMillis(getFirstTimeCalendar().getTimeInMillis()); - newTrack.setFirstTimeCalendar(newFirstTimeCalendar); -// newTrack.setFirstTimeCalendar(getFirstTimeCalendar()); - - Calendar newSecondTimeCalendar = Calendar.getInstance(); - newSecondTimeCalendar.setTimeInMillis(getSecondTimeCalendar().getTimeInMillis()); - newTrack.setSecondTimeCalendar(newSecondTimeCalendar); -// newTrack.setSecondTimeCalendar(getSecondTimeCalendar()); - - TrackPoint[] newInitTrackPoints = new TrackPoint[getInitTrackPoints().length]; -// log.info("######, before enter the loop for TrackPoint.clone, newInitTrackPoints.length="+newInitTrackPoints.length); - for(int i=0; i0) - this.setRoundBtnSelected(true); - else - this.setRoundBtnSelected(false); - - setRoundDirComboSelectedIndex(trackAttrDlg.getRoundDirComboSelectedIndex()); - if (trackAttrDlg.getRoundDirComboSelectedIndex() >0) - this.setRoundDirBtnSelected(true); - else - this.setRoundDirBtnSelected(false); - - //This method can be called only after all of the above settings are completed! - calculateExtrapTrackPoints(); - /** - * For now, the type is the name of a LinePattern defined in - * "gov.noaa.nws.ncep.ui.pgen.display.LinePatternList" - * However, there is no type has been decided for Track element - * yet. Thus, it is now hard coded. - */ -// setType("Solid Lines"); - setPgenType(Track.TRACK_PGEN_TYPE); - setPgenCategory(Track.TRACK_PGEN_CATEGORY); - } - - public void addPoint(int index, Coordinate point) { - ArrayList allLinePoints = getPoints(); - if(allLinePoints == null) - allLinePoints = new ArrayList(); - - if(allLinePoints.size() <= index) - allLinePoints.add(point); - else - allLinePoints.add(index, point); - - int initialPointSize= getInitialPoints().length; - int extrapPointSize = getExtrapPoints().length; - - if(index < initialPointSize) { - TrackPoint modifiedTrackPoint = getInitialPoints()[index]; - modifiedTrackPoint.setLocation(point); - } else { - int extrapindex = index - initialPointSize; - if(extrapindex >= 0 && extrapindex < extrapPointSize) { - TrackPoint modifiedTrackPoint = getExtrapPoints()[extrapindex]; - modifiedTrackPoint.setLocation(point); - } - } -// linePoints.add(index, point); - } - - public void removePoint(int index ) { - ArrayList allLinePoints = getPoints(); - if(allLinePoints == null) - return; -// if(allLinePoints.size() > index && getInitialPoints().length > index) { - if(allLinePoints.size() > index) { - allLinePoints.remove(index); - } - -// linePoints.remove( index ); - - } - - public void setPoints( ArrayList pts ){ - if(pts == null) - return; - /* - * call MultiPointElement.setPoint(...) - */ - super.setPoints(pts); - /* - * Now initialize initPoint and ExtrapPoint arrays - */ - int allPointsSize = pts.size(); - - int initTrackPointSize = 0; - if(getInitTrackPoints() != null) - initTrackPointSize = getInitTrackPoints().length; - int index = 0; - - /* - * reset coordinate values for initial track points - */ - while(index < initTrackPointSize && index < allPointsSize) { - TrackPoint currentTrackPoint = getInitTrackPoints()[index]; - if(currentTrackPoint != null) - currentTrackPoint.setLocation(pts.get(index)); - index++; - } - - - - - int extrapTrackPointSize = 0; - if(getExtrapPoints() != null) - extrapTrackPointSize = getExtrapPoints().length; - int extrapIndex = 0; - while(extrapIndex < extrapTrackPointSize && - index < allPointsSize) { - TrackPoint currentTrackPoint = getExtrapPoints()[extrapIndex]; - if(currentTrackPoint != null) - currentTrackPoint.setLocation(pts.get(index)); - index++; - extrapIndex++; - } - - -// this.linePoints = pts; - - } - - /* - * All private help methods start here - */ - private String getIntervalTimeTextStringValue(ITrack trackAttrDlg) { - - return trackAttrDlg.getIntervalTimeString(); - } - - private void addArrayToArrayList(ArrayList coordinatePointList, TrackPoint[] trackPoints) { - if(trackPoints == null) - return; - for(TrackPoint trackPoint : trackPoints) { - coordinatePointList.add(trackPoint.getLocation()); - } - } - - private TrackPoint[] calculateExtrapTrackPoints(TrackPoint[] initialPoints, - Calendar initPointBeforeLastInitPointTimeCal, - Calendar lastInitPointTimeCal, - int extraDrawingPointNumber, - int elapsedHourForExtraPointValue, - int elapsedMinuteForExtraPointValue, - ExtraPointTimeDisplayOption extraPointTimeDisplayOption, - String skipFactorTextString) { - if(initialPoints == null || initialPoints.length < 2) { -// log.error("Method:calculateExtrapTrackPoints, the input initialPoints is null or initialPoints.length less than 2"); - return null; - } - - int arrayLength = initialPoints.length; - Coordinate initPointBeforeLastInitPointCoordinate = initialPoints[arrayLength - 2].getLocation(); - Coordinate lastInitPointCoordinate = initialPoints[arrayLength - 1].getLocation(); - if(!isCoordinateValid(initPointBeforeLastInitPointCoordinate) || - !isCoordinateValid(lastInitPointCoordinate) || - initPointBeforeLastInitPointTimeCal == null || - lastInitPointTimeCal == null) { -// log.error("Method: calculateExtrapTrackPoints, find 4 possible invalid input: startPointCoordinate or "+ -// "destPointCoordinate is invalid. firstTimeCal or secondTimeCal is null"); - return null; - } - - GeodeticCalculator gc = new GeodeticCalculator(DefaultEllipsoid.WGS84); - gc.setStartingGeographicPoint(initPointBeforeLastInitPointCoordinate.x, - initPointBeforeLastInitPointCoordinate.y); - gc.setDestinationGeographicPoint(lastInitPointCoordinate.x, - lastInitPointCoordinate.y); - double direction = gc.getAzimuth(); - setDirectionForExtraPoints(direction); - - double distanceInMeter = gc.getOrthodromicDistance(); - long timeDifference = getTimeDifferenceInMillisecond(initPointBeforeLastInitPointTimeCal, - lastInitPointTimeCal); - double speed = distanceInMeter / (double)timeDifference; - setSpeed(speed); - - //Calculate the first extra point time Calendar - Calendar firstExtraPointTimeCal = getTimeElapsedCalendarForFirstExtraPoint(lastInitPointTimeCal, - elapsedHourForExtraPointValue, - elapsedMinuteForExtraPointValue); - - //calculate the distance between the last Initial point and the first extra point - double distanceBetweenLastInitPointAndFirstExtraPoint = calculateDistanceBetweenLastInitPointAndFirstExtraPoint(speed, - lastInitPointTimeCal, firstExtraPointTimeCal); - - //calculate the distance among extra points - double distanceForExtraPoint = calculateDistanceForExtraPoints(speed, - firstExtraPointTimeCal, elapsedHourForExtraPointValue, - elapsedMinuteForExtraPointValue); - - TrackPoint[] extrapTrackPointArray = calculateExtrapTrackPoints(gc, - lastInitPointCoordinate, direction, - distanceBetweenLastInitPointAndFirstExtraPoint, - distanceForExtraPoint, - extraDrawingPointNumber, lastInitPointTimeCal, - firstExtraPointTimeCal, - elapsedHourForExtraPointValue, - elapsedMinuteForExtraPointValue); - disableSomeTimeTagsDisplayBasedOnExtraPointTimeDisplayOption(extrapTrackPointArray, - extraPointTimeDisplayOption, skipFactorTextString); - - return extrapTrackPointArray; - } - - private void disableSomeTimeTagsDisplayBasedOnExtraPointTimeDisplayOption(TrackPoint[] extrapTrackPointArray, - ExtraPointTimeDisplayOption extraPointTimeDisplayOption, String skipFactorTextString) { - if(extrapTrackPointArray == null) - return; - boolean[] extraPointTimeTagFlagArray = new boolean[extrapTrackPointArray.length]; - initializeBooleanArray(extraPointTimeTagFlagArray, true); - - if(extraPointTimeDisplayOption == ITrack.ExtraPointTimeDisplayOption.SKIP_FACTOR) { - removeTimeTagsBasedOnSkipFactor(extrapTrackPointArray, skipFactorTextString, extraPointTimeTagFlagArray); - } else if(extraPointTimeDisplayOption == ITrack.ExtraPointTimeDisplayOption.SHOW_FIRST_LAST) { - removeTimeTagsBasedOnShowLastFirstOnly(extrapTrackPointArray, extraPointTimeTagFlagArray); - } else if(extraPointTimeDisplayOption == ITrack.ExtraPointTimeDisplayOption.ON_ONE_HOUR) { - removeTimeTagsBasedOnHourMinuteValue(extrapTrackPointArray, true, extraPointTimeTagFlagArray); - } else if(extraPointTimeDisplayOption == ITrack.ExtraPointTimeDisplayOption.ON_HALF_HOUR) { - removeTimeTagsBasedOnHourMinuteValue(extrapTrackPointArray, false, extraPointTimeTagFlagArray); - } - else { - removeTimeTagsBasedOnHourMinuteValue(extrapTrackPointArray, false, extraPointTimeTagFlagArray); - } - - /* - * set the updated boolean array back to the indicator, - * in displayElementFactory, this boolean array will be - * used to indicate if a time text should be skipped - */ - setExtraPointTimeTextDisplayIndicator(extraPointTimeTagFlagArray); - } - - private void removeTimeTagsBasedOnShowLastFirstOnly(TrackPoint[] extrapTrackPointArray, boolean[] timeTagIndicatorArray) { - if(extrapTrackPointArray.length < 3) - return; - for(int i=1; i<(extrapTrackPointArray.length - 1); i++) { - timeTagIndicatorArray[i] = false; - } - } - - private void removeTimeTagsBasedOnSkipFactor(TrackPoint[] extrapTrackPointArray, - String skipFactorTextString, boolean[] timeTagIndicatorArray) { - if(skipFactorTextString == null) - return; - /* - * always show the time tags of the first and last extra points - */ - if(extrapTrackPointArray.length < 3) - return; - - int skipFactorIntValue = 0; - try { - skipFactorIntValue = Integer.parseInt(skipFactorTextString); - } catch(NumberFormatException nfe) { -// log.error("The input of skipFactorTextString is invalid, skipFactorTextString="+ -// skipFactorTextString); - } - - /* - * 1. make sure skipFactorIntValue is a valid value - * 2. since the last and first extra points are always - * displayed, thus do skipFactorIntValue > (extrapTrackPointArray.length - 2) - * check - */ - if(!(skipFactorIntValue > 0) || skipFactorIntValue > (extrapTrackPointArray.length - 2)) - return; - - for(int i=1; i<=skipFactorIntValue; i++) { - timeTagIndicatorArray[i] = false; - } - } - - private void removeTimeTagsBasedOnHourMinuteValue(TrackPoint[] extrapTrackPointArray, - boolean isExactHourDisplayed, boolean[] timeTagIndicatorArray) { - for(int i=0; i<(extrapTrackPointArray.length); i++) { - TrackPoint targetTrackPoint = extrapTrackPointArray[i]; - Calendar targetPointTimeCal = targetTrackPoint.getTime(); - - if(!isTimeTagDisplayable(targetPointTimeCal, isExactHourDisplayed)) { - /* - * mark the flag array index for the time needs to be hided - */ - timeTagIndicatorArray[i] = false; - } - } - } - - private void initializeBooleanArray(boolean[] booleanArray, boolean initValue) { - if(booleanArray == null) - return; - for(int i=0; i 180.0 || coordinate.x < -180.0 || coordinate.y > 90.0 || - coordinate.y < -90.0) - return false; - return true; - } - - private Calendar getIntervalCalendarByParsingString(String dateString, - String formatStringPattern, Calendar secondTimeCal) { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat(formatStringPattern); - Calendar cal = null; - int elapsedHour = 1; - int elapsedMinute = 0; - if(dateString != null) { - try { - Date date = simpleDateFormat.parse(dateString); - cal = Calendar.getInstance(); - cal.setTime(date); - elapsedHour = cal.get(Calendar.HOUR_OF_DAY); - elapsedMinute = cal.get(Calendar.MINUTE); - } catch(ParseException pe) { -// log.error("The input of dateString is invalid, parse fails, dateString="+dateString); - elapsedHour = 1; - } - } - setElapsedHourForExtraPoint(elapsedHour); - setElapsedMinuteForExtraPoint(elapsedMinute); - cal = getTimeElapsedCalendar(secondTimeCal, elapsedHour, elapsedMinute); - return cal; - } - - private Calendar getTimeElapsedCalendarForFirstExtraPoint(Calendar startCalendar, int elapsedHour, - int elapsedMinute) { - Calendar nextCal = Calendar.getInstance(); - nextCal.setTimeInMillis(startCalendar.getTimeInMillis()); - /* - * played with the nmap2 APP, get confused with the logic behind, right now, calculate - * the first extra point as the logic described below: - * 1. if elapsedHour > 1 hour, set the first extra point time as the next exact hour - * 2. if elapsedHour == 0 and last init. point MINUTE value >= elapsedMinute, - * set the first time extra point as the next exact hour - * 3. if elapsedHour == 0 and last init. point MINUTE value < elapsedMinute, - * set the first time extra point as the exact hour of the last init. point + elapsedMinute - * In the future, this logic may be changed once the real logic is figured. Michael Gao comment. - */ - if(elapsedHour >= 1) { - nextCal.set(Calendar.MINUTE, 0); - nextCal.add(Calendar.HOUR_OF_DAY, 1); - } else { - int currentMinute = nextCal.get(Calendar.MINUTE); - if(currentMinute >= elapsedMinute) { - nextCal.set(Calendar.MINUTE, 0); - nextCal.add(Calendar.HOUR_OF_DAY, 1); - } else { - nextCal.set(Calendar.MINUTE, elapsedMinute); - } - } - return nextCal; - } - - private Calendar getTimeElapsedCalendar(Calendar startCalendar, int elapsedHour, - int elapsedMinute) { - Calendar nextCal = Calendar.getInstance(); - nextCal.setTimeInMillis(startCalendar.getTimeInMillis()); - nextCal.add(Calendar.HOUR_OF_DAY, elapsedHour); - nextCal.add(Calendar.MINUTE, elapsedMinute); - return nextCal; - } - - - /* - * all override setters and getters of the instance variables go here - */ - @Override - public Color getExtrapColor() { - return this.extrapColor; - } - - @Override - public String getExtrapLinePattern() { - return EXTRAP_LINE_PATTERN; - } - - @Override - public String getExtrapMarker() { - return EXTRAP_MARKER; - } - - public TrackPoint[] getInitTrackPoints() { - return initTrackPoints; - } - - public void setInitTrackPoints(TrackPoint[] initTrackPoints) { - this.initTrackPoints = initTrackPoints; - } - - public void setExtrapPoints(TrackPoint[] extrapPoints) { - this.extrapPoints = extrapPoints; - } - - @Override - public TrackPoint[] getExtrapPoints() { - return extrapPoints; - } - - @Override - public Color getInitialColor() { - return this.initialColor; - } - - @Override - public String getInitialLinePattern() { - return INITIAL_LINE_PATTERN; - } - - @Override - public String getInitialMarker() { - return INITIAL_MARKER; - } - - @Override - public TrackPoint[] getInitialPoints() { - return initTrackPoints; - } - - @Override - public String getFontName() { - return this.fontName; - } - - public void setFontName(String _fontName) { - this.fontName = _fontName; - } - - @Override - public float getFontSize() { - if(this.fontSize <= 0.0) - return DEFAULT_FONT_SIZE; - return this.fontSize; - } - - public void setFontSize(float _fontSize) { - this.fontSize = _fontSize; - } - - public FontStyle getFontStyle() { - return fontStyle; - } - - public void setFontStyle(FontStyle fontStyle) { - this.fontStyle = fontStyle; - } - - @Override - public float getLineWidth() { - if(this.lineWidth <= 0.0) - return DEFAULT_LINE_WIDTH; - return this.lineWidth; - } - - /* - * all non-override setters and getters of the instance variables go here - */ - public boolean isSetTimeButtonSelected() { - return setTimeButtonSelected; - } - - public void setSetTimeButtonSelected(boolean setTimeButtonSelected) { - this.setTimeButtonSelected = setTimeButtonSelected; - } - - public int getFontSizeComboSelectedIndex() { - return fontSizeComboSelectedIndex; - } - - public void setFontSizeComboSelectedIndex(int fontSizeComboSelectedIndex) { - this.fontSizeComboSelectedIndex = fontSizeComboSelectedIndex; - } - - public int getFontNameComboSelectedIndex() { - return fontNameComboSelectedIndex; - } - - public void setFontNameComboSelectedIndex(int fontNameComboSelectedIndex) { - this.fontNameComboSelectedIndex = fontNameComboSelectedIndex; - } - - public int getFontStyleComboSelectedIndex() { - return fontStyleComboSelectedIndex; - } - - public void setFontStyleComboSelectedIndex(int fontStyleComboSelectedIndex) { - this.fontStyleComboSelectedIndex = fontStyleComboSelectedIndex; - } - - public int getIntervalComboSelectedIndex() { - return intervalComboSelectedIndex; - } - - public void setIntervalComboSelectedIndex(int intervalComboSelectedIndex) { - this.intervalComboSelectedIndex = intervalComboSelectedIndex; - } - - public int getUnitComboSelectedIndex() { - return unitComboSelectedIndex; - } - - public void setUnitComboSelectedIndex(int unitComboSelectedIndex) { - this.unitComboSelectedIndex = unitComboSelectedIndex; - } - - public int getRoundComboSelectedIndex() { - return roundComboSelectedIndex; - } - - public void setRoundComboSelectedIndex(int roundComboSelectedIndex) { - this.roundComboSelectedIndex = roundComboSelectedIndex; - } - - public boolean getRoundBtnSelected() { - return roundBtnSelected; - } - - public void setRoundBtnSelected(boolean roundBtnSelected) { - this.roundBtnSelected = roundBtnSelected; - } - - public int getRoundDirComboSelectedIndex() { - return roundDirComboSelectedIndex; - } - - public void setRoundDirComboSelectedIndex(int roundDirComboSelectedIndex) { - this.roundDirComboSelectedIndex = roundDirComboSelectedIndex; - } - - public boolean getRoundDirBtnSelected() { - return roundDirBtnSelected; - } - - public void setRoundDirBtnSelected(boolean roundDirBtnSelected) { - this.roundDirBtnSelected = roundDirBtnSelected; - } - - public double getDirectionForExtraPoints() { - return directionForExtraPoints; - } - - public double getFromdirection(){ - - Coordinate initPointBeforeLastInitPointCoordinate = initTrackPoints[initTrackPoints.length - 2].getLocation(); - Coordinate lastInitPointCoordinate = initTrackPoints[initTrackPoints.length - 1].getLocation(); - - GeodeticCalculator gc = new GeodeticCalculator(DefaultEllipsoid.WGS84); - gc.setStartingGeographicPoint(lastInitPointCoordinate.x, - lastInitPointCoordinate.y); - gc.setDestinationGeographicPoint(initPointBeforeLastInitPointCoordinate.x, - initPointBeforeLastInitPointCoordinate.y); - double dir = gc.getAzimuth(); - if ( dir < 0 ) dir += 360; - return dir; - } - - public void setDirectionForExtraPoints(double directionForExtraPoints) { - this.directionForExtraPoints = directionForExtraPoints; - } - - public double getSpeed() { - return speed; - } - - public void setSpeed(double speed) { - this.speed = speed; - /* - * The original speed is meters / millisecond, now it needs - * to be converted to following units - */ - this.speedInKnotOverHour = speed * 1944; - this.speedInKilometerOverHour = speed * 3600; - this.speedInMileOverHour = speed * 2237; - } - - public double getSpeedInKnotOverHour() { - return speedInKnotOverHour; - } - public double getSpeedInKilometerOverHour() { - return speedInKilometerOverHour; - } - public double getSpeedInMileOverHour() { - return speedInMileOverHour; - } - - - public ExtraPointTimeDisplayOption getExtraPointTimeDisplayOption() { - return extraPointTimeDisplayOption; - } - - public void setExtraPointTimeDisplayOption(ExtraPointTimeDisplayOption extraPointTimeDisplayOption) { - this.extraPointTimeDisplayOption = extraPointTimeDisplayOption; - } - - public String getSkipFactorTextString() { - return skipFactorTextString; - } - - public void setSkipFactorTextString(String skipFactorTextString) { - this.skipFactorTextString = skipFactorTextString; - } - - public boolean[] getExtraPointTimeTextDisplayIndicator() { - return extraPointTimeTextDisplayIndicator; - } - - public void setExtraPointTimeTextDisplayIndicator( - boolean[] extraPointTimeTextDisplayIndicator) { - this.extraPointTimeTextDisplayIndicator = extraPointTimeTextDisplayIndicator; - } - - public void setInitialColor(Color initialColor) { - this.initialColor = initialColor; - } - - public void setExtrapColor(Color extrapColor) { - this.extrapColor = extrapColor; - } - - public void setInitialMarker(String initialMarker) { - this.initialMarker = initialMarker; - } - - public void setInitialLinePattern(String initialLinePattern) { - this.initialLinePattern = initialLinePattern; - } - - public void setLineWidth(float lineWidth) { - this.lineWidth = lineWidth; - } - - public int getExtraDrawingPointNumber() { - if(!(this.extraDrawingPointNumber > 0)) - return DEFAULT_EXTRA_POINT_NUMBER; - return this.extraDrawingPointNumber; - } - - public void setExtraDrawingPointNumber(int extraDrawingPointNumber) { - this.extraDrawingPointNumber = extraDrawingPointNumber; - } - - public Calendar getFirstTimeCalendar() { - return firstTimeCalendar; - } - - public void setFirstTimeCalendar(Calendar firstTimeCalendar) { - this.firstTimeCalendar = firstTimeCalendar; - } - - public Calendar getSecondTimeCalendar() { - return secondTimeCalendar; - } - - public void setSecondTimeCalendar(Calendar secondTimeCalendar) { - this.secondTimeCalendar = secondTimeCalendar; - } - - public String getIntervalTimeString() { - return intervalTimeString; - } - - public void setIntervalTimeString(String _intervalTimeString) { - /* - * intervalTimeString == null is allowed - */ - this.intervalTimeString = _intervalTimeString; - - Calendar intervalTimeCal = getIntervalCalendarByParsingString(_intervalTimeString, - INTERVAL_TIME_FORMAT_PATTERN, getSecondTimeCalendar()); - //setIntervalTimeCalendar(intervalTimeCal); - } - - public int getElapsedHourForExtraPoint() { - return elapsedHourForExtraPoint; - } - - private void setElapsedHourForExtraPoint(int elapsedHourForExtraPoint) { - this.elapsedHourForExtraPoint = elapsedHourForExtraPoint; - } - - public int getElapsedMinuteForExtraPoint() { - return elapsedMinuteForExtraPoint; - } - - private void setElapsedMinuteForExtraPoint(int elapsedMinuteForExtraPoint) { - this.elapsedMinuteForExtraPoint = elapsedMinuteForExtraPoint; - } - - @Override - public String getSkipFactorText() { - return skipFactorTextString; - } - - @Override - public FontStyle getStyle() { - // TODO Auto-generated method stub - return null; - } + private final static float DEFAULT_FONT_SIZE = 14.0f; + + private final static float DEFAULT_LINE_WIDTH = 0.1f; + + private final static int DEFAULT_EXTRA_POINT_NUMBER = 5; + + // private final static int DEFAULT_INTERVAL_HOUR = 1; + private final static String INTERVAL_TIME_FORMAT_PATTERN = "HH:mm"; + + public void setExtrapMarker(String extrapMarker) { + this.extrapMarker = extrapMarker; + } + + public void setExtrapLinePattern(String extrapLinePattern) { + this.extrapLinePattern = extrapLinePattern; + } + + private final static String INITIAL_MARKER = "FILLED_DIAMOND"; + + private final static String EXTRAP_MARKER = "FILLED_TRIANGLE"; + + private final static String INITIAL_LINE_PATTERN = "LINE_SOLID"; + + private final static String EXTRAP_LINE_PATTERN = "LINE_SOLID"; + + /* + * This value of DEFAULT_LINE_PATTERN is a temporary solution Eventually a + * decision needs to be done for what a value should be used + */ + public final static String TRACK_PGEN_CATEGORY = "Track"; + + public final static String TRACK_INFO_DLG_CATEGORY_NAME = "TRACK_EXTRA_POINTS_INFO"; + + public final static String TRACK_PGEN_TYPE = "STORM_TRACK"; + + private Color initialColor; + + private Color extrapColor; + + private String initialMarker; + + private String initialLinePattern; + + private String extrapMarker; + + private String extrapLinePattern; + + private TrackPoint[] initTrackPoints; + + private TrackPoint[] extrapPoints; + + private String fontName; + + private float fontSize; + + private FontStyle fontStyle; + + private float lineWidth; + + private int extraDrawingPointNumber; + + private boolean setTimeButtonSelected; + + private Calendar firstTimeCalendar; + + private Calendar secondTimeCalendar; + + private String intervalTimeString; + + private int intervalComboSelectedIndex; + + private int fontSizeComboSelectedIndex; + + private int fontNameComboSelectedIndex; + + private int fontStyleComboSelectedIndex; + + private int elapsedHourForExtraPoint; + + private int elapsedMinuteForExtraPoint; + + private ExtraPointTimeDisplayOption extraPointTimeDisplayOption; + + private String skipFactorTextString; + + private boolean[] extraPointTimeTextDisplayIndicator; + + // direction, speed and unit are not saved to a file + private double directionForExtraPoints; + + private boolean roundDirBtnSelected; + + private int roundDirComboSelectedIndex; + + private double speed; // speed in meter/millisecond + + private double speedInKnotOverHour; + + private double speedInKilometerOverHour; + + private double speedInMileOverHour; + + private boolean roundBtnSelected; + + private int unitComboSelectedIndex; + + private int roundComboSelectedIndex; + + public Track() { + } + + public Track(ArrayList _locations, Calendar _firstTimeCalendar, + Calendar _secondTimeCalendar) { + initializeInitTrackPoints(_locations, _firstTimeCalendar, + _secondTimeCalendar); + } + + public void initializeInitTrackPoints(ArrayList locations, + Calendar firstTimeCalendar, Calendar secondTimeCalendar) { + initializeInitTrackPoints(locations); + initializeInitFirstTimeCalendar(firstTimeCalendar); + initializeInitSecondTimeCalendar(secondTimeCalendar); + } + + public void initializeTrackByTrackAttrDlgAndLocationList( + ITrack trackAttrDlgObject, ArrayList locations) { + initializeInitTrackPoints(locations); + initializeInitFirstTimeCalendar(trackAttrDlgObject + .getFirstTimeCalendar()); + initializeInitSecondTimeCalendar(trackAttrDlgObject + .getSecondTimeCalendar()); + + this.setInitialMarker(""); + this.setSetTimeButtonSelected(trackAttrDlgObject + .isSetTimeButtonSelected()); + this.setExtraDrawingPointNumber(trackAttrDlgObject + .getExtraDrawingPointNumber()); + + this.setIntervalTimeString(getIntervalTimeTextStringValue(trackAttrDlgObject)); + + this.setFontName(trackAttrDlgObject.getFontName()); + this.setFontStyle(trackAttrDlgObject.getFontStyle()); + this.setFontSize(trackAttrDlgObject.getFontSize()); + this.setInitialColor(trackAttrDlgObject.getInitialColor()); + this.setExtrapColor(trackAttrDlgObject.getExtrapColor()); + this.setExtraPointTimeDisplayOption(trackAttrDlgObject + .getExtraPointTimeDisplayOption()); + this.setSkipFactorTextString(trackAttrDlgObject.getSkipFactorText()); + this.setFontNameComboSelectedIndex(trackAttrDlgObject + .getFontNameComboSelectedIndex()); + this.setFontSizeComboSelectedIndex(trackAttrDlgObject + .getFontSizeComboSelectedIndex()); + this.setFontStyleComboSelectedIndex(trackAttrDlgObject + .getFontStyleComboSelectedIndex()); + this.setUnitComboSelectedIndex(trackAttrDlgObject + .getUnitComboSelectedIndex()); + this.setRoundComboSelectedIndex(trackAttrDlgObject + .getRoundComboSelectedIndex()); + if (trackAttrDlgObject.getRoundComboSelectedIndex() > 0) + this.setRoundBtnSelected(true); + else + this.setRoundBtnSelected(false); + + this.setRoundDirComboSelectedIndex(trackAttrDlgObject + .getRoundDirComboSelectedIndex()); + if (trackAttrDlgObject.getRoundDirComboSelectedIndex() > 0) + this.setRoundDirBtnSelected(true); + else + this.setRoundDirBtnSelected(false); + + // This method can be called only after all of the above settings are + // completed! + this.calculateExtrapTrackPoints(); + /** + * For now, the type is the name of a LinePattern defined in + * "gov.noaa.nws.ncep.ui.pgen.display.LinePatternList" However, there is + * no type has been decided for Track element yet. Thus, it is now hard + * coded. + */ + this.setPgenCategory(Track.TRACK_PGEN_CATEGORY); + this.setPgenType(Track.TRACK_PGEN_TYPE); + } + + public void initializeInitTrackPoints(ArrayList locations) { + TrackPoint[] initTrackPointArray = new TrackPoint[locations.size()]; + int arrayIndex = 0; + + for (Coordinate currentCoordinate : locations) { + TrackPoint eachTrackPoint = new TrackPoint(currentCoordinate, null); + initTrackPointArray[arrayIndex++] = eachTrackPoint; + } + setInitTrackPoints(initTrackPointArray); + } + + public void initializeInitFirstTimeCalendar(Calendar firstCalendar) { + setFirstTimeCalendar(firstCalendar); + if (getInitTrackPoints() != null) { + int initTrackPointLength = getInitTrackPoints().length; + if (initTrackPointLength >= 2) { + getInitTrackPoints()[initTrackPointLength - 2] + .setTime(firstCalendar); + } + } + } + + public void initializeInitSecondTimeCalendar(Calendar secondCalendar) { + setSecondTimeCalendar(secondCalendar); + if (getInitTrackPoints() != null) { + int initTrackPointLength = getInitTrackPoints().length; + if (initTrackPointLength >= 2) { + getInitTrackPoints()[initTrackPointLength - 1] + .setTime(secondCalendar); + } + } + } + + public void calculateExtrapTrackPoints() { + extrapPoints = calculateExtrapTrackPoints(getInitialPoints(), + getFirstTimeCalendar(), getSecondTimeCalendar(), + getExtraDrawingPointNumber(), getElapsedHourForExtraPoint(), + getElapsedMinuteForExtraPoint(), + getExtraPointTimeDisplayOption(), getSkipFactorTextString()); + + /* + * it is important to override the variable + * "ArrayList linePoints" with initTrackPoints and + * extrapPoints arrays + */ + setLinePointsValue(getInitialPoints(), getExtrapPoints()); + + /* + * a linePattern needs to be set for PgenSelectingTool to pick up the + * correct dialogue window to popup + */ + setPgenCategory(Track.TRACK_PGEN_CATEGORY); + setPgenType(Track.TRACK_PGEN_TYPE); + } + + public void setLinePointsValue(TrackPoint[] initTrackPoints, + TrackPoint[] extrapPoints) { + int listSize = 1; + if (initTrackPoints != null) + listSize += initTrackPoints.length; + if (extrapPoints != null) + listSize += extrapPoints.length; + ArrayList coordinatePointList = new ArrayList( + listSize); + addArrayToArrayList(coordinatePointList, initTrackPoints); + addArrayToArrayList(coordinatePointList, extrapPoints); + + /* + * Now use the inherited method setLinePoints to set the linPoints value + */ + setLinePoints(coordinatePointList); + } + + /** + * Creates a copy of this object. This is a deep copy and new objects are + * created so that we are not just copying references of objects + */ + // @Override + // public DrawableElement copy() { + public Track copy() { + + /* + * create a new Track object and initially set its attributes to this + * one's + */ + Track newTrack = new Track(); + Calendar newFirstTimeCalendar = Calendar.getInstance(); + newFirstTimeCalendar.setTimeInMillis(getFirstTimeCalendar() + .getTimeInMillis()); + newTrack.setFirstTimeCalendar(newFirstTimeCalendar); + + Calendar newSecondTimeCalendar = Calendar.getInstance(); + newSecondTimeCalendar.setTimeInMillis(getSecondTimeCalendar() + .getTimeInMillis()); + newTrack.setSecondTimeCalendar(newSecondTimeCalendar); + + TrackPoint[] newInitTrackPoints = new TrackPoint[getInitTrackPoints().length]; + + for (int i = 0; i < newInitTrackPoints.length; i++) { + + newInitTrackPoints[i] = TrackPoint.clone( + getInitTrackPoints()[i].getLocation(), + getInitTrackPoints()[i].getTime()); + } + newTrack.setInitTrackPoints(newInitTrackPoints); + + newTrack.setFontStyle(getFontStyle()); + newTrack.setFontSize(getFontSize()); + newTrack.setFontName(new String(getFontName())); + newTrack.setExtraPointTimeDisplayOption(getExtraPointTimeDisplayOption()); + + boolean[] newExtraPointTimeTextDisplayIndicator = new boolean[getExtraPointTimeTextDisplayIndicator().length]; + for (int i = 0; i < getExtraPointTimeTextDisplayIndicator().length; i++) { + newExtraPointTimeTextDisplayIndicator[i] = getExtraPointTimeTextDisplayIndicator()[i]; + } + newTrack.setExtraPointTimeTextDisplayIndicator(newExtraPointTimeTextDisplayIndicator); + + newTrack.setSkipFactorTextString(new String(getSkipFactorTextString())); + newTrack.setInitialColor(new Color(getInitialColor().getRed(), + getInitialColor().getGreen(), getInitialColor().getBlue())); + newTrack.setExtrapColor(new Color(getExtrapColor().getRed(), + getExtrapColor().getGreen(), getExtrapColor().getBlue())); + + newTrack.setIntervalTimeString(new String(getIntervalTimeString())); + + /* + * Under some scenarios, e.g. marshall/unmarshall procees, the + * ExtraDrawingPointNumber is not serialized. Thus, first try to use the + * length of ExtrapPoints array + */ + if (getExtrapPoints() != null) + newTrack.setExtraDrawingPointNumber(getExtrapPoints().length); + else + newTrack.setExtraDrawingPointNumber(getExtraDrawingPointNumber()); + + newTrack.setExtrapLinePattern(new String(getExtrapLinePattern())); + newTrack.setExtrapMarker(new String(getExtrapMarker())); + + newTrack.setInitialLinePattern(new String(getInitialLinePattern())); + newTrack.setInitialMarker(new String(getInitialMarker())); + + if (getPgenCategory() != null) + newTrack.setPgenCategory(new String(getPgenCategory())); + if (getPgenType() != null) + newTrack.setPgenType(new String(getPgenType())); + + newTrack.calculateExtrapTrackPoints(); + + /* + * Now copy some important attributes that make a Line or multi-points + * element can be displayed + */ + newTrack.setClosed(isClosedLine()); + newTrack.setFilled(isFilled()); + + /* + * colors value in Track will only be used in dragging initial points. + * Thus, here the color of the initial points is used + */ + Color[] initColors = new Color[1]; + initColors[0] = getInitialColor(); + newTrack.setColors(initColors); + newTrack.setLineWidth(getLineWidth()); + newTrack.setSizeScale(getSizeScale()); + + newTrack.setSmoothFactor(2); + newTrack.setFillPattern(getFillPattern()); + + newTrack.setParent(this.getParent()); + + return newTrack; + } + + public void update(ITrack trackAttrDlg) { + + initializeInitFirstTimeCalendar(trackAttrDlg.getFirstTimeCalendar()); + initializeInitSecondTimeCalendar(trackAttrDlg.getSecondTimeCalendar()); + + setInitialMarker(INITIAL_MARKER); + setSetTimeButtonSelected(trackAttrDlg.isSetTimeButtonSelected()); + setExtraDrawingPointNumber(trackAttrDlg.getExtraDrawingPointNumber()); + setIntervalTimeString(trackAttrDlg.getIntervalTimeString()); + setFontName(trackAttrDlg.getFontName()); + setFontStyle(trackAttrDlg.getFontStyle()); + setFontSize(trackAttrDlg.getFontSize()); + setInitialColor(trackAttrDlg.getInitialColor()); + setExtrapColor(trackAttrDlg.getExtrapColor()); + setExtraPointTimeDisplayOption(trackAttrDlg + .getExtraPointTimeDisplayOption()); + setSkipFactorTextString(trackAttrDlg.getSkipFactorText()); + setFontNameComboSelectedIndex(trackAttrDlg + .getFontNameComboSelectedIndex()); + setFontSizeComboSelectedIndex(trackAttrDlg + .getFontSizeComboSelectedIndex()); + setFontStyleComboSelectedIndex(trackAttrDlg + .getFontStyleComboSelectedIndex()); + setUnitComboSelectedIndex(trackAttrDlg.getUnitComboSelectedIndex()); + setRoundComboSelectedIndex(trackAttrDlg.getRoundComboSelectedIndex()); + if (trackAttrDlg.getRoundComboSelectedIndex() > 0) + this.setRoundBtnSelected(true); + else + this.setRoundBtnSelected(false); + + setRoundDirComboSelectedIndex(trackAttrDlg + .getRoundDirComboSelectedIndex()); + if (trackAttrDlg.getRoundDirComboSelectedIndex() > 0) + this.setRoundDirBtnSelected(true); + else + this.setRoundDirBtnSelected(false); + + // This method can be called only after all of the above settings are + // completed! + calculateExtrapTrackPoints(); + + /** + * For now, the type is the name of a LinePattern defined in + * "gov.noaa.nws.ncep.ui.pgen.display.LinePatternList" However, there is + * no type has been decided for Track element yet. Thus, it is now hard + * coded. + */ + setPgenType(Track.TRACK_PGEN_TYPE); + setPgenCategory(Track.TRACK_PGEN_CATEGORY); + } + + public void addPoint(int index, Coordinate point) { + ArrayList allLinePoints = getPoints(); + if (allLinePoints == null) + allLinePoints = new ArrayList(); + + if (allLinePoints.size() <= index) + allLinePoints.add(point); + else + allLinePoints.add(index, point); + + int initialPointSize = getInitialPoints().length; + int extrapPointSize = getExtrapPoints().length; + + if (index < initialPointSize) { + TrackPoint modifiedTrackPoint = getInitialPoints()[index]; + modifiedTrackPoint.setLocation(point); + } else { + int extrapindex = index - initialPointSize; + if (extrapindex >= 0 && extrapindex < extrapPointSize) { + TrackPoint modifiedTrackPoint = getExtrapPoints()[extrapindex]; + modifiedTrackPoint.setLocation(point); + } + } + + } + + public void removePoint(int index) { + ArrayList allLinePoints = getPoints(); + if (allLinePoints == null) + return; + + if (allLinePoints.size() > index) { + allLinePoints.remove(index); + } + + } + + public void setPoints(ArrayList pts) { + if (pts == null) + return; + /* + * call MultiPointElement.setPoint(...) + */ + super.setPoints(pts); + + /* + * Now initialize initPoint and ExtrapPoint arrays + */ + int allPointsSize = pts.size(); + + int initTrackPointSize = 0; + if (getInitTrackPoints() != null) + initTrackPointSize = getInitTrackPoints().length; + int index = 0; + + /* + * reset coordinate values for initial track points + */ + while (index < initTrackPointSize && index < allPointsSize) { + TrackPoint currentTrackPoint = getInitTrackPoints()[index]; + if (currentTrackPoint != null) + currentTrackPoint.setLocation(pts.get(index)); + index++; + } + + int extrapTrackPointSize = 0; + if (getExtrapPoints() != null) + extrapTrackPointSize = getExtrapPoints().length; + int extrapIndex = 0; + while (extrapIndex < extrapTrackPointSize && index < allPointsSize) { + TrackPoint currentTrackPoint = getExtrapPoints()[extrapIndex]; + if (currentTrackPoint != null) + currentTrackPoint.setLocation(pts.get(index)); + index++; + extrapIndex++; + } + + } + + /* + * All private help methods start here + */ + private String getIntervalTimeTextStringValue(ITrack trackAttrDlg) { + + return trackAttrDlg.getIntervalTimeString(); + } + + private void addArrayToArrayList(ArrayList coordinatePointList, + TrackPoint[] trackPoints) { + if (trackPoints == null) + return; + for (TrackPoint trackPoint : trackPoints) { + coordinatePointList.add(trackPoint.getLocation()); + } + } + + private TrackPoint[] calculateExtrapTrackPoints(TrackPoint[] initialPoints, + Calendar initPointBeforeLastInitPointTimeCal, + Calendar lastInitPointTimeCal, int extraDrawingPointNumber, + int elapsedHourForExtraPointValue, + int elapsedMinuteForExtraPointValue, + ExtraPointTimeDisplayOption extraPointTimeDisplayOption, + String skipFactorTextString) { + if (initialPoints == null || initialPoints.length < 2) { + // log.error("Method:calculateExtrapTrackPoints, the input initialPoints is null or initialPoints.length less than 2"); + return null; + } + + int arrayLength = initialPoints.length; + Coordinate initPointBeforeLastInitPointCoordinate = initialPoints[arrayLength - 2] + .getLocation(); + Coordinate lastInitPointCoordinate = initialPoints[arrayLength - 1] + .getLocation(); + if (!isCoordinateValid(initPointBeforeLastInitPointCoordinate) + || !isCoordinateValid(lastInitPointCoordinate) + || initPointBeforeLastInitPointTimeCal == null + || lastInitPointTimeCal == null) { + + return null; + } + + GeodeticCalculator gc = new GeodeticCalculator(DefaultEllipsoid.WGS84); + gc.setStartingGeographicPoint(initPointBeforeLastInitPointCoordinate.x, + initPointBeforeLastInitPointCoordinate.y); + gc.setDestinationGeographicPoint(lastInitPointCoordinate.x, + lastInitPointCoordinate.y); + double direction = gc.getAzimuth(); + setDirectionForExtraPoints(direction); + + double distanceInMeter = gc.getOrthodromicDistance(); + long timeDifference = getTimeDifferenceInMillisecond( + initPointBeforeLastInitPointTimeCal, lastInitPointTimeCal); + double speed = distanceInMeter / (double) timeDifference; + setSpeed(speed); + + // Calculate the first extra point time Calendar + Calendar firstExtraPointTimeCal = getTimeElapsedCalendarForFirstExtraPoint( + lastInitPointTimeCal, elapsedHourForExtraPointValue, + elapsedMinuteForExtraPointValue); + + // calculate the distance between the last Initial point and the first + // extra point + double distanceBetweenLastInitPointAndFirstExtraPoint = calculateDistanceBetweenLastInitPointAndFirstExtraPoint( + speed, lastInitPointTimeCal, firstExtraPointTimeCal); + + // calculate the distance among extra points + double distanceForExtraPoint = calculateDistanceForExtraPoints(speed, + firstExtraPointTimeCal, elapsedHourForExtraPointValue, + elapsedMinuteForExtraPointValue); + + TrackPoint[] extrapTrackPointArray = calculateExtrapTrackPoints(gc, + lastInitPointCoordinate, direction, + distanceBetweenLastInitPointAndFirstExtraPoint, + distanceForExtraPoint, extraDrawingPointNumber, + lastInitPointTimeCal, firstExtraPointTimeCal, + elapsedHourForExtraPointValue, elapsedMinuteForExtraPointValue); + disableSomeTimeTagsDisplayBasedOnExtraPointTimeDisplayOption( + extrapTrackPointArray, extraPointTimeDisplayOption, + skipFactorTextString); + + return extrapTrackPointArray; + } + + private void disableSomeTimeTagsDisplayBasedOnExtraPointTimeDisplayOption( + TrackPoint[] extrapTrackPointArray, + ExtraPointTimeDisplayOption extraPointTimeDisplayOption, + String skipFactorTextString) { + if (extrapTrackPointArray == null) + return; + boolean[] extraPointTimeTagFlagArray = new boolean[extrapTrackPointArray.length]; + initializeBooleanArray(extraPointTimeTagFlagArray, true); + + if (extraPointTimeDisplayOption == ITrack.ExtraPointTimeDisplayOption.SKIP_FACTOR) { + removeTimeTagsBasedOnSkipFactor(extrapTrackPointArray, + skipFactorTextString, extraPointTimeTagFlagArray); + } else if (extraPointTimeDisplayOption == ITrack.ExtraPointTimeDisplayOption.SHOW_FIRST_LAST) { + removeTimeTagsBasedOnShowLastFirstOnly(extrapTrackPointArray, + extraPointTimeTagFlagArray); + } else if (extraPointTimeDisplayOption == ITrack.ExtraPointTimeDisplayOption.ON_ONE_HOUR) { + removeTimeTagsBasedOnHourMinuteValue(extrapTrackPointArray, true, + extraPointTimeTagFlagArray); + } else if (extraPointTimeDisplayOption == ITrack.ExtraPointTimeDisplayOption.ON_HALF_HOUR) { + removeTimeTagsBasedOnHourMinuteValue(extrapTrackPointArray, false, + extraPointTimeTagFlagArray); + } else { + removeTimeTagsBasedOnHourMinuteValue(extrapTrackPointArray, false, + extraPointTimeTagFlagArray); + } + + /* + * set the updated boolean array back to the indicator, in + * displayElementFactory, this boolean array will be used to indicate if + * a time text should be skipped + */ + setExtraPointTimeTextDisplayIndicator(extraPointTimeTagFlagArray); + } + + private void removeTimeTagsBasedOnShowLastFirstOnly( + TrackPoint[] extrapTrackPointArray, boolean[] timeTagIndicatorArray) { + if (extrapTrackPointArray.length < 3) + return; + for (int i = 1; i < (extrapTrackPointArray.length - 1); i++) { + timeTagIndicatorArray[i] = false; + } + } + + private void removeTimeTagsBasedOnSkipFactor( + TrackPoint[] extrapTrackPointArray, String skipFactorTextString, + boolean[] timeTagIndicatorArray) { + if (skipFactorTextString == null) + return; + /* + * always show the time tags of the first and last extra points + */ + if (extrapTrackPointArray.length < 3) + return; + + int skipFactorIntValue = 0; + try { + skipFactorIntValue = Integer.parseInt(skipFactorTextString); + } catch (NumberFormatException nfe) { + } + + /* + * 1. make sure skipFactorIntValue is a valid value 2. since the last + * and first extra points are always displayed, thus do + * skipFactorIntValue > (extrapTrackPointArray.length - 2) check + */ + if (!(skipFactorIntValue > 0) + || skipFactorIntValue > (extrapTrackPointArray.length - 2)) + return; + + for (int i = 1; i <= skipFactorIntValue; i++) { + timeTagIndicatorArray[i] = false; + } + } + + private void removeTimeTagsBasedOnHourMinuteValue( + TrackPoint[] extrapTrackPointArray, boolean isExactHourDisplayed, + boolean[] timeTagIndicatorArray) { + for (int i = 0; i < (extrapTrackPointArray.length); i++) { + TrackPoint targetTrackPoint = extrapTrackPointArray[i]; + Calendar targetPointTimeCal = targetTrackPoint.getTime(); + + if (!isTimeTagDisplayable(targetPointTimeCal, isExactHourDisplayed)) { + /* + * mark the flag array index for the time needs to be hided + */ + timeTagIndicatorArray[i] = false; + } + } + } + + private void initializeBooleanArray(boolean[] booleanArray, + boolean initValue) { + if (booleanArray == null) + return; + for (int i = 0; i < booleanArray.length; i++) + booleanArray[i] = initValue; + } + + private boolean isTimeTagDisplayable(Calendar targetPointTimeCal, + boolean isExactHourDisplayed) { + boolean isDisplayable = false; + if (targetPointTimeCal == null) + return isDisplayable; + + int minuteIntValue = targetPointTimeCal.get(Calendar.MINUTE); + if (isExactHourDisplayed) { + if (minuteIntValue == 0) + isDisplayable = true; + } else { + if (minuteIntValue == 0 || minuteIntValue == 30) + isDisplayable = true; + } + return isDisplayable; + } + + private double calculateDistanceBetweenLastInitPointAndFirstExtraPoint( + double speed, Calendar lastInitPointCal, Calendar firstExtraPointCal) { + long timeDifferenceBetweenExtraPoints = getTimeDifferenceInMillisecond( + lastInitPointCal, firstExtraPointCal); + double distanceBetweenLastInitPointAndFirstExtraPoint = speed + * timeDifferenceBetweenExtraPoints; + return distanceBetweenLastInitPointAndFirstExtraPoint; + } + + private double calculateDistanceForExtraPoints(double speed, + Calendar firstExtraPointCal, int elapsedHourForExtraPoint, + int elapsedMinuteForExtraPoint) { + Calendar nextExtraPointTimeCal = getTimeElapsedCalendar( + firstExtraPointCal, elapsedHourForExtraPoint, + elapsedMinuteForExtraPoint); + long timeDifferenceBetweenExtraPoints = getTimeDifferenceInMillisecond( + firstExtraPointCal, nextExtraPointTimeCal); + double distanceForExtraPoint = speed * timeDifferenceBetweenExtraPoints; + return distanceForExtraPoint; + } + + private TrackPoint[] calculateExtrapTrackPoints(GeodeticCalculator gc, + Coordinate lastInitPointCoordinate, double direction, + double distanceBetweenLastInitPointAndFirstExtraPoint, + double distanceBetweenExtraPoint, int extraPointNumber, + Calendar lastInitPointTimeCal, Calendar firstExtraPointTimeCal, + int elapsedHourForExtraPoint, int elapsedMinuteForExtraPoint) { + double startLongitude = lastInitPointCoordinate.x; + double startLatitude = lastInitPointCoordinate.y; + TrackPoint[] trackPointArray = new TrackPoint[extraPointNumber]; + + /* + * Add the first extra point + */ + java.awt.geom.Point2D firstExtraPointPoint2dValue = getNextPoint2DValue( + gc, startLongitude, startLatitude, direction, + distanceBetweenLastInitPointAndFirstExtraPoint); + startLongitude = firstExtraPointPoint2dValue.getX(); + startLatitude = firstExtraPointPoint2dValue.getY(); + Coordinate firstExtraPointCoordinate = new Coordinate(startLongitude, + startLatitude); + TrackPoint firstExtraTrackPoint = new TrackPoint( + firstExtraPointCoordinate, firstExtraPointTimeCal); + trackPointArray[0] = firstExtraTrackPoint; + + Calendar newPointCal = firstExtraPointTimeCal; + for (int i = 1; i < (extraPointNumber); i++) { + java.awt.geom.Point2D pt = getNextPoint2DValue(gc, startLongitude, + startLatitude, direction, distanceBetweenExtraPoint); + startLongitude = pt.getX(); + startLatitude = pt.getY(); + Coordinate nextCoordinate = new Coordinate(startLongitude, + startLatitude); + newPointCal = getTimeElapsedCalendar(newPointCal, + elapsedHourForExtraPoint, elapsedMinuteForExtraPoint); + TrackPoint eachTrackPoint = new TrackPoint(nextCoordinate, + newPointCal); + trackPointArray[i] = eachTrackPoint; + } + return trackPointArray; + } + + private java.awt.geom.Point2D getNextPoint2DValue(GeodeticCalculator gc, + double startingPointLongitude, double startIngPointLatitude, + double direction, double distanceBetweenTwoPoints) { + gc.setStartingGeographicPoint(startingPointLongitude, + startIngPointLatitude); + gc.setDirection(direction, distanceBetweenTwoPoints); + java.awt.geom.Point2D pt = gc.getDestinationGeographicPoint(); + return pt; + } + + private long getTimeDifferenceInMillisecond(Calendar startTimeCal, + Calendar endTimeCal) { + long startTimeInMillisecond = startTimeCal.getTimeInMillis(); + long endTimeInMillisecond = endTimeCal.getTimeInMillis(); + + long timeDiffInMillisecond = endTimeInMillisecond + - startTimeInMillisecond; + return timeDiffInMillisecond; + } + + private boolean isCoordinateValid(Coordinate coordinate) { + if (coordinate.x > 180.0 || coordinate.x < -180.0 + || coordinate.y > 90.0 || coordinate.y < -90.0) + return false; + return true; + } + + private Calendar getIntervalCalendarByParsingString(String dateString, + String formatStringPattern, Calendar secondTimeCal) { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat( + formatStringPattern); + Calendar cal = null; + int elapsedHour = 1; + int elapsedMinute = 0; + if (dateString != null) { + try { + Date date = simpleDateFormat.parse(dateString); + cal = Calendar.getInstance(); + cal.setTime(date); + elapsedHour = cal.get(Calendar.HOUR_OF_DAY); + elapsedMinute = cal.get(Calendar.MINUTE); + } catch (ParseException pe) { + elapsedHour = 1; + } + } + setElapsedHourForExtraPoint(elapsedHour); + setElapsedMinuteForExtraPoint(elapsedMinute); + cal = getTimeElapsedCalendar(secondTimeCal, elapsedHour, elapsedMinute); + return cal; + } + + private Calendar getTimeElapsedCalendarForFirstExtraPoint( + Calendar startCalendar, int elapsedHour, int elapsedMinute) { + Calendar nextCal = Calendar.getInstance(); + nextCal.setTimeInMillis(startCalendar.getTimeInMillis()); + /* + * played with the nmap2 APP, get confused with the logic behind, right + * now, calculate the first extra point as the logic described below: 1. + * if elapsedHour > 1 hour, set the first extra point time as the next + * exact hour 2. if elapsedHour == 0 and last init. point MINUTE value + * >= elapsedMinute, set the first time extra point as the next exact + * hour 3. if elapsedHour == 0 and last init. point MINUTE value < + * elapsedMinute, set the first time extra point as the exact hour of + * the last init. point + elapsedMinute In the future, this logic may be + * changed once the real logic is figured. Michael Gao comment. + */ + if (elapsedHour >= 1) { + nextCal.set(Calendar.MINUTE, 0); + nextCal.add(Calendar.HOUR_OF_DAY, 1); + } else { + int currentMinute = nextCal.get(Calendar.MINUTE); + if (currentMinute >= elapsedMinute) { + nextCal.set(Calendar.MINUTE, 0); + nextCal.add(Calendar.HOUR_OF_DAY, 1); + } else { + nextCal.set(Calendar.MINUTE, elapsedMinute); + } + } + return nextCal; + } + + private Calendar getTimeElapsedCalendar(Calendar startCalendar, + int elapsedHour, int elapsedMinute) { + Calendar nextCal = Calendar.getInstance(); + nextCal.setTimeInMillis(startCalendar.getTimeInMillis()); + nextCal.add(Calendar.HOUR_OF_DAY, elapsedHour); + nextCal.add(Calendar.MINUTE, elapsedMinute); + return nextCal; + } + + /* + * all override setters and getters of the instance variables go here + */ + @Override + public Color getExtrapColor() { + return this.extrapColor; + } + + @Override + public String getExtrapLinePattern() { + return EXTRAP_LINE_PATTERN; + } + + @Override + public String getExtrapMarker() { + return EXTRAP_MARKER; + } + + public TrackPoint[] getInitTrackPoints() { + return initTrackPoints; + } + + public void setInitTrackPoints(TrackPoint[] initTrackPoints) { + this.initTrackPoints = initTrackPoints; + } + + public void setExtrapPoints(TrackPoint[] extrapPoints) { + this.extrapPoints = extrapPoints; + } + + @Override + public TrackPoint[] getExtrapPoints() { + return extrapPoints; + } + + @Override + public Color getInitialColor() { + return this.initialColor; + } + + @Override + public String getInitialLinePattern() { + return INITIAL_LINE_PATTERN; + } + + @Override + public String getInitialMarker() { + return INITIAL_MARKER; + } + + @Override + public TrackPoint[] getInitialPoints() { + return initTrackPoints; + } + + @Override + public String getFontName() { + return this.fontName; + } + + public void setFontName(String _fontName) { + this.fontName = _fontName; + } + + @Override + public float getFontSize() { + if (this.fontSize <= 0.0) + return DEFAULT_FONT_SIZE; + return this.fontSize; + } + + public void setFontSize(float _fontSize) { + this.fontSize = _fontSize; + } + + public FontStyle getFontStyle() { + return fontStyle; + } + + public void setFontStyle(FontStyle fontStyle) { + this.fontStyle = fontStyle; + } + + @Override + public float getLineWidth() { + if (this.lineWidth <= 0.0) + return DEFAULT_LINE_WIDTH; + return this.lineWidth; + } + + /* + * all non-override setters and getters of the instance variables go here + */ + public boolean isSetTimeButtonSelected() { + return setTimeButtonSelected; + } + + public void setSetTimeButtonSelected(boolean setTimeButtonSelected) { + this.setTimeButtonSelected = setTimeButtonSelected; + } + + public int getFontSizeComboSelectedIndex() { + return fontSizeComboSelectedIndex; + } + + public void setFontSizeComboSelectedIndex(int fontSizeComboSelectedIndex) { + this.fontSizeComboSelectedIndex = fontSizeComboSelectedIndex; + } + + public int getFontNameComboSelectedIndex() { + return fontNameComboSelectedIndex; + } + + public void setFontNameComboSelectedIndex(int fontNameComboSelectedIndex) { + this.fontNameComboSelectedIndex = fontNameComboSelectedIndex; + } + + public int getFontStyleComboSelectedIndex() { + return fontStyleComboSelectedIndex; + } + + public void setFontStyleComboSelectedIndex(int fontStyleComboSelectedIndex) { + this.fontStyleComboSelectedIndex = fontStyleComboSelectedIndex; + } + + public int getIntervalComboSelectedIndex() { + return intervalComboSelectedIndex; + } + + public void setIntervalComboSelectedIndex(int intervalComboSelectedIndex) { + this.intervalComboSelectedIndex = intervalComboSelectedIndex; + } + + public int getUnitComboSelectedIndex() { + return unitComboSelectedIndex; + } + + public void setUnitComboSelectedIndex(int unitComboSelectedIndex) { + this.unitComboSelectedIndex = unitComboSelectedIndex; + } + + public int getRoundComboSelectedIndex() { + return roundComboSelectedIndex; + } + + public void setRoundComboSelectedIndex(int roundComboSelectedIndex) { + this.roundComboSelectedIndex = roundComboSelectedIndex; + } + + public boolean getRoundBtnSelected() { + return roundBtnSelected; + } + + public void setRoundBtnSelected(boolean roundBtnSelected) { + this.roundBtnSelected = roundBtnSelected; + } + + public int getRoundDirComboSelectedIndex() { + return roundDirComboSelectedIndex; + } + + public void setRoundDirComboSelectedIndex(int roundDirComboSelectedIndex) { + this.roundDirComboSelectedIndex = roundDirComboSelectedIndex; + } + + public boolean getRoundDirBtnSelected() { + return roundDirBtnSelected; + } + + public void setRoundDirBtnSelected(boolean roundDirBtnSelected) { + this.roundDirBtnSelected = roundDirBtnSelected; + } + + public double getDirectionForExtraPoints() { + return directionForExtraPoints; + } + + public double getFromdirection() { + + Coordinate initPointBeforeLastInitPointCoordinate = initTrackPoints[initTrackPoints.length - 2] + .getLocation(); + Coordinate lastInitPointCoordinate = initTrackPoints[initTrackPoints.length - 1] + .getLocation(); + + GeodeticCalculator gc = new GeodeticCalculator(DefaultEllipsoid.WGS84); + gc.setStartingGeographicPoint(lastInitPointCoordinate.x, + lastInitPointCoordinate.y); + gc.setDestinationGeographicPoint( + initPointBeforeLastInitPointCoordinate.x, + initPointBeforeLastInitPointCoordinate.y); + double dir = gc.getAzimuth(); + if (dir < 0) + dir += 360; + return dir; + } + + public void setDirectionForExtraPoints(double directionForExtraPoints) { + this.directionForExtraPoints = directionForExtraPoints; + } + + public double getSpeed() { + return speed; + } + + public void setSpeed(double speed) { + this.speed = speed; + /* + * The original speed is meters / millisecond, now it needs to be + * converted to following units + */ + this.speedInKnotOverHour = speed * 1944; + this.speedInKilometerOverHour = speed * 3600; + this.speedInMileOverHour = speed * 2237; + } + + public double getSpeedInKnotOverHour() { + return speedInKnotOverHour; + } + + public double getSpeedInKilometerOverHour() { + return speedInKilometerOverHour; + } + + public double getSpeedInMileOverHour() { + return speedInMileOverHour; + } + + public ExtraPointTimeDisplayOption getExtraPointTimeDisplayOption() { + return extraPointTimeDisplayOption; + } + + public void setExtraPointTimeDisplayOption( + ExtraPointTimeDisplayOption extraPointTimeDisplayOption) { + this.extraPointTimeDisplayOption = extraPointTimeDisplayOption; + } + + public String getSkipFactorTextString() { + return skipFactorTextString; + } + + public void setSkipFactorTextString(String skipFactorTextString) { + this.skipFactorTextString = skipFactorTextString; + } + + public boolean[] getExtraPointTimeTextDisplayIndicator() { + return extraPointTimeTextDisplayIndicator; + } + + public void setExtraPointTimeTextDisplayIndicator( + boolean[] extraPointTimeTextDisplayIndicator) { + this.extraPointTimeTextDisplayIndicator = extraPointTimeTextDisplayIndicator; + } + + public void setInitialColor(Color initialColor) { + this.initialColor = initialColor; + } + + public void setExtrapColor(Color extrapColor) { + this.extrapColor = extrapColor; + } + + public void setInitialMarker(String initialMarker) { + this.initialMarker = initialMarker; + } + + public void setInitialLinePattern(String initialLinePattern) { + this.initialLinePattern = initialLinePattern; + } + + public void setLineWidth(float lineWidth) { + this.lineWidth = lineWidth; + } + + public int getExtraDrawingPointNumber() { + if (!(this.extraDrawingPointNumber > 0)) + return DEFAULT_EXTRA_POINT_NUMBER; + return this.extraDrawingPointNumber; + } + + public void setExtraDrawingPointNumber(int extraDrawingPointNumber) { + this.extraDrawingPointNumber = extraDrawingPointNumber; + } + + public Calendar getFirstTimeCalendar() { + return firstTimeCalendar; + } + + public void setFirstTimeCalendar(Calendar firstTimeCalendar) { + this.firstTimeCalendar = firstTimeCalendar; + } + + public Calendar getSecondTimeCalendar() { + return secondTimeCalendar; + } + + public void setSecondTimeCalendar(Calendar secondTimeCalendar) { + this.secondTimeCalendar = secondTimeCalendar; + } + + public String getIntervalTimeString() { + return intervalTimeString; + } + + public void setIntervalTimeString(String _intervalTimeString) { + /* + * intervalTimeString == null is allowed + */ + this.intervalTimeString = _intervalTimeString; + + Calendar intervalTimeCal = getIntervalCalendarByParsingString( + _intervalTimeString, INTERVAL_TIME_FORMAT_PATTERN, + getSecondTimeCalendar()); + // setIntervalTimeCalendar(intervalTimeCal); + } + + public int getElapsedHourForExtraPoint() { + return elapsedHourForExtraPoint; + } + + private void setElapsedHourForExtraPoint(int elapsedHourForExtraPoint) { + this.elapsedHourForExtraPoint = elapsedHourForExtraPoint; + } + + public int getElapsedMinuteForExtraPoint() { + return elapsedMinuteForExtraPoint; + } + + private void setElapsedMinuteForExtraPoint(int elapsedMinuteForExtraPoint) { + this.elapsedMinuteForExtraPoint = elapsedMinuteForExtraPoint; + } + + @Override + public String getSkipFactorText() { + return skipFactorTextString; + } } diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/file/ProductConverter.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/file/ProductConverter.java index 4c2fb4e4a8..9886d020af 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/file/ProductConverter.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/file/ProductConverter.java @@ -134,6 +134,7 @@ import com.vividsolutions.jts.geom.Coordinate; * 12/13 TTR904 B. Yin Added back the water zone string for Watch county list * 11/13 #1065 J. Wu Added Kink lines. * 05/14 TTR995 J. Wu Set Text's 'auto" flag to false. + * 09/14 TTR716 J. Wu Use "-" for GFA Outlook's Vor text. * * * @@ -735,6 +736,12 @@ public class ProductConverter { gfa.setGfaValue("Type", fgfa.getType()); } + // textVOR + String vorStr = fgfa.getTextVor(); + if (vorStr != null) { + gfa.setGfaVorText(nvl(vorStr)); + } + String cig = fgfa.getCig(); if (cig != null) { gfa.setGfaValue(Gfa.CIG, fgfa.getCig()); @@ -1098,7 +1105,11 @@ public class ProductConverter { } // textVOR - fgfa.setTextVor(nvl(((Gfa) de).getGfaVorText())); + String vorStr = ((Gfa) de).getGfaVorText(); + if (vorStr != null && ((Gfa) de).isOutlook()) { + vorStr = vorStr.replaceAll(" TO ", "-"); + } + fgfa.setTextVor(nvl(vorStr)); fgfa.setFillPattern(nvl(((Gfa) de).getFillPattern() .name())); diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/file/Track.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/file/Track.java index 02cce275df..0ab12d7884 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/file/Track.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/file/Track.java @@ -5,11 +5,11 @@ // Generated on: 2009.05.28 at 02:35:15 PM EDT // - package gov.noaa.nws.ncep.ui.pgen.file; import java.util.ArrayList; import java.util.List; + import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; @@ -17,11 +17,13 @@ import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; - /** - *

Java class for anonymous complex type. + *

+ * Java class for anonymous complex type. * - *

The following schema fragment specifies the expected content contained within this class. + *

+ * The following schema fragment specifies the expected content contained within + * this class. * *

  * <complexType>
@@ -38,6 +40,7 @@ import javax.xml.bind.annotation.XmlType;
  *       <attribute name="extrapLinePattern" type="{http://www.w3.org/2001/XMLSchema}string" />
  *       <attribute name="extrapMarker" type="{http://www.w3.org/2001/XMLSchema}string" />
  *       <attribute name="fontName" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       <attribute name="fontStyle" type="{http://www.w3.org/2001/XMLSchema}string" />
  *       <attribute name="fontNameComboSelectedIndex" type="{http://www.w3.org/2001/XMLSchema}int" />
  *       <attribute name="fontSize" type="{http://www.w3.org/2001/XMLSchema}float" />
  *       <attribute name="fontSizeComboSelectedIndex" type="{http://www.w3.org/2001/XMLSchema}int" />
@@ -60,68 +63,85 @@ import javax.xml.bind.annotation.XmlType;
  * 
  */
 @XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "", propOrder = {
-    "initialColor",
-    "extrapColor",
-    "initialPoints",
-    "extrapPoints",
-    "extraPointTimeTextDisplayIndicator"
-})
+@XmlType(name = "", propOrder = { "initialColor", "extrapColor",
+        "initialPoints", "extrapPoints", "extraPointTimeTextDisplayIndicator" })
 @XmlRootElement(name = "Track")
 public class Track {
 
     @XmlElement(required = true)
     protected ColorType initialColor;
+
     @XmlElement(required = true)
     protected ColorType extrapColor;
+
     @XmlElement(required = true)
     protected List initialPoints;
+
     @XmlElement(required = true)
     protected List extrapPoints;
+
     @XmlElement(type = Boolean.class)
     protected List extraPointTimeTextDisplayIndicator;
+
     @XmlAttribute
     protected String extraPointTimeDisplayOptionName;
+
     @XmlAttribute
     protected String extrapLinePattern;
+
     @XmlAttribute
     protected String extrapMarker;
+
     @XmlAttribute
     protected String fontName;
+
+    @XmlAttribute
+    protected String fontStyle;
+
     @XmlAttribute
     protected Integer fontNameComboSelectedIndex;
+
     @XmlAttribute
     protected Float fontSize;
+
     @XmlAttribute
     protected Integer fontSizeComboSelectedIndex;
+
     @XmlAttribute
     protected Integer fontStyleComboSelectedIndex;
+
     @XmlAttribute
     protected String initialLinePattern;
+
     @XmlAttribute
     protected String initialMarker;
+
     @XmlAttribute
     protected Integer intervalComboSelectedIndex;
+
     @XmlAttribute
     protected String intervalTimeTextString;
+
     @XmlAttribute
     protected Float lineWidth;
+
     @XmlAttribute
     protected String pgenCategory;
+
     @XmlAttribute
     protected String pgenType;
+
     @XmlAttribute
     protected Boolean setTimeButtonSelected;
+
     @XmlAttribute
     protected String skipFactorTextString;
 
     /**
      * Gets the value of the initialColor property.
      * 
-     * @return
-     *     possible object is
-     *     {@link ColorType }
-     *     
+     * @return possible object is {@link ColorType }
+     * 
      */
     public ColorType getInitialColor() {
         return initialColor;
@@ -131,9 +151,8 @@ public class Track {
      * Sets the value of the initialColor property.
      * 
      * @param value
-     *     allowed object is
-     *     {@link ColorType }
-     *     
+     *            allowed object is {@link ColorType }
+     * 
      */
     public void setInitialColor(ColorType value) {
         this.initialColor = value;
@@ -142,10 +161,8 @@ public class Track {
     /**
      * Gets the value of the extrapColor property.
      * 
-     * @return
-     *     possible object is
-     *     {@link ColorType }
-     *     
+     * @return possible object is {@link ColorType }
+     * 
      */
     public ColorType getExtrapColor() {
         return extrapColor;
@@ -155,9 +172,8 @@ public class Track {
      * Sets the value of the extrapColor property.
      * 
      * @param value
-     *     allowed object is
-     *     {@link ColorType }
-     *     
+     *            allowed object is {@link ColorType }
+     * 
      */
     public void setExtrapColor(ColorType value) {
         this.extrapColor = value;
@@ -167,15 +183,16 @@ public class Track {
      * Gets the value of the initialPoints property.
      * 
      * 

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the initialPoints property. + * This accessor method returns a reference to the live list, not a + * snapshot. Therefore any modification you make to the returned list will + * be present inside the JAXB object. This is why there is not a + * set method for the initialPoints property. * *

* For example, to add a new item, do as follows: + * *

-     *    getInitialPoints().add(newItem);
+     * getInitialPoints().add(newItem);
      * 
* * @@ -196,15 +213,16 @@ public class Track { * Gets the value of the extrapPoints property. * *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the extrapPoints property. + * This accessor method returns a reference to the live list, not a + * snapshot. Therefore any modification you make to the returned list will + * be present inside the JAXB object. This is why there is not a + * set method for the extrapPoints property. * *

* For example, to add a new item, do as follows: + * *

-     *    getExtrapPoints().add(newItem);
+     * getExtrapPoints().add(newItem);
      * 
* * @@ -225,21 +243,22 @@ public class Track { * Gets the value of the extraPointTimeTextDisplayIndicator property. * *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the extraPointTimeTextDisplayIndicator property. + * This accessor method returns a reference to the live list, not a + * snapshot. Therefore any modification you make to the returned list will + * be present inside the JAXB object. This is why there is not a + * set method for the extraPointTimeTextDisplayIndicator + * property. * *

* For example, to add a new item, do as follows: + * *

-     *    getExtraPointTimeTextDisplayIndicator().add(newItem);
+     * getExtraPointTimeTextDisplayIndicator().add(newItem);
      * 
* * *

- * Objects of the following type(s) are allowed in the list - * {@link Boolean } + * Objects of the following type(s) are allowed in the list {@link Boolean } * * */ @@ -253,10 +272,8 @@ public class Track { /** * Gets the value of the extraPointTimeDisplayOptionName property. * - * @return - * possible object is - * {@link String } - * + * @return possible object is {@link String } + * */ public String getExtraPointTimeDisplayOptionName() { return extraPointTimeDisplayOptionName; @@ -266,9 +283,8 @@ public class Track { * Sets the value of the extraPointTimeDisplayOptionName property. * * @param value - * allowed object is - * {@link String } - * + * allowed object is {@link String } + * */ public void setExtraPointTimeDisplayOptionName(String value) { this.extraPointTimeDisplayOptionName = value; @@ -277,10 +293,8 @@ public class Track { /** * Gets the value of the extrapLinePattern property. * - * @return - * possible object is - * {@link String } - * + * @return possible object is {@link String } + * */ public String getExtrapLinePattern() { return extrapLinePattern; @@ -290,9 +304,8 @@ public class Track { * Sets the value of the extrapLinePattern property. * * @param value - * allowed object is - * {@link String } - * + * allowed object is {@link String } + * */ public void setExtrapLinePattern(String value) { this.extrapLinePattern = value; @@ -301,10 +314,8 @@ public class Track { /** * Gets the value of the extrapMarker property. * - * @return - * possible object is - * {@link String } - * + * @return possible object is {@link String } + * */ public String getExtrapMarker() { return extrapMarker; @@ -314,9 +325,8 @@ public class Track { * Sets the value of the extrapMarker property. * * @param value - * allowed object is - * {@link String } - * + * allowed object is {@link String } + * */ public void setExtrapMarker(String value) { this.extrapMarker = value; @@ -325,10 +335,8 @@ public class Track { /** * Gets the value of the fontName property. * - * @return - * possible object is - * {@link String } - * + * @return possible object is {@link String } + * */ public String getFontName() { return fontName; @@ -338,21 +346,39 @@ public class Track { * Sets the value of the fontName property. * * @param value - * allowed object is - * {@link String } - * + * allowed object is {@link String } + * */ public void setFontName(String value) { this.fontName = value; } + /** + * Gets the value of the fontStyle property. + * + * @return possible object is {@link String } + * + */ + public String getFontStyle() { + return fontStyle; + } + + /** + * Sets the value of the fontStyle property. + * + * @param value + * allowed object is {@link String } + * + */ + public void setFontStyle(String value) { + this.fontStyle = value; + } + /** * Gets the value of the fontNameComboSelectedIndex property. * - * @return - * possible object is - * {@link Integer } - * + * @return possible object is {@link Integer } + * */ public Integer getFontNameComboSelectedIndex() { return fontNameComboSelectedIndex; @@ -362,9 +388,8 @@ public class Track { * Sets the value of the fontNameComboSelectedIndex property. * * @param value - * allowed object is - * {@link Integer } - * + * allowed object is {@link Integer } + * */ public void setFontNameComboSelectedIndex(Integer value) { this.fontNameComboSelectedIndex = value; @@ -373,10 +398,8 @@ public class Track { /** * Gets the value of the fontSize property. * - * @return - * possible object is - * {@link Float } - * + * @return possible object is {@link Float } + * */ public Float getFontSize() { return fontSize; @@ -386,9 +409,8 @@ public class Track { * Sets the value of the fontSize property. * * @param value - * allowed object is - * {@link Float } - * + * allowed object is {@link Float } + * */ public void setFontSize(Float value) { this.fontSize = value; @@ -397,10 +419,8 @@ public class Track { /** * Gets the value of the fontSizeComboSelectedIndex property. * - * @return - * possible object is - * {@link Integer } - * + * @return possible object is {@link Integer } + * */ public Integer getFontSizeComboSelectedIndex() { return fontSizeComboSelectedIndex; @@ -410,9 +430,8 @@ public class Track { * Sets the value of the fontSizeComboSelectedIndex property. * * @param value - * allowed object is - * {@link Integer } - * + * allowed object is {@link Integer } + * */ public void setFontSizeComboSelectedIndex(Integer value) { this.fontSizeComboSelectedIndex = value; @@ -421,10 +440,8 @@ public class Track { /** * Gets the value of the fontStyleComboSelectedIndex property. * - * @return - * possible object is - * {@link Integer } - * + * @return possible object is {@link Integer } + * */ public Integer getFontStyleComboSelectedIndex() { return fontStyleComboSelectedIndex; @@ -434,9 +451,8 @@ public class Track { * Sets the value of the fontStyleComboSelectedIndex property. * * @param value - * allowed object is - * {@link Integer } - * + * allowed object is {@link Integer } + * */ public void setFontStyleComboSelectedIndex(Integer value) { this.fontStyleComboSelectedIndex = value; @@ -445,10 +461,8 @@ public class Track { /** * Gets the value of the initialLinePattern property. * - * @return - * possible object is - * {@link String } - * + * @return possible object is {@link String } + * */ public String getInitialLinePattern() { return initialLinePattern; @@ -458,9 +472,8 @@ public class Track { * Sets the value of the initialLinePattern property. * * @param value - * allowed object is - * {@link String } - * + * allowed object is {@link String } + * */ public void setInitialLinePattern(String value) { this.initialLinePattern = value; @@ -469,10 +482,8 @@ public class Track { /** * Gets the value of the initialMarker property. * - * @return - * possible object is - * {@link String } - * + * @return possible object is {@link String } + * */ public String getInitialMarker() { return initialMarker; @@ -482,9 +493,8 @@ public class Track { * Sets the value of the initialMarker property. * * @param value - * allowed object is - * {@link String } - * + * allowed object is {@link String } + * */ public void setInitialMarker(String value) { this.initialMarker = value; @@ -493,10 +503,8 @@ public class Track { /** * Gets the value of the intervalComboSelectedIndex property. * - * @return - * possible object is - * {@link Integer } - * + * @return possible object is {@link Integer } + * */ public Integer getIntervalComboSelectedIndex() { return intervalComboSelectedIndex; @@ -506,9 +514,8 @@ public class Track { * Sets the value of the intervalComboSelectedIndex property. * * @param value - * allowed object is - * {@link Integer } - * + * allowed object is {@link Integer } + * */ public void setIntervalComboSelectedIndex(Integer value) { this.intervalComboSelectedIndex = value; @@ -517,10 +524,8 @@ public class Track { /** * Gets the value of the intervalTimeTextString property. * - * @return - * possible object is - * {@link String } - * + * @return possible object is {@link String } + * */ public String getIntervalTimeTextString() { return intervalTimeTextString; @@ -530,9 +535,8 @@ public class Track { * Sets the value of the intervalTimeTextString property. * * @param value - * allowed object is - * {@link String } - * + * allowed object is {@link String } + * */ public void setIntervalTimeTextString(String value) { this.intervalTimeTextString = value; @@ -541,10 +545,8 @@ public class Track { /** * Gets the value of the lineWidth property. * - * @return - * possible object is - * {@link Float } - * + * @return possible object is {@link Float } + * */ public Float getLineWidth() { return lineWidth; @@ -554,9 +556,8 @@ public class Track { * Sets the value of the lineWidth property. * * @param value - * allowed object is - * {@link Float } - * + * allowed object is {@link Float } + * */ public void setLineWidth(Float value) { this.lineWidth = value; @@ -565,10 +566,8 @@ public class Track { /** * Gets the value of the pgenCategory property. * - * @return - * possible object is - * {@link String } - * + * @return possible object is {@link String } + * */ public String getPgenCategory() { return pgenCategory; @@ -578,9 +577,8 @@ public class Track { * Sets the value of the pgenCategory property. * * @param value - * allowed object is - * {@link String } - * + * allowed object is {@link String } + * */ public void setPgenCategory(String value) { this.pgenCategory = value; @@ -589,10 +587,8 @@ public class Track { /** * Gets the value of the pgenType property. * - * @return - * possible object is - * {@link String } - * + * @return possible object is {@link String } + * */ public String getPgenType() { return pgenType; @@ -602,9 +598,8 @@ public class Track { * Sets the value of the pgenType property. * * @param value - * allowed object is - * {@link String } - * + * allowed object is {@link String } + * */ public void setPgenType(String value) { this.pgenType = value; @@ -613,10 +608,8 @@ public class Track { /** * Gets the value of the setTimeButtonSelected property. * - * @return - * possible object is - * {@link Boolean } - * + * @return possible object is {@link Boolean } + * */ public Boolean isSetTimeButtonSelected() { return setTimeButtonSelected; @@ -626,9 +619,8 @@ public class Track { * Sets the value of the setTimeButtonSelected property. * * @param value - * allowed object is - * {@link Boolean } - * + * allowed object is {@link Boolean } + * */ public void setSetTimeButtonSelected(Boolean value) { this.setTimeButtonSelected = value; @@ -637,10 +629,8 @@ public class Track { /** * Gets the value of the skipFactorTextString property. * - * @return - * possible object is - * {@link String } - * + * @return possible object is {@link String } + * */ public String getSkipFactorTextString() { return skipFactorTextString; @@ -650,9 +640,8 @@ public class Track { * Sets the value of the skipFactorTextString property. * * @param value - * allowed object is - * {@link String } - * + * allowed object is {@link String } + * */ public void setSkipFactorTextString(String value) { this.skipFactorTextString = value; diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/file/TrackConverter.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/file/TrackConverter.java index 940cec1409..02e50623d6 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/file/TrackConverter.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/file/TrackConverter.java @@ -7,11 +7,17 @@ */ package gov.noaa.nws.ncep.ui.pgen.file; +import gov.noaa.nws.ncep.ui.pgen.display.FillPatternList.FillPattern; +import gov.noaa.nws.ncep.ui.pgen.display.IText.FontStyle; +import gov.noaa.nws.ncep.ui.pgen.display.ITrack; +import gov.noaa.nws.ncep.ui.pgen.display.TrackPoint; +import gov.noaa.nws.ncep.ui.pgen.elements.Track; + +import java.awt.Color; +import java.util.ArrayList; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.List; -import java.util.ArrayList; -import java.awt.Color; import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeFactory; @@ -22,318 +28,423 @@ import org.geotools.referencing.datum.DefaultEllipsoid; import com.vividsolutions.jts.geom.Coordinate; -import gov.noaa.nws.ncep.ui.pgen.elements.Track; -import gov.noaa.nws.ncep.ui.pgen.display.ITrack; -import gov.noaa.nws.ncep.ui.pgen.display.TrackPoint; -import gov.noaa.nws.ncep.ui.pgen.display.FillPatternList.FillPattern; - /** - * Define a ProductConverter Class - some methods to convert the products between XML format - * and the actual in-memory PGEN products. + * Define a ProductConverter Class - some methods to convert the products + * between XML format and the actual in-memory PGEN products. * *

  * SOFTWARE HISTORY
  * Date       	Ticket#		Engineer	Description
  * ------------	----------	-----------	--------------------------
- * 02/2012		TTR456			Q. Zhou   	Added speed, dir. Default to kts, no round
+ * 02/2012		TTR456		Q. Zhou   	Added speed, dir. Default to kts, no round
+ * 09/2014      TTR750      J. Wu       Use FontStyle instead of "index".
  * 
* */ public class TrackConverter { -// private final static org.apache.log4j.Logger log = -// org.apache.log4j.Logger.getLogger(TrackConverter.class); - - /* - * Convert a XML file DrawableElement object to a list of PGEN in-memory - * DrawableElement objects - */ - public static List getTrackElementListByTrackBeanList ( - List trackBeanList) { - List trackElementList = new ArrayList(trackBeanList.size()); - - for(gov.noaa.nws.ncep.ui.pgen.file.Track trackBean : trackBeanList) { - Track trackElement = new Track(); - - trackElement.setInitialColor(getColorByColorTypeBean(trackBean.initialColor, true)); - trackElement.setExtrapColor(getColorByColorTypeBean(trackBean.extrapColor, false)); - - trackElement.setInitTrackPoints(getTrackPointElementListByTrackPointBeanList(trackBean.getInitialPoints()).toArray(new TrackPoint[trackBean.getInitialPoints().size()])); - trackElement.setExtrapPoints(getTrackPointElementListByTrackPointBeanList(trackBean.getExtrapPoints()).toArray(new TrackPoint[trackBean.getExtrapPoints().size()])); - - /* - * Now initialize track's firstTimeCalendar and secondTimeCalendar using initTrackPoints - */ - trackElement.setFirstTimeCalendar(getFirstOrSecondTimeCalendarByTrackBean(trackBean, true)); - trackElement.setSecondTimeCalendar(getFirstOrSecondTimeCalendarByTrackBean(trackBean, false)); - - /* - * Important note: the following two method calls are necessary. - * 1. combine init and extrap points to allow PgenSource to go over every point for drawing - * 2. setLinePattern is from the parent class of Track, the name is kind of misleading - * It is hard coded now, for future, a new field is needed to the XSD file. - */ - trackElement.setLinePointsValue(trackElement.getInitialPoints(), trackElement.getExtrapPoints()); - - trackElement.setExtraPointTimeTextDisplayIndicator(getBooleanArrayByBooleanList(trackBean.extraPointTimeTextDisplayIndicator)); - - trackElement.setInitialLinePattern(trackBean.getInitialLinePattern()); - trackElement.setExtrapLinePattern(trackBean.getExtrapLinePattern()); - trackElement.setInitialMarker(trackBean.getInitialMarker()); - trackElement.setExtrapMarker(trackBean.getExtrapMarker()); - trackElement.setFontName(trackBean.getFontName()); - if(trackBean.getLineWidth() != null) - trackElement.setLineWidth(trackBean.getLineWidth().floatValue()); - else - trackElement.setLineWidth((float)1.0); //set a 1.0 as the default value - if(trackBean.getFontSize() != null) - trackElement.setFontSize(trackBean.getFontSize().floatValue()); - else - trackElement.setFontSize((float)2.0); //set a 2.0 as the default value - - if(trackBean.getPgenCategory() == null) - trackElement.setPgenCategory(Track.TRACK_PGEN_CATEGORY); - else - trackElement.setPgenCategory(trackBean.getPgenCategory()); - - if(trackBean.getPgenType() == null) - trackElement.setPgenType(Track.TRACK_PGEN_TYPE); - else - trackElement.setPgenType(trackBean.getPgenType()); - - /* - * add speed, dir. Default to kts, no round --Quan - */ - TrackPoint[] initPts = trackElement.getInitTrackPoints(); - int initPtsLength = initPts.length; - Coordinate initPointBeforeLastInitPointCoordinate = initPts[initPtsLength - 2].getLocation(); - Coordinate lastInitPointCoordinate = initPts[initPtsLength - 1].getLocation(); - - GeodeticCalculator gc = new GeodeticCalculator(DefaultEllipsoid.WGS84); - gc.setStartingGeographicPoint(initPointBeforeLastInitPointCoordinate.x, - initPointBeforeLastInitPointCoordinate.y); - gc.setDestinationGeographicPoint(lastInitPointCoordinate.x, - lastInitPointCoordinate.y); - double direction = gc.getAzimuth(); - - double distanceInMeter = gc.getOrthodromicDistance(); - long timeDifference = initPts[initPtsLength - 1].getTime().getTimeInMillis() - - initPts[initPtsLength - 2].getTime().getTimeInMillis(); - double speed = distanceInMeter / (double)timeDifference; - - trackElement.setDirectionForExtraPoints(direction); - trackElement.setSpeed(speed); - - /* - * add something related to line drawing - */ - trackElement.setSizeScale((double) 1.0); - trackElement.setSmoothFactor(0); - trackElement.setClosed(false); - trackElement.setFilled(false); - trackElement.setFillPattern(FillPattern.FILL_PATTERN_0); - - /* - * The following attributes are necessary to fill values for the pop-up - * TrackAttiDlg window from the restored line images. - */ - boolean setTimeButtonSelectedFlag = true; // set the default value as TRUE - if(trackBean.isSetTimeButtonSelected() != null) - setTimeButtonSelectedFlag = trackBean.isSetTimeButtonSelected().booleanValue(); - trackElement.setSetTimeButtonSelected(setTimeButtonSelectedFlag); - - int intervalComboSelectedIndexValue = 0; //set the default value - if(trackBean.getIntervalComboSelectedIndex() != null) - intervalComboSelectedIndexValue = trackBean.getIntervalComboSelectedIndex().intValue(); - trackElement.setIntervalComboSelectedIndex(intervalComboSelectedIndexValue); - - trackElement.setIntervalTimeString(trackBean.getIntervalTimeTextString()); - - String extraPointTimeDisplayOptionName = ITrack.ExtraPointTimeDisplayOption.SKIP_FACTOR.name(); // set the default value - if(trackBean.getExtraPointTimeDisplayOptionName() != null) - extraPointTimeDisplayOptionName = trackBean.getExtraPointTimeDisplayOptionName(); - trackElement.setExtraPointTimeDisplayOption(ITrack.ExtraPointTimeDisplayOption.valueOf(extraPointTimeDisplayOptionName)); - - String skipFactorTextString = "0"; //set the default value - if(trackBean.getSkipFactorTextString() != null) - skipFactorTextString = trackBean.getSkipFactorTextString(); - trackElement.setSkipFactorTextString(skipFactorTextString); - - int fontNameComboSelectedIndex = 0; //set the default value - if(trackBean.getFontNameComboSelectedIndex() != null) - fontNameComboSelectedIndex = trackBean.getFontNameComboSelectedIndex().intValue(); - trackElement.setFontNameComboSelectedIndex(fontNameComboSelectedIndex); - - int fontSizeComboSelectedIndex = 0; //set the default value - if(trackBean.getFontSizeComboSelectedIndex() != null) - fontSizeComboSelectedIndex = trackBean.getFontSizeComboSelectedIndex().intValue(); - trackElement.setFontSizeComboSelectedIndex(fontSizeComboSelectedIndex); - - int fontStyleComboSelectedIndex = 0; //set the default value - if(trackBean.getFontStyleComboSelectedIndex() != null) - fontStyleComboSelectedIndex = trackBean.getFontStyleComboSelectedIndex().intValue(); - trackElement.setFontStyleComboSelectedIndex(fontStyleComboSelectedIndex); - - trackElementList.add(trackElement); - } - + // private final static org.apache.log4j.Logger log = + // org.apache.log4j.Logger.getLogger(TrackConverter.class); + + /* + * Convert a XML file DrawableElement object to a list of PGEN in-memory + * DrawableElement objects + */ + public static List getTrackElementListByTrackBeanList( + List trackBeanList) { + List trackElementList = new ArrayList( + trackBeanList.size()); + + for (gov.noaa.nws.ncep.ui.pgen.file.Track trackBean : trackBeanList) { + Track trackElement = new Track(); + + trackElement.setInitialColor(getColorByColorTypeBean( + trackBean.initialColor, true)); + trackElement.setExtrapColor(getColorByColorTypeBean( + trackBean.extrapColor, false)); + + trackElement + .setInitTrackPoints(getTrackPointElementListByTrackPointBeanList( + trackBean.getInitialPoints()) + .toArray( + new TrackPoint[trackBean.getInitialPoints() + .size()])); + trackElement + .setExtrapPoints(getTrackPointElementListByTrackPointBeanList( + trackBean.getExtrapPoints()).toArray( + new TrackPoint[trackBean.getExtrapPoints().size()])); + + /* + * Now initialize track's firstTimeCalendar and secondTimeCalendar + * using initTrackPoints + */ + trackElement + .setFirstTimeCalendar(getFirstOrSecondTimeCalendarByTrackBean( + trackBean, true)); + trackElement + .setSecondTimeCalendar(getFirstOrSecondTimeCalendarByTrackBean( + trackBean, false)); + + /* + * Important note: the following two method calls are necessary. 1. + * combine init and extrap points to allow PgenSource to go over + * every point for drawing 2. setLinePattern is from the parent + * class of Track, the name is kind of misleading It is hard coded + * now, for future, a new field is needed to the XSD file. + */ + trackElement.setLinePointsValue(trackElement.getInitialPoints(), + trackElement.getExtrapPoints()); + + trackElement + .setExtraPointTimeTextDisplayIndicator(getBooleanArrayByBooleanList(trackBean.extraPointTimeTextDisplayIndicator)); + + trackElement.setInitialLinePattern(trackBean + .getInitialLinePattern()); + trackElement.setExtrapLinePattern(trackBean.getExtrapLinePattern()); + trackElement.setInitialMarker(trackBean.getInitialMarker()); + trackElement.setExtrapMarker(trackBean.getExtrapMarker()); + trackElement.setFontName(trackBean.getFontName()); + + // TTR 950 - Font Style + int styleInd = 0; + FontStyle dstyle = FontStyle.BOLD; + if (trackBean.getFontStyle() != null) { + int jj = 0; + for (FontStyle ft : FontStyle.values()) { + if (ft == FontStyle.valueOf(trackBean.getFontStyle() + .toUpperCase())) { + styleInd = jj; + dstyle = ft; + break; + } + + jj++; + } + } + + trackElement.setFontStyle(dstyle); + trackElement.setFontStyleComboSelectedIndex(styleInd); + + if (trackBean.getLineWidth() != null) + trackElement + .setLineWidth(trackBean.getLineWidth().floatValue()); + else + trackElement.setLineWidth((float) 1.0); // set a 1.0 as the + // default value + if (trackBean.getFontSize() != null) + trackElement.setFontSize(trackBean.getFontSize().floatValue()); + else + trackElement.setFontSize((float) 2.0); // set a 2.0 as the + // default value + + if (trackBean.getPgenCategory() == null) + trackElement.setPgenCategory(Track.TRACK_PGEN_CATEGORY); + else + trackElement.setPgenCategory(trackBean.getPgenCategory()); + + if (trackBean.getPgenType() == null) + trackElement.setPgenType(Track.TRACK_PGEN_TYPE); + else + trackElement.setPgenType(trackBean.getPgenType()); + + /* + * add speed, dir. Default to kts, no round --Quan + */ + TrackPoint[] initPts = trackElement.getInitTrackPoints(); + int initPtsLength = initPts.length; + Coordinate initPointBeforeLastInitPointCoordinate = initPts[initPtsLength - 2] + .getLocation(); + Coordinate lastInitPointCoordinate = initPts[initPtsLength - 1] + .getLocation(); + + GeodeticCalculator gc = new GeodeticCalculator( + DefaultEllipsoid.WGS84); + gc.setStartingGeographicPoint( + initPointBeforeLastInitPointCoordinate.x, + initPointBeforeLastInitPointCoordinate.y); + gc.setDestinationGeographicPoint(lastInitPointCoordinate.x, + lastInitPointCoordinate.y); + double direction = gc.getAzimuth(); + + double distanceInMeter = gc.getOrthodromicDistance(); + long timeDifference = initPts[initPtsLength - 1].getTime() + .getTimeInMillis() + - initPts[initPtsLength - 2].getTime().getTimeInMillis(); + double speed = distanceInMeter / (double) timeDifference; + + trackElement.setDirectionForExtraPoints(direction); + trackElement.setSpeed(speed); + + /* + * add something related to line drawing + */ + trackElement.setSizeScale((double) 1.0); + trackElement.setSmoothFactor(0); + trackElement.setClosed(false); + trackElement.setFilled(false); + trackElement.setFillPattern(FillPattern.FILL_PATTERN_0); + + /* + * The following attributes are necessary to fill values for the + * pop-up TrackAttiDlg window from the restored line images. + */ + boolean setTimeButtonSelectedFlag = true; // set the default value + // as TRUE + if (trackBean.isSetTimeButtonSelected() != null) + setTimeButtonSelectedFlag = trackBean.isSetTimeButtonSelected() + .booleanValue(); + trackElement.setSetTimeButtonSelected(setTimeButtonSelectedFlag); + + int intervalComboSelectedIndexValue = 0; // set the default value + if (trackBean.getIntervalComboSelectedIndex() != null) + intervalComboSelectedIndexValue = trackBean + .getIntervalComboSelectedIndex().intValue(); + trackElement + .setIntervalComboSelectedIndex(intervalComboSelectedIndexValue); + + trackElement.setIntervalTimeString(trackBean + .getIntervalTimeTextString()); + + String extraPointTimeDisplayOptionName = ITrack.ExtraPointTimeDisplayOption.SKIP_FACTOR + .name(); // set the default value + if (trackBean.getExtraPointTimeDisplayOptionName() != null) + extraPointTimeDisplayOptionName = trackBean + .getExtraPointTimeDisplayOptionName(); + trackElement + .setExtraPointTimeDisplayOption(ITrack.ExtraPointTimeDisplayOption + .valueOf(extraPointTimeDisplayOptionName)); + + String skipFactorTextString = "0"; // set the default value + if (trackBean.getSkipFactorTextString() != null) + skipFactorTextString = trackBean.getSkipFactorTextString(); + trackElement.setSkipFactorTextString(skipFactorTextString); + + int fontNameComboSelectedIndex = 0; // set the default value + if (trackBean.getFontNameComboSelectedIndex() != null) + fontNameComboSelectedIndex = trackBean + .getFontNameComboSelectedIndex().intValue(); + trackElement + .setFontNameComboSelectedIndex(fontNameComboSelectedIndex); + + int fontSizeComboSelectedIndex = 0; // set the default value + if (trackBean.getFontSizeComboSelectedIndex() != null) + fontSizeComboSelectedIndex = trackBean + .getFontSizeComboSelectedIndex().intValue(); + trackElement + .setFontSizeComboSelectedIndex(fontSizeComboSelectedIndex); + + trackElementList.add(trackElement); + } + return trackElementList; } - public static gov.noaa.nws.ncep.ui.pgen.file.Track getTrackBeanByTrackElement( + public static gov.noaa.nws.ncep.ui.pgen.file.Track getTrackBeanByTrackElement( Track trackElement) { - gov.noaa.nws.ncep.ui.pgen.file.Track trackBean = new gov.noaa.nws.ncep.ui.pgen.file.Track(); + gov.noaa.nws.ncep.ui.pgen.file.Track trackBean = new gov.noaa.nws.ncep.ui.pgen.file.Track(); - trackBean.setInitialColor(getColorTypeBeanByColorElement(trackElement.getInitialColor())); - trackBean.setExtrapColor(getColorTypeBeanByColorElement(trackElement.getExtrapColor())); - - if(trackElement.getInitialPoints() != null) { - for(TrackPoint currentTrackPoint : trackElement.getInitialPoints()) { - trackBean.getInitialPoints().add(getTrackPointBeanByTrackPointElement(currentTrackPoint)); - } - } - if(trackElement.getExtrapPoints() != null) { - for(TrackPoint currentTrackPoint : trackElement.getExtrapPoints()) { - trackBean.getExtrapPoints().add(getTrackPointBeanByTrackPointElement(currentTrackPoint)); - } - } - - trackBean.getExtraPointTimeTextDisplayIndicator().addAll(getBooleanObjectList(trackElement.getExtraPointTimeTextDisplayIndicator())); + trackBean.setInitialColor(getColorTypeBeanByColorElement(trackElement + .getInitialColor())); + trackBean.setExtrapColor(getColorTypeBeanByColorElement(trackElement + .getExtrapColor())); - trackBean.setInitialLinePattern(trackElement.getInitialLinePattern()); - trackBean.setExtrapLinePattern(trackElement.getExtrapLinePattern()); - trackBean.setInitialMarker(trackElement.getInitialMarker()); - trackBean.setExtrapMarker(trackElement.getExtrapMarker()); - trackBean.setFontName(trackElement.getFontName()); - trackBean.setFontSize(new Float(trackElement.getFontSize())); - trackBean.setLineWidth(new Float(trackElement.getLineWidth())); - - trackBean.setPgenCategory(trackElement.getPgenCategory()); - trackBean.setPgenType(trackElement.getPgenType()); - - /* - * The following attributes are not necessary to save the line images - * and late to restore them back on the map. However, they are necessary - * values to pop-up and set up the correct attributes of the TrackAttrDlg - */ - trackBean.setSetTimeButtonSelected(new Boolean(trackElement.isSetTimeButtonSelected())); - trackBean.setIntervalComboSelectedIndex(new Integer(trackElement.getIntervalComboSelectedIndex())); - trackBean.setIntervalTimeTextString(trackElement.getIntervalTimeString()); - trackBean.setExtraPointTimeDisplayOptionName(trackElement.getExtraPointTimeDisplayOption().name()); - trackBean.setSkipFactorTextString(trackElement.getSkipFactorTextString()); - trackBean.setFontNameComboSelectedIndex(new Integer(trackElement.getFontNameComboSelectedIndex())); - trackBean.setFontSizeComboSelectedIndex(new Integer(trackElement.getFontSizeComboSelectedIndex())); - trackBean.setFontStyleComboSelectedIndex(new Integer(trackElement.getFontStyleComboSelectedIndex())); - - return trackBean; + if (trackElement.getInitialPoints() != null) { + for (TrackPoint currentTrackPoint : trackElement.getInitialPoints()) { + trackBean + .getInitialPoints() + .add(getTrackPointBeanByTrackPointElement(currentTrackPoint)); + } + } + if (trackElement.getExtrapPoints() != null) { + for (TrackPoint currentTrackPoint : trackElement.getExtrapPoints()) { + trackBean + .getExtrapPoints() + .add(getTrackPointBeanByTrackPointElement(currentTrackPoint)); + } + } + + trackBean.getExtraPointTimeTextDisplayIndicator().addAll( + getBooleanObjectList(trackElement + .getExtraPointTimeTextDisplayIndicator())); + + trackBean.setInitialLinePattern(trackElement.getInitialLinePattern()); + trackBean.setExtrapLinePattern(trackElement.getExtrapLinePattern()); + trackBean.setInitialMarker(trackElement.getInitialMarker()); + trackBean.setExtrapMarker(trackElement.getExtrapMarker()); + trackBean.setFontName(trackElement.getFontName()); + + // Font style + int styleInd = 0; + FontStyle dstyle = FontStyle.BOLD; + if (trackElement.getFontStyle() != null) { + int jj = 0; + for (FontStyle ft : FontStyle.values()) { + if (ft == trackElement.getFontStyle()) { + styleInd = jj; + dstyle = ft; + break; + } + + jj++; + } + } + + trackBean.setFontStyle(dstyle.toString()); + trackBean.setFontStyleComboSelectedIndex(styleInd); + + trackBean.setFontSize(new Float(trackElement.getFontSize())); + trackBean.setLineWidth(new Float(trackElement.getLineWidth())); + + trackBean.setPgenCategory(trackElement.getPgenCategory()); + trackBean.setPgenType(trackElement.getPgenType()); + + /* + * The following attributes are not necessary to save the line images + * and late to restore them back on the map. However, they are necessary + * values to pop-up and set up the correct attributes of the + * TrackAttrDlg + */ + trackBean.setSetTimeButtonSelected(new Boolean(trackElement + .isSetTimeButtonSelected())); + trackBean.setIntervalComboSelectedIndex(new Integer(trackElement + .getIntervalComboSelectedIndex())); + trackBean.setIntervalTimeTextString(trackElement + .getIntervalTimeString()); + trackBean.setExtraPointTimeDisplayOptionName(trackElement + .getExtraPointTimeDisplayOption().name()); + trackBean.setSkipFactorTextString(trackElement + .getSkipFactorTextString()); + trackBean.setFontNameComboSelectedIndex(new Integer(trackElement + .getFontNameComboSelectedIndex())); + trackBean.setFontSizeComboSelectedIndex(new Integer(trackElement + .getFontSizeComboSelectedIndex())); + + return trackBean; } - + /* - * help methods for transferring objects back and forth between class objects and JAXB beans + * help methods for transferring objects back and forth between class + * objects and JAXB beans */ - private static Calendar getFirstOrSecondTimeCalendarByTrackBean(gov.noaa.nws.ncep.ui.pgen.file.Track trackBean, boolean isFirstTimeCalendar) { - int indexOffSet = 1; - if(isFirstTimeCalendar) - indexOffSet++; - List trackPointElementList = getTrackPointElementListByTrackPointBeanList(trackBean.getInitialPoints()); - if(trackPointElementList == null || trackPointElementList.size() < 2) { -// log.error("Retrieved List trackPointElementList is NULL or the initial points are less than 2 points"); - return null; - } - int listSize = trackPointElementList.size(); - return trackPointElementList.get(listSize - indexOffSet).getTime(); - } - - private static java.awt.Color getColorByColorTypeBean(gov.noaa.nws.ncep.ui.pgen.file.ColorType colorTypeBean, - boolean isInitColor) { - if(colorTypeBean == null || colorTypeBean.getColor() == null) { - if(isInitColor) - return new Color(0, 0, 255); //return a default color as Blue - else - return new Color(0, 192, 0); //return a green color as the default color for extrapPoint - } - gov.noaa.nws.ncep.ui.pgen.file.Color colorBean = colorTypeBean.getColor(); - return new Color(colorBean.getRed(), colorBean.getGreen(), colorBean.getBlue(), - colorBean.getAlpha()); - } - - private static List getTrackPointElementListByTrackPointBeanList(List trackPointBeanList) { - List trackPointElementList = new ArrayList(trackPointBeanList.size()); - for(gov.noaa.nws.ncep.ui.pgen.file.TrackPoint trackPointBean : trackPointBeanList) { - java.util.Calendar currentCalendar = null; - if(trackPointBean.getTime() != null) { - currentCalendar = trackPointBean.getTime().toGregorianCalendar(); - } - Coordinate currentCoordinate = getCoordinateByTrackPointBean(trackPointBean); - TrackPoint currentTrackPointElement = new TrackPoint(currentCoordinate, currentCalendar); - trackPointElementList.add(currentTrackPointElement); - } - return trackPointElementList; - } - - private static Coordinate getCoordinateByTrackPointBean(gov.noaa.nws.ncep.ui.pgen.file.TrackPoint trackPointBean) { - Coordinate coordinate = new Coordinate(); - if(trackPointBean.getLocation() != null) { - coordinate.x = trackPointBean.getLocation().getLongitude(); - coordinate.y = trackPointBean.getLocation().getLatitude(); - } - return coordinate; - } - - private static boolean[] getBooleanArrayByBooleanList(List booleanList) { - boolean[] booleanArray = new boolean[booleanList.size()]; - int arrayIndex = 0; - for(Boolean currentBoolean : booleanList) { - booleanArray[arrayIndex++] = currentBoolean.booleanValue(); - } - return booleanArray; + private static Calendar getFirstOrSecondTimeCalendarByTrackBean( + gov.noaa.nws.ncep.ui.pgen.file.Track trackBean, + boolean isFirstTimeCalendar) { + int indexOffSet = 1; + if (isFirstTimeCalendar) + indexOffSet++; + List trackPointElementList = getTrackPointElementListByTrackPointBeanList(trackBean + .getInitialPoints()); + if (trackPointElementList == null || trackPointElementList.size() < 2) { + // log.error("Retrieved List trackPointElementList is NULL or the initial points are less than 2 points"); + return null; + } + int listSize = trackPointElementList.size(); + return trackPointElementList.get(listSize - indexOffSet).getTime(); } - - private static gov.noaa.nws.ncep.ui.pgen.file.ColorType getColorTypeBeanByColorElement(java.awt.Color colorElement) { - gov.noaa.nws.ncep.ui.pgen.file.ColorType colorTypeBean = new gov.noaa.nws.ncep.ui.pgen.file.ColorType(); - gov.noaa.nws.ncep.ui.pgen.file.Color colorBean = new gov.noaa.nws.ncep.ui.pgen.file.Color(); - colorBean.setAlpha(colorElement.getAlpha()); - colorBean.setBlue(colorElement.getBlue()); - colorBean.setRed(colorElement.getRed()); - colorBean.setGreen(colorElement.getGreen()); - colorTypeBean.setColor(colorBean); - return colorTypeBean; + private static java.awt.Color getColorByColorTypeBean( + gov.noaa.nws.ncep.ui.pgen.file.ColorType colorTypeBean, + boolean isInitColor) { + if (colorTypeBean == null || colorTypeBean.getColor() == null) { + if (isInitColor) + return new Color(0, 0, 255); // return a default color as Blue + else + return new Color(0, 192, 0); // return a green color as the + // default color for extrapPoint + } + gov.noaa.nws.ncep.ui.pgen.file.Color colorBean = colorTypeBean + .getColor(); + return new Color(colorBean.getRed(), colorBean.getGreen(), + colorBean.getBlue(), colorBean.getAlpha()); } - - private static gov.noaa.nws.ncep.ui.pgen.file.TrackPoint getTrackPointBeanByTrackPointElement(TrackPoint trackPointElement) { - gov.noaa.nws.ncep.ui.pgen.file.TrackPoint trackPointBean = new gov.noaa.nws.ncep.ui.pgen.file.TrackPoint(); - if(trackPointElement.getTime() != null) { - GregorianCalendar gregorianCalendar = new GregorianCalendar(); - gregorianCalendar.setTimeInMillis(trackPointElement.getTime().getTimeInMillis()); - try { - XMLGregorianCalendar xmlGregorianCalendar = DatatypeFactory.newInstance().newXMLGregorianCalendar(gregorianCalendar); - trackPointBean.setTime(xmlGregorianCalendar); - } catch(DatatypeConfigurationException dce) { -// log.error("Error, instantiating XMLGregorianCalendar failed, error="+dce.getMessage()); - } - } - if(trackPointElement.getLocation() != null) { - trackPointBean.location = new gov.noaa.nws.ncep.ui.pgen.file.TrackPoint.Location(); - trackPointBean.getLocation().setLongitude(trackPointElement.getLocation().x); - trackPointBean.getLocation().setLatitude(trackPointElement.getLocation().y); - } - return trackPointBean; + private static List getTrackPointElementListByTrackPointBeanList( + List trackPointBeanList) { + List trackPointElementList = new ArrayList( + trackPointBeanList.size()); + for (gov.noaa.nws.ncep.ui.pgen.file.TrackPoint trackPointBean : trackPointBeanList) { + java.util.Calendar currentCalendar = null; + if (trackPointBean.getTime() != null) { + currentCalendar = trackPointBean.getTime() + .toGregorianCalendar(); + } + Coordinate currentCoordinate = getCoordinateByTrackPointBean(trackPointBean); + TrackPoint currentTrackPointElement = new TrackPoint( + currentCoordinate, currentCalendar); + trackPointElementList.add(currentTrackPointElement); + } + return trackPointElementList; } - + + private static Coordinate getCoordinateByTrackPointBean( + gov.noaa.nws.ncep.ui.pgen.file.TrackPoint trackPointBean) { + Coordinate coordinate = new Coordinate(); + if (trackPointBean.getLocation() != null) { + coordinate.x = trackPointBean.getLocation().getLongitude(); + coordinate.y = trackPointBean.getLocation().getLatitude(); + } + return coordinate; + } + + private static boolean[] getBooleanArrayByBooleanList( + List booleanList) { + boolean[] booleanArray = new boolean[booleanList.size()]; + int arrayIndex = 0; + for (Boolean currentBoolean : booleanList) { + booleanArray[arrayIndex++] = currentBoolean.booleanValue(); + } + return booleanArray; + } + + private static gov.noaa.nws.ncep.ui.pgen.file.ColorType getColorTypeBeanByColorElement( + java.awt.Color colorElement) { + gov.noaa.nws.ncep.ui.pgen.file.ColorType colorTypeBean = new gov.noaa.nws.ncep.ui.pgen.file.ColorType(); + gov.noaa.nws.ncep.ui.pgen.file.Color colorBean = new gov.noaa.nws.ncep.ui.pgen.file.Color(); + colorBean.setAlpha(colorElement.getAlpha()); + colorBean.setBlue(colorElement.getBlue()); + colorBean.setRed(colorElement.getRed()); + colorBean.setGreen(colorElement.getGreen()); + colorTypeBean.setColor(colorBean); + return colorTypeBean; + } + + private static gov.noaa.nws.ncep.ui.pgen.file.TrackPoint getTrackPointBeanByTrackPointElement( + TrackPoint trackPointElement) { + gov.noaa.nws.ncep.ui.pgen.file.TrackPoint trackPointBean = new gov.noaa.nws.ncep.ui.pgen.file.TrackPoint(); + + if (trackPointElement.getTime() != null) { + GregorianCalendar gregorianCalendar = new GregorianCalendar(); + gregorianCalendar.setTimeInMillis(trackPointElement.getTime() + .getTimeInMillis()); + try { + XMLGregorianCalendar xmlGregorianCalendar = DatatypeFactory + .newInstance().newXMLGregorianCalendar( + gregorianCalendar); + trackPointBean.setTime(xmlGregorianCalendar); + } catch (DatatypeConfigurationException dce) { + // log.error("Error, instantiating XMLGregorianCalendar failed, error="+dce.getMessage()); + } + } + if (trackPointElement.getLocation() != null) { + trackPointBean.location = new gov.noaa.nws.ncep.ui.pgen.file.TrackPoint.Location(); + trackPointBean.getLocation().setLongitude( + trackPointElement.getLocation().x); + trackPointBean.getLocation().setLatitude( + trackPointElement.getLocation().y); + } + return trackPointBean; + } + private static List getBooleanObjectList(boolean[] booleanArray) { - List booleanList = null; - if(booleanArray == null) - booleanList = new ArrayList(); - else - booleanList = new ArrayList(booleanArray.length); - for(boolean booleanValue : booleanArray) { - Boolean booleanObject = new Boolean(booleanValue); - booleanList.add(booleanObject); - } - return booleanList; + List booleanList = null; + if (booleanArray == null) + booleanList = new ArrayList(); + else + booleanList = new ArrayList(booleanArray.length); + for (boolean booleanValue : booleanArray) { + Boolean booleanObject = new Boolean(booleanValue); + booleanList.add(booleanObject); + } + return booleanList; } - - -} +} diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/file/product.xsd b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/file/product.xsd index 7b56012fba..6aed5f6601 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/file/product.xsd +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/file/product.xsd @@ -411,27 +411,52 @@ - - - + + + + + + - + + + - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/gfa/GfaGenerate.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/gfa/GfaGenerate.java index e54fc3f253..e34d8f932d 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/gfa/GfaGenerate.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/gfa/GfaGenerate.java @@ -14,10 +14,10 @@ import gov.noaa.nws.ncep.ui.pgen.elements.Product; import gov.noaa.nws.ncep.ui.pgen.file.FileTools; import gov.noaa.nws.ncep.ui.pgen.file.ProductConverter; import gov.noaa.nws.ncep.ui.pgen.file.Products; +import gov.noaa.nws.ncep.ui.pgen.rsc.PgenResource; import gov.noaa.nws.ncep.ui.pgen.store.PgenStorageException; import gov.noaa.nws.ncep.ui.pgen.store.StorageUtils; import gov.noaa.nws.ncep.ui.pgen.tools.PgenCycleTool; -import gov.noaa.nws.ncep.ui.pgen.rsc.PgenResource; import java.io.File; import java.io.IOException; @@ -61,6 +61,7 @@ import com.vividsolutions.jts.geom.GeometryFactory; * 05/13 #610 J. Wu Implemented FZLVL range (TTR425) * 07/13 ? J. Wu Move state list ordering to GfaRules. * 08/13 TTR714/715 J. Wu Fixed issue type and times. + * 10/14 TTR714 J. Wu Check issue type in get_status.xml. * *
* @@ -70,7 +71,9 @@ import com.vividsolutions.jts.geom.GeometryFactory; public class GfaGenerate { private static final String TEXT_TYPE = "TEXT"; - private GeometryFactory gf = new GeometryFactory(); + + private GeometryFactory gf = new GeometryFactory(); + private static final String ISSUE_TYPE_FROM_OUTLOOK = "ISSUE_TYPE_FROM_OUTLOOK"; // private final static Logger logger = Logger.getLogger(GfaGenerate.class); @@ -109,20 +112,22 @@ public class GfaGenerate { /* * Create an additional smear for the adjacent area. */ - for ( Gfa g : all) { - Gfa sg = createAdjacentGfa( g ); + for (Gfa g : all) { + Gfa sg = createAdjacentGfa(g); - adjusted.add( g ); + adjusted.add(g); - if ( sg != null ) { - adjusted.add( sg ); + if (sg != null) { + adjusted.add(sg); } } /* - * Find issue type for an Airmet's associated Outlook + * Find issue type for an Airmet's associated Outlook. Note: TTR 714 - + * J. Wu: this may cause other issues. Instead, we should check the + * issue types in "get_status.xsl". */ - trackOtlkIssueTypeToAirmet( adjusted ); + // trackOtlkIssueTypeToAirmet(adjusted); /* * Find GFA smears in each area and hazard category, generate xml, and @@ -130,14 +135,14 @@ public class GfaGenerate { */ for (String category : categories) { for (String area : areas) { - - List ret = filterSelected( adjusted, area, category ); + + List ret = filterSelected(adjusted, area, category); // If no issue/until times, assign them. for (Gfa de : ret) { if (!de.isSnapshot() && de.getAttribute(Gfa.ISSUE_TIME) == null) { - GfaRules.assignIssueTime( de ); + GfaRules.assignIssueTime(de); } } @@ -154,24 +159,25 @@ public class GfaGenerate { /* * Find freezing range for this area! */ - String fzlvlRange = findFreezingRange( all, ret, area, category ); + String fzlvlRange = findFreezingRange(all, ret, area, category); /* * Note - needs to use a copy so it won't change the parent of * the original G-Airmets, e.g. l.add( de ) will set the parent * of the 'de" to be "l"! */ - for ( Gfa gss : ret) { - Gfa gfaCopy = gss.copy(); - String otlkIssueType = nvl( gfaCopy.getGfaValue( ISSUE_TYPE_FROM_OUTLOOK ) ); - if ( !otlkIssueType.equals( "NRML" ) ) { - gfaCopy.setGfaIssueType( otlkIssueType ); - } - - if ( fzlvlRange != null ) { - gfaCopy.setGfaValue( Gfa.FZL_RANGE, fzlvlRange ); - } - l.add( gfaCopy ); + for (Gfa gss : ret) { + Gfa gfaCopy = gss.copy(); + /* + * String otlkIssueType = nvl(gfaCopy + * .getGfaValue(ISSUE_TYPE_FROM_OUTLOOK)); if + * (!otlkIssueType.equals("NRML")) { + * gfaCopy.setGfaIssueType( otlkIssueType ); } + */ + if (fzlvlRange != null) { + gfaCopy.setGfaValue(Gfa.FZL_RANGE, fzlvlRange); + } + l.add(gfaCopy); } // l.add( ret ); @@ -183,7 +189,7 @@ public class GfaGenerate { // Needs to add an empty Gfa to carry the issue/until for proper // formatting. if (ret.size() == 0) { - addNullGfa( products, category, fzlvlRange ); + addNullGfa(products, category, fzlvlRange); } String xml = SerializationUtil.marshalToXml(products); @@ -191,7 +197,7 @@ public class GfaGenerate { if (sb.length() > 0 && !sb.toString().endsWith("\n\n")) { sb.append("\n\n"); } - + String prdXml = generateProduct(xml, category, area).trim(); temp.append(prdXml); @@ -233,7 +239,8 @@ public class GfaGenerate { * @param cats * @return */ - private static List filterSelected( List all, String area, String category) { + private static List filterSelected(List all, String area, + String category) { ArrayList ret = new ArrayList(); @@ -258,6 +265,7 @@ public class GfaGenerate { } public String generateProduct(String prdxml, String category, String area) { + System.out.println("\nprdxml is:\n" + prdxml + "\n"); String xml1 = prdxml.replaceAll("TURB-HI", "TURB"); String xml = xml1.replaceAll("TURB-LO", "TURB"); @@ -279,6 +287,7 @@ public class GfaGenerate { transformer.transform(xmlSource, result); res = result.getWriter().toString().trim(); + System.out.println("\nres is:\n" + res + "\n"); } catch (Exception e) { // logger.error( "", e ); @@ -295,11 +304,13 @@ public class GfaGenerate { } /** - * Create a new smear for smears with two FA areas and re-order the state list. + * Create a new smear for smears with two FA areas and re-order the state + * list. * - * The States in the primary area precede states in the adjacent area. + * The States in the primary area precede states in the adjacent area. * - * @param g Gfa to be processed + * @param g + * Gfa to be processed * * @return */ @@ -310,12 +321,12 @@ public class GfaGenerate { String[] s = nvl(g.getGfaArea()).split("-"); if (s.length > 1) { - String sname = new String( s[1].trim() + "-" + s[0].trim() ); + String sname = new String(s[1].trim() + "-" + s[0].trim()); // create an additional smear and re-order state list. - secondg = g.copy(); - secondg.setGfaArea( sname ); - GfaRules.reorderStateList( secondg ); + secondg = g.copy(); + secondg.setGfaArea(sname); + GfaRules.reorderStateList(secondg); } return secondg; @@ -362,12 +373,12 @@ public class GfaGenerate { /* * Adds an empty Gfa to the product so it can pass issue/until time for - * correct formatting. Freezing range should be set if provided. + * correct formatting. Freezing range should be set if provided. * * Note - this should be called only when there is no Gfa smears in the * "prds". */ - private void addNullGfa(Products prds, String category, String fzlRange ) { + private void addNullGfa(Products prds, String category, String fzlRange) { gov.noaa.nws.ncep.ui.pgen.file.Gfa fgfa = new gov.noaa.nws.ncep.ui.pgen.file.Gfa(); @@ -380,9 +391,9 @@ public class GfaGenerate { fgfa.setFcstHr("0-6"); // If freezing range is provided, set it and set hazard type as "FZLVL". - if ( fzlRange != null ) { - fgfa.setHazard( "FZLVL" ); - fgfa.setFzlRange( fzlRange ); + if (fzlRange != null) { + fgfa.setHazard("FZLVL"); + fgfa.setFzlRange(fzlRange); } // @@ -429,398 +440,395 @@ public class GfaGenerate { } /* - * Find the freezing range from FZLVL/M_FZLVL airmets. + * Find the freezing range from FZLVL/M_FZLVL airmets. */ - private String findFreezingRange( List all, List selected, - String area, String cat ) { - - if ( !cat.equalsIgnoreCase( "ZULU" ) ) { - return null; - } - - - String fzlRange = null; - String topStr = null; - String botStr = null; - - /* - * If no FZLVL/M_FZLVL in this area, find range using those outside of - * this area, if any. - */ - if ( selected == null || selected.size() == 0 ) { - int[] extRange = findExernalFzlvlRange( all, area ); - if ( extRange[0] != -1 ) { - topStr = padding( extRange[0] ); - botStr = padding( extRange[1] ); - } - } - else { - /* - * First - find the worst range from existing FZL_RANGE in FZLVL airmets. - * If no existing range found, then find the worst top/bottom from - * FZLVLs' levels ( top = level + 40 and bottom = level - 40) - * Second - find the worst top/bottom from M_FZLVLs - * - * Third - find the worst case range using info from step 1 and 2. - * - */ - int[] existingRange = findExistingFzlRange( all, selected, area ); - int[] mfzlRange = findMfzlvlRange( all, selected, area ); + private String findFreezingRange(List all, List selected, + String area, String cat) { - if ( existingRange[0] == -1 ) { - existingRange = findFzlvlLevelRange( all, selected, area ); - } + if (!cat.equalsIgnoreCase("ZULU")) { + return null; + } - if ( existingRange[0] != -1 || mfzlRange[0] != -1 ) { - topStr = padding( Math.max( existingRange[0], mfzlRange[0] ) ); - } + String fzlRange = null; + String topStr = null; + String botStr = null; - if ( existingRange[1] != 9999 || mfzlRange[1] != 9999 ){ - botStr = padding( Math.min( existingRange[1], mfzlRange[1] ) ); - } - } - - // Now create a range string. - if ( topStr != null && botStr != null ) { - fzlRange = area + ";" + topStr + ";" + botStr; - } - - return fzlRange; - - } - - - /* - * Retrieve the worst FZLVL range from ranges existing in FZLVL airmet/outlook. - * Such existing range should be in the form as "MIA;160;40", retrievable as - * gfa.getGfaValue( Gfa.FZL_RANGE ). - */ - private int[] findExistingFzlRange( List all, List selected, String area ) { - - int[] topBot = { -1, 9999 }; - - for ( Gfa elem : selected ) { - - String gtype = elem.getGfaHazard(); - - if ( !gtype.equalsIgnoreCase("FZLVL") || elem.isSnapshot() ) { - continue; - } - - String range1 = elem.getGfaValue( Gfa.FZL_RANGE ); - if ( range1 != null ) { - String[] rangeInfo = range1.split(";"); - if ( rangeInfo.length >= 3 && rangeInfo[0].equalsIgnoreCase( area ) ) { - int top1 = -1; - int bot1 = -1; - - try { - top1 = Integer.parseInt( rangeInfo[1] ); - } - catch ( Exception e ) { - e.printStackTrace(); - } - - if ( rangeInfo[2].equalsIgnoreCase("SFC") ) { - bot1 = 0; - } - else { - try { - bot1 = Integer.parseInt( rangeInfo[2] ); - } - catch ( Exception e ) { - e.printStackTrace(); - } - } - - if ( top1 >= 0 && bot1 >= 0 ) { - topBot[0] = Math.max( topBot[0], top1 ); - topBot[1] = Math.min( topBot[1], bot1 ); - } - } - } - } - - return topBot; - } - - /* - * Retrieve the worst range from existing top/bottom of M_FZLVL airmet/outlook. - * Such top/bottom are retrievable as gfa.getGfaTop() & gfa.getGfaBottom(). - */ - private int[] findMfzlvlRange( List all, List selected, String area ) { - - int[] topBot = { -1, 9999 }; - - for ( Gfa elem : selected ) { - - String gtype = elem.getGfaHazard(); - - if ( !gtype.equalsIgnoreCase("M_FZLVL") || elem.isSnapshot() ) { - continue; - } - - int top2 = -1; - int bot2 = -1; - - if ( elem.getGfaTop() != null ) { - try { - top2 = Integer.parseInt( elem.getGfaTop() ); - } - catch ( Exception e ) { - e.printStackTrace(); - } - } - - String botStr = elem.getGfaBottom(); - if ( botStr != null ) { - if ( botStr.equalsIgnoreCase( "SFC") ) { - bot2 = 0; - } - else { - try { - bot2 = Integer.parseInt( elem.getGfaBottom() ); - } - catch ( Exception e ) { - e.printStackTrace(); - } - } - } - - if ( top2 >= 0 && bot2 >= 0 ) { - topBot[0] = Math.max( topBot[0], top2 ); - topBot[1] = Math.min( topBot[1], bot2 ); - } - - } - - return topBot; - - } - - /* - * Retrieve the worst range from existing levels of FZLVL airmet/outlook. - * Such levels are retrievable as gfa.getGfaValue( Gfa.LEVEL ). - */ - private int[] findFzlvlLevelRange( List all, List selected, String area ) { - - int[] topBot = { -1, 9999 }; - for ( Gfa elem : selected ) { - - String gtype = elem.getGfaHazard(); - - if ( !gtype.equalsIgnoreCase("FZLVL") || elem.isSnapshot() ) { - continue; - } - - int top2 = -1; - int bot2 = -1; - - String levelStr = elem.getGfaValue( Gfa.LEVEL ); - int lvl = -1; - - if ( levelStr != null ) { - - if ( levelStr.equalsIgnoreCase( "SFC" ) ) { - top2 = 40; - bot2 = 0; - } - else { - try { - lvl = Integer.parseInt( levelStr ); - } - catch ( Exception e ) { - e.printStackTrace(); - } - - if ( lvl >= 0 && lvl <= 40 ) { - top2 = 40; - bot2 = 0; - } - else { - top2 = lvl + 40; - bot2 = lvl - 40; - } - } - } - - - if ( top2 >= 0 && bot2 >= 0 ) { - topBot[0] = Math.max( topBot[0], top2 ); - topBot[1] = Math.min( topBot[1], bot2 ); - } - - } - - return topBot; - - } - - /* - * Find the top and base levels for a FA area that is not intersected by any FZLVL - * contours. It sorts all external fzlvls by distance from the area centroid, then - * uses the level from that contour. If the contour is to the left of the area then - * the answer is base = contour level, top = base + 040. If the contour is to the - * right of the area then the answer top = contour level, base = top - 040. - * - * See legacy af_getExternalFzlvlRng() in af_getAirmetXml.c. - * - * Note (1) only FZLVLs are used, not M_FZLVLs. - * (2) All FZLVLs are used, including snapshots. - * - */ - private int[] findExernalFzlvlRange( List all, String area ) { - - int[] topBot = { -1, 9999 }; - - HashMap areaBnds = GfaClip.getInstance().getFaAreaBounds(); - - Coordinate center = gf.createLinearRing( areaBnds.get(area ).getCoordinates() ).getCentroid().getCoordinate(); - - Gfa closestGfa = null; - double minDist = Double.MAX_VALUE; - - for ( Gfa elem : all ) { - - String gtype = elem.getGfaHazard(); - - if ( !gtype.equalsIgnoreCase("FZLVL") ) { - continue; - } - - // Find distance from the FA Area's centroid to this FZLVL. - double dist = distance( elem, center ); - if ( dist < minDist ) { - minDist = dist; - closestGfa = elem; + /* + * If no FZLVL/M_FZLVL in this area, find range using those outside of + * this area, if any. + */ + if (selected == null || selected.size() == 0) { + int[] extRange = findExernalFzlvlRange(all, area); + if (extRange[0] != -1) { + topStr = padding(extRange[0]); + botStr = padding(extRange[1]); } - - } - - if ( closestGfa != null ) { - boolean isLeft = GfaSnap.getInstance().atLeft( center, closestGfa.getLinePoints(), - closestGfa.isClosedLine(), 0.0 ); - - String levelStr = closestGfa.getGfaValue( Gfa.LEVEL ); - int lvl = -1; - - if ( levelStr != null ) { - - if ( levelStr.equalsIgnoreCase( "SFC" ) ) { + } else { + /* + * First - find the worst range from existing FZL_RANGE in FZLVL + * airmets. If no existing range found, then find the worst + * top/bottom from FZLVLs' levels ( top = level + 40 and bottom = + * level - 40) Second - find the worst top/bottom from M_FZLVLs + * + * Third - find the worst case range using info from step 1 and 2. + */ + int[] existingRange = findExistingFzlRange(all, selected, area); + int[] mfzlRange = findMfzlvlRange(all, selected, area); + + if (existingRange[0] == -1) { + existingRange = findFzlvlLevelRange(all, selected, area); + } + + if (existingRange[0] != -1 || mfzlRange[0] != -1) { + topStr = padding(Math.max(existingRange[0], mfzlRange[0])); + } + + if (existingRange[1] != 9999 || mfzlRange[1] != 9999) { + botStr = padding(Math.min(existingRange[1], mfzlRange[1])); + } + } + + // Now create a range string. + if (topStr != null && botStr != null) { + fzlRange = area + ";" + topStr + ";" + botStr; + } + + return fzlRange; + + } + + /* + * Retrieve the worst FZLVL range from ranges existing in FZLVL + * airmet/outlook. Such existing range should be in the form as + * "MIA;160;40", retrievable as gfa.getGfaValue( Gfa.FZL_RANGE ). + */ + private int[] findExistingFzlRange(List all, List selected, + String area) { + + int[] topBot = { -1, 9999 }; + + for (Gfa elem : selected) { + + String gtype = elem.getGfaHazard(); + + if (!gtype.equalsIgnoreCase("FZLVL") || elem.isSnapshot()) { + continue; + } + + String range1 = elem.getGfaValue(Gfa.FZL_RANGE); + if (range1 != null) { + String[] rangeInfo = range1.split(";"); + if (rangeInfo.length >= 3 + && rangeInfo[0].equalsIgnoreCase(area)) { + int top1 = -1; + int bot1 = -1; + + try { + top1 = Integer.parseInt(rangeInfo[1]); + } catch (Exception e) { + e.printStackTrace(); + } + + if (rangeInfo[2].equalsIgnoreCase("SFC")) { + bot1 = 0; + } else { + try { + bot1 = Integer.parseInt(rangeInfo[2]); + } catch (Exception e) { + e.printStackTrace(); + } + } + + if (top1 >= 0 && bot1 >= 0) { + topBot[0] = Math.max(topBot[0], top1); + topBot[1] = Math.min(topBot[1], bot1); + } + } + } + } + + return topBot; + } + + /* + * Retrieve the worst range from existing top/bottom of M_FZLVL + * airmet/outlook. Such top/bottom are retrievable as gfa.getGfaTop() & + * gfa.getGfaBottom(). + */ + private int[] findMfzlvlRange(List all, List selected, String area) { + + int[] topBot = { -1, 9999 }; + + for (Gfa elem : selected) { + + String gtype = elem.getGfaHazard(); + + if (!gtype.equalsIgnoreCase("M_FZLVL") || elem.isSnapshot()) { + continue; + } + + int top2 = -1; + int bot2 = -1; + + if (elem.getGfaTop() != null) { + try { + top2 = Integer.parseInt(elem.getGfaTop()); + } catch (Exception e) { + e.printStackTrace(); + } + } + + String botStr = elem.getGfaBottom(); + if (botStr != null) { + if (botStr.equalsIgnoreCase("SFC")) { + bot2 = 0; + } else { + try { + bot2 = Integer.parseInt(elem.getGfaBottom()); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + if (top2 >= 0 && bot2 >= 0) { + topBot[0] = Math.max(topBot[0], top2); + topBot[1] = Math.min(topBot[1], bot2); + } + + } + + return topBot; + + } + + /* + * Retrieve the worst range from existing levels of FZLVL airmet/outlook. + * Such levels are retrievable as gfa.getGfaValue( Gfa.LEVEL ). + */ + private int[] findFzlvlLevelRange(List all, List selected, + String area) { + + int[] topBot = { -1, 9999 }; + for (Gfa elem : selected) { + + String gtype = elem.getGfaHazard(); + + if (!gtype.equalsIgnoreCase("FZLVL") || elem.isSnapshot()) { + continue; + } + + int top2 = -1; + int bot2 = -1; + + String levelStr = elem.getGfaValue(Gfa.LEVEL); + int lvl = -1; + + if (levelStr != null) { + + if (levelStr.equalsIgnoreCase("SFC")) { + top2 = 40; + bot2 = 0; + } else { + try { + lvl = Integer.parseInt(levelStr); + } catch (Exception e) { + e.printStackTrace(); + } + + if (lvl >= 0 && lvl <= 40) { + top2 = 40; + bot2 = 0; + } else { + top2 = lvl + 40; + bot2 = lvl - 40; + } + } + } + + if (top2 >= 0 && bot2 >= 0) { + topBot[0] = Math.max(topBot[0], top2); + topBot[1] = Math.min(topBot[1], bot2); + } + + } + + return topBot; + + } + + /* + * Find the top and base levels for a FA area that is not intersected by any + * FZLVL contours. It sorts all external fzlvls by distance from the area + * centroid, then uses the level from that contour. If the contour is to the + * left of the area then the answer is base = contour level, top = base + + * 040. If the contour is to the right of the area then the answer top = + * contour level, base = top - 040. + * + * See legacy af_getExternalFzlvlRng() in af_getAirmetXml.c. + * + * Note (1) only FZLVLs are used, not M_FZLVLs. (2) All FZLVLs are used, + * including snapshots. + */ + private int[] findExernalFzlvlRange(List all, String area) { + + int[] topBot = { -1, 9999 }; + + HashMap areaBnds = GfaClip.getInstance() + .getFaAreaBounds(); + + Coordinate center = gf + .createLinearRing(areaBnds.get(area).getCoordinates()) + .getCentroid().getCoordinate(); + + Gfa closestGfa = null; + double minDist = Double.MAX_VALUE; + + for (Gfa elem : all) { + + String gtype = elem.getGfaHazard(); + + if (!gtype.equalsIgnoreCase("FZLVL")) { + continue; + } + + // Find distance from the FA Area's centroid to this FZLVL. + double dist = distance(elem, center); + if (dist < minDist) { + minDist = dist; + closestGfa = elem; + } + + } + + if (closestGfa != null) { + boolean isLeft = GfaSnap.getInstance().atLeft(center, + closestGfa.getLinePoints(), closestGfa.isClosedLine(), 0.0); + + String levelStr = closestGfa.getGfaValue(Gfa.LEVEL); + int lvl = -1; + + if (levelStr != null) { + + if (levelStr.equalsIgnoreCase("SFC")) { lvl = 0; - } - else { - try { - lvl = Integer.parseInt( levelStr ); - } - catch ( Exception e ) { - e.printStackTrace(); - } - } - } - - if ( lvl >= 0 ) { - if ( !isLeft ) { // FZLVL is at right of FA area - topBot[0] = lvl + 40; - topBot[1] = lvl; - } - else { // FZLVL is at left of FA area - topBot[0] = lvl; - topBot[1] = lvl - 40; - if ( topBot[1] < 0 ) topBot[1] = 0; - } - } - } - - return topBot; - + } else { + try { + lvl = Integer.parseInt(levelStr); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + if (lvl >= 0) { + if (!isLeft) { // FZLVL is at right of FA area + topBot[0] = lvl + 40; + topBot[1] = lvl; + } else { // FZLVL is at left of FA area + topBot[0] = lvl; + topBot[1] = lvl - 40; + if (topBot[1] < 0) + topBot[1] = 0; + } + } + } + + return topBot; + } - + /* - * Pad a value between 0 to 100 in format of "0xx". - */ - private String padding( int value ) { - - StringBuilder str = new StringBuilder(); - if ( value <= 0 ) { - str.append( "SFC" ); - } - else { - if ( value < 100 ) { - str.append( "0" + value ); - } - else { - str.append( value ); - } - } - - return str.toString(); - + * Pad a value between 0 to 100 in format of "0xx". + */ + private String padding(int value) { + + StringBuilder str = new StringBuilder(); + if (value <= 0) { + str.append("SFC"); + } else { + if (value < 100) { + str.append("0" + value); + } else { + str.append(value); + } + } + + return str.toString(); + } - + /* - * Find the distance from a given point to a Gfa line or polygon. - */ - private double distance( Gfa gfa, Coordinate loc ) { - + * Find the distance from a given point to a Gfa line or polygon. + */ + private double distance(Gfa gfa, Coordinate loc) { + double dist = Double.MAX_VALUE; double minDist = Double.MAX_VALUE; - + Object pts[] = gfa.getPoints().toArray(); - for ( int ii = 0; ii < pts.length; ii++ ) { + for (int ii = 0; ii < pts.length; ii++) { - if ( ii == pts.length - 1 ) { - if ( gfa.isClosedLine() ) { - dist = PgenResource.distanceFromLineSegment( loc, + if (ii == pts.length - 1) { + if (gfa.isClosedLine()) { + dist = PgenResource.distanceFromLineSegment(loc, (Coordinate) pts[ii], (Coordinate) pts[0]); - } - else { + } else { break; } - } - else { - dist = PgenResource.distanceFromLineSegment( loc, (Coordinate) pts[ii], - (Coordinate) pts[ii + 1]); + } else { + dist = PgenResource.distanceFromLineSegment(loc, + (Coordinate) pts[ii], (Coordinate) pts[ii + 1]); } - if ( dist < minDist ) { + if (dist < minDist) { minDist = dist; - } - } - - return minDist; - + } + } + + return minDist; + } - + /** - * Find if a smear has an associated outlook that are generated from the same series of - * snapshots (with same hazard type, tag and desk. + * Find if a smear has an associated outlook that are generated from the + * same series of snapshots (with same hazard type, tag and desk. * - * This is used to get around the issue when a pair of airmet and outlook is generated from - * the same series of snapshots, and the airmet's issue tyep is "NRML" while outlook's issue - * type is not "NRML". In this case, the formatted header should show the outlook's issue type. + * This is used to get around the issue when a pair of airmet and outlook is + * generated from the same series of snapshots, and the airmet's issue type + * is "NRML" while outlook's issue type is not "NRML". In this case, the + * formatted header should show the outlook's issue type. + * + * Note: TTR 714 - 10/2014: for the above case, we should modify + * "get_status.xsl" to get the formatted header by looping through all + * airmets and outlooks instead of modifying it here. * * @param all * @return */ - private static void trackOtlkIssueTypeToAirmet( List all ) { + private static void trackOtlkIssueTypeToAirmet(List all) { - for ( Gfa gg : all) { - gg.setGfaValue( ISSUE_TYPE_FROM_OUTLOOK, "NRML" ); - if ( gg.isAirmet() && "NRML".equalsIgnoreCase( gg.getGfaIssueType() ) ) { - String akey = gg.getGfaHazard() + gg.getGfaTag() + gg.getGfaDesk(); - for ( Gfa gotlk : all) { - if ( gotlk.isOutlook() && !("NRML".equalsIgnoreCase( gotlk.getGfaIssueType() ) ) ) { - String okey = gotlk.getGfaHazard() + gotlk.getGfaTag() + gotlk.getGfaDesk(); - if ( okey.equals( akey ) ) { - gg.setGfaValue( ISSUE_TYPE_FROM_OUTLOOK, gotlk.getGfaIssueType() ); - break; - } - } - } - } + for (Gfa gg : all) { + gg.setGfaValue(ISSUE_TYPE_FROM_OUTLOOK, "NRML"); + if (gg.isAirmet() && "NRML".equalsIgnoreCase(gg.getGfaIssueType())) { + String akey = gg.getGfaHazard() + gg.getGfaTag() + + gg.getGfaDesk(); + for (Gfa gotlk : all) { + if (gotlk.isOutlook() + && !("NRML".equalsIgnoreCase(gotlk + .getGfaIssueType()))) { + String okey = gotlk.getGfaHazard() + gotlk.getGfaTag() + + gotlk.getGfaDesk(); + if (okey.equals(akey)) { + gg.setGfaValue(ISSUE_TYPE_FROM_OUTLOOK, + gotlk.getGfaIssueType()); + break; + } + } + } + } } } - + } diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/gfa/GfaInfo.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/gfa/GfaInfo.java index 3693d2745e..2cac8c7acc 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/gfa/GfaInfo.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/gfa/GfaInfo.java @@ -7,6 +7,12 @@ */ package gov.noaa.nws.ncep.ui.pgen.gfa; +import static gov.noaa.nws.ncep.ui.pgen.gfa.Gfa.BOS; +import static gov.noaa.nws.ncep.ui.pgen.gfa.Gfa.CHI; +import static gov.noaa.nws.ncep.ui.pgen.gfa.Gfa.DFW; +import static gov.noaa.nws.ncep.ui.pgen.gfa.Gfa.MIA; +import static gov.noaa.nws.ncep.ui.pgen.gfa.Gfa.SFO; +import static gov.noaa.nws.ncep.ui.pgen.gfa.Gfa.SLC; import gov.noaa.nws.ncep.ui.pgen.PgenStaticDataProvider; import java.awt.Color; @@ -20,8 +26,6 @@ import org.dom4j.Node; import org.dom4j.io.SAXReader; import org.eclipse.swt.graphics.RGB; -import static gov.noaa.nws.ncep.ui.pgen.gfa.Gfa.*; - /** * Helper class to read the GFA configuration. * @@ -41,379 +45,390 @@ import static gov.noaa.nws.ncep.ui.pgen.gfa.Gfa.*; */ public class GfaInfo { - // gui settings - private static Document doc; + // gui settings + private static Document doc; - public static final String HAZARD_XPATH = "/root/hazard"; - public static final String FCSTHR_XPATH = "/root/fcstHr"; - public static final String TAG_XPATH = "/root/tag"; - public static final String DESK_XPATH = "/root/desk"; - public static final String ISSUE_TYPE_XPATH = "/root/issueType"; - public static final String GFA_OTLKGEN_RATIO_XPATH = "/root/gfaOtlkgenRatio"; - - public static final String AIRMET_ELEMENT_XPATH = "/airmetcycle/element"; - - public static final String GFA_SNAPSHOT = "snapshot"; - public static final String GFA_SMEAR = "smear"; - public static final String GFA_OUTLOOK = "outlook"; + public static final String HAZARD_XPATH = "/root/hazard"; - public static final int GFA_SMEAR_LINEWIDTH = 3; - public static final int GFA_OUTLOOK_LINEWIDTH = 4; - public static final int GFA_OTHER_LINEWIDTH = 2; - + public static final String FCSTHR_XPATH = "/root/fcstHr"; - /** - * Hazard type vs color array (index means the same as the position - * in fcstHr combo box) - */ - private static HashMap rgbMap; + public static final String TAG_XPATH = "/root/tag"; - /** - * Pairs like ("red", new RGB(255, 0, 0)) read from gfa.xml - */ - private static HashMap definedColors; - - /** - * Hazard categories - */ - private static HashMap hazardCategories; - - public enum HazardCategory{ - SIERRA, TANGO, ZULU, NONE; - } + public static final String DESK_XPATH = "/root/desk"; - /** - * State orders in each FA area. - */ - private static HashMap > stateOrderByArea; - - /** - * Pairs like ("red", new RGB(255, 0, 0)) read from gfa.xml - */ - private static HashMap fzlvlSfcColors; - - /** - * Getter for the document. - * - * @return - */ - public static Document getDocument() { - if (doc == null) { - readOptions(); - } - return doc; - } + public static final String ISSUE_TYPE_XPATH = "/root/issueType"; - /** - * Read the menu configuration from gfa.xml file - */ - private static void readOptions() { - File gfainfoFile = PgenStaticDataProvider.getProvider().getStaticFile( - PgenStaticDataProvider.getProvider().getPgenLocalizationRoot() + "gfa.xml"); + public static final String GFA_OTLKGEN_RATIO_XPATH = "/root/gfaOtlkgenRatio"; - try { - SAXReader reader = new SAXReader(); - doc = reader.read(gfainfoFile.getAbsoluteFile()); - } catch (Exception e) { - e.printStackTrace(); - } - } + public static final String AIRMET_ELEMENT_XPATH = "/airmetcycle/element"; - /* - * This method is just to suppress warning - */ - @SuppressWarnings("unchecked") - public static List selectNodes(String xPath) { - return (List) GfaInfo.getDocument().selectNodes(xPath); - } + public static final String GFA_SNAPSHOT = "snapshot"; - /** - * Creates an rgb map for hazard types and returns the corresponding color. - * - * @param hazard - * @return - */ - public static RGB getRGB(String hazard, int fcstHrIndex) { - if (rgbMap == null) { - loadColors(); - } + public static final String GFA_SMEAR = "smear"; - if (fcstHrIndex < 0 || fcstHrIndex >= rgbMap.get(hazard).length) { - // take last as default if parameter is out of range (fcstHr=Other) - fcstHrIndex = rgbMap.get(hazard).length-1; - } + public static final String GFA_OUTLOOK = "outlook"; - return rgbMap.get(hazard)[fcstHrIndex]; - } - - /** - * Load colors. - */ - private static void loadColors() { - List colorNodes = selectNodes("/root/color/value"); + public static final int GFA_SMEAR_LINEWIDTH = 3; - definedColors = new HashMap(); - for (Node n : colorNodes) { - int r = Integer.parseInt(n.valueOf("@r")); - int g = Integer.parseInt(n.valueOf("@g")); - int b = Integer.parseInt(n.valueOf("@b")); - // for example, <"red", (255,0,0)> - definedColors.put(n.valueOf("@name"), new RGB(r, g, b)); - } + public static final int GFA_OUTLOOK_LINEWIDTH = 4; - List hazardNodes = selectNodes(HAZARD_XPATH); - List fcstHrNodes = selectNodes(FCSTHR_XPATH); + public static final int GFA_OTHER_LINEWIDTH = 2; - // hazard type vs. color array (index means the same as the position - // in fcstHr combo box) - rgbMap = new HashMap(); + /** + * Hazard type vs color array (index means the same as the position in + * fcstHr combo box) + */ + private static HashMap rgbMap; - for (Node n : hazardNodes) { - RGB[] colors = new RGB[fcstHrNodes.size()]; - int i = 0; - for (Node f : fcstHrNodes) { - String type = f.valueOf("@type"); // for example, "smear" - String colorStr = n.valueOf("@" + type); // for example, - // "blue" - colors[i++] = definedColors.get(colorStr); - } - rgbMap.put(n.valueOf("@name"), colors); - } - } + /** + * Pairs like ("red", new RGB(255, 0, 0)) read from gfa.xml + */ + private static HashMap definedColors; - /** - * Returns the default colors for the hazard and forecast hour pair. - * - * @param hazard - * @param fcstHr - * @return Color[] - */ - public static Color[] getDefaultColors(String hazard, String fcstHr) { - RGB rgb = getDefaultRGB( hazard, fcstHr ); - - Color color = new Color(rgb.red, rgb.green, rgb.blue); - return new Color[]{color, color}; - } + /** + * Hazard categories + */ + private static HashMap hazardCategories; - /** - * Returns the default color's RGB for the hazard and forecast hour pair. - * - * @param hazard - * @param fcstHr - * @return RGB - */ - public static RGB getDefaultRGB(String hazard, String fcstHr) { - if (definedColors == null) { - loadColors(); - } - - String xPath = HAZARD_XPATH + "[@name='" + hazard + "']"; - List hazardNodes = selectNodes(xPath); - - xPath = FCSTHR_XPATH + "[@name='" + fcstHr + "']"; - List fcsthrNodes = selectNodes(xPath); - - if (fcsthrNodes.size() != 1) { - try{ - if(fcstHr.indexOf("-") == -1) { // snapshot - xPath = FCSTHR_XPATH + "[@name='0 Z']"; - } else { - String second= fcstHr.split("-")[1]; - String hour = second.split(":")[0]; - if(Integer.parseInt(hour) <=6){ // smear - xPath = FCSTHR_XPATH + "[@name='0-6']"; - } else { // outlook - xPath = FCSTHR_XPATH + "[@name='6-9']"; - } - } - } catch (Exception e){ - xPath = FCSTHR_XPATH + "[@name='Other']"; - } - fcsthrNodes = selectNodes(xPath); - } - - String gfaType = GFA_SNAPSHOT; - if ( fcsthrNodes.size() != 1 ) { //hard-coded - if ( fcstHr.indexOf("-") >= 0 ) { - String second= fcstHr.split("-")[1]; - String hour = second.split(":")[0]; - if(Integer.parseInt(hour) <=6) { - gfaType = GFA_SMEAR; - } else { - gfaType = GFA_OUTLOOK; - } - } - } - else { - gfaType = fcsthrNodes.get(0).valueOf("@type"); // from table - } - - if (hazardNodes.size() != 1 ) { - throw new IllegalArgumentException("Please check hazard name"); - } - - String colorStr = hazardNodes.get(0).valueOf("@" + gfaType ); - - RGB rgb = definedColors.get(colorStr); - - return rgb; - } - - /** - * Returns the default line width for the forecast hour. - * - * @param fcstHr - * @return - */ - public static int getLineWidth(String fcstHr) { - String xPath = FCSTHR_XPATH + "[@name='" + fcstHr + "']"; - List fcsthrNodes = selectNodes(xPath); - - int lineWidth = GFA_OTHER_LINEWIDTH; - if ( fcsthrNodes.size() > 0 ) { - lineWidth = Integer.parseInt( fcsthrNodes.get(0).valueOf("@linewidth") ); - } - else { - if ( fcstHr.indexOf("-") >= 0 ) { - String second= fcstHr.split("-")[1]; - String hour = second.split(":")[0]; - if( Integer.parseInt(hour) <= 6 ) { - lineWidth = GFA_SMEAR_LINEWIDTH; - } else { - lineWidth = GFA_OUTLOOK_LINEWIDTH; - } - } - - } + public enum HazardCategory { + SIERRA, TANGO, ZULU, NONE; + } - return lineWidth; - } - - public static boolean isFormat(String hazard){ - if (definedColors == null) { - loadColors(); - } - - String xPath = HAZARD_XPATH + "[@name='" + hazard + "']"; - List hazardNodes = selectNodes(xPath); - if (hazardNodes.size() != 1) { - throw new IllegalArgumentException("Please check hazard name"); - } - String format = hazardNodes.get(0).valueOf("@format"); - return !"false".equals(format); - } + /** + * State orders in each FA area. + */ + private static HashMap> stateOrderByArea; - private static HashMap getHazardCategories() { - if(hazardCategories == null) { - hazardCategories = new HashMap(); - List nodes = selectNodes(HAZARD_XPATH); - for(Node n: nodes){ - String key = n.valueOf("@name"); - String category = n.valueOf("@category"); - HazardCategory cat = HazardCategory.valueOf(HazardCategory.class, category); - if(cat == null) cat = HazardCategory.NONE; - hazardCategories.put(key, cat); - } - } - return hazardCategories; - } - - public static HazardCategory getHazardCategory(String hazard){ - return getHazardCategories().get(hazard); - } - - public static double getGfaOtlkgenRatio(){ - List nodes = selectNodes(GFA_OTLKGEN_RATIO_XPATH); - Node n = nodes.get(0); - String rationStr = n.getStringValue(); - return Double.parseDouble(rationStr); - } + /** + * Pairs like ("red", new RGB(255, 0, 0)) read from gfa.xml + */ + private static HashMap fzlvlSfcColors; + + /** + * Getter for the document. + * + * @return + */ + public static Document getDocument() { + if (doc == null) { + readOptions(); + } + return doc; + } + + /** + * Read the menu configuration from gfa.xml file + */ + private static void readOptions() { + File gfainfoFile = PgenStaticDataProvider.getProvider().getStaticFile( + PgenStaticDataProvider.getProvider().getPgenLocalizationRoot() + + "gfa.xml"); + + try { + SAXReader reader = new SAXReader(); + doc = reader.read(gfainfoFile.getAbsoluteFile()); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /* + * This method is just to suppress warning + */ + @SuppressWarnings("unchecked") + public static List selectNodes(String xPath) { + return (List) GfaInfo.getDocument().selectNodes(xPath); + } + + /** + * Creates an rgb map for hazard types and returns the corresponding color. + * + * @param hazard + * @return + */ + public static RGB getRGB(String hazard, int fcstHrIndex) { + if (rgbMap == null) { + loadColors(); + } + + if (fcstHrIndex < 0 || fcstHrIndex >= rgbMap.get(hazard).length) { + // take last as default if parameter is out of range (fcstHr=Other) + fcstHrIndex = rgbMap.get(hazard).length - 1; + } + + return rgbMap.get(hazard)[fcstHrIndex]; + } + + /** + * Load colors. + */ + private static void loadColors() { + List colorNodes = selectNodes("/root/color/value"); + + definedColors = new HashMap(); + for (Node n : colorNodes) { + int r = Integer.parseInt(n.valueOf("@r")); + int g = Integer.parseInt(n.valueOf("@g")); + int b = Integer.parseInt(n.valueOf("@b")); + // for example, <"red", (255,0,0)> + definedColors.put(n.valueOf("@name"), new RGB(r, g, b)); + } + + List hazardNodes = selectNodes(HAZARD_XPATH); + List fcstHrNodes = selectNodes(FCSTHR_XPATH); + + // hazard type vs. color array (index means the same as the position + // in fcstHr combo box) + rgbMap = new HashMap(); + + for (Node n : hazardNodes) { + RGB[] colors = new RGB[fcstHrNodes.size()]; + int i = 0; + for (Node f : fcstHrNodes) { + String type = f.valueOf("@type"); // for example, "smear" + String colorStr = n.valueOf("@" + type); // for example, + // "blue" + colors[i++] = definedColors.get(colorStr); + } + rgbMap.put(n.valueOf("@name"), colors); + } + } + + /** + * Returns the default colors for the hazard and forecast hour pair. + * + * @param hazard + * @param fcstHr + * @return Color[] + */ + public static Color[] getDefaultColors(String hazard, String fcstHr) { + RGB rgb = getDefaultRGB(hazard, fcstHr); + + Color color = new Color(rgb.red, rgb.green, rgb.blue); + return new Color[] { color, color }; + } + + /** + * Returns the default color's RGB for the hazard and forecast hour pair. + * + * @param hazard + * @param fcstHr + * @return RGB + */ + public static RGB getDefaultRGB(String hazard, String fcstHr) { + if (definedColors == null) { + loadColors(); + } + + String xPath = HAZARD_XPATH + "[@name='" + hazard + "']"; + List hazardNodes = selectNodes(xPath); + + xPath = FCSTHR_XPATH + "[@name='" + fcstHr + "']"; + List fcsthrNodes = selectNodes(xPath); + + if (fcsthrNodes.size() != 1) { + try { + if (fcstHr.indexOf("-") == -1) { // snapshot + xPath = FCSTHR_XPATH + "[@name='0 Z']"; + } else { + String second = fcstHr.split("-")[1]; + String hour = second.split(":")[0]; + if (Integer.parseInt(hour) <= 6) { // smear + xPath = FCSTHR_XPATH + "[@name='0-6']"; + } else { // outlook + xPath = FCSTHR_XPATH + "[@name='6-9']"; + } + } + } catch (Exception e) { + xPath = FCSTHR_XPATH + "[@name='Other']"; + } + fcsthrNodes = selectNodes(xPath); + } + + String gfaType = GFA_SNAPSHOT; + if (fcsthrNodes.size() != 1) { // hard-coded + if (fcstHr.indexOf("-") >= 0) { + String second = fcstHr.split("-")[1]; + String hour = second.split(":")[0]; + if (Integer.parseInt(hour) <= 6) { + gfaType = GFA_SMEAR; + } else { + gfaType = GFA_OUTLOOK; + } + } + } else { + gfaType = fcsthrNodes.get(0).valueOf("@type"); // from table + } + + if (hazardNodes.size() != 1) { + throw new IllegalArgumentException("Please check hazard name"); + } + + String colorStr = hazardNodes.get(0).valueOf("@" + gfaType); + + RGB rgb = definedColors.get(colorStr); + + return rgb; + } + + /** + * Returns the default line width for the forecast hour. + * + * @param fcstHr + * @return + */ + public static int getLineWidth(String fcstHr) { + String xPath = FCSTHR_XPATH + "[@name='" + fcstHr + "']"; + List fcsthrNodes = selectNodes(xPath); + + int lineWidth = GFA_OTHER_LINEWIDTH; + if (fcsthrNodes.size() > 0) { + lineWidth = Integer.parseInt(fcsthrNodes.get(0).valueOf( + "@linewidth")); + } else { + if (fcstHr.indexOf("-") >= 0) { + String second = fcstHr.split("-")[1]; + String hour = second.split(":")[0]; + if (Integer.parseInt(hour) <= 6) { + lineWidth = GFA_SMEAR_LINEWIDTH; + } else { + lineWidth = GFA_OUTLOOK_LINEWIDTH; + } + } + + } + + return lineWidth; + } + + public static boolean isFormat(String hazard) { + if (definedColors == null) { + loadColors(); + } + + String xPath = HAZARD_XPATH + "[@name='" + hazard + "']"; + List hazardNodes = selectNodes(xPath); + if (hazardNodes.size() != 1) { + throw new IllegalArgumentException("Please check hazard name"); + } + String format = hazardNodes.get(0).valueOf("@format"); + return !"false".equals(format); + } + + private static HashMap getHazardCategories() { + if (hazardCategories == null) { + hazardCategories = new HashMap(); + List nodes = selectNodes(HAZARD_XPATH); + for (Node n : nodes) { + String key = n.valueOf("@name"); + String category = n.valueOf("@category"); + HazardCategory cat = HazardCategory.valueOf( + HazardCategory.class, category); + if (cat == null) + cat = HazardCategory.NONE; + hazardCategories.put(key, cat); + } + } + return hazardCategories; + } + + public static HazardCategory getHazardCategory(String hazard) { + return getHazardCategories().get(hazard); + } + + public static double getGfaOtlkgenRatio() { + List nodes = selectNodes(GFA_OTLKGEN_RATIO_XPATH); + Node n = nodes.get(0); + String rationStr = n.getStringValue(); + return Double.parseDouble(rationStr); + } /** * Return the fixed ordered state list in each FA area. */ - public static HashMap > getStateOrderByArea() { - - if ( stateOrderByArea == null ) { - stateOrderByArea = new HashMap >(); - ArrayList bos = new ArrayList(); - String[] bosStr = new String[]{"ME","NH","VT","MA","RI","CT","NY", - "LO","PA","NJ","OH","LE","WV","MD", - "DC", "DE", "VA", "CSTL WTRS"}; - for ( String st : bosStr ) { - bos.add( st ); - } - stateOrderByArea.put( BOS, bos); - - ArrayList mia = new ArrayList(); - String[] miaStr = new String[]{"NC", "SC", "GA", "FL" , "CSTL WTRS"}; - for ( String st : miaStr ) { - mia.add( st ); - } - stateOrderByArea.put( MIA, mia ); + public static HashMap> getStateOrderByArea() { - ArrayList chi = new ArrayList(); - String[] chiStr = new String[]{"ND", "SD", "NE", "KS", "MN", "IA", - "MO", "WI", "LM", "LS", "MI", "LH", - "IL", "IN", "KY"}; - for ( String st : chiStr ) { - chi.add( st ); - } - stateOrderByArea.put( CHI, chi ); + if (stateOrderByArea == null) { + stateOrderByArea = new HashMap>(); + ArrayList bos = new ArrayList(); + String[] bosStr = new String[] { "ME", "NH", "VT", "MA", "RI", + "CT", "NY", "LO", "NJ", "PA", "OH", "LE", "WV", "MD", "DC", + "DE", "VA", "CSTL WTRS" }; + for (String st : bosStr) { + bos.add(st); + } + stateOrderByArea.put(BOS, bos); - ArrayList dfw = new ArrayList(); - String[] dfwStr = new String[]{"OK", "TX", "AR", "TN", "LA", "MS", - "AL", "CSTL WTRS"}; - for ( String st : dfwStr ) { - dfw.add( st ); - } - stateOrderByArea.put( DFW, dfw ); - - ArrayList slc = new ArrayList(); - String[] slcStr = new String[]{"ID", "MT", "WY", "NV", "UT", "CO", - "AZ", "NM"} ; - for ( String st : slcStr ) { - slc.add( st ); - } - stateOrderByArea.put( SLC, slc ); - - ArrayList sfo = new ArrayList(); - String[] sfoStr = new String[]{"WA", "OR", "CA", "CSTL WTRS"}; - for ( String st : sfoStr ) { - sfo.add( st ); - } - stateOrderByArea.put( SFO, sfo ); - - } - - return stateOrderByArea; - } - - /** - * Get colors for FZLVL SFC snapshot, smear, or outlook. - * Default is "sky". - */ - public static RGB getFzlvlSfcColor( String name ) { + ArrayList mia = new ArrayList(); + String[] miaStr = new String[] { "NC", "SC", "GA", "FL", + "CSTL WTRS" }; + for (String st : miaStr) { + mia.add(st); + } + stateOrderByArea.put(MIA, mia); - if ( definedColors == null ) { - loadColors(); - } - - List colorNodes = selectNodes("/root/fzlvlSFC/value"); - - if ( fzlvlSfcColors == null ) { - fzlvlSfcColors = new HashMap(); - for ( Node nd : colorNodes ) { - fzlvlSfcColors.put( nd.valueOf("@name"), definedColors.get( nd.valueOf("@nmapcolor") ) ); - } - } - - RGB clr = fzlvlSfcColors.get( name ); - - if ( clr == null ) clr = definedColors.get( "sky" ); - - return clr; + ArrayList chi = new ArrayList(); + String[] chiStr = new String[] { "ND", "SD", "NE", "KS", "MN", + "IA", "MO", "WI", "LM", "LS", "MI", "LH", "IL", "IN", "KY" }; + for (String st : chiStr) { + chi.add(st); + } + stateOrderByArea.put(CHI, chi); + + ArrayList dfw = new ArrayList(); + String[] dfwStr = new String[] { "OK", "TX", "AR", "TN", "LA", + "MS", "AL", "CSTL WTRS" }; + for (String st : dfwStr) { + dfw.add(st); + } + stateOrderByArea.put(DFW, dfw); + + ArrayList slc = new ArrayList(); + String[] slcStr = new String[] { "ID", "MT", "WY", "NV", "UT", + "CO", "AZ", "NM" }; + for (String st : slcStr) { + slc.add(st); + } + stateOrderByArea.put(SLC, slc); + + ArrayList sfo = new ArrayList(); + String[] sfoStr = new String[] { "WA", "OR", "CA", "CSTL WTRS" }; + for (String st : sfoStr) { + sfo.add(st); + } + stateOrderByArea.put(SFO, sfo); + + } + + return stateOrderByArea; + } + + /** + * Get colors for FZLVL SFC snapshot, smear, or outlook. Default is "sky". + */ + public static RGB getFzlvlSfcColor(String name) { + + if (definedColors == null) { + loadColors(); + } + + List colorNodes = selectNodes("/root/fzlvlSFC/value"); + + if (fzlvlSfcColors == null) { + fzlvlSfcColors = new HashMap(); + for (Node nd : colorNodes) { + fzlvlSfcColors.put(nd.valueOf("@name"), + definedColors.get(nd.valueOf("@nmapcolor"))); + } + } + + RGB clr = fzlvlSfcColors.get(name); + + if (clr == null) + clr = definedColors.get("sky"); + + return clr; + + } - } - } diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/gfa/GfaRules.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/gfa/GfaRules.java index e1640eac65..e79b4aa90a 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/gfa/GfaRules.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/gfa/GfaRules.java @@ -7,7 +7,18 @@ */ package gov.noaa.nws.ncep.ui.pgen.gfa; -import static gov.noaa.nws.ncep.ui.pgen.gfa.Gfa.*; +import static gov.noaa.nws.ncep.ui.pgen.gfa.Gfa.BOS; +import static gov.noaa.nws.ncep.ui.pgen.gfa.Gfa.CHI; +import static gov.noaa.nws.ncep.ui.pgen.gfa.Gfa.DFW; +import static gov.noaa.nws.ncep.ui.pgen.gfa.Gfa.DVLPG_HR; +import static gov.noaa.nws.ncep.ui.pgen.gfa.Gfa.ENDG_HR; +import static gov.noaa.nws.ncep.ui.pgen.gfa.Gfa.ISSUE_TIME; +import static gov.noaa.nws.ncep.ui.pgen.gfa.Gfa.MIA; +import static gov.noaa.nws.ncep.ui.pgen.gfa.Gfa.OUTLOOK_END_TIME; +import static gov.noaa.nws.ncep.ui.pgen.gfa.Gfa.SFO; +import static gov.noaa.nws.ncep.ui.pgen.gfa.Gfa.SLC; +import static gov.noaa.nws.ncep.ui.pgen.gfa.Gfa.SNAPSHOT_TYPE; +import static gov.noaa.nws.ncep.ui.pgen.gfa.Gfa.UNTIL_TIME; import static gov.noaa.nws.ncep.ui.pgen.tools.PgenCycleTool.pad; import static java.lang.Math.abs; import static java.lang.Math.ceil; @@ -23,14 +34,11 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.TreeSet; -//import org.apache.log4j.Logger; - import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.MultiPolygon; import com.vividsolutions.jts.geom.Polygon; - /** * GFA rules functionality. * @@ -61,1591 +69,1649 @@ import com.vividsolutions.jts.geom.Polygon; */ public class GfaRules { + public static final String WORDING = "WORDING"; - public static final String WORDING = "WORDING"; + /** Area limit in square nautical miles */ + public static final double AREA_LIMIT = 3000.0; - /** Logger */ -// private final static Logger logger = Logger.getLogger(GfaRules.class); + /** Tolerance for coordinates to be treated as the same /close points. */ + private static final double PRECISION = 0.000000001; - /** Area limit in square nautical miles */ - public static final double AREA_LIMIT = 3000.0; + public enum SnapshotType { + /* Snapshot intersects FROM/BOUNDED BY line. */ + X, + /* Snapshot does not intersect FROM/BOUNDED BY line. */ + O + }; - /** Tolerance for coordinates to be treated as the same /close points. */ - private static final double PRECISION = 0.000000001; + /** XPATH for states in document */ + public static String MTOBSC_XPATH = "/MT_OBSC"; - - public enum SnapshotType { - /* Snapshot intersects FROM/BOUNDED BY line. */ - X, - /* Snapshot does not intersect FROM/BOUNDED BY line. */ - O - }; - - /** XPATH for states in document */ - public static String MTOBSC_XPATH = "/MT_OBSC"; - - - /** - * Applies all the rules one by one by calling the corresponding method of this class. - * - * @param smear Original smear before clipped - Airmet or Outlook - * @param list List of GFAs from clipping - * @param snapshots List of original snapshots which were used to create the smear - */ - public static void applyRules( Gfa smear, ArrayList clipped, ArrayList snapshots ) { - - /* - * Pass GFA format structures through area rules to set up area/adjarea info. - */ - areaRules( smear, clipped, snapshots ); - - /* - * Removes outlooks which cover only "6"-hour snapshots. - */ - removeOutlooks( clipped, snapshots ); + /** + * Applies all the rules one by one by calling the corresponding method of + * this class. + * + * @param smear + * Original smear before clipped - Airmet or Outlook + * @param list + * List of GFAs from clipping + * @param snapshots + * List of original snapshots which were used to create the smear + */ + public static void applyRules(Gfa smear, ArrayList clipped, + ArrayList snapshots) { - /* - * Reduce points to desired threshold set in prefs.tbl. Check the flag - * before doing the above. - */ - GfaReducePoint.getInstance().reducePoints( clipped, snapshots ); - - /* - * Set wording, area, region, and state list for each format structure. - */ - setWording( clipped, snapshots ); - - } - - /** - * This routine clips the GFA smears against two FA areas in a FA region (the input GFA - * smear is assumed to have been clipped against FA regions) and checks the size of the - * clipped parts in each FA area to determine the primary area and the possible adjacent - * area they belong to, if the smear intersects both FA areas with an area >= 3K square - * nautical miles. - * - * @param original Original smear before clipped - Airmet or Outlook - * @param clippedList List of GFAs from clipping - * @param clippedList List of original snapshots - */ - private static void areaRules( Gfa original, ArrayList clippedList, - ArrayList snapshots ) { - - /* - * Toss out all freezing level contours. The area rules are - * applied to them within af_fzlvl2fmt(). - */ - if ( original.getGfaHazard().equals( "FZLVL") ) { - return; - } - - /* - * Clipped against FA areas to update area info - */ - for ( Gfa g : clippedList ) { - findGfaAreaInGrid( g, snapshots ); - } - - } - - /** - * Removes outlooks which cover only "6"-hour snapshots. - * - * @param original - * @param list - */ - private static void removeOutlooks(ArrayList clipped, ArrayList original) { - - ArrayList toRemove = new ArrayList(); - for(Gfa g: clipped) { - if (!g.isOutlook()) continue; - boolean intersectsWithAtLeastOneOriginal = false; - for(Gfa o : original) { - if("6".equals(o.getGfaFcstHr())) continue; // ignore 6 (see tests 49-50) - // if g covers o, leave it - Polygon gP = GfaClip.getInstance().gfaToPolygonInGrid(g); - Polygon oP = GfaClip.getInstance().gfaToPolygonInGrid(o); - Geometry intersection = gP.intersection(oP); - if (intersection instanceof Polygon || intersection instanceof MultiPolygon) { - intersectsWithAtLeastOneOriginal = true; - } - } - if(!intersectsWithAtLeastOneOriginal) toRemove.add(g); - } - clipped.removeAll(toRemove); - } - - - /** - * Compares two Coordinate objects by comparing x and y coordinates. If the coordinates are - * close within a precision, returns true, otherwise false. - * - * @param c1 - * - * @param c2 - * - * @return true is c1 and c2 are very close, false otherwise - */ - public static boolean compareCoordinates(Coordinate c1, Coordinate c2) { - if (abs(c1.x - c2.x) < PRECISION && abs(c1.y - c2.y) < PRECISION) { - return true; - } - return false; - } - - /** - * This routine sets the beginning/ending wording, area, region, and state list for all VALID - * GFA format structures. Invalid structures are marked "delete", including those polygons - * having less than 3 points (closed) or 2 points (open), and those having no state list. - * Outlooks for LLWS, M_FZLVLS, and FZLVL are deleted as well. - * - * @param clipped - * @param originalSS - */ - private static void setWording(ArrayList clipped, ArrayList originalSS ) { - - ArrayList checkStates= new ArrayList(); - for ( Gfa smear : clipped ) { - - // Create state list - updateGfaStates( smear ); - - // If state is empty, remove this Gfa! - String stList = smear.getGfaStates(); - if ( stList != null && stList.trim().length() > 1 ) { - checkStates.add( smear ); - } - - } - - /* - * Now do conditional wording. - */ - ArrayList invalidOtlk = new ArrayList(); - for ( Gfa smear : checkStates ) { - - /* see corresponding method af_getSSAttr in the legacy code - * /nawips/gempak/source/textlib/airmet/afutils.c * - * / - - /* - * Find the type of each snapshot and assign to SNAPSHOT_TYPE attribute. - * - * X_SNAPSHOTS - SS intersects with the clipped polygon with an area > 3K. - * O_SNAPSHOTS - SS do not intersect with the clipped polygon - */ - assignXorO( originalSS, smear ); - - /* - * Retrieve each snapshot's forecast time. - * - * Round UP - X_SNAPSHOTS for development wording or O_SNAPSHOTS for ending wording - * Round Down - X_SNAPSHOTS for ending wording or O_SNAPSHOTS for development wording - */ - assignSSForecastTime( originalSS ); - - assignIssueTime( smear ); - - /* - * Assign "airmetTag". - */ - assignAirmetTag( smear ); - - /* - * Do wording - */ - GfaWording wording = new GfaWording(); - - // wording. - wording.fromCondsDvlpg = fromCondsDvlpg( smear, originalSS ); - - // wording. - wording.fromCondsEndg = fromCondsEndg( smear, originalSS ); - - int[] olkSeq = findOtlkSeq(originalSS); - - // GEN_OLK wording - wording.genOlk = otlkGenWording( originalSS, olkSeq ); - if("MAYBE".equals( wording.genOlk ) ) { - wording.genOlk = processMAYBE( smear, originalSS ); - } - - /* - * Outlooks should be removed if "genOlk" is "NO". - */ - if ( smear.isOutlook() && !("YES".equalsIgnoreCase(wording.genOlk)) ) { - invalidOtlk.add( smear ); - } - - // OTLK CONDS CONTG BYD wording - // since "smear" element can be either Smear or Outlook, we need an if statement - if (smear.isAirmet()) { // not for outlooks - wording.condsContg = contgBydWording( originalSS, olkSeq, smear ); - } - - // OTLK CONDS DVLPG wording - if ("YES".equalsIgnoreCase(wording.genOlk)) { - wording.otlkCondsDvlpg = otlkDvlpgWording( originalSS, olkSeq ); - } - - // OTLK CONDS ENDG wording - if ("YES".equalsIgnoreCase(wording.genOlk)) { - wording.otlkCondsEndg = otlkEndgWording( originalSS, olkSeq ); - } - smear.addAttribute( WORDING, wording ); - -// logger.trace( smear.toString() ); -// logger.debug( "\n" + wording ); - - // create beginning and ending - parseWording( smear, wording ); - - clearAttributes( originalSS ); - - } - - // Return valid Gfa - those with at least one state in it and outlooks with GenOlk is "YES" - clipped.clear(); - if ( invalidOtlk.size() > 0 ) checkStates.removeAll( invalidOtlk ); - clipped.addAll( checkStates ); - } - - - /** - * Generate the state list for a smear. - * - * Note: 1. The state list is not sorted. - * 2. If a smear has two FA areas, the state list is generated but not - * in final order (states in primary FA area precede states in adjacent - * area). This will be done in GfaGeneate.java instead. - * Warning: the validity check of the state bounds should be done when pre-loading - * them (if necessary), not here - since geometry().isValid() is a quite - * expensive call. - * - * @param smear - */ - private static void updateGfaStates( Gfa smear ) { - - HashMap states = GfaClip.getInstance().getStateBoundsInGrid(); - HashMap greatLakes = GfaClip.getInstance().getGreatLakesBoundsInGrid(); - HashMap coastalWater = GfaClip.getInstance().getCoastalWaterBoundsInGrid(); - LinkedHashMap stateMaps = new LinkedHashMap(); // keep insertion order - stateMaps.putAll( states ); - - /* - * Find all states that touches the smear. - * - * If this is a MT_OBSC, only those MT_OBSC states will be - * tested and added to the state list. - * - */ - List mtobscsts = GfaClip.getInstance().getMtObscStates(); - Polygon smearP = GfaClip.getInstance().gfaToPolygonInGrid( smear ); - boolean is_MTOBSC = false; - if ( smear.getGfaHazard().equalsIgnoreCase( "MT_OBSC" ) ) { - is_MTOBSC = true; - } - - int nState = 0; - for ( String key : stateMaps.keySet() ) { - Geometry g = stateMaps.get( key) ; - - if ( is_MTOBSC && !mtobscsts.contains( key ) ) continue; - - if ( smearP.intersects( g ) ) { - nState++; - updateGfaStatesField( smear, key ); - } - - } - - - /** - * Check for the airmet over Great Lakes and coastal waters. - * - * If the state to which those waters belong is not already - * in the stList, then add it. - * - * MT_OBSC hazards can never include any Great Lakes & coastal waters. - */ - int nWaters = 0; - if ( !is_MTOBSC ) { - - for ( String key : greatLakes.keySet() ) { - Geometry g = greatLakes.get( key ); - - if ( !g.intersects( smearP ) ) continue; - updateGfaStatesField( smear, key ); - - } - - for ( String key : coastalWater.keySet() ) { - Geometry g = coastalWater.get( key ); - - if ( !g.intersects( smearP ) ) continue; - - nWaters++; - updateGfaStatesField( smear, key ); - } - - } - - - /** - * If the airmet covers land and water then append "AND CSTL WTRS" - * to the state list. If only water then use just "CSTL WTRS" (no AND). - */ - if ( nWaters > 0 ) { - - StringBuilder s = new StringBuilder ( nvl( smear.getGfaStates() ) ); - - /* - * Note - nState should be states on land, not including states from - * Great Lakes and Coastal Waters. - */ - if ( nState > 0 ) { - s.append( " AND" ); - } - - s.append( " CSTL WTRS" ); - - smear.setGfaStates( s.toString() ); - } - - /* - * Re-order the state list in the specified FA-Area based order. - */ - reorderStateList( smear ); - - } - - - /** - * Updates the states field. - * - * @param gfa - * @param state - * @param polygon - */ - private static boolean updateGfaStatesField( Gfa gfa, String state ) { - boolean added = false; - String s = nvl( gfa.getGfaStates() ); - if( !s.contains( state ) ) { - if ( !s.isEmpty() ) s += " "; - s += state; - gfa.setGfaStates( s ); - added = true; - } - - return added; - } - - - /** - * Find the type of each snapshot and assign to SNAPSHOT_TYPE attribute. - * - *
-	 * X_SNAPSHOTS - SS intersects with the clipped polygon with an area > 3K. 
-	 * O_SNAPSHOTS - SS do not intersect with the clipped polygon
-	 * 
- * - * @param originalSS - * @param smear - */ - private static void assignXorO(ArrayList originalSS, Gfa smear) { -// Polygon smearP = GfaClip.getInstance().gfaToPolygon(smear); - Polygon smearP = GfaClip.getInstance().gfaToPolygonInGrid( smear ); - boolean allOutlook = true; - for(Gfa ss: originalSS){ // snapshots - assignSnapshotType(smearP, ss); - String fcstHr = ss.getGfaFcstHr(); - if(! ("9".equals(fcstHr) || "12".equals(fcstHr)) ) { - allOutlook = false; - } - } - - Gfa first = originalSS.get(0); - ArrayList outlooks = first.getAttribute("OUTLOOKS", ArrayList.class); - - // SMEAR or OUTLOKOS - list of created clipped smears - // OTLK_LIST - original list of outlook gfa elements (6,9,12) - if("6".equals(first.getGfaFcstHr()) && !allOutlook - && outlooks != null) { - // only for smears which have "6" hour snapshots - ArrayList otkl = first.getAttribute("OTLK_LIST", ArrayList.class); - if (otkl == null || otkl.isEmpty()) return; - smearP = findTheSmear(smearP, outlooks); - //smearP = GfaClip.gfaToPolygon((Gfa)otkl.get(0).getAttribute("AIRMETS")); - for(Gfa g: otkl) { - if(g == originalSS.get(0)) continue; - assignSnapshotType(smearP, g); - } - } - } - - /** - *
-	 * X snapshots - SS intersects with the clipped polygon smearP with an area > 3K. 
-	 * O snapshots - SS do not intersect with the clipped polygon
-	 * 
- * - * - * @param smearP Polygon - * @param ss - */ - private static void assignSnapshotType(Polygon smearP, Gfa ss) { - - Polygon ssP = GfaClip.getInstance().gfaToPolygonInGrid(ss); - Geometry intersection = ssP.intersection(smearP); - - ss.addAttribute(SNAPSHOT_TYPE, SnapshotType.O); - - if( PgenUtil.getSphPolyAreaInGrid( intersection ) > AREA_LIMIT) { - ss.addAttribute(SNAPSHOT_TYPE, SnapshotType.X); - } - - } - - private static Polygon findTheSmear(Polygon smearP, ArrayList outlooks) { - for(Gfa g: outlooks) { - - Polygon p = GfaClip.getInstance().gfaToPolygonInGrid(g); - - Geometry intersection = p.intersection(smearP); - - double area = PgenUtil.getSphPolyAreaInGrid ( intersection ); - - if( area > AREA_LIMIT ) { - return p; - } - } - return smearP; - } - - /** - * Retrieve each snapshot's forecast time. - * - *
-	 * Round UP - X_SNAPSHOTS for development wording or O_SNAPSHOTS for ending wording. 
-	 * Round Down - X_SNAPSHOTS for ending wording or O_SNAPSHOTS for development wording
-	 * 
- * - * @param originalSS - */ - private static void assignSSForecastTime(ArrayList originalSS) { - for(Gfa ss: originalSS) { - String fcstHr = ss.getGfaFcstHr(); - int[] hm = Gfa.getHourMinInt(nvl(fcstHr)); - ss.addAttribute("HOUR_INT", hm[0]); - ss.addAttribute("MIN_INT", hm[1]); - double hmD = hm[0] + hm[1] / 60.0; - SnapshotType type = ss.getAttribute(SNAPSHOT_TYPE, SnapshotType.class); - if(type == SnapshotType.X){ - ss.addAttribute(DVLPG_HR, (int)ceil(hmD)); - ss.addAttribute(ENDG_HR, (int)floor(hmD)); - } else if (type == SnapshotType.O){ - ss.addAttribute(DVLPG_HR, (int)floor(hmD)); - ss.addAttribute(ENDG_HR, (int)ceil(hmD)); - } else { - // sanity check - should never reach this place - // check asssignXorO if this happens - String err = "Snapshot type must be assigned by this time"; -// logger.error(err); - throw new IllegalArgumentException(err); - } - } - } - - /** - * Assigns issue time to the smear. - * - * @param smear - */ - static void assignIssueTime(Gfa smear) { - /* - * First determine if the standard issue time should be overridden. An issue time is - * overridden if any of the hazards (smears) are of an issuance type that is CAN, COR, NEW, - * or AMD. - */ - boolean overrideIssueTime = !"NRML".equalsIgnoreCase(smear.getGfaIssueType()); - - Calendar localTimeCal = Calendar.getInstance(); - - String timeStr = AirmetCycleInfo.getIssueTime(); - Calendar issueTimeCal = Calendar.getInstance(); - int hour = Integer.parseInt(timeStr.substring(0, 2)); - int min = Integer.parseInt(timeStr.substring(2)); - issueTimeCal.set(Calendar.HOUR_OF_DAY, hour); - issueTimeCal.set(Calendar.MINUTE, min); - issueTimeCal.set(Calendar.SECOND, 0); - - if (overrideIssueTime) { - // Compare the local time to the issue time if overrideIssueTm flag is TRUE. - if (issueTimeCal.before(localTimeCal)) { - issueTimeCal = localTimeCal; - } else { - // set issue time = issue time + 1 min - issueTimeCal.add(Calendar.MINUTE, 1); - } - } - - smear.addAttribute(ISSUE_TIME, issueTimeCal); - - Calendar untilTimeCal = AirmetCycleInfo.getUntilTime(); - smear.addAttribute(UNTIL_TIME, untilTimeCal ); - - Calendar otlkEndTime = Calendar.getInstance(); - otlkEndTime.set(Calendar.DAY_OF_MONTH, untilTimeCal.get(Calendar.DAY_OF_MONTH)); - otlkEndTime.set(Calendar.HOUR_OF_DAY, untilTimeCal.get(Calendar.HOUR_OF_DAY) + 6 ); - otlkEndTime.set(Calendar.MINUTE, untilTimeCal.get(Calendar.MINUTE) ); - otlkEndTime.set(Calendar.SECOND, untilTimeCal.get(Calendar.SECOND) ); - - smear.addAttribute( OUTLOOK_END_TIME, otlkEndTime ); - - } - - /** - * Generates "" wording. - * - * @param smear - * @param originalSS - * @return - */ - private static String fromCondsDvlpg(Gfa smear, ArrayList originalSS) { - - int endHour = 6; - /* - * from the legacy system (af_condsWording method in source/textlib/airmet/afconditions.c): - * - * Wording rules: - * If the first ss in the sequence is an 'X_SNAPSHOTS' { - * If the first ss time is 00, there is no wording. - * If the first ss time is 03 or less, wording is "+00-+TTZ", - * where 'TT' is the ss time. - * If the first ss time is 06 or less (on-time cycles only), - * wording is "+03-+TTZ", where 'TT' is the ss time. - * } - * - * If the first ss is an 'O_SNAPSHOTS' { - * Scan the sequence forward from the first ss to find the - * last 'O' before encountering an 'X' ss. - * The wording is "AFT +TTZ" where 'TT' is this 'O' ss time. - * } - */ - String wording = ""; - int xx = 0; - int yy = 0; - Gfa ss = originalSS.get(0); - int dvlpgHr = ss.getAttribute(DVLPG_HR, Integer.class); - if (ss.getAttribute(SNAPSHOT_TYPE) == SnapshotType.X) { - if (dvlpgHr == 0) { - // no wording - } else if (dvlpgHr <= 3) { - wording = "CONDS DVLPG +00-+" + pad(dvlpgHr) + "Z"; - yy = dvlpgHr; - } else if (dvlpgHr <= 6) { - wording = "CONDS DVLPG +03-+" + pad(dvlpgHr) + "Z"; - xx = 3; - yy = dvlpgHr; - } - } else { - int lastO = 0; - for (int i = 1; i < originalSS.size(); i++) { - Gfa g = originalSS.get(i); - dvlpgHr = ss.getAttribute(DVLPG_HR, Integer.class); - if (g.getAttribute(SNAPSHOT_TYPE) == SnapshotType.X && dvlpgHr <= endHour) { - lastO = i - 1; - break; - } - } - dvlpgHr = originalSS.get(lastO).getAttribute(DVLPG_HR, Integer.class); - wording = "CONDS DVLPG AFT +" + pad(dvlpgHr) + "Z"; - xx = dvlpgHr; - yy = -1; - } - - if(!PgenCycleTool.isRoutine() && !wording.isEmpty() && xx >= 0 && yy >= 0) { - - Calendar cal = smear.getAttribute(ISSUE_TIME, Calendar.class); - int issueHrMin = cal.get(Calendar.HOUR_OF_DAY) * 100 + cal.get(Calendar.MINUTE); - - int basetime = PgenCycleTool.getCycleHour(); - - if ((yy + basetime) * 100 <= issueHrMin) { /* yy in past */ - wording = ""; - } else { /* yy in future */ - if ((xx + basetime) * 100 <= issueHrMin) {/* xx in past */ - wording = "CONDS DVLPG BY +" + pad(yy) + "Z"; // BY +23Z - } else { - wording = "CONDS DVLPG +" + pad(xx) + "-+" + pad(yy) + "Z"; // +03-+06Z - } - } - } - - return wording; - } - - /** - * Generates "" wording. - * - * @param smear - * @param originalSS - * @return - */ - private static String fromCondsEndg(Gfa smear, ArrayList originalSS) { - - int endHour = 6; - /* - * from the legacy system (af_fromEndgWording) - * - * Wording Rules: - * - * If last ss in the sequence is an 'X_SNAPSHOTS' { - * If the last ss time is the last possible time (06 for on-time cycles - * or 03 for off-time cycles), wording is determined by the outlook - * component snapshots rules. See the 'Outlook BOUNDED BY lines' - * section below for "CONDS CONTG BYD +06Z" wording - * (or "CONDS CONTG BYD +03Z" for cycles 00, 06, 12 and 18). - * If the last ss time is less than 03, wording is "+TT-+03Z", - * where 'TT' is the ss time. - * If the last ss time is less than 06 (on-time cycles only), - * wording is "+TT-+06Z", where 'TT' is the ss time. - * } - * - * If last ss is an 'O_SNAPSHOT' { - * Scan the sequence backward from the last ss to find the first 'O' - * after encountering an 'X' ss. The wording is "BY +TTZ" where 'TT' - * is this 'O' ss time. - * } - * - */ - String wording = ""; - int xx = -1; - int yy = -1; - int lastSSIndex = originalSS.size() - 1; - for (int i = originalSS.size() - 1; i >= 0; i--) { - lastSSIndex = i; - int hr = originalSS.get(lastSSIndex).getAttribute(ENDG_HR, Integer.class); - if(hr <= endHour) break; - } - Gfa lastSS = originalSS.get(lastSSIndex); - int lastEndgHr = lastSS.getAttribute(ENDG_HR, Integer.class); - String lastFcstHr = lastSS.getGfaFcstHr(); - int[] hm = Gfa.getHourMinInt(lastFcstHr); - - if (lastSS.getAttribute(SNAPSHOT_TYPE) == SnapshotType.X) { - - if(hm[0] == endHour && hm[1] == 0) { - /* Handled separately by af_contgBydWording() */ - } else if(lastEndgHr < 3){ - // sprintf(wording, "CONDS ENDG +0%d-+03Z", last_ss_hr) - wording = "CONDS ENDG +" + pad(lastEndgHr) + "-+03Z"; - xx = lastEndgHr; - yy=3; - } else if (lastEndgHr <= 6) { - // sprintf(wording, "CONDS ENDG +0%d-+06Z", last_ss_hr); - wording = "CONDS ENDG +" + pad(lastEndgHr) + "-+06Z"; - xx = lastEndgHr; - yy = 6; - } - } else { - int firstO = lastSSIndex; - - ArrayList otlkList = lastSS.getAttribute("OTLK_LIST", ArrayList.class); - if("6".equals(originalSS.get(originalSS.size()-1).getGfaFcstHr()) && otlkList != null) { - lastSSIndex = otlkList.size()-1; - lastSS = otlkList.get(lastSSIndex); - for (int jj = otlkList.size() - 2; jj >= 0; jj--) { - lastSS = otlkList.get(jj); - if(lastSS.getAttribute(SNAPSHOT_TYPE) == SnapshotType.X) { - firstO = jj + 1; - break; - } - } - lastEndgHr = Integer.parseInt(otlkList.get(firstO).getGfaFcstHr()); - } else { - for (int jj = lastSSIndex-1; jj >= 0; jj--) { - lastSS = originalSS.get(jj); - if(lastSS.getAttribute(SNAPSHOT_TYPE) == SnapshotType.X) { - firstO = jj + 1; - break; - } - } - lastEndgHr = originalSS.get(firstO).getAttribute(ENDG_HR, Integer.class); - } - wording = "CONDS ENDG BY +" + pad(lastEndgHr) + "Z"; - } - - - if (!PgenCycleTool.isRoutine() && !wording.isEmpty() && xx >= 0 && yy >= 0) { - - Calendar cal = smear.getAttribute(ISSUE_TIME, Calendar.class); - int issueHrMin = cal.get(Calendar.HOUR_OF_DAY) * 100 + cal.get(Calendar.MINUTE); - - int basetime = PgenCycleTool.getCycleHour(); - - if ((yy + basetime) * 100 <= issueHrMin) { /* yy in past */ - wording = "CONDS HV ENDED"; - } else { /* yy in future */ - if ((xx + basetime) * 100 <= issueHrMin) {/* xx in past */ - wording = "CONDS ENDG BY +" + pad(yy) + "Z"; // BY +23Z - } else { - wording = "CONDS ENDG +" + pad(xx) + "-+" + pad(yy) + "Z"; // +03-+06Z - } - } - } - - return wording; - } - - private static int[] findOtlkSeq(ArrayList originalSS) { - int startHour = 6; // ontime - - int[] olkSeq = new int[3]; - for(int i=0; i<3; i++) { - olkSeq[i] = -1; - } - - for(int ii=0; ii< originalSS.size(); ii++) { - String fcstHr = originalSS.get(ii).getGfaFcstHr(); - int[] hm = Gfa.getHourMinInt(nvl(fcstHr)); - if (hm[1] != 0) continue; - - if (hm[0] == startHour) { - olkSeq[0] = ii; - } else if (hm[0] == (startHour + 3)) { - olkSeq[1] = ii; - } else if (hm[0] == (startHour + 6)) { - olkSeq[2] = ii; - } - } - return olkSeq; - } - - /** - * Generates wording - * - * @param smear - * @param originalSS - * @return - */ - private static String otlkGenWording(ArrayList originalSS, int[] olkSeq) { -// af_otlkGenWording(ss_attr, olk_seq, tmpstr); - - /* - * Wording Rules: - * Assume there is at least one SS in the sequence. - * 1SS - 06 ss (03 for off-time cycles) - * 2SS - 09 ss (06 for off-time cycles) - * 3SS - 12 ss (09 for off-time cycles) - * - * If 1SS does not exist or exists as an O_SNAPSHOTS { - * is "YES" - * } - * - * If both 1SS and 2SS exist as X_SNAPSHOTSs { - * is "MAYBE" - * } - * - * If 1SS & 3SS exist X_SNAPSHOTSs { - * is "MAYBE" (X-O-X case and X---X case) - * } - * - * All other cases - is "NO" - */ - - String genOlk = "NO"; - if (olkSeq[0] >= 0 || olkSeq[1] >= 0 || olkSeq[2] >= 0) { - if (olkSeq[0] < 0 - || (olkSeq[0] >= 0 && originalSS.get(olkSeq[0]).getAttribute(SNAPSHOT_TYPE) == SnapshotType.O)) { - genOlk = "YES"; - } else if ((olkSeq[1] >= 0 && originalSS.get(olkSeq[1]).getAttribute(SNAPSHOT_TYPE) == SnapshotType.X) || - (olkSeq[2] >= 0 && originalSS.get(olkSeq[2]).getAttribute(SNAPSHOT_TYPE) == SnapshotType.X)) { - genOlk = "MAYBE"; - } - } - - return genOlk; - } - - private static String processMAYBE(Gfa outlook, ArrayList originalSS) { - // corresponds to afconditions.af_processMAYBE - - Polygon outlookP = GfaClip.getInstance().gfaToPolygon(outlook); - HashMap states = GfaClip.getInstance().getStateBounds(); - - Gfa g6 = null; - for(Gfa g: originalSS) { - updateGfaStates(g); - if("6".equals(g.getGfaFcstHr())) g6 = g; - } - - // smears list is not null here, because MAYBE can only be called - // for outlooks containing "6" and "9" hour snapshots. - // and at least one "6-6" airmet exists, g6 is not be null - ArrayList airmets = g6.getAttribute("AIRMETS", ArrayList.class); // from 0 to 6 hours - - // loop through airmets and find the one which overlaps with the outlook we process - // then the overlapping one is the one we will use to apply rules. - TreeSet statesInAirmet = new TreeSet(); - Gfa airmet = null; - for(Gfa g: airmets){ - Polygon gP = GfaClip.getInstance().gfaToPolygon(g); - Geometry intersection = outlookP.intersection(gP); - if (intersection instanceof Polygon || intersection instanceof MultiPolygon) { - // states - String [] statesArray = nvl(g.getGfaStates()).split(" "); - for(String s: statesArray) { - statesInAirmet.add(s.trim()); - } - airmet = g; - break; - } - } - - /* - * Rule 1: For states in the outlook's state list but not listed in the - * airmet's state list, check the sizes of the intersection areas - * between the outlook with those states. If there is at least - * one of them is greater than or equal to 3K, set the flag to True - * to issue the outlook. - * - * Rule 2: For states both in the outlook's state list and the airmet's state - * list, check the in-state outlook generation ratio with the threshold - * set in the prefs.tbl. If it's greater than the threshold, issue the - * outlook. - * - * Both checks should be done for the state bound, the Great Lakes - * bound, and the coastal water bound. - */ - String[] statesInOutlook = nvl(outlook.getGfaStates()).split(" "); - double gfaOtlkgenRatio = GfaInfo.getGfaOtlkgenRatio(); - Polygon airmetP = GfaClip.getInstance().gfaToPolygon(airmet); - for(String stateStr: statesInOutlook) { - if(stateStr.isEmpty()) continue; - Geometry stateP = states.get(stateStr); - - if(stateP == null) continue; - - if(statesInAirmet.contains(stateStr)) { - // rule 2 - // - // the formula from tt 8.106 takes precedence over the earlier one - // - // ratio = (Outlook Area - Intersect Area)/ State Area - // - // June, 2012 - adjust algorithm to find the ratio due to high-resolution state bounds. - // - // Prevoius - Intersection Area = (A^S) ^ (O^S) - // Now - Intersection Area = (A^O)^S - // - // - Geometry a = airmetP.intersection( outlookP ); - if ( a == null ) continue; - - Geometry o = outlookP.intersection(stateP); - - Geometry i = a.intersection( stateP ); - if ( i == null ) continue; - - double oArea = PgenUtil.getSphPolyArea(o); - double iArea = PgenUtil.getSphPolyArea(i); - - double ratio = 0.0; - if ( (oArea - iArea) > 0.0 ) { - double sArea = PgenUtil.getSphPolyArea(stateP); - ratio = (oArea - iArea)/sArea; - } - - if (ratio >= gfaOtlkgenRatio) return "YES"; - - } else { - // rule 1 - Geometry intersection = outlookP.intersection(stateP); - double area = PgenUtil.getSphPolyArea(intersection ); - if(area > AREA_LIMIT) { - // stop here, yes we need to issue the outlook - return "YES"; - } - } - } - - return "NO"; - } - - /** - * OTLK CONDS CONTG BYD wording - * - * @param origSS - * @param olkSeq - * @param smr - * @return - */ - private static String contgBydWording(ArrayList origSS, int[] olkSeqIn, Gfa smr ) { - - /* - * Wording Rules: - * - * Proceed only if the 06 ss exists ( 03 ss for off-time cycles ) - * as an "X_SNAPSHOTS". - * - * If the last ss in the sequence is an 'X' { - * If its time is 12, wording - "CONDS CONTG BYD +0NZ THRU +12Z". - * If its time is 09, wording - "CONDS CONTG BYD +0NZ ENDG +09-+12Z". - * If its time is 06, wording - "CONDS CONTG BYD +0NZ ENDG +06-+09Z". - * If its time is 03, wording - "CONDS CONTG BYD +0NZ ENDG +03-+06Z". - * } - * - * If the last ss in the sequence is an 'O' { - * Scan the sequence backward from the last ss to find the first 'O' - * after encountering an 'X' ss. - * - * If this 'O' ss time is 12, wording - "CONDS CONTG BYD +0NZ ENDG BY +12Z". - * If this 'O' ss time is 09, wording - "CONDS CONTG BYD +0NZ ENDG BY +09Z". - * } - * - * Where "N" is "6" for on-time cycle and "3" for off-time cycle. - * - */ - - // Proceed only if the 06 ss exists as an "X_SNAPSHOTS" - boolean ss06Exists = false; - for (Gfa g : origSS) { - int[] hm = Gfa.getHourMinInt(g.getGfaFcstHr()); - if (hm[0] == 6 && hm[1] == 0 && g.getAttribute(SNAPSHOT_TYPE) == SnapshotType.X) { - ss06Exists = true; - break; - } - } - if (!ss06Exists) return ""; - - // Make a copy, since we need to adjust it here. - int[] olkSeq = new int[ olkSeqIn.length ]; - for ( int ii = 0; ii < olkSeqIn.length; ii++ ) { - olkSeq[ ii ] = olkSeqIn[ ii ]; - } - - String wording = ""; - int lastSS; - if (olkSeq[2] >= 0) - lastSS = 2; - else if (olkSeq[1] >= 0) - lastSS = 1; - else - lastSS = 0; - - ArrayList originalSS = new ArrayList(); - originalSS.addAll( origSS ); - - boolean isX = originalSS.get(olkSeq[lastSS]).getAttribute(SNAPSHOT_TYPE) == SnapshotType.X; - ArrayList otlkList = originalSS.get(olkSeq[lastSS]).getAttribute("OTLK_LIST", ArrayList.class); - - // now test if OTLK_LIST list has - if(lastSS == 0 && otlkList != null) { - for(Gfa g: otlkList) { - if(g.getAttribute(SNAPSHOT_TYPE) == SnapshotType.O && !"6".equals(g.getGfaFcstHr())) { - isX = false; - break; - } - } - } - /* - * Find the types of outlook snapshots embedded in the airmet and adjust the - * type of outlook snapshots - */ - boolean adjEmbedOtlk = false; - ArrayList embedOtlks = originalSS.get(olkSeq[lastSS]).getAttribute( "OUTLOOKS", ArrayList.class); - if ( embedOtlks != null && embedOtlks.size() > 0 ) { - - /* - * Find the outlook originated from the same snapshots and clipped to - * the same region - */ - Gfa otlkInSameRegion = null; - for ( Gfa gg : embedOtlks ) { - if ( gg.getAttribute( "FA_REGION").equals( smr.getAttribute( "FA_REGION") ) ) { - otlkInSameRegion = gg; - break; - } - } - - //Adjust the type - FcstHrListPair p = embedOtlks.get(0).getAttribute( "PAIR", FcstHrListPair.class ); - for ( Gfa gg : p.getOriginal() ) { - if ( !originalSS.contains( gg ) ) { - Gfa temp = gg.copy(); - temp.addAttribute( SNAPSHOT_TYPE, SnapshotType.O ); - - if ( otlkInSameRegion != null ) { - Polygon otlkPoly = GfaClip.getInstance().gfaToPolygonInGrid( otlkInSameRegion ); - assignSnapshotType( otlkPoly, temp ); - } + * Pass GFA format structures through area rules to set up area/adjarea + * info. + */ + areaRules(smear, clipped, snapshots); - originalSS.add( temp ); - } - } - - adjEmbedOtlk = true; - } - - if ( adjEmbedOtlk ) { - olkSeq = findOtlkSeq( originalSS ); - if (olkSeq[2] >= 0) - lastSS = 2; - else if (olkSeq[1] >= 0) - lastSS = 1; - else - lastSS = 0; - - isX = originalSS.get( olkSeq[lastSS] ).getAttribute(SNAPSHOT_TYPE) == SnapshotType.X; - } - - /* - * wording.... - */ - if ( isX ) { + /* + * Removes outlooks which cover only "6"-hour snapshots. + */ + removeOutlooks(clipped, snapshots); - String hourMinStr = originalSS.get(olkSeq[lastSS]).getGfaFcstHr(); - int [] hm = Gfa.getHourMinInt(hourMinStr); - String lastXinOtlk= ""; - if(otlkList != null && !otlkList.isEmpty() - && otlkList.get(otlkList.size() -1).getAttribute(SNAPSHOT_TYPE) == SnapshotType.X) { - lastXinOtlk = otlkList.get(otlkList.size()-1).getGfaFcstHr(); - } - - if(hm[0] == 12 || "12".equals(lastXinOtlk)) { - wording = "CONDS CONTG BYD +06Z THRU +12Z"; - } else if (hm[0] == 9 || "9".equals(lastXinOtlk)) { - wording = "CONDS CONTG BYD +06Z ENDG +09-+12Z"; - } else if (hm[0] == 6 ) { - wording = "CONDS CONTG BYD +06Z ENDG +06-+09Z"; - } - } - else { - int firstO = lastSS; - int firstX = -1; + /* + * Reduce points to desired threshold set in prefs.tbl. Check the flag + * before doing the above. + */ + GfaReducePoint.getInstance().reducePoints(clipped, snapshots); - for (int ii = lastSS; ii >= 0; ii--) { - if (olkSeq[ii] >= 0 - && originalSS.get(olkSeq[ii]).getAttribute(SNAPSHOT_TYPE) == SnapshotType.X) { - firstX = ii; - break; - } - } + /* + * Set wording, area, region, and state list for each format structure. + */ + setWording(clipped, snapshots); - if (firstX >= 0) { - for (int ii = firstX + 1; ii <= lastSS; ii++) { - if (olkSeq[ii] >= 0 - && originalSS.get(olkSeq[ii]).getAttribute(SNAPSHOT_TYPE) == SnapshotType.O) { - firstO = ii; - break; - } - } - } + } - String hourMinStr = originalSS.get(olkSeq[firstO]).getGfaFcstHr(); - int[] hm = Gfa.getHourMinInt(hourMinStr); - String firstOinOtlk= ""; - if(otlkList != null && !otlkList.isEmpty()) { - for(Gfa el: otlkList) { - if(el.getAttribute(SNAPSHOT_TYPE) == SnapshotType.O) { - firstOinOtlk = el.getGfaFcstHr(); - break; - } - } - } + /** + * This routine clips the GFA smears against two FA areas in a FA region + * (the input GFA smear is assumed to have been clipped against FA regions) + * and checks the size of the clipped parts in each FA area to determine the + * primary area and the possible adjacent area they belong to, if the smear + * intersects both FA areas with an area >= 3K square nautical miles. + * + * @param original + * Original smear before clipped - Airmet or Outlook + * @param clippedList + * List of GFAs from clipping + * @param clippedList + * List of original snapshots + */ + private static void areaRules(Gfa original, ArrayList clippedList, + ArrayList snapshots) { - if (hm[0] == 12 || "12".equals(firstOinOtlk)) { - wording = "CONDS CONTG BYD +06Z ENDG BY +12Z"; - } else if (hm[0] == 9 || "9".equals(firstOinOtlk)) { - wording = "CONDS CONTG BYD +06Z ENDG BY +09Z"; - } else if (hm[0] == 6) { - wording = "CONDS CONTG BYD +03Z ENDG BY +06Z"; - } - } + /* + * Toss out all freezing level contours. The area rules are applied to + * them within af_fzlvl2fmt(). + */ + if (original.getGfaHazard().equals("FZLVL")) { + return; + } - return wording; - } - - /** - * OTLK CONDS DVLPG wording - * - * @param smear - * @param originalSS - * @param olkSeq - * @return - */ - private static String otlkDvlpgWording(ArrayList originalSS, int[] olkSeq) { - // afconditions.af_otlkDvlpgWording - - /* - * Wording Rules: - * - * If the first ss in the sequence is an 'X' { - * If first ss time is 06, there is no wording. - * If first ss time is 09, wording is "+06-+09Z". - * If first ss time is 12, wording is "+09-+12Z". - * } - * If the first ss is an 'O' { - * Scan the sequence forward from the first ss to find the last 'O' - * before encountering an 'X' ss. The wording is "AFT +TTZ" where 'TT' - * is this 'O' ss time. - * } - * - */ - int firstSS = -1; - for (int ii = 0; ii < 3; ii++) { - if (olkSeq[ii] >= 0) { - firstSS = ii; - break; - } - } - - String hourMinStr = originalSS.get(olkSeq[firstSS]).getGfaFcstHr(); - int[] hm = Gfa.getHourMinInt(hourMinStr); - - String wording = ""; + /* + * Clipped against FA areas to update area info + */ + for (Gfa g : clippedList) { + findGfaAreaInGrid(g, snapshots); + } - if (originalSS.get(olkSeq[firstSS]).getAttribute(SNAPSHOT_TYPE) == SnapshotType.X) { + } - if (firstSS == olkSeq[0]) { - /* No wording */ - } else if (hm[0] == 6) { - wording = "CONDS DVLPG +03-+06Z"; - } else if (hm[0] == 9) { - wording = "CONDS DVLPG +06-+09Z"; - } else if (hm[0] == 12) { - wording = "CONDS DVLPG +09-+12Z"; - } - } else { - int lastO = firstSS; - for (int ii = 0; ii < 2; ii++) { - if (lastO == olkSeq[ii] - && olkSeq[ii + 1] >= 0 - && originalSS.get(olkSeq[ii + 1]).getAttribute(SNAPSHOT_TYPE) == SnapshotType.O) { - lastO = olkSeq[ii + 1]; - } - } - hourMinStr = originalSS.get(olkSeq[lastO]).getGfaFcstHr(); - hm = Gfa.getHourMinInt(hourMinStr); + /** + * Removes outlooks which cover only "6"-hour snapshots. + * + * @param original + * @param list + */ + private static void removeOutlooks(ArrayList clipped, + ArrayList original) { - wording = "CONDS DVLPG AFT +" + pad(hm[0]) + "Z"; - } - return wording; - } - - /** - * OTLK CONDS ENDG wording - * @param originalSS - * @param olkSeq - * @return - */ - private static String otlkEndgWording(ArrayList originalSS, int[] olkSeq) { - // afconditions.af_otlkEndgWording - - /* - * Wording Rules: - * - * If last ss in the sequence is an 'X' { - * If its time is 12 (09 for off-time), wording is "CONTG THRU +12Z" - * ("CONTG THRU +09Z" for off-time cycle). - * If its time is 09, wording is "ENDG +09-+12Z" for on-time cycle and - * "CONTG THRU +09Z" for off-time cycle. - * If its time is 06, wording is "ENDG +03-+06Z" for off-time cycle. - * } - * - * If last ss is an 'O' { - * Scan the sequence backward from the last ss to find the first 'O' - * after encountering an 'X' ss. The wording is "ENDG BY +TTZ" - * where 'TT' is this ss time. - * - * If this time is 12 (09 for off-time cycle). - * If this time is 09 (06 for off-time cycle), no wording. - * } - * - */ - int lastSS; - if (olkSeq[2] >= 0) - lastSS = 2; - else if (olkSeq[1] >= 0) - lastSS = 1; - else - lastSS = 0; + ArrayList toRemove = new ArrayList(); + for (Gfa g : clipped) { + if (!g.isOutlook()) + continue; + boolean intersectsWithAtLeastOneOriginal = false; + for (Gfa o : original) { + if ("6".equals(o.getGfaFcstHr())) + continue; // ignore 6 (see tests 49-50) + // if g covers o, leave it + Polygon gP = GfaClip.getInstance().gfaToPolygonInGrid(g); + Polygon oP = GfaClip.getInstance().gfaToPolygonInGrid(o); + Geometry intersection = gP.intersection(oP); + if (intersection instanceof Polygon + || intersection instanceof MultiPolygon) { + intersectsWithAtLeastOneOriginal = true; + } + } + if (!intersectsWithAtLeastOneOriginal) + toRemove.add(g); + } + clipped.removeAll(toRemove); + } - String hourMinStr = originalSS.get(olkSeq[lastSS]).getGfaFcstHr(); - int[] hm = Gfa.getHourMinInt(hourMinStr); + /** + * Compares two Coordinate objects by comparing x and y coordinates. If the + * coordinates are close within a precision, returns true, otherwise false. + * + * @param c1 + * + * @param c2 + * + * @return true is c1 and c2 are very close, false otherwise + */ + public static boolean compareCoordinates(Coordinate c1, Coordinate c2) { + if (abs(c1.x - c2.x) < PRECISION && abs(c1.y - c2.y) < PRECISION) { + return true; + } + return false; + } - String wording = ""; + /** + * This routine sets the beginning/ending wording, area, region, and state + * list for all VALID GFA format structures. Invalid structures are marked + * "delete", including those polygons having less than 3 points (closed) or + * 2 points (open), and those having no state list. Outlooks for LLWS, + * M_FZLVLS, and FZLVL are deleted as well. + * + * @param clipped + * @param originalSS + */ + private static void setWording(ArrayList clipped, + ArrayList originalSS) { - if (originalSS.get(olkSeq[lastSS]).getAttribute(SNAPSHOT_TYPE) == SnapshotType.X) { + ArrayList checkStates = new ArrayList(); + for (Gfa smear : clipped) { - if (hm[0] == 12) { - wording = "CONDS CONTG THRU +12Z"; - } else if (hm[0] == 9) { - wording = "CONDS ENDG +09-+12Z"; - } else if (hm[0] == 6) { - // no wording for on-time - } - } else { - int firstO = lastSS; - int firstX = -1; + // Create state list + updateGfaStates(smear); - for (int ii = lastSS; ii >= 0; ii--) { - if (olkSeq[ii] >= 0 - && originalSS.get(olkSeq[ii]).getAttribute(SNAPSHOT_TYPE) == SnapshotType.X) { - firstX = ii; - break; - } - } + // If state is empty, remove this Gfa! + String stList = smear.getGfaStates(); + if (stList != null && stList.trim().length() > 1) { + checkStates.add(smear); + } - if (firstX >= 0) { - for (int ii = firstX + 1; ii <= lastSS; ii++) { - if (olkSeq[ii] >= 0 - && originalSS.get(olkSeq[ii]).getAttribute(SNAPSHOT_TYPE) == SnapshotType.O) { - firstO = ii; - break; - } - } - } + } - hourMinStr = originalSS.get(olkSeq[firstO]).getGfaFcstHr(); - hm = Gfa.getHourMinInt(hourMinStr); + /* + * Now do conditional wording. + */ + ArrayList invalidOtlk = new ArrayList(); + for (Gfa smear : checkStates) { - if (hm[0] == 12) { - wording = "CONDS ENDG BY +12Z"; - } else if (hm[0] == 9) { - // no wording for on-time - } - } + /* + * see corresponding method af_getSSAttr in the legacy code + * /nawips/gempak/source/textlib/airmet/afutils.c * / + * + * /* Find the type of each snapshot and assign to SNAPSHOT_TYPE + * attribute. + * + * X_SNAPSHOTS - SS intersects with the clipped polygon with an area + * > 3K. O_SNAPSHOTS - SS do not intersect with the clipped polygon + */ + assignXorO(originalSS, smear); - return wording; - } - - /** - * This routine gets the starting and ending wordings from the format string. - * - * @param smear - * @param wording - */ - private static void parseWording(Gfa smear, GfaWording wording) { - - String beginWording = ""; - String endWording = ""; - // For smear wording - if (smear.isAirmet()) { - //Get developing wording - - beginWording = wording.fromCondsDvlpg; - - if(!wording.condsContg.isEmpty()) { - if(beginWording.isEmpty()) { - beginWording += wording.condsContg; - } else { - beginWording += ". " + wording.condsContg; - } - } - endWording = wording.fromCondsEndg; + /* + * Retrieve each snapshot's forecast time. + * + * Round UP - X_SNAPSHOTS for development wording or O_SNAPSHOTS for + * ending wording Round Down - X_SNAPSHOTS for ending wording or + * O_SNAPSHOTS for development wording + */ + assignSSForecastTime(originalSS); - } else { //For outlook wording - - beginWording = wording.otlkCondsDvlpg; - - if(!wording.condsContg.isEmpty()){ - if(beginWording.isEmpty()) { - beginWording += wording.condsContg; - } else { - beginWording += ". " + wording.condsContg; - } - } - - if(!wording.otlkCondsEndg.isEmpty()) { - endWording = wording.otlkCondsEndg; - } - } - - smear.setGfaBeginning(beginWording); - smear.setGfaEnding(endWording); + assignIssueTime(smear); - replacePlusWithCycle(smear); - } + /* + * Assign "airmetTag". + */ + assignAirmetTag(smear); - /** - * Replaces all occurrences of substrings like +ii in beginning and ending words with the - * strings calculated as a sum of ii and a cycle. For example, "CONDS ENDG +09-+12Z" becomes - * "CONDS ENDG 05-08Z" if the gfa cycle is 20. - * - * @param gfa - */ - public static void replacePlusWithCycle(Gfa gfa) { - int cycle = gfa.getGfaCycleHour(); + /* + * Do wording + */ + GfaWording wording = new GfaWording(); - String b = gfa.getGfaBeginning(); - b = replacePlusWithCycle(b, cycle); - gfa.setGfaBeginning(b); + // wording. + wording.fromCondsDvlpg = fromCondsDvlpg(smear, originalSS); - String e = gfa.getGfaEnding(); - e = replacePlusWithCycle(e, cycle); - gfa.setGfaEnding(e); - } + // wording. + wording.fromCondsEndg = fromCondsEndg(smear, originalSS); - /** - * Replaces all occurrences of substrings like +ii with the string calculated as a sum of ii + - * cycle. For example, CONDS ENDG +09-+12Z becomes CONDS ENDG 05-08Z if cycle is 20. - * - * @param b - * @param cycle - * @return - */ - public static String replacePlusWithCycle(String b, int cycle) { - int i; - while ((i = b.indexOf("+")) > -1) { - String toReplace = b.substring(i, i + 3); - String hour = toReplace.substring(1); - int h = Integer.parseInt(hour); - hour = pad((h + cycle) % 24); - b = b.replace(toReplace, hour); - } - return b; - } + int[] olkSeq = findOtlkSeq(originalSS); - /** - * Deletes all the parameters added in this class to avoid confusion in the future. - * - * @param originalSS - */ - private static void clearAttributes(ArrayList originalSS) { - for (Gfa ss : originalSS) { - ss.removeAttribute(SNAPSHOT_TYPE); - ss.removeAttribute(DVLPG_HR); - ss.removeAttribute(ENDG_HR); - } - } - - private static String nvl(String value) { - return value == null ? "" : value; - } - - - /** - * This routine clips ONE GFA smear against two FA areas in a FA region (the input GFA - * smear is assumed to have been clipped against FA regions) and checks the size of the - * clipped parts in each FA area to determine the primary area and the possible adjacent - * area they belong to. Additional Airmet/Outlook may need to be created when generating - * text product for such an smear (see GfaGenerate.java) - * - * @param current GFA to be processed - * @param clippedlist List of GFA snapshots from clipping - */ - private static void findGfaAreaInGrid( Gfa current, ArrayList snapShots ) { - - /* - * Clip against the FA areas - * - * 1. Clip against the FA areas and compute the size of the intersection - * in each FA area. - * 2. Find the area that the smear has the largest intersection - * 3. Find the area that the smear has the second largest intersection, if any. - * 4. Apply the area rules: - * a. The primary "area" is the area that the smear intersects with a larger size. - * b. When both areas >= 3K, both areas are considered as primary areas and - * one additional AIRMET should be created (in GfaGenerate.java) - * c. the part in an FA area must also intersect with one of the snapshots - * with an area >= 3K, if there are associated snapshots. - */ - HashMap areaBnds = GfaClip.getInstance().getFaAreaBoundsInGrid(); - HashMap interSizes = new HashMap(); - HashMap interWithSS = new HashMap(); - - Polygon clipPoly = GfaClip.getInstance().gfaToPolygonInGrid( current ); + // GEN_OLK wording + wording.genOlk = otlkGenWording(originalSS, olkSeq); + if ("MAYBE".equals(wording.genOlk)) { + wording.genOlk = processMAYBE(smear, originalSS); + } - for ( String areaName : areaBnds.keySet() ) { - - Geometry g = areaBnds.get( areaName ); + /* + * Outlooks should be removed if "genOlk" is "NO". + */ + if (smear.isOutlook() && !("YES".equalsIgnoreCase(wording.genOlk))) { + invalidOtlk.add(smear); + } - if ( clipPoly.intersects( g ) ) { + // OTLK CONDS CONTG BYD wording + // since "smear" element can be either Smear or Outlook, we need an + // if statement + if (smear.isAirmet()) { // not for outlooks + wording.condsContg = contgBydWording(originalSS, olkSeq, smear); + } - Geometry interAA = clipPoly.intersection( g ); - - double ss = PgenUtil.getSphPolyAreaInGrid( interAA ); - - interSizes.put( areaName, ss ); - - boolean interSSBig = false; - if ( snapShots == null || snapShots.size() <= 0 ) { - interSSBig = true; - } - else { - for ( Gfa gfa : snapShots ) { + // OTLK CONDS DVLPG wording + if ("YES".equalsIgnoreCase(wording.genOlk)) { + wording.otlkCondsDvlpg = otlkDvlpgWording(originalSS, olkSeq); + } - Polygon p = GfaClip.getInstance().gfaToPolygonInGrid( gfa ); - //Note: interAA might be an GeometryCollection and thus - // will be illegal parameter for intersects(). - - double narea = 0.0; - for ( int nn = 0; nn < interAA.getNumGeometries(); nn++ ) { - if ( p.intersects( interAA.getGeometryN( nn ) ) ) { - Geometry in_1 = p.intersection( interAA.getGeometryN( nn ) ); - narea += PgenUtil.getSphPolyAreaInGrid( in_1 ); - } - } - - if ( narea >= AREA_LIMIT ) { - interSSBig = true; - break; - } - } - } - - interWithSS.put( areaName, interSSBig ); - } - } - - // Find the primary and the secondary area - String primaryArea = null; - double biggest = 0.0; - for ( String areaName : interSizes.keySet() ) { - if ( interSizes.get( areaName ) > biggest ) { - primaryArea = new String( areaName ); - biggest = interSizes.get( areaName ); - } - } - - String secondArea = null; - double second = 0.0; - for ( String areaName : interSizes.keySet() ) { - if ( !areaName.equals( primaryArea ) && - interSizes.get( areaName ) > second ) { - - secondArea = areaName; - second = interSizes.get( areaName ); - } - } - - // Set up "area" info in the smear. - StringBuilder gfaArea = new StringBuilder(); - if ( primaryArea != null && interWithSS.get( primaryArea ) ) { - - gfaArea.append( primaryArea ); - - if ( secondArea != null && interSizes.get( secondArea ) >= AREA_LIMIT && - interWithSS.get( secondArea ) ) { + // OTLK CONDS ENDG wording + if ("YES".equalsIgnoreCase(wording.genOlk)) { + wording.otlkCondsEndg = otlkEndgWording(originalSS, olkSeq); + } + smear.addAttribute(WORDING, wording); - gfaArea.append( "-" + secondArea ); - } - } - - current.setGfaArea( gfaArea.toString() ); - - } - - /** - * Assigns airmetTag to the smear. - * - * @param smear - */ - static void assignAirmetTag(Gfa smear) { - - /* - * Note, if necessary, this could be controlled as a preference? - */ - boolean addAirmetTag = true; - String haz = smear.getGfaHazard(); - if ( addAirmetTag && !("FZLVL".equals( haz ) ) && !("M_FZLVL".equals( haz ) )) { - String prefix = ""; - if ( haz.equals( "TURB-HI") ) { - prefix = "H"; - } - else if ( haz.equals( "TURB-LO") ) { - prefix = "L"; - } - - String airmetTag = new String ( prefix + smear.getGfaTag()+smear.getGfaDesk() ); - smear.setGfaValue( Gfa.AIRMET_TAG, airmetTag ); - - } + // logger.trace( smear.toString() ); + // logger.debug( "\n" + wording ); - } - - /** - * Re-order the state list in a GFA. - * - * 1. If there are two FA areas, the state in the primary area go first. - * 2. For each FA area, the states in that area should follow the given order. - * 3. "CSTL WATERS" goes last, if exists. - * - */ - public static void reorderStateList( Gfa gg ) { - - String area = gg.getGfaArea(); + // create beginning and ending + parseWording(smear, wording); - if ( area == null || !isValidGfaArea( area ) || gg.getGfaStates() == null || - gg.getGfaStates().trim().length() == 0 ) { - return; - } + clearAttributes(originalSS); - ArrayList oldStates = new ArrayList(); - ArrayList oldStatesNoWater = new ArrayList(); - for ( String ss : gg.getGfaStates().split(" ") ) { - oldStates.add( ss ); - if ( ss.length() == 2 ) - oldStatesNoWater.add(ss); - } + } - String[] s = area.split( "-" ); + // Return valid Gfa - those with at least one state in it and outlooks + // with GenOlk is "YES" + clipped.clear(); + if (invalidOtlk.size() > 0) + checkStates.removeAll(invalidOtlk); + clipped.addAll(checkStates); + } - ArrayList statesInArea1 = GfaInfo.getStateOrderByArea().get( s[0] ); - ArrayList statesInArea2 = null; - if ( s.length > 1 ) { - statesInArea2 = GfaInfo.getStateOrderByArea().get( s[1] ); - } + /** + * Generate the state list for a smear. + * + * Note: 1. The state list is not sorted. 2. If a smear has two FA areas, + * the state list is generated but not in final order (states in primary FA + * area precede states in adjacent area). This will be done in + * GfaGeneate.java instead. Warning: the validity check of the state bounds + * should be done when pre-loading them (if necessary), not here - since + * geometry().isValid() is a quite expensive call. + * + * @param smear + */ + private static void updateGfaStates(Gfa smear) { - // Sort states in primary FA area - StringBuilder newStates = new StringBuilder(); - for (String st : statesInArea1) { - if ( st.length() == 2 && oldStatesNoWater.contains( st ) ) { - newStates.append( st ); - newStates.append(" "); - } - } + HashMap states = GfaClip.getInstance() + .getStateBoundsInGrid(); + HashMap greatLakes = GfaClip.getInstance() + .getGreatLakesBoundsInGrid(); + HashMap coastalWater = GfaClip.getInstance() + .getCoastalWaterBoundsInGrid(); + LinkedHashMap stateMaps = new LinkedHashMap(); // keep + // insertion + // order + stateMaps.putAll(states); - // Sort and add states in second FA area, if any. - if ( statesInArea2 != null ) { - for ( String st : statesInArea2 ) { - if ( st.length() == 2 && oldStatesNoWater.contains( st ) ) { - newStates.append( st ); - newStates.append(" "); - } - } - } + /* + * Find all states that touches the smear. + * + * If this is a MT_OBSC, only those MT_OBSC states will be tested and + * added to the state list. + */ + List mtobscsts = GfaClip.getInstance().getMtObscStates(); + Polygon smearP = GfaClip.getInstance().gfaToPolygonInGrid(smear); + boolean is_MTOBSC = false; + if (smear.getGfaHazard().equalsIgnoreCase("MT_OBSC")) { + is_MTOBSC = true; + } + + int nState = 0; + for (String key : stateMaps.keySet()) { + Geometry g = stateMaps.get(key); + + if (is_MTOBSC && !mtobscsts.contains(key)) + continue; + + if (smearP.intersects(g)) { + nState++; + updateGfaStatesField(smear, key); + } + + } + + /** + * Check for the airmet over Great Lakes and coastal waters. + * + * If the state to which those waters belong is not already in the + * stList, then add it. + * + * MT_OBSC hazards can never include any Great Lakes & coastal waters. + */ + int nWaters = 0; + if (!is_MTOBSC) { + + for (String key : greatLakes.keySet()) { + Geometry g = greatLakes.get(key); + + if (!g.intersects(smearP)) + continue; + updateGfaStatesField(smear, key); + + } + + for (String key : coastalWater.keySet()) { + Geometry g = coastalWater.get(key); + + if (!g.intersects(smearP)) + continue; + + nWaters++; + updateGfaStatesField(smear, key); + } + + } + + /** + * If the airmet covers land and water then append "AND CSTL WTRS" to + * the state list. If only water then use just "CSTL WTRS" (no AND). + */ + if (nWaters > 0) { + + StringBuilder s = new StringBuilder(nvl(smear.getGfaStates())); + + /* + * Note - nState should be states on land, not including states from + * Great Lakes and Coastal Waters. + */ + if (nState > 0) { + s.append(" AND"); + } + + s.append(" CSTL WTRS"); + + smear.setGfaStates(s.toString()); + } + + /* + * Re-order the state list in the specified FA-Area based order. + */ + reorderStateList(smear); + + } + + /** + * Updates the states field. + * + * @param gfa + * @param state + * @param polygon + */ + private static boolean updateGfaStatesField(Gfa gfa, String state) { + boolean added = false; + String s = nvl(gfa.getGfaStates()); + if (!s.contains(state)) { + if (!s.isEmpty()) + s += " "; + s += state; + gfa.setGfaStates(s); + added = true; + } + + return added; + } + + /** + * Find the type of each snapshot and assign to SNAPSHOT_TYPE attribute. + * + *
+     * X_SNAPSHOTS - SS intersects with the clipped polygon with an area > 3K. 
+     * O_SNAPSHOTS - SS do not intersect with the clipped polygon
+     * 
+ * + * @param originalSS + * @param smear + */ + private static void assignXorO(ArrayList originalSS, Gfa smear) { + // Polygon smearP = GfaClip.getInstance().gfaToPolygon(smear); + Polygon smearP = GfaClip.getInstance().gfaToPolygonInGrid(smear); + boolean allOutlook = true; + for (Gfa ss : originalSS) { // snapshots + assignSnapshotType(smearP, ss); + String fcstHr = ss.getGfaFcstHr(); + if (!("9".equals(fcstHr) || "12".equals(fcstHr))) { + allOutlook = false; + } + } + + Gfa first = originalSS.get(0); + ArrayList outlooks = first.getAttribute("OUTLOOKS", + ArrayList.class); + + // SMEAR or OUTLOKOS - list of created clipped smears + // OTLK_LIST - original list of outlook gfa elements (6,9,12) + if ("6".equals(first.getGfaFcstHr()) && !allOutlook && outlooks != null) { + // only for smears which have "6" hour snapshots + ArrayList otkl = first.getAttribute("OTLK_LIST", + ArrayList.class); + if (otkl == null || otkl.isEmpty()) + return; + smearP = findTheSmear(smearP, outlooks); + // smearP = + // GfaClip.gfaToPolygon((Gfa)otkl.get(0).getAttribute("AIRMETS")); + for (Gfa g : otkl) { + if (g == originalSS.get(0)) + continue; + assignSnapshotType(smearP, g); + } + } + } + + /** + *
+     * X snapshots - SS intersects with the clipped polygon smearP with an area > 3K. 
+     * O snapshots - SS do not intersect with the clipped polygon
+     * 
+ * + * + * @param smearP + * Polygon + * @param ss + */ + private static void assignSnapshotType(Polygon smearP, Gfa ss) { + + Polygon ssP = GfaClip.getInstance().gfaToPolygonInGrid(ss); + Geometry intersection = ssP.intersection(smearP); + + ss.addAttribute(SNAPSHOT_TYPE, SnapshotType.O); + + if (PgenUtil.getSphPolyAreaInGrid(intersection) > AREA_LIMIT) { + ss.addAttribute(SNAPSHOT_TYPE, SnapshotType.X); + } + + } + + private static Polygon findTheSmear(Polygon smearP, ArrayList outlooks) { + for (Gfa g : outlooks) { + + Polygon p = GfaClip.getInstance().gfaToPolygonInGrid(g); + + Geometry intersection = p.intersection(smearP); + + double area = PgenUtil.getSphPolyAreaInGrid(intersection); + + if (area > AREA_LIMIT) { + return p; + } + } + return smearP; + } + + /** + * Retrieve each snapshot's forecast time. + * + *
+     * Round UP - X_SNAPSHOTS for development wording or O_SNAPSHOTS for ending wording. 
+     * Round Down - X_SNAPSHOTS for ending wording or O_SNAPSHOTS for development wording
+     * 
+ * + * @param originalSS + */ + private static void assignSSForecastTime(ArrayList originalSS) { + for (Gfa ss : originalSS) { + String fcstHr = ss.getGfaFcstHr(); + int[] hm = Gfa.getHourMinInt(nvl(fcstHr)); + ss.addAttribute("HOUR_INT", hm[0]); + ss.addAttribute("MIN_INT", hm[1]); + double hmD = hm[0] + hm[1] / 60.0; + SnapshotType type = ss.getAttribute(SNAPSHOT_TYPE, + SnapshotType.class); + if (type == SnapshotType.X) { + ss.addAttribute(DVLPG_HR, (int) ceil(hmD)); + ss.addAttribute(ENDG_HR, (int) floor(hmD)); + } else if (type == SnapshotType.O) { + ss.addAttribute(DVLPG_HR, (int) floor(hmD)); + ss.addAttribute(ENDG_HR, (int) ceil(hmD)); + } else { + // sanity check - should never reach this place + // check asssignXorO if this happens + String err = "Snapshot type must be assigned by this time"; + // logger.error(err); + throw new IllegalArgumentException(err); + } + } + } + + /** + * Assigns issue time to the smear. + * + * @param smear + */ + static void assignIssueTime(Gfa smear) { + /* + * First determine if the standard issue time should be overridden. An + * issue time is overridden if any of the hazards (smears) are of an + * issuance type that is CAN, COR, NEW, or AMD. + */ + boolean overrideIssueTime = !"NRML".equalsIgnoreCase(smear + .getGfaIssueType()); + + Calendar localTimeCal = Calendar.getInstance(); + + String timeStr = AirmetCycleInfo.getIssueTime(); + Calendar issueTimeCal = Calendar.getInstance(); + int hour = Integer.parseInt(timeStr.substring(0, 2)); + int min = Integer.parseInt(timeStr.substring(2)); + issueTimeCal.set(Calendar.HOUR_OF_DAY, hour); + issueTimeCal.set(Calendar.MINUTE, min); + issueTimeCal.set(Calendar.SECOND, 0); + + if (overrideIssueTime) { + // Compare the local time to the issue time if overrideIssueTm flag + // is TRUE. + if (issueTimeCal.before(localTimeCal)) { + issueTimeCal = localTimeCal; + } else { + // set issue time = issue time + 1 min + issueTimeCal.add(Calendar.MINUTE, 1); + } + } + + smear.addAttribute(ISSUE_TIME, issueTimeCal); + + Calendar untilTimeCal = AirmetCycleInfo.getUntilTime(); + smear.addAttribute(UNTIL_TIME, untilTimeCal); + + Calendar otlkEndTime = Calendar.getInstance(); + otlkEndTime.set(Calendar.DAY_OF_MONTH, + untilTimeCal.get(Calendar.DAY_OF_MONTH)); + otlkEndTime.set(Calendar.HOUR_OF_DAY, + untilTimeCal.get(Calendar.HOUR_OF_DAY) + 6); + otlkEndTime.set(Calendar.MINUTE, untilTimeCal.get(Calendar.MINUTE)); + otlkEndTime.set(Calendar.SECOND, untilTimeCal.get(Calendar.SECOND)); + + smear.addAttribute(OUTLOOK_END_TIME, otlkEndTime); + + } + + /** + * Generates "" wording. + * + * @param smear + * @param originalSS + * @return + */ + private static String fromCondsDvlpg(Gfa smear, ArrayList originalSS) { + + int endHour = 6; + /* + * from the legacy system (af_condsWording method in + * source/textlib/airmet/afconditions.c): + * + * Wording rules: If the first ss in the sequence is an 'X_SNAPSHOTS' { + * If the first ss time is 00, there is no wording. If the first ss time + * is 03 or less, wording is "+00-+TTZ", where 'TT' is the ss time. If + * the first ss time is 06 or less (on-time cycles only), wording is + * "+03-+TTZ", where 'TT' is the ss time. } + * + * If the first ss is an 'O_SNAPSHOTS' { Scan the sequence forward from + * the first ss to find the last 'O' before encountering an 'X' ss. The + * wording is "AFT +TTZ" where 'TT' is this 'O' ss time. } + */ + String wording = ""; + int xx = 0; + int yy = 0; + Gfa ss = originalSS.get(0); + int dvlpgHr = ss.getAttribute(DVLPG_HR, Integer.class); + if (ss.getAttribute(SNAPSHOT_TYPE) == SnapshotType.X) { + if (dvlpgHr == 0) { + // no wording + } else if (dvlpgHr <= 3) { + wording = "CONDS DVLPG +00-+" + pad(dvlpgHr) + "Z"; + yy = dvlpgHr; + } else if (dvlpgHr <= 6) { + wording = "CONDS DVLPG +03-+" + pad(dvlpgHr) + "Z"; + xx = 3; + yy = dvlpgHr; + } + } else { + int lastO = 0; + for (int i = 1; i < originalSS.size(); i++) { + Gfa g = originalSS.get(i); + dvlpgHr = ss.getAttribute(DVLPG_HR, Integer.class); + if (g.getAttribute(SNAPSHOT_TYPE) == SnapshotType.X + && dvlpgHr <= endHour) { + lastO = i - 1; + break; + } + } + dvlpgHr = originalSS.get(lastO).getAttribute(DVLPG_HR, + Integer.class); + wording = "CONDS DVLPG AFT +" + pad(dvlpgHr) + "Z"; + xx = dvlpgHr; + yy = -1; + } + + if (!PgenCycleTool.isRoutine() && !wording.isEmpty() && xx >= 0 + && yy >= 0) { + + Calendar cal = smear.getAttribute(ISSUE_TIME, Calendar.class); + int issueHrMin = cal.get(Calendar.HOUR_OF_DAY) * 100 + + cal.get(Calendar.MINUTE); + + int basetime = PgenCycleTool.getCycleHour(); + + if ((yy + basetime) * 100 <= issueHrMin) { /* yy in past */ + wording = ""; + } else { /* yy in future */ + if ((xx + basetime) * 100 <= issueHrMin) {/* xx in past */ + wording = "CONDS DVLPG BY +" + pad(yy) + "Z"; // BY +23Z + } else { + wording = "CONDS DVLPG +" + pad(xx) + "-+" + pad(yy) + "Z"; // +03-+06Z + } + } + } + + return wording; + } + + /** + * Generates "" wording. + * + * @param smear + * @param originalSS + * @return + */ + private static String fromCondsEndg(Gfa smear, ArrayList originalSS) { + + int endHour = 6; + /* + * from the legacy system (af_fromEndgWording) + * + * Wording Rules: + * + * If last ss in the sequence is an 'X_SNAPSHOTS' { If the last ss time + * is the last possible time (06 for on-time cycles or 03 for off-time + * cycles), wording is determined by the outlook component snapshots + * rules. See the 'Outlook BOUNDED BY lines' section below for + * "CONDS CONTG BYD +06Z" wording (or "CONDS CONTG BYD +03Z" for cycles + * 00, 06, 12 and 18). If the last ss time is less than 03, wording is + * "+TT-+03Z", where 'TT' is the ss time. If the last ss time is less + * than 06 (on-time cycles only), wording is "+TT-+06Z", where 'TT' is + * the ss time. } + * + * If last ss is an 'O_SNAPSHOT' { Scan the sequence backward from the + * last ss to find the first 'O' after encountering an 'X' ss. The + * wording is "BY +TTZ" where 'TT' is this 'O' ss time. } + */ + String wording = ""; + int xx = -1; + int yy = -1; + int lastSSIndex = originalSS.size() - 1; + for (int i = originalSS.size() - 1; i >= 0; i--) { + lastSSIndex = i; + int hr = originalSS.get(lastSSIndex).getAttribute(ENDG_HR, + Integer.class); + if (hr <= endHour) + break; + } + Gfa lastSS = originalSS.get(lastSSIndex); + int lastEndgHr = lastSS.getAttribute(ENDG_HR, Integer.class); + String lastFcstHr = lastSS.getGfaFcstHr(); + int[] hm = Gfa.getHourMinInt(lastFcstHr); + + if (lastSS.getAttribute(SNAPSHOT_TYPE) == SnapshotType.X) { + + if (hm[0] == endHour && hm[1] == 0) { + /* Handled separately by af_contgBydWording() */ + } else if (lastEndgHr < 3) { + // sprintf(wording, "CONDS ENDG +0%d-+03Z", last_ss_hr) + wording = "CONDS ENDG +" + pad(lastEndgHr) + "-+03Z"; + xx = lastEndgHr; + yy = 3; + } else if (lastEndgHr <= 6) { + // sprintf(wording, "CONDS ENDG +0%d-+06Z", last_ss_hr); + wording = "CONDS ENDG +" + pad(lastEndgHr) + "-+06Z"; + xx = lastEndgHr; + yy = 6; + } + } else { + int firstO = lastSSIndex; + + ArrayList otlkList = lastSS.getAttribute("OTLK_LIST", + ArrayList.class); + if ("6".equals(originalSS.get(originalSS.size() - 1).getGfaFcstHr()) + && otlkList != null) { + lastSSIndex = otlkList.size() - 1; + lastSS = otlkList.get(lastSSIndex); + for (int jj = otlkList.size() - 2; jj >= 0; jj--) { + lastSS = otlkList.get(jj); + if (lastSS.getAttribute(SNAPSHOT_TYPE) == SnapshotType.X) { + firstO = jj + 1; + break; + } + } + lastEndgHr = Integer.parseInt(otlkList.get(firstO) + .getGfaFcstHr()); + } else { + for (int jj = lastSSIndex - 1; jj >= 0; jj--) { + lastSS = originalSS.get(jj); + if (lastSS.getAttribute(SNAPSHOT_TYPE) == SnapshotType.X) { + firstO = jj + 1; + break; + } + } + lastEndgHr = originalSS.get(firstO).getAttribute(ENDG_HR, + Integer.class); + } + wording = "CONDS ENDG BY +" + pad(lastEndgHr) + "Z"; + } + + if (!PgenCycleTool.isRoutine() && !wording.isEmpty() && xx >= 0 + && yy >= 0) { + + Calendar cal = smear.getAttribute(ISSUE_TIME, Calendar.class); + int issueHrMin = cal.get(Calendar.HOUR_OF_DAY) * 100 + + cal.get(Calendar.MINUTE); + + int basetime = PgenCycleTool.getCycleHour(); + + if ((yy + basetime) * 100 <= issueHrMin) { /* yy in past */ + wording = "CONDS HV ENDED"; + } else { /* yy in future */ + if ((xx + basetime) * 100 <= issueHrMin) {/* xx in past */ + wording = "CONDS ENDG BY +" + pad(yy) + "Z"; // BY +23Z + } else { + wording = "CONDS ENDG +" + pad(xx) + "-+" + pad(yy) + "Z"; // +03-+06Z + } + } + } + + return wording; + } + + private static int[] findOtlkSeq(ArrayList originalSS) { + int startHour = 6; // ontime + + int[] olkSeq = new int[3]; + for (int i = 0; i < 3; i++) { + olkSeq[i] = -1; + } + + for (int ii = 0; ii < originalSS.size(); ii++) { + String fcstHr = originalSS.get(ii).getGfaFcstHr(); + int[] hm = Gfa.getHourMinInt(nvl(fcstHr)); + if (hm[1] != 0) + continue; + + if (hm[0] == startHour) { + olkSeq[0] = ii; + } else if (hm[0] == (startHour + 3)) { + olkSeq[1] = ii; + } else if (hm[0] == (startHour + 6)) { + olkSeq[2] = ii; + } + } + return olkSeq; + } + + /** + * Generates wording + * + * @param smear + * @param originalSS + * @return + */ + private static String otlkGenWording(ArrayList originalSS, int[] olkSeq) { + // af_otlkGenWording(ss_attr, olk_seq, tmpstr); + + /* + * Wording Rules: Assume there is at least one SS in the sequence. 1SS - + * 06 ss (03 for off-time cycles) 2SS - 09 ss (06 for off-time cycles) + * 3SS - 12 ss (09 for off-time cycles) + * + * If 1SS does not exist or exists as an O_SNAPSHOTS { is + * "YES" } + * + * If both 1SS and 2SS exist as X_SNAPSHOTSs { is "MAYBE" } + * + * If 1SS & 3SS exist X_SNAPSHOTSs { is "MAYBE" (X-O-X case + * and X---X case) } + * + * All other cases - is "NO" + */ + + String genOlk = "NO"; + if (olkSeq[0] >= 0 || olkSeq[1] >= 0 || olkSeq[2] >= 0) { + if (olkSeq[0] < 0 + || (olkSeq[0] >= 0 && originalSS.get(olkSeq[0]) + .getAttribute(SNAPSHOT_TYPE) == SnapshotType.O)) { + genOlk = "YES"; + } else if ((olkSeq[1] >= 0 && originalSS.get(olkSeq[1]) + .getAttribute(SNAPSHOT_TYPE) == SnapshotType.X) + || (olkSeq[2] >= 0 && originalSS.get(olkSeq[2]) + .getAttribute(SNAPSHOT_TYPE) == SnapshotType.X)) { + genOlk = "MAYBE"; + } + } + + return genOlk; + } + + private static String processMAYBE(Gfa outlook, ArrayList originalSS) { + // corresponds to afconditions.af_processMAYBE + + Polygon outlookP = GfaClip.getInstance().gfaToPolygon(outlook); + HashMap states = GfaClip.getInstance() + .getStateBounds(); + + Gfa g6 = null; + for (Gfa g : originalSS) { + updateGfaStates(g); + if ("6".equals(g.getGfaFcstHr())) + g6 = g; + } + + // smears list is not null here, because MAYBE can only be called + // for outlooks containing "6" and "9" hour snapshots. + // and at least one "6-6" airmet exists, g6 is not be null + ArrayList airmets = g6.getAttribute("AIRMETS", ArrayList.class); // from + // 0 + // to + // 6 + // hours + + // loop through airmets and find the one which overlaps with the outlook + // we process + // then the overlapping one is the one we will use to apply rules. + TreeSet statesInAirmet = new TreeSet(); + Gfa airmet = null; + for (Gfa g : airmets) { + Polygon gP = GfaClip.getInstance().gfaToPolygon(g); + Geometry intersection = outlookP.intersection(gP); + if (intersection instanceof Polygon + || intersection instanceof MultiPolygon) { + // states + String[] statesArray = nvl(g.getGfaStates()).split(" "); + for (String s : statesArray) { + statesInAirmet.add(s.trim()); + } + airmet = g; + break; + } + } + + /* + * Rule 1: For states in the outlook's state list but not listed in the + * airmet's state list, check the sizes of the intersection areas + * between the outlook with those states. If there is at least one of + * them is greater than or equal to 3K, set the flag to True to issue + * the outlook. + * + * Rule 2: For states both in the outlook's state list and the airmet's + * state list, check the in-state outlook generation ratio with the + * threshold set in the prefs.tbl. If it's greater than the threshold, + * issue the outlook. + * + * Both checks should be done for the state bound, the Great Lakes + * bound, and the coastal water bound. + */ + String[] statesInOutlook = nvl(outlook.getGfaStates()).split(" "); + double gfaOtlkgenRatio = GfaInfo.getGfaOtlkgenRatio(); + Polygon airmetP = GfaClip.getInstance().gfaToPolygon(airmet); + for (String stateStr : statesInOutlook) { + if (stateStr.isEmpty()) + continue; + Geometry stateP = states.get(stateStr); + + if (stateP == null) + continue; + + if (statesInAirmet.contains(stateStr)) { + // rule 2 + // + // the formula from tt 8.106 takes precedence over the earlier + // one + // + // ratio = (Outlook Area - Intersect Area)/ State Area + // + // June, 2012 - adjust algorithm to find the ratio due to + // high-resolution state bounds. + // + // Prevoius - Intersection Area = (A^S) ^ (O^S) + // Now - Intersection Area = (A^O)^S + // + // + Geometry a = airmetP.intersection(outlookP); + if (a == null) + continue; + + Geometry o = outlookP.intersection(stateP); + + Geometry i = a.intersection(stateP); + if (i == null) + continue; + + double oArea = PgenUtil.getSphPolyArea(o); + double iArea = PgenUtil.getSphPolyArea(i); + + double ratio = 0.0; + if ((oArea - iArea) > 0.0) { + double sArea = PgenUtil.getSphPolyArea(stateP); + ratio = (oArea - iArea) / sArea; + } + + if (ratio >= gfaOtlkgenRatio) + return "YES"; + + } else { + // rule 1 + Geometry intersection = outlookP.intersection(stateP); + double area = PgenUtil.getSphPolyArea(intersection); + if (area > AREA_LIMIT) { + // stop here, yes we need to issue the outlook + return "YES"; + } + } + } + + return "NO"; + } + + /** + * OTLK CONDS CONTG BYD wording + * + * @param origSS + * @param olkSeq + * @param smr + * @return + */ + private static String contgBydWording(ArrayList origSS, + int[] olkSeqIn, Gfa smr) { + + /* + * Wording Rules: + * + * Proceed only if the 06 ss exists ( 03 ss for off-time cycles ) as an + * "X_SNAPSHOTS". + * + * If the last ss in the sequence is an 'X' { If its time is 12, wording + * - "CONDS CONTG BYD +0NZ THRU +12Z". If its time is 09, wording - + * "CONDS CONTG BYD +0NZ ENDG +09-+12Z". If its time is 06, wording - + * "CONDS CONTG BYD +0NZ ENDG +06-+09Z". If its time is 03, wording - + * "CONDS CONTG BYD +0NZ ENDG +03-+06Z". } + * + * If the last ss in the sequence is an 'O' { Scan the sequence backward + * from the last ss to find the first 'O' after encountering an 'X' ss. + * + * If this 'O' ss time is 12, wording - + * "CONDS CONTG BYD +0NZ ENDG BY +12Z". If this 'O' ss time is 09, + * wording - "CONDS CONTG BYD +0NZ ENDG BY +09Z". } + * + * Where "N" is "6" for on-time cycle and "3" for off-time cycle. + */ + + // Proceed only if the 06 ss exists as an "X_SNAPSHOTS" + boolean ss06Exists = false; + for (Gfa g : origSS) { + int[] hm = Gfa.getHourMinInt(g.getGfaFcstHr()); + if (hm[0] == 6 && hm[1] == 0 + && g.getAttribute(SNAPSHOT_TYPE) == SnapshotType.X) { + ss06Exists = true; + break; + } + } + if (!ss06Exists) + return ""; + + // Make a copy, since we need to adjust it here. + int[] olkSeq = new int[olkSeqIn.length]; + for (int ii = 0; ii < olkSeqIn.length; ii++) { + olkSeq[ii] = olkSeqIn[ii]; + } + + String wording = ""; + int lastSS; + if (olkSeq[2] >= 0) + lastSS = 2; + else if (olkSeq[1] >= 0) + lastSS = 1; + else + lastSS = 0; + + ArrayList originalSS = new ArrayList(); + originalSS.addAll(origSS); + + boolean isX = originalSS.get(olkSeq[lastSS]) + .getAttribute(SNAPSHOT_TYPE) == SnapshotType.X; + ArrayList otlkList = originalSS.get(olkSeq[lastSS]).getAttribute( + "OTLK_LIST", ArrayList.class); + + // now test if OTLK_LIST list has + if (lastSS == 0 && otlkList != null) { + for (Gfa g : otlkList) { + if (g.getAttribute(SNAPSHOT_TYPE) == SnapshotType.O + && !"6".equals(g.getGfaFcstHr())) { + isX = false; + break; + } + } + } + + /* + * Find the types of outlook snapshots embedded in the airmet and adjust + * the type of outlook snapshots + */ + boolean adjEmbedOtlk = false; + ArrayList embedOtlks = originalSS.get(olkSeq[lastSS]) + .getAttribute("OUTLOOKS", ArrayList.class); + if (embedOtlks != null && embedOtlks.size() > 0) { + + /* + * Find the outlook originated from the same snapshots and clipped + * to the same region + */ + Gfa otlkInSameRegion = null; + for (Gfa gg : embedOtlks) { + if (gg.getAttribute("FA_REGION").equals( + smr.getAttribute("FA_REGION"))) { + otlkInSameRegion = gg; + break; + } + } + + // Adjust the type + FcstHrListPair p = embedOtlks.get(0).getAttribute("PAIR", + FcstHrListPair.class); + for (Gfa gg : p.getOriginal()) { + if (!originalSS.contains(gg)) { + Gfa temp = gg.copy(); + temp.addAttribute(SNAPSHOT_TYPE, SnapshotType.O); + + if (otlkInSameRegion != null) { + Polygon otlkPoly = GfaClip.getInstance() + .gfaToPolygonInGrid(otlkInSameRegion); + assignSnapshotType(otlkPoly, temp); + } + + originalSS.add(temp); + } + } + + adjEmbedOtlk = true; + } + + if (adjEmbedOtlk) { + olkSeq = findOtlkSeq(originalSS); + if (olkSeq[2] >= 0) + lastSS = 2; + else if (olkSeq[1] >= 0) + lastSS = 1; + else + lastSS = 0; + + isX = originalSS.get(olkSeq[lastSS]).getAttribute(SNAPSHOT_TYPE) == SnapshotType.X; + } + + /* + * wording.... + */ + if (isX) { + + String hourMinStr = originalSS.get(olkSeq[lastSS]).getGfaFcstHr(); + int[] hm = Gfa.getHourMinInt(hourMinStr); + String lastXinOtlk = ""; + if (otlkList != null + && !otlkList.isEmpty() + && otlkList.get(otlkList.size() - 1).getAttribute( + SNAPSHOT_TYPE) == SnapshotType.X) { + lastXinOtlk = otlkList.get(otlkList.size() - 1).getGfaFcstHr(); + } + + if (hm[0] == 12 || "12".equals(lastXinOtlk)) { + wording = "CONDS CONTG BYD +06Z THRU +12Z"; + } else if (hm[0] == 9 || "9".equals(lastXinOtlk)) { + wording = "CONDS CONTG BYD +06Z ENDG +09-+12Z"; + } else if (hm[0] == 6) { + wording = "CONDS CONTG BYD +06Z ENDG +06-+09Z"; + } + } else { + int firstO = lastSS; + int firstX = -1; + + for (int ii = lastSS; ii >= 0; ii--) { + if (olkSeq[ii] >= 0 + && originalSS.get(olkSeq[ii]).getAttribute( + SNAPSHOT_TYPE) == SnapshotType.X) { + firstX = ii; + break; + } + } + + if (firstX >= 0) { + for (int ii = firstX + 1; ii <= lastSS; ii++) { + if (olkSeq[ii] >= 0 + && originalSS.get(olkSeq[ii]).getAttribute( + SNAPSHOT_TYPE) == SnapshotType.O) { + firstO = ii; + break; + } + } + } + + String hourMinStr = originalSS.get(olkSeq[firstO]).getGfaFcstHr(); + int[] hm = Gfa.getHourMinInt(hourMinStr); + String firstOinOtlk = ""; + if (otlkList != null && !otlkList.isEmpty()) { + for (Gfa el : otlkList) { + if (el.getAttribute(SNAPSHOT_TYPE) == SnapshotType.O) { + firstOinOtlk = el.getGfaFcstHr(); + break; + } + } + } + + if (hm[0] == 12 || "12".equals(firstOinOtlk)) { + wording = "CONDS CONTG BYD +06Z ENDG BY +12Z"; + } else if (hm[0] == 9 || "9".equals(firstOinOtlk)) { + wording = "CONDS CONTG BYD +06Z ENDG BY +09Z"; + } else if (hm[0] == 6) { + wording = "CONDS CONTG BYD +03Z ENDG BY +06Z"; + } + } + + return wording; + } + + /** + * OTLK CONDS DVLPG wording + * + * @param smear + * @param originalSS + * @param olkSeq + * @return + */ + private static String otlkDvlpgWording(ArrayList originalSS, + int[] olkSeq) { + // afconditions.af_otlkDvlpgWording + + /* + * Wording Rules: + * + * If the first ss in the sequence is an 'X' { If first ss time is 06, + * there is no wording. If first ss time is 09, wording is "+06-+09Z". + * If first ss time is 12, wording is "+09-+12Z". } If the first ss is + * an 'O' { Scan the sequence forward from the first ss to find the last + * 'O' before encountering an 'X' ss. The wording is "AFT +TTZ" where + * 'TT' is this 'O' ss time. } + */ + int firstSS = -1; + for (int ii = 0; ii < 3; ii++) { + if (olkSeq[ii] >= 0) { + firstSS = ii; + break; + } + } + + String hourMinStr = originalSS.get(olkSeq[firstSS]).getGfaFcstHr(); + int[] hm = Gfa.getHourMinInt(hourMinStr); + + String wording = ""; + + if (originalSS.get(olkSeq[firstSS]).getAttribute(SNAPSHOT_TYPE) == SnapshotType.X) { + + if (firstSS == olkSeq[0]) { + /* No wording */ + } else if (hm[0] == 6) { + wording = "CONDS DVLPG +03-+06Z"; + } else if (hm[0] == 9) { + wording = "CONDS DVLPG +06-+09Z"; + } else if (hm[0] == 12) { + wording = "CONDS DVLPG +09-+12Z"; + } + } else { + int lastO = firstSS; + for (int ii = 0; ii < 2; ii++) { + if (lastO == olkSeq[ii] + && olkSeq[ii + 1] >= 0 + && originalSS.get(olkSeq[ii + 1]).getAttribute( + SNAPSHOT_TYPE) == SnapshotType.O) { + lastO = olkSeq[ii + 1]; + } + } + hourMinStr = originalSS.get(olkSeq[lastO]).getGfaFcstHr(); + hm = Gfa.getHourMinInt(hourMinStr); + + wording = "CONDS DVLPG AFT +" + pad(hm[0]) + "Z"; + } + return wording; + } + + /** + * OTLK CONDS ENDG wording + * + * @param originalSS + * @param olkSeq + * @return + */ + private static String otlkEndgWording(ArrayList originalSS, + int[] olkSeq) { + // afconditions.af_otlkEndgWording + + /* + * Wording Rules: + * + * If last ss in the sequence is an 'X' { If its time is 12 (09 for + * off-time), wording is "CONTG THRU +12Z" ("CONTG THRU +09Z" for + * off-time cycle). If its time is 09, wording is "ENDG +09-+12Z" for + * on-time cycle and "CONTG THRU +09Z" for off-time cycle. If its time + * is 06, wording is "ENDG +03-+06Z" for off-time cycle. } + * + * If last ss is an 'O' { Scan the sequence backward from the last ss to + * find the first 'O' after encountering an 'X' ss. The wording is + * "ENDG BY +TTZ" where 'TT' is this ss time. + * + * If this time is 12 (09 for off-time cycle). If this time is 09 (06 + * for off-time cycle), no wording. } + */ + int lastSS; + if (olkSeq[2] >= 0) + lastSS = 2; + else if (olkSeq[1] >= 0) + lastSS = 1; + else + lastSS = 0; + + String hourMinStr = originalSS.get(olkSeq[lastSS]).getGfaFcstHr(); + int[] hm = Gfa.getHourMinInt(hourMinStr); + + String wording = ""; + + if (originalSS.get(olkSeq[lastSS]).getAttribute(SNAPSHOT_TYPE) == SnapshotType.X) { + + if (hm[0] == 12) { + wording = "CONDS CONTG THRU +12Z"; + } else if (hm[0] == 9) { + wording = "CONDS ENDG +09-+12Z"; + } else if (hm[0] == 6) { + // no wording for on-time + } + } else { + int firstO = lastSS; + int firstX = -1; + + for (int ii = lastSS; ii >= 0; ii--) { + if (olkSeq[ii] >= 0 + && originalSS.get(olkSeq[ii]).getAttribute( + SNAPSHOT_TYPE) == SnapshotType.X) { + firstX = ii; + break; + } + } + + if (firstX >= 0) { + for (int ii = firstX + 1; ii <= lastSS; ii++) { + if (olkSeq[ii] >= 0 + && originalSS.get(olkSeq[ii]).getAttribute( + SNAPSHOT_TYPE) == SnapshotType.O) { + firstO = ii; + break; + } + } + } + + hourMinStr = originalSS.get(olkSeq[firstO]).getGfaFcstHr(); + hm = Gfa.getHourMinInt(hourMinStr); + + if (hm[0] == 12) { + wording = "CONDS ENDG BY +12Z"; + } else if (hm[0] == 9) { + // no wording for on-time + } + } + + return wording; + } + + /** + * This routine gets the starting and ending wordings from the format + * string. + * + * @param smear + * @param wording + */ + private static void parseWording(Gfa smear, GfaWording wording) { + + String beginWording = ""; + String endWording = ""; + // For smear wording + if (smear.isAirmet()) { + // Get developing wording + + beginWording = wording.fromCondsDvlpg; + + if (!wording.condsContg.isEmpty()) { + if (beginWording.isEmpty()) { + beginWording += wording.condsContg; + } else { + beginWording += ". " + wording.condsContg; + } + } + endWording = wording.fromCondsEndg; + + } else { // For outlook wording + + beginWording = wording.otlkCondsDvlpg; + + if (!wording.condsContg.isEmpty()) { + if (beginWording.isEmpty()) { + beginWording += wording.condsContg; + } else { + beginWording += ". " + wording.condsContg; + } + } + + if (!wording.otlkCondsEndg.isEmpty()) { + endWording = wording.otlkCondsEndg; + } + } + + smear.setGfaBeginning(beginWording); + smear.setGfaEnding(endWording); + + replacePlusWithCycle(smear); + } + + /** + * Replaces all occurrences of substrings like +ii in beginning and ending + * words with the strings calculated as a sum of ii and a cycle. For + * example, "CONDS ENDG +09-+12Z" becomes "CONDS ENDG 05-08Z" if the gfa + * cycle is 20. + * + * @param gfa + */ + public static void replacePlusWithCycle(Gfa gfa) { + int cycle = gfa.getGfaCycleHour(); + + String b = gfa.getGfaBeginning(); + b = replacePlusWithCycle(b, cycle); + gfa.setGfaBeginning(b); + + String e = gfa.getGfaEnding(); + e = replacePlusWithCycle(e, cycle); + gfa.setGfaEnding(e); + } + + /** + * Replaces all occurrences of substrings like +ii with the string + * calculated as a sum of ii + cycle. For example, CONDS ENDG +09-+12Z + * becomes CONDS ENDG 05-08Z if cycle is 20. + * + * @param b + * @param cycle + * @return + */ + public static String replacePlusWithCycle(String b, int cycle) { + int i; + while ((i = b.indexOf("+")) > -1) { + String toReplace = b.substring(i, i + 3); + String hour = toReplace.substring(1); + int h = Integer.parseInt(hour); + hour = pad((h + cycle) % 24); + b = b.replace(toReplace, hour); + } + return b; + } + + /** + * Deletes all the parameters added in this class to avoid confusion in the + * future. + * + * @param originalSS + */ + private static void clearAttributes(ArrayList originalSS) { + for (Gfa ss : originalSS) { + ss.removeAttribute(SNAPSHOT_TYPE); + ss.removeAttribute(DVLPG_HR); + ss.removeAttribute(ENDG_HR); + } + } + + private static String nvl(String value) { + return value == null ? "" : value; + } + + /** + * This routine clips ONE GFA smear against two FA areas in a FA region (the + * input GFA smear is assumed to have been clipped against FA regions) and + * checks the size of the clipped parts in each FA area to determine the + * primary area and the possible adjacent area they belong to. Additional + * Airmet/Outlook may need to be created when generating text product for + * such an smear (see GfaGenerate.java) + * + * @param current + * GFA to be processed + * @param clippedlist + * List of GFA snapshots from clipping + */ + private static void findGfaAreaInGrid(Gfa current, ArrayList snapShots) { + + /* + * Clip against the FA areas + * + * 1. Clip against the FA areas and compute the size of the intersection + * in each FA area. 2. Find the area that the smear has the largest + * intersection 3. Find the area that the smear has the second largest + * intersection, if any. 4. Apply the area rules: a. The primary "area" + * is the area that the smear intersects with a larger size. b. When + * both areas >= 3K, both areas are considered as primary areas and one + * additional AIRMET should be created (in GfaGenerate.java) c. the part + * in an FA area must also intersect with one of the snapshots with an + * area >= 3K, if there are associated snapshots. + */ + HashMap areaBnds = GfaClip.getInstance() + .getFaAreaBoundsInGrid(); + HashMap interSizes = new HashMap(); + HashMap interWithSS = new HashMap(); + + Polygon clipPoly = GfaClip.getInstance().gfaToPolygonInGrid(current); + + for (String areaName : areaBnds.keySet()) { + + Geometry g = areaBnds.get(areaName); + + if (clipPoly.intersects(g)) { + + Geometry interAA = clipPoly.intersection(g); + + double ss = PgenUtil.getSphPolyAreaInGrid(interAA); + + interSizes.put(areaName, ss); + + boolean interSSBig = false; + if (snapShots == null || snapShots.size() <= 0) { + interSSBig = true; + } else { + for (Gfa gfa : snapShots) { + + Polygon p = GfaClip.getInstance().gfaToPolygonInGrid( + gfa); + // Note: interAA might be an GeometryCollection and thus + // will be illegal parameter for intersects(). + + double narea = 0.0; + for (int nn = 0; nn < interAA.getNumGeometries(); nn++) { + if (p.intersects(interAA.getGeometryN(nn))) { + Geometry in_1 = p.intersection(interAA + .getGeometryN(nn)); + narea += PgenUtil.getSphPolyAreaInGrid(in_1); + } + } + + if (narea >= AREA_LIMIT) { + interSSBig = true; + break; + } + } + } + + interWithSS.put(areaName, interSSBig); + } + } + + // Find the primary and the secondary area + String primaryArea = null; + double biggest = 0.0; + for (String areaName : interSizes.keySet()) { + if (interSizes.get(areaName) > biggest) { + primaryArea = new String(areaName); + biggest = interSizes.get(areaName); + } + } + + String secondArea = null; + double second = 0.0; + for (String areaName : interSizes.keySet()) { + if (!areaName.equals(primaryArea) + && interSizes.get(areaName) > second) { + + secondArea = areaName; + second = interSizes.get(areaName); + } + } + + // Set up "area" info in the smear. + StringBuilder gfaArea = new StringBuilder(); + if (primaryArea != null && interWithSS.get(primaryArea)) { + + gfaArea.append(primaryArea); + + if (secondArea != null && interSizes.get(secondArea) >= AREA_LIMIT + && interWithSS.get(secondArea)) { + + gfaArea.append("-" + secondArea); + } + } + + current.setGfaArea(gfaArea.toString()); + + } + + /** + * Assigns airmetTag to the smear. + * + * @param smear + */ + static void assignAirmetTag(Gfa smear) { + + /* + * Note, if necessary, this could be controlled as a preference? + */ + boolean addAirmetTag = true; + String haz = smear.getGfaHazard(); + if (addAirmetTag && !("FZLVL".equals(haz)) && !("M_FZLVL".equals(haz))) { + String prefix = ""; + if (haz.equals("TURB-HI")) { + prefix = "H"; + } else if (haz.equals("TURB-LO")) { + prefix = "L"; + } + + String airmetTag = new String(prefix + smear.getGfaTag() + + smear.getGfaDesk()); + smear.setGfaValue(Gfa.AIRMET_TAG, airmetTag); + + } + + } + + /** + * Re-order the state list in a GFA. + * + * 1. If there are two FA areas, the state in the primary area go first. 2. + * For each FA area, the states in that area should follow the given order. + * 3. "CSTL WATERS" goes last, if exists. + * + */ + public static void reorderStateList(Gfa gg) { + + String area = gg.getGfaArea(); + + if (area == null || !isValidGfaArea(area) || gg.getGfaStates() == null + || gg.getGfaStates().trim().length() == 0) { + return; + } + + ArrayList oldStates = new ArrayList(); + ArrayList oldStatesNoWater = new ArrayList(); + for (String ss : gg.getGfaStates().split(" ")) { + oldStates.add(ss); + if (ss.length() == 2) + oldStatesNoWater.add(ss); + } + + String[] s = area.split("-"); + + ArrayList statesInArea1 = GfaInfo.getStateOrderByArea().get( + s[0]); + ArrayList statesInArea2 = null; + if (s.length > 1) { + statesInArea2 = GfaInfo.getStateOrderByArea().get(s[1]); + } + + // Sort states in primary FA area + StringBuilder newStates = new StringBuilder(); + for (String st : statesInArea1) { + if (st.length() == 2 && oldStatesNoWater.contains(st)) { + newStates.append(st); + newStates.append(" "); + } + } + + // Sort and add states in second FA area, if any. + if (statesInArea2 != null) { + for (String st : statesInArea2) { + if (st.length() == 2 && oldStatesNoWater.contains(st)) { + newStates.append(st); + newStates.append(" "); + } + } + } + + // Add back "CSTL WTRS" or "AND CSTL WTRS". + for (String st : oldStates) { + if (st.length() > 2) { + newStates.append(st); + newStates.append(" "); + } + } + + // Set the state list to the re-ordered one. + gg.setGfaStates(newStates.toString().trim()); + + } + + /* + * Check if the input is a valid FA area name. + * + * Note: A combination of two or more FA area names with "-" is valid. + */ + private static boolean isValidGfaArea(String gfaArea) { + boolean validArea = false; + + for (String area : gfaArea.split("-")) + if (area.equalsIgnoreCase(BOS) || area.equalsIgnoreCase(MIA) + || area.equalsIgnoreCase(CHI) || area.equalsIgnoreCase(DFW) + || area.equalsIgnoreCase(SLC) || area.equalsIgnoreCase(SFO)) { + + validArea = true; + break; + } + + return validArea; + } - // Add back "CSTL WTRS" or "AND CSTL WTRS". - for ( String st : oldStates ) { - if ( st.length() > 2 ) { - newStates.append( st ); - newStates.append(" "); - } - } - - // Set the state list to the re-ordered one. - gg.setGfaStates( newStates.toString().trim() ); - - } - - /* - * Check if the input is a valid FA area name. - */ - private static boolean isValidGfaArea( String area ) { - boolean validArea = false; - - if ( area.equalsIgnoreCase( BOS ) || area.equalsIgnoreCase( MIA ) || - area.equalsIgnoreCase( CHI ) || area.equalsIgnoreCase( DFW ) || - area.equalsIgnoreCase( SLC ) || area.equalsIgnoreCase( SFO ) ) { - - validArea = true; - } - - return validArea; - } - } diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/layering/PgenLayeringControlDialog.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/layering/PgenLayeringControlDialog.java index cb1805bc7e..654f7ca675 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/layering/PgenLayeringControlDialog.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/layering/PgenLayeringControlDialog.java @@ -27,11 +27,9 @@ import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; - import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.PlatformUI; - /** * This class controls PGEN layering in National Centers perspective. * @@ -39,7 +37,7 @@ import org.eclipse.ui.PlatformUI; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 07/09 #131 J. Wu Initial creation. + * 07/09 #131 J. Wu Initial creation. * * * @@ -50,738 +48,754 @@ import org.eclipse.ui.PlatformUI; public class PgenLayeringControlDialog extends PgenLayeringDialog { - /** + /** * Default color for the active layer name button. */ private final Color defaultLayerButtonColor = Color.lightGray; + private final Color activeLayerButtonColor = Color.green; - + /** * Layer name edit dialog. */ - protected PgenLayeringNameDialog layerNameDlg = null; - protected PgenLayeringDisplayDialog displayDlg = null; - - - /** + protected PgenLayeringNameDialog layerNameDlg = null; + + protected PgenLayeringDisplayDialog displayDlg = null; + + /** * List of layers and buttons. */ - private ArrayList layerList = null; - private ArrayList