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 c0997426b5..79f271435c 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 @@ -35,7 +35,7 @@ FL300 - + diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/prod/f000.xslt b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/prod/f000.xslt index 6f868a9243..887d46481c 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/prod/f000.xslt +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/prod/f000.xslt @@ -12,6 +12,7 @@ B. Yin/Chugach 08/11 Initial Coding B. Yin/SGT 02/14 Added contour support + P.Swamy 05/2014 TTR 993 - Highs and Lows do not decode for WPC SFC text product --> @@ -35,19 +36,19 @@ - + COLD WK - + WARM WK - + STNRY WK - + OCFNT WK - + TROF diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/prod/f000_hires.xslt b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/prod/f000_hires.xslt index 4afc2d2c0e..1f2728f5d4 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/prod/f000_hires.xslt +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/localization/ncep/pgen/xslt/prod/f000_hires.xslt @@ -11,6 +11,7 @@ Change Log: B. Yin/Chugach 08/11 Initial Coding + P.Swamy 05/2014 TTR 993 - Highs and Lows do not decode for WPC SFC text product --> @@ -33,19 +34,19 @@ - - COLD + + COLD WK - - WARM + + WARM WK - - STNRY + + STNRY WK - - OCFNT + + OCFNT WK - + TROF diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/Activator.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/Activator.java index 987de16012..8150e4104c 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/Activator.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/Activator.java @@ -85,6 +85,7 @@ public class Activator extends AbstractUIPlugin { myprefs.setDefault(PgenPreferences.P_COMP_COORD, PgenPreferences.CED_COMP_COORD); myprefs.setDefault(PgenPreferences.P_AUTOPLACE_TEXT, false); + myprefs.setDefault(PgenPreferences.P_AUTOPLACE_CONTOUR_LABEL, false); myprefs.setDefault(PgenPreferences.P_LAYER_MERGE, 4); } diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/PgenPreferences.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/PgenPreferences.java index 157c08a9ef..9055b0d11b 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/PgenPreferences.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/PgenPreferences.java @@ -40,6 +40,7 @@ import org.eclipse.ui.IWorkbenchPreferencePage; * 04/12 #977 S. Gilbert PGEN Database support * 11/13 TTR752 J. Wu Added P_AUTOPLACE_TEXT * 12/13 TTR776 J. Wu Added P_LAYER_MERGE + * 05/14 TTR 995 J. Wu Added P_AUTOPLACE_CONTOUR_LABEL. * * * @@ -84,6 +85,11 @@ public class PgenPreferences extends FieldEditorPreferencePage implements private BooleanFieldEditor autoPlaceText; + // Preference to place text box automatically (CCFP); + public final static String P_AUTOPLACE_CONTOUR_LABEL = "PGEN_AUTOPLACE_CONTOUR_LABEL"; + + private BooleanFieldEditor autoPlaceContourLabel; + public final static String P_LAYER_MERGE = "P_LAYER_MERGE"; private BooleanFieldEditor layerLink; @@ -142,10 +148,16 @@ public class PgenPreferences extends FieldEditorPreferencePage implements this.addField(projCombo); autoPlaceText = new BooleanFieldEditor(P_AUTOPLACE_TEXT, - "&Text Auto Placement (where applicable)", + "&Enable Auto Placement for CCFP Text Boxes", BooleanFieldEditor.DEFAULT, getFieldEditorParent()); this.addField(autoPlaceText); + autoPlaceContourLabel = new BooleanFieldEditor( + P_AUTOPLACE_CONTOUR_LABEL, + "&Enable Auto Placement for Contour Labels", + BooleanFieldEditor.DEFAULT, getFieldEditorParent()); + this.addField(autoPlaceContourLabel); + ComboFieldEditor layerMerge = new ComboFieldEditor(P_LAYER_MERGE, "&Default Action for PGEN Layer Merge:", new String[][] { { "Take no action", "0" }, diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/PgenUtil.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/PgenUtil.java index d871cb5a9a..c6488c3c11 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/PgenUtil.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/PgenUtil.java @@ -140,6 +140,8 @@ import com.vividsolutions.jts.linearref.LocationIndexedLine; * 07/26 TTR J. Wu Extract "DEL_PART" in DeletePartCommand into deleteLinePart(). * 12/13 #1089 B. Yin Removed the UTC time functions to a new class. * 12/13 #1091 J. Wu Added getLayerMergeOption() + * 05/14 TTR 995 J. Wu Added getContourLabelAutoPlacement(). + * 05/14 TTR998 J. Wu Added pixelToLatlon(). * * * @@ -825,7 +827,7 @@ public class PgenUtil { * @param pts * An array of points in lat/lon coordinates * @param mapDescriptor - * Descriptoer to use for world to pixel transform + * Descriptor to use for world to pixel transform * @return The array of points in pixel coordinates */ public static final double[][] latlonToPixel(Coordinate[] pts, @@ -843,6 +845,27 @@ public class PgenUtil { return pixels; } + /** + * Converts an array of point in pixel coordinates to lat/lons + * + * @param pixels + * An array of points in pixel coordinates + * @param mapDescriptor + * Descriptor to use for world to pixel transform + * @return The array list of points in lat/lon coordinates + */ + public static final ArrayList pixelToLatlon(double[][] pixels, + IMapDescriptor mapDescriptor) { + ArrayList crd = new ArrayList(); + + for (int ii = 0; ii < pixels.length; ii++) { + double[] pt = mapDescriptor.pixelToWorld(pixels[ii]); + crd.add(new Coordinate(pt[0], pt[1])); + } + + return crd; + } + /** * Gets the current site id from the localization Manager * @@ -2344,7 +2367,7 @@ public class PgenUtil { } /** - * Returns text auto placement flag + * ReturnsCCFP text box auto placement flag * * @return */ @@ -2353,6 +2376,16 @@ public class PgenUtil { return prefs.getBoolean(PgenPreferences.P_AUTOPLACE_TEXT); } + /** + * Returns contour's label auto placement flag + * + * @return + */ + public static boolean getContourLabelAutoPlacement() { + IPreferenceStore prefs = Activator.getDefault().getPreferenceStore(); + return prefs.getBoolean(PgenPreferences.P_AUTOPLACE_CONTOUR_LABEL); + } + /** * Returns the default PGEN layer merge option. * 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 1c1054a174..4a2afcd8ed 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 @@ -113,6 +113,10 @@ import com.vividsolutions.jts.geom.Coordinate; * similar changes to labels for other contour objects * caused a similar error (label or object or both * would disappear), this should now be fixed. + * 05/02/2014 ? D. Sushon In testing solution for trac 1132, it was found that + * multiple instances of the contour dialog's Edit + * windows could be created with no way to remove, + * should now be fixed. * 05/14 TTR1008 J. Wu Set default contour parameters through settings_tbl.xml. * * @@ -1960,6 +1964,16 @@ public class ContoursAttrDlg extends AttrDlg implements IContours, } + @Override + public int open() { + + if (this.getShell() == null || this.getShell().isDisposed()) { + return super.open(); + } else { + return CANCEL; + } + } + /** * Update the label attributes */ @@ -1994,6 +2008,11 @@ public class ContoursAttrDlg extends AttrDlg implements IContours, this.close(); } + @Override + public void handleShellCloseEvent() { + this.close(); + } + /** * disable un-used widgets */ @@ -2260,6 +2279,11 @@ public class ContoursAttrDlg extends AttrDlg implements IContours, this.close(); } + @Override + public void handleShellCloseEvent() { + this.close(); + } + /** * disable un-used widgets */ @@ -2425,6 +2449,11 @@ public class ContoursAttrDlg extends AttrDlg implements IContours, this.close(); } + @Override + public void handleShellCloseEvent() { + this.close(); + } + /** * disable un-used widgets */ @@ -3123,6 +3152,16 @@ public class ContoursAttrDlg extends AttrDlg implements IContours, } + @Override + public int open() { + + if (this.getShell() == null || this.getShell().isDisposed()) { + return super.open(); + } else { + return CANCEL; + } + } + /** * Update the min/max attributes */ @@ -3159,6 +3198,11 @@ public class ContoursAttrDlg extends AttrDlg implements IContours, this.close(); } + @Override + public void handleShellCloseEvent() { + this.close(); + } + /** * initialize dialog */ @@ -3902,4 +3946,4 @@ public class ContoursAttrDlg extends AttrDlg implements IContours, return typeChanged; } -} +} \ No newline at end of file diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/controls/StoreActivityDialog.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/controls/StoreActivityDialog.java index c8204c4a2b..31c02152ba 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/controls/StoreActivityDialog.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/controls/StoreActivityDialog.java @@ -49,6 +49,7 @@ import com.raytheon.viz.ui.dialogs.CaveJFACEDialog; * ------------ ---------- ----------- ----------------------------------- * 03/13 #977 S. Gilbert Initial creation * 01/14 #1105 J. Wu Pre-fill for each activity info. + * 05/14 TTR 963 J. Wu Change activity Info to Activity Label. * * * @@ -440,7 +441,7 @@ public class StoreActivityDialog extends CaveJFACEDialog { .getShell(), "Need More Information", null, - "Activity Info field is required.\nPlease enter an appropriate string and then try saving!", + "Activity Label field is required.\nPlease enter an appropriate string and then try saving!", MessageDialog.WARNING, new String[] { "OK" }, 0); confirmDlg.open(); 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 a4622ce8e5..d75db7d729 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 @@ -140,6 +140,7 @@ import com.vividsolutions.jts.operation.distance.DistanceOp; * this class * 11/13 TTR 752 J. Wu added methods to compute an element's range record. * 12/13 #1089 B. Yin Modify watch to display county list + * 05/14 TTR 995 J. Wu Make contour label auto-placement an option. * * * @author sgilbert @@ -336,10 +337,6 @@ public class DisplayElementFactory { list.addAll(createDisplayElementsForLines(de, smoothpts, paintProps)); - // Draw labels for contour lines. - // list.addAll( adjustContourLineLabels( elem, paintProps, - // smoothpts ) ); - } return list; @@ -382,7 +379,6 @@ public class DisplayElementFactory { LinePatternManager lpl = LinePatternManager.getInstance(); try { pattern = lpl.getLinePattern(de.getPatternName()); - // System.out.println("&&&pattern "+pattern.getMaxExtent()); } catch (LinePatternException lpe) { /* * could not find desired line pattern. Used solid line as default. @@ -623,7 +619,7 @@ public class DisplayElementFactory { /* * Draw labels for contour lines. */ - list.addAll(adjustContourLineLabels(elem, paintProps, smoothpts)); + // ???list.addAll(adjustContourLineLabels(elem, paintProps, smoothpts)); return list; } @@ -1342,7 +1338,9 @@ public class DisplayElementFactory { || tparent instanceof ContourCircle) { return slist; } else if (tparent instanceof ContourMinmax) { - if (((Text) txt).getAuto() != null && ((Text) txt).getAuto()) { + boolean forceAuto = PgenUtil.getContourLabelAutoPlacement(); + if (((Text) txt).getAuto() != null && ((Text) txt).getAuto() + || forceAuto) { Coordinate loc = ((ISinglePoint) ((ContourMinmax) tparent) .getSymbol()).getLocation(); double[] pixel = iDescriptor.worldToPixel(new double[] { @@ -1356,6 +1354,11 @@ public class DisplayElementFactory { pixel[0], pixel[1], 0.0 }); ((Text) txt).setLocationOnly(new Coordinate(nloc[0], nloc[1])); + // Only adjust once if auto-place flag in preference is + // false. + if (!forceAuto) { + ((Text) txt).setAuto(false); + } } } } @@ -3093,7 +3096,6 @@ public class DisplayElementFactory { */ double psize = pattern.getLength() * sfactor; double numPatterns = Math.floor(totalDist / psize); - // System.out.println("NUM_OF_PATTERN_ITERATIONS="+numPatterns+":"+psize); /* * Calculate the amount to increase or decrease the pattern length so @@ -5153,6 +5155,8 @@ public class DisplayElementFactory { boolean lineClosed = cline.getLine().isClosedLine(); + boolean forceAuto = PgenUtil.getContourLabelAutoPlacement(); + /* * Find the visible part of the line. */ @@ -5328,13 +5332,17 @@ public class DisplayElementFactory { loc[1] = txtPositions.get(kk).y; tps = iDescriptor.pixelToWorld(loc); - if (txt.getAuto() != null && txt.getAuto()) { + if (txt.getAuto() != null && txt.getAuto() || forceAuto) { txt.setLocationOnly(new Coordinate(tps[0], tps[1])); } txt.setParent(null); dlist.addAll(createDisplayElements((IText) txt, paintProps)); txt.setParent(cline); + + if (!forceAuto) { + txt.setAuto(false); + } } } @@ -5356,7 +5364,9 @@ public class DisplayElementFactory { Text labelText = ((ContourCircle) parent).getLabel(); - if (labelText.getAuto() != null && labelText.getAuto()) { + boolean forceAuto = PgenUtil.getContourLabelAutoPlacement(); + + if (labelText.getAuto() != null && labelText.getAuto() || forceAuto) { /* * Find the visible part of the circle. */ @@ -5409,6 +5419,10 @@ public class DisplayElementFactory { dlist.addAll(createDisplayElements((IText) labelText, paintProps)); labelText.setParent(parent); + if (!forceAuto) { + labelText.setAuto(false); + } + } return dlist; @@ -5455,8 +5469,7 @@ public class DisplayElementFactory { spdCoors.get(0), gov.noaa.nws.ncep.ui.pgen.display.IVector.VectorType.ARROW, 10, vDir, 1.0, false, "Vector", "Arrow"); - // System.out.println("generate a text for " + spd + " at: " - // + getCcfpTxtPts(v).x + "," + getCcfpTxtPts(v).y); + Text spdTxt = new Text(null, "Courier", 14.0f, TextJustification.CENTER,// .LEFT_JUSTIFY, @@ -5582,13 +5595,10 @@ public class DisplayElementFactory { */ public PgenRangeRecord findTextBoxRange(IText txt, PaintProperties paintProps) { - // System.out.println("findTextBoxRange for IText .... enter "); setScales(paintProps); double[] tmp = { txt.getPosition().x, txt.getPosition().y, 0.0 }; - // System.out.println("findTextBoxRange for IText .... " - // + txt.getPosition().x + "," + txt.getPosition().y); double[] loc = iDescriptor.worldToPixel(tmp); double horizRatio = paintProps.getView().getExtent().getWidth() @@ -5601,7 +5611,6 @@ public class DisplayElementFactory { */ IFont font = initializeFont(txt.getFontName(), txt.getFontSize(), txt.getStyle()); - // System.out.println("findTextBoxRange for IText .... 1 "); /* * apply X offset in half-characters @@ -5638,14 +5647,12 @@ public class DisplayElementFactory { ((Text) txt).setXOffset(0); ((Text) txt).setYOffset(0); } - // System.out.println("findTextBoxRange for IText .... 2 "); /* * Get text color */ Color clr = getDisplayColor(txt.getTextColor()); RGB textColor = new RGB(clr.getRed(), clr.getGreen(), clr.getBlue()); - // System.out.println("findTextBoxRange for IText .... 2.5 "); /* * Get angle rotation for text. If rotation is "North" relative, @@ -5654,7 +5661,6 @@ public class DisplayElementFactory { double rotation = txt.getRotation(); if (txt.getRotationRelativity() == TextRotation.NORTH_RELATIVE) rotation += northOffsetAngle(txt.getPosition()); - // System.out.println("findTextBoxRange for IText .... 3 "); /* * create drawableString and calculate its bounds @@ -5666,13 +5672,10 @@ public class DisplayElementFactory { dstring.horizontalAlignment = HorizontalAlignment.CENTER; dstring.verticallAlignment = VerticalAlignment.MIDDLE; dstring.rotation = rotation; - // System.out.println("findTextBoxRange for IText .... 3.1 "); Rectangle2D bounds = target.getStringsBounds(dstring); - // System.out.println("findTextBoxRange for IText .... 3.1.1 "); double xOffset = (bounds.getWidth() + 1) * horizRatio / 2; double yOffset = (bounds.getHeight() + 1) * vertRatio / 2; - // System.out.println("findTextBoxRange for IText .... 3.2 "); /* * Set proper alignment @@ -5699,7 +5702,6 @@ public class DisplayElementFactory { break; } } - // System.out.println("findTextBoxRange for IText .... 4 "); dstring.horizontalAlignment = align; @@ -5711,7 +5713,6 @@ public class DisplayElementFactory { IExtent box = new PixelExtent(dstring.basics.x - left, dstring.basics.x + right, dstring.basics.y - yOffset, dstring.basics.y + yOffset); - // System.out.println("findTextBoxRange for IText .... 5 "); List rngBox = new ArrayList(); rngBox.add(new Coordinate(box.getMinX() - PgenRangeRecord.RANGE_OFFSET, @@ -5726,8 +5727,6 @@ public class DisplayElementFactory { List textPos = new ArrayList(); textPos.add(new Coordinate(loc[0], loc[1])); - // System.out.println("findTextBoxRange for IText .... return "); - return new PgenRangeRecord(rngBox, textPos, false); } 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 86798de25b..4c2fb4e4a8 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 @@ -133,6 +133,7 @@ import com.vividsolutions.jts.geom.Coordinate; * 11/13 #1049 B. Yin Handle outlook type defined in layer. * 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. * * * @@ -367,10 +368,11 @@ public class ProductConverter { text.setHide(fText.isHide()); } - if (fText.isAuto() != null) { - text.setAuto(fText.isAuto()); - } - + /* + * if (fText.isAuto() != null) { // + * text.setAuto(fText.isAuto()); text.setAuto(false); } + */ + text.setAuto(false); des.add(text); } diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/gfa/GfaClip.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/gfa/GfaClip.java index 30a4e6920c..cd70686001 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/gfa/GfaClip.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/gfa/GfaClip.java @@ -36,7 +36,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; -//import org.apache.log4j.Logger; import org.dom4j.Document; import org.dom4j.Node; import org.dom4j.io.SAXReader; @@ -54,6 +53,8 @@ import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.Polygon; import com.vividsolutions.jts.geom.impl.CoordinateArraySequence; +//import org.apache.log4j.Logger; + /** * GFA clipping functionality. * @@ -82,2178 +83,2235 @@ import com.vividsolutions.jts.geom.impl.CoordinateArraySequence; * 07/11 #450 G. Hull NcPathManager * 02/12 #597 S. Gurung Moved snap functionalities to SnapUtil from SigmetInfo. * 10/12 J. Wu Fix a special case in getRegionIntersectionPt(). + * 05/14 J. Wu Fix CAVE hang-up when polygon outside of international + * bound. * * * * @author M.Laryukhin * @version 1 */ -public class GfaClip { +public class GfaClip { - private static GfaClip instance = new GfaClip(); - -// private final static Logger logger = Logger.getLogger( GfaClip.class ); + private static GfaClip instance = new GfaClip(); - /** Factory */ - private static GeometryFactory geometryFactory; + // private final static Logger logger = Logger.getLogger( GfaClip.class ); - /** Database name, currently defaulted to "ncep". */ - public final String DATABASE = "ncep"; + /** Factory */ + private static GeometryFactory geometryFactory; - /** Schema name, currently defaulted to "bounds". */ - public final String SCHEMA = "bounds"; + /** Database name, currently defaulted to "ncep". */ + public final String DATABASE = "ncep"; - public final String FA_REGION_TABLE = "fa_region"; - public final String FA_AREA_TABLE = "fa_area"; - public final String STATE_BNDS_TABLE = "statebnds"; - public final String GREATE_LAKE_BNDS_TABLE = "greatlakesbnds"; - public final String COASTAL_WATER_BNDS_TABLE = "airmetcstlbnds"; - public final String FA_AREAX_TABLE = "fa_areax"; - - /** - * The states listed in Raytheon's database but we do not need for GFA. - * Note: the first entry in Reytheon's state list is a "null" one - * which is part of Canada. - */ - private final String[] EXCLUDE_STATES = new String[]{ "AK", "HI", "UM", "GU", "AS", "PR", "VI" }; -// private final String[] WRONG_STATES = new String[] {"VT", "ID", "OH", "FL", "WA", "AK", "HI", "UM", "GU", "AS", "PR", "VI"}; -// private final String[] WRONG_STATES = new String[] {"VT", "ID", "OH", "FL", "WA"}; //OB11.5 - private final String[] WRONG_STATES = new String[] {"HI","VI","ME","VA","MI","MD","MA","AS","AR", - "IL","MN", "MS","NJ","PR","AK","AL","TX","NC","ND","NY","OK","OH", - "FL","SD","SC","WI","LA","GU","WA" }; //OB11.7 - - /** - * The union of three FA region bound shapes. - */ - private Geometry faInternationalBound; - private Geometry faInternationalBoundInGrid; - - /** - * The list of region bound shapes to clip against. - */ - private HashMap faRegionBounds; - private HashMap faRegionBoundsInGrid; + /** Schema name, currently defaulted to "bounds". */ + public final String SCHEMA = "bounds"; - /** - * The list of area bound shapes to clip against. - */ - private HashMap faAreaBounds; - private HashMap faAreaBoundsInGrid; + public final String FA_REGION_TABLE = "fa_region"; - /** - * The list of extended area bound shapes to clip against. - */ - private HashMap faAreaXBounds; - private HashMap faAreaXBoundsInGrid; + public final String FA_AREA_TABLE = "fa_area"; - /** - * The list of state bound shapes to clip against. - */ - private HashMap stateBounds; - private HashMap stateBoundsInGrid; + public final String STATE_BNDS_TABLE = "statebnds"; - /** - * The list of great lake shapes to clip against. - */ - private HashMap greatLakesBounds; - private HashMap greatLakesBoundsInGrid; - - /** - * The list of great lake shapes to clip against. - */ - private HashMap coastalWaterBounds; - private HashMap coastalWaterBoundsInGrid; - - /** - * The list of region bound shapes to clip against. - */ - private HashMap faRegionCommBounds; - private HashMap faRegionCommBoundsInGrid; + public final String GREATE_LAKE_BNDS_TABLE = "greatlakesbnds"; - /** - * The list of region bound shapes to clip against. - */ - private HashMap faAreaXCommBounds; - private HashMap faAreaXCommBoundsInGrid; - - - /** State list that allows MT_OBSC */ - private static Document mtObscTbl = null; - - /** XPATH for states in document */ - public static String MTOBSC_XPATH = "/MT_OBSC"; - - /** State list that allows MT_OBSC */ - private static List mtObscStates = null; - - /** State list that allows MT_OBSC */ - private static final int NEW_POINT = 2; - private static final int BOUND_POINT = 1; - private static final int ORIGINAL_POINT = 0; - - /** Tie distance for two points in map coord */ - private static final double SMALLF = (0.01); - - - /** - * Private constructor, we only need to read the database once. - */ - private GfaClip() { - geometryFactory = new GeometryFactory(); - } + public final String COASTAL_WATER_BNDS_TABLE = "airmetcstlbnds"; - /** - * Singleton instance. - * - * @return - */ - public static GfaClip getInstance() { - return instance; - } + public final String FA_AREAX_TABLE = "fa_areax"; - /** - * Clips to regions. - * - * @param smear - * @return - */ - public ArrayList simpleclip(Gfa smear) { - -// logger.debug("clipping started"); - - ArrayList list = new ArrayList(); - for (String key : getFaRegionBounds().keySet()) { - Geometry region = faRegionBounds.get(key); + /** + * The states listed in Raytheon's database but we do not need for GFA. + * Note: the first entry in Reytheon's state list is a "null" one which is + * part of Canada. + */ + private final String[] EXCLUDE_STATES = new String[] { "AK", "HI", "UM", + "GU", "AS", "PR", "VI" }; - Polygon polygon = gfaToPolygon(smear); + // private final String[] WRONG_STATES = new String[] {"VT", "ID", "OH", + // "FL", "WA", "AK", "HI", "UM", "GU", "AS", "PR", "VI"}; + // private final String[] WRONG_STATES = new String[] {"VT", "ID", "OH", + // "FL", "WA"}; //OB11.5 + private final String[] WRONG_STATES = new String[] { "HI", "VI", "ME", + "VA", "MI", "MD", "MA", "AS", "AR", "IL", "MN", "MS", "NJ", "PR", + "AK", "AL", "TX", "NC", "ND", "NY", "OK", "OH", "FL", "SD", "SC", + "WI", "LA", "GU", "WA" }; // OB11.7 - Geometry intersection = null; - if (region.intersects(polygon)) { - intersection = region.intersection(polygon); - if (intersection instanceof MultiPolygon) { - MultiPolygon mp = (MultiPolygon) intersection; - for (int i = 0; i < mp.getNumGeometries(); i++) { - Gfa g = geometryToGfa(smear, mp.getGeometryN(i)); - g.addNotToBeSnapped(region.getCoordinates()); - list.add(g); - } - } else { - Gfa g = geometryToGfa(smear, intersection); - g.addNotToBeSnapped(region.getCoordinates()); - list.add(g); - } - } else if (region.covers(polygon)) { - smear.addNotToBeSnapped(region.getCoordinates()); - list.add(smear); - } - } - - return list; - } + /** + * The union of three FA region bound shapes. + */ + private Geometry faInternationalBound; - - /** - * Generate a JTS polygon from a GFA polygon. - * - * @param gfa a GFA element - * @return - */ - public Polygon gfaToPolygon( Gfa gfa ) { - if ( gfa != null ) { - return pointsToPolygon( gfa.getLinePoints() ); - } - else { - return null; - } - } + private Geometry faInternationalBoundInGrid; - /** - * Generate a JTS polygon in grid coordinate from a GFA polygon. - * - * @param gfa a GFA element - * @return - */ - public Polygon gfaToPolygonInGrid( Gfa gfa ) { - if ( gfa != null ) { - return pointsToPolygon( PgenUtil.latlonToGrid( gfa.getLinePoints() ) ); - } - else { - return null; - } - } + /** + * The list of region bound shapes to clip against. + */ + private HashMap faRegionBounds; - /** - * Generate a JTS polygon from a set of points. + private HashMap faRegionBoundsInGrid; + + /** + * The list of area bound shapes to clip against. + */ + private HashMap faAreaBounds; + + private HashMap faAreaBoundsInGrid; + + /** + * The list of extended area bound shapes to clip against. + */ + private HashMap faAreaXBounds; + + private HashMap faAreaXBoundsInGrid; + + /** + * The list of state bound shapes to clip against. + */ + private HashMap stateBounds; + + private HashMap stateBoundsInGrid; + + /** + * The list of great lake shapes to clip against. + */ + private HashMap greatLakesBounds; + + private HashMap greatLakesBoundsInGrid; + + /** + * The list of great lake shapes to clip against. + */ + private HashMap coastalWaterBounds; + + private HashMap coastalWaterBoundsInGrid; + + /** + * The list of region bound shapes to clip against. + */ + private HashMap faRegionCommBounds; + + private HashMap faRegionCommBoundsInGrid; + + /** + * The list of region bound shapes to clip against. + */ + private HashMap faAreaXCommBounds; + + private HashMap faAreaXCommBoundsInGrid; + + /** State list that allows MT_OBSC */ + private static Document mtObscTbl = null; + + /** XPATH for states in document */ + public static String MTOBSC_XPATH = "/MT_OBSC"; + + /** State list that allows MT_OBSC */ + private static List mtObscStates = null; + + /** State list that allows MT_OBSC */ + private static final int NEW_POINT = 2; + + private static final int BOUND_POINT = 1; + + private static final int ORIGINAL_POINT = 0; + + /** Tie distance for two points in map coord */ + private static final double SMALLF = (0.01); + + /** + * Private constructor, we only need to read the database once. + */ + private GfaClip() { + geometryFactory = new GeometryFactory(); + } + + /** + * Singleton instance. * - * It is assumed that the first point is not repeated at the end - * in the input array of point. - * - * @param points array of points * @return */ - public Polygon pointsToPolygon( Coordinate[] points ) { - - Coordinate[] coords = Arrays.copyOf( points, points.length + 1 ); - coords[coords.length - 1] = coords[0]; + public static GfaClip getInstance() { + return instance; + } - CoordinateArraySequence cas = new CoordinateArraySequence( coords ); - LinearRing ring = new LinearRing( cas, geometryFactory ); + /** + * Clips to regions. + * + * @param smear + * @return + */ + public ArrayList simpleclip(Gfa smear) { - Polygon polygon = new Polygon( ring, null, geometryFactory ); - - return polygon; - } + // logger.debug("clipping started"); + + ArrayList list = new ArrayList(); + for (String key : getFaRegionBounds().keySet()) { + Geometry region = faRegionBounds.get(key); + + Polygon polygon = gfaToPolygon(smear); + + Geometry intersection = null; + if (region.intersects(polygon)) { + intersection = region.intersection(polygon); + if (intersection instanceof MultiPolygon) { + MultiPolygon mp = (MultiPolygon) intersection; + for (int i = 0; i < mp.getNumGeometries(); i++) { + Gfa g = geometryToGfa(smear, mp.getGeometryN(i)); + g.addNotToBeSnapped(region.getCoordinates()); + list.add(g); + } + } else { + Gfa g = geometryToGfa(smear, intersection); + g.addNotToBeSnapped(region.getCoordinates()); + list.add(g); + } + } else if (region.covers(polygon)) { + smear.addNotToBeSnapped(region.getCoordinates()); + list.add(smear); + } + } + + return list; + } + + /** + * Generate a JTS polygon from a GFA polygon. + * + * @param gfa + * a GFA element + * @return + */ + public Polygon gfaToPolygon(Gfa gfa) { + if (gfa != null) { + return pointsToPolygon(gfa.getLinePoints()); + } else { + return null; + } + } + + /** + * Generate a JTS polygon in grid coordinate from a GFA polygon. + * + * @param gfa + * a GFA element + * @return + */ + public Polygon gfaToPolygonInGrid(Gfa gfa) { + if (gfa != null) { + return pointsToPolygon(PgenUtil.latlonToGrid(gfa.getLinePoints())); + } else { + return null; + } + } /** * Generate a JTS polygon from a set of points. * - * @param points array of points + * It is assumed that the first point is not repeated at the end in the + * input array of point. + * + * @param points + * array of points * @return */ - public Geometry pointsToGeometry( Coordinate[] points ) { - - Geometry geom; - if ( points == null || points.length == 0 ) { - geom = null; - } - else if ( points.length == 1 ) { - CoordinateArraySequence cas = new CoordinateArraySequence( points ); - geom = new Point( cas, geometryFactory ) ; - } - else if ( points.length == 2 ) { - geom = pointsToLineString( points ); - } - else { - geom = pointsToPolygon( points ); - } - - return geom; - } + public Polygon pointsToPolygon(Coordinate[] points) { - /** + Coordinate[] coords = Arrays.copyOf(points, points.length + 1); + coords[coords.length - 1] = coords[0]; + + CoordinateArraySequence cas = new CoordinateArraySequence(coords); + LinearRing ring = new LinearRing(cas, geometryFactory); + + Polygon polygon = new Polygon(ring, null, geometryFactory); + + return polygon; + } + + /** * Generate a JTS polygon from a set of points. * - * @param pots list of points + * @param points + * array of points * @return */ - public Geometry pointsToGeometry( ArrayList pts ) { - - Coordinate[] points = new Coordinate[ pts.size() ]; - pts.toArray( points ); - - return pointsToGeometry( points ); - } - - + public Geometry pointsToGeometry(Coordinate[] points) { + + Geometry geom; + if (points == null || points.length == 0) { + geom = null; + } else if (points.length == 1) { + CoordinateArraySequence cas = new CoordinateArraySequence(points); + geom = new Point(cas, geometryFactory); + } else if (points.length == 2) { + geom = pointsToLineString(points); + } else { + geom = pointsToPolygon(points); + } + + return geom; + } + + /** + * Generate a JTS polygon from a set of points. + * + * @param pots + * list of points + * @return + */ + public Geometry pointsToGeometry(ArrayList pts) { + + Coordinate[] points = new Coordinate[pts.size()]; + pts.toArray(points); + + return pointsToGeometry(points); + } + /** * Generate a JTS LineString from a set of points. * - * @param points array of points + * @param points + * array of points * @return */ - public Geometry pointsToLineString( Coordinate[] points ) { - - CoordinateArraySequence cas = new CoordinateArraySequence( points ); - - return new LineString( cas, geometryFactory ); - } - - /** - * Create a new GFA from an input GFA with points in a given Geometry. - * - * Note: the input geometry should not have holes in it. - * - * @param gfaIn - * @param geomIn - * @return - */ - public Gfa geometryToGfa( Gfa gfaIn, Geometry geomIn ) { - - Coordinate[] c = geomIn.getCoordinates(); - ArrayList coor = new ArrayList(); - - coor.addAll( Arrays.asList( c ) ); - coor.remove( coor.size() - 1 ); // remove last - - Gfa g = gfaIn.copy(); - - g.setPoints( coor ); - g.setGfaTextCoordinate( g.getCentroid() ); - - return g; - } + public Geometry pointsToLineString(Coordinate[] points) { - /** - * Creates the bounds polygon. - * - * @throws VizException - */ - private void readFaRegionBounds() throws VizException { - faRegionBounds = new HashMap(); - for ( FARegion fa : PgenStaticDataProvider.getProvider().getFARegions()){ - faRegionBounds.put(fa.getRegion(), fa.getGeometry()); - } - loadFaRegionCommBounds(); - } - - /** - * Creates the FA area bounds polygon. - * - * @throws VizException - */ - private void readFaAreaBounds() throws VizException { - faAreaBounds = new HashMap(); - for ( FAArea fa : PgenStaticDataProvider.getProvider().getFAAreas()){ - faAreaBounds.put(fa.getArea(), fa.getGeometry()); - } - } - - /** - * Creates the extended FA area bounds polygon. - * - * @throws VizException - */ - private void readFaAreaXBounds() throws VizException { - faAreaXBounds = new HashMap(); - for ( FAArea fa : PgenStaticDataProvider.getProvider().getFAAreaX()){ - faAreaXBounds.put(fa.getArea(), fa.getGeometry()); - } - } - - /** - * Creates the state bounds polygon - only include States used for GFA. - * - * @throws VizException - */ - private void readStateBounds() throws VizException { - // TODO change to use SCHEMA, DATABASE, and STATE_BNDS_TABLE -// String sql = "select t.state, AsBinary(t.the_geom) from mapdata.states t"; -// String sql = "select t.state, AsBinary(t.the_geom_0) from mapdata.states t"; -// String sql = "select t.state, AsBinary(t.the_geom_0_001) from mapdata.states t"; -// String sql = "select t.state, AsBinary(t.the_geom_0_004) from mapdata.states t"; -// String sql = "select t.state, AsBinary(t.the_geom_0_016) from mapdata.states t"; -// String sql = "select t.state, AsBinary(t.the_geom_0_064) from mapdata.states t"; - -// long l1 = System.currentTimeMillis(); -// stateBounds = readBounds( "maps", sql ); -// System.out.println("Time to load state bounds = " + (System.currentTimeMillis() - l1 ) ); + CoordinateArraySequence cas = new CoordinateArraySequence(points); - - HashMap originalStateBounds = new HashMap(); - - for ( USState st : PgenStaticDataProvider.getProvider().getAllstates()){ - originalStateBounds.put(st.getStateAbrv(), st.getShape()); - } - - //Exclude a few states. - for ( String s : EXCLUDE_STATES ) { - originalStateBounds.remove( s ); - } - - stateBounds = fixStateBounds( originalStateBounds ); - - } - - /** - * Creates the great Lakes bounds polygon. - * - * @throws VizException - */ - private void readGreatLakeBounds() throws VizException { - greatLakesBounds = new HashMap(); - for ( GreatLake lake : PgenStaticDataProvider.getProvider().getGreatLakes()){ - greatLakesBounds.put(lake.getId(), lake.getGeometry()); - } - } - - /** - * Creates the coastal water bounds polygon. - * - * @throws VizException - */ - private void readCoastalWaterBounds() throws VizException { - coastalWaterBounds = new HashMap(); - for ( CostalWater water : PgenStaticDataProvider.getProvider().getCostalWaters()){ - coastalWaterBounds.put(water.getId(), water.getGeometry()); - } - } + return new LineString(cas, geometryFactory); + } - /** - * Load FA Region bounds into a HashMap (West, Central, East) - * @return - */ - public HashMap getFaRegionBounds() { - if ( faRegionBounds == null ){ - try { - readFaRegionBounds(); - } catch ( VizException e) { -// logger.error("Error ", e); - e.printStackTrace(); - } - } - - return faRegionBounds; - } + /** + * Create a new GFA from an input GFA with points in a given Geometry. + * + * Note: the input geometry should not have holes in it. + * + * @param gfaIn + * @param geomIn + * @return + */ + public Gfa geometryToGfa(Gfa gfaIn, Geometry geomIn) { - /** - * Load FA Area bounds into a HashMap (SLC, SFO, CHI, DFW, BOS, MIA) - * @return - */ - public HashMap getFaAreaBounds() { - if ( faAreaBounds == null ) { - try { - readFaAreaBounds(); - } catch ( VizException e ) { -// logger.error("Error ", e); - e.printStackTrace(); - } - } - - return faAreaBounds; - } + Coordinate[] c = geomIn.getCoordinates(); + ArrayList coor = new ArrayList(); - /** - * Load extended FA Area bounds into a HashMap (SLC, SFO, CHI, DFW, BOS, MIA) - * @return - */ - public HashMap getFaAreaXBounds() { - if ( faAreaXBounds == null ) { - try { - readFaAreaXBounds(); - } catch ( VizException e ) { -// logger.error("Error ", e); - e.printStackTrace(); - } - } + coor.addAll(Arrays.asList(c)); + coor.remove(coor.size() - 1); // remove last - return faAreaXBounds; - } + Gfa g = gfaIn.copy(); - /** - * Load state bounds into a HashMap keyed by state name - * - * @return - */ - public HashMap getStateBounds() { - if ( stateBounds == null ) { - try { - readStateBounds(); - } catch ( VizException e ) { -// logger.error("Error ", e); - e.printStackTrace(); - } - } - - return stateBounds; - } - - /** - * Load Great Lake bounds into a HashMap - * @return - */ - public HashMap getGreatLakeBounds() { - if ( greatLakesBounds == null ) { - try { - readGreatLakeBounds(); - } catch ( VizException e) { -// logger.error("Error ", e); - e.printStackTrace(); - } - } - - return greatLakesBounds; - } - - /** - * Load Coastal Water bounds into a HashMap - * @return - */ - public HashMap getCoastalWaterBounds() { - if ( coastalWaterBounds == null ) { - try { - readCoastalWaterBounds(); - } catch ( VizException e ) { -// logger.error("Error ", e); - e.printStackTrace(); - } - } - - return coastalWaterBounds; - } - - /** - * Create a union of three FA Region bounds (international bound) - * @return - */ - public Geometry getFaInternationalBound() { - - if ( faInternationalBound == null ) { - ArrayList rbnds = new ArrayList( getFaRegionBounds().values() ); - faInternationalBound = quickUnion( rbnds ); - } + g.setPoints(coor); + g.setGfaTextCoordinate(g.getCentroid()); - return faInternationalBound; - } - - /** - * Create a union of a list of Geometries. - * - * This method uses GeometryCollection's buffer method to union - * a collection of Geometries, which is believed to be faster than - * using Geometry's union method to union geometries one by one, - * according to JTS documentation. - * - * @param geoms A list of geometries - * @return - */ - public Geometry quickUnion( ArrayList geoms ) { - - if ( geoms.size() <= 0 ) return null; - - Geometry[] regs = new Geometry[ geoms.size() ]; - regs = geoms.toArray( regs ); - - GeometryCollection gc = new GeometryCollection( regs, geometryFactory ); - - return gc.buffer( 0.0 ); - - } + return g; + } - - /** - * Clip to FA regions. - * - * This routine clips a non-FZLVL GFA airmet/outlook against FA region + /** + * Creates the bounds polygon. + * + * @throws VizException + */ + private void readFaRegionBounds() throws VizException { + faRegionBounds = new HashMap(); + for (FARegion fa : PgenStaticDataProvider.getProvider().getFARegions()) { + faRegionBounds.put(fa.getRegion(), fa.getGeometry()); + } + loadFaRegionCommBounds(); + } + + /** + * Creates the FA area bounds polygon. + * + * @throws VizException + */ + private void readFaAreaBounds() throws VizException { + faAreaBounds = new HashMap(); + for (FAArea fa : PgenStaticDataProvider.getProvider().getFAAreas()) { + faAreaBounds.put(fa.getArea(), fa.getGeometry()); + } + } + + /** + * Creates the extended FA area bounds polygon. + * + * @throws VizException + */ + private void readFaAreaXBounds() throws VizException { + faAreaXBounds = new HashMap(); + for (FAArea fa : PgenStaticDataProvider.getProvider().getFAAreaX()) { + faAreaXBounds.put(fa.getArea(), fa.getGeometry()); + } + } + + /** + * Creates the state bounds polygon - only include States used for GFA. + * + * @throws VizException + */ + private void readStateBounds() throws VizException { + // TODO change to use SCHEMA, DATABASE, and STATE_BNDS_TABLE + // String sql = + // "select t.state, AsBinary(t.the_geom) from mapdata.states t"; + // String sql = + // "select t.state, AsBinary(t.the_geom_0) from mapdata.states t"; + // String sql = + // "select t.state, AsBinary(t.the_geom_0_001) from mapdata.states t"; + // String sql = + // "select t.state, AsBinary(t.the_geom_0_004) from mapdata.states t"; + // String sql = + // "select t.state, AsBinary(t.the_geom_0_016) from mapdata.states t"; + // String sql = + // "select t.state, AsBinary(t.the_geom_0_064) from mapdata.states t"; + + // long l1 = System.currentTimeMillis(); + // stateBounds = readBounds( "maps", sql ); + // System.out.println("Time to load state bounds = " + + // (System.currentTimeMillis() - l1 ) ); + + HashMap originalStateBounds = new HashMap(); + + for (USState st : PgenStaticDataProvider.getProvider().getAllstates()) { + originalStateBounds.put(st.getStateAbrv(), st.getShape()); + } + + // Exclude a few states. + for (String s : EXCLUDE_STATES) { + originalStateBounds.remove(s); + } + + stateBounds = fixStateBounds(originalStateBounds); + + } + + /** + * Creates the great Lakes bounds polygon. + * + * @throws VizException + */ + private void readGreatLakeBounds() throws VizException { + greatLakesBounds = new HashMap(); + for (GreatLake lake : PgenStaticDataProvider.getProvider() + .getGreatLakes()) { + greatLakesBounds.put(lake.getId(), lake.getGeometry()); + } + } + + /** + * Creates the coastal water bounds polygon. + * + * @throws VizException + */ + private void readCoastalWaterBounds() throws VizException { + coastalWaterBounds = new HashMap(); + for (CostalWater water : PgenStaticDataProvider.getProvider() + .getCostalWaters()) { + coastalWaterBounds.put(water.getId(), water.getGeometry()); + } + } + + /** + * Load FA Region bounds into a HashMap (West, Central, East) + * + * @return + */ + public HashMap getFaRegionBounds() { + if (faRegionBounds == null) { + try { + readFaRegionBounds(); + } catch (VizException e) { + // logger.error("Error ", e); + e.printStackTrace(); + } + } + + return faRegionBounds; + } + + /** + * Load FA Area bounds into a HashMap (SLC, SFO, CHI, DFW, BOS, MIA) + * + * @return + */ + public HashMap getFaAreaBounds() { + if (faAreaBounds == null) { + try { + readFaAreaBounds(); + } catch (VizException e) { + // logger.error("Error ", e); + e.printStackTrace(); + } + } + + return faAreaBounds; + } + + /** + * Load extended FA Area bounds into a HashMap (SLC, SFO, CHI, DFW, BOS, + * MIA) + * + * @return + */ + public HashMap getFaAreaXBounds() { + if (faAreaXBounds == null) { + try { + readFaAreaXBounds(); + } catch (VizException e) { + // logger.error("Error ", e); + e.printStackTrace(); + } + } + + return faAreaXBounds; + } + + /** + * Load state bounds into a HashMap keyed by state name + * + * @return + */ + public HashMap getStateBounds() { + if (stateBounds == null) { + try { + readStateBounds(); + } catch (VizException e) { + // logger.error("Error ", e); + e.printStackTrace(); + } + } + + return stateBounds; + } + + /** + * Load Great Lake bounds into a HashMap + * + * @return + */ + public HashMap getGreatLakeBounds() { + if (greatLakesBounds == null) { + try { + readGreatLakeBounds(); + } catch (VizException e) { + // logger.error("Error ", e); + e.printStackTrace(); + } + } + + return greatLakesBounds; + } + + /** + * Load Coastal Water bounds into a HashMap + * + * @return + */ + public HashMap getCoastalWaterBounds() { + if (coastalWaterBounds == null) { + try { + readCoastalWaterBounds(); + } catch (VizException e) { + // logger.error("Error ", e); + e.printStackTrace(); + } + } + + return coastalWaterBounds; + } + + /** + * Create a union of three FA Region bounds (international bound) + * + * @return + */ + public Geometry getFaInternationalBound() { + + if (faInternationalBound == null) { + ArrayList rbnds = new ArrayList( + getFaRegionBounds().values()); + faInternationalBound = quickUnion(rbnds); + } + + return faInternationalBound; + } + + /** + * Create a union of a list of Geometries. + * + * This method uses GeometryCollection's buffer method to union a collection + * of Geometries, which is believed to be faster than using Geometry's union + * method to union geometries one by one, according to JTS documentation. + * + * @param geoms + * A list of geometries + * @return + */ + public Geometry quickUnion(ArrayList geoms) { + + if (geoms.size() <= 0) + return null; + + Geometry[] regs = new Geometry[geoms.size()]; + regs = geoms.toArray(regs); + + GeometryCollection gc = new GeometryCollection(regs, geometryFactory); + + return gc.buffer(0.0); + + } + + /** + * Clip to FA regions. + * + * This routine clips a non-FZLVL GFA airmet/outlook against FA region * boundaries to generates a list of clipped smears. * * The algorithm is as following: * - * 1. Check if the smear is big enough ( >= 3K sq. nautical miles ) - * 2. Clip against the international boundary and check if the intersection is big enough - * 3. Clip against FA region boundaries - - * 3.1 clip the smear polygon against international boundary. - * 3.2 clip the result against each FA region (WEST, CENTRAL, EAST) - * 3.3 create a list of parts bigger than/equal to 3K for each region - * 3.4 hold the parts smaller than 3K for all regions in another list. - * 4. Create smears from VALID parts and add into the return list - * 4.1 Union the parts in each FA region with the list of small parts - - * If a small part touches one of the bigs (only one, I believe), it - * will be united into that big and thus be included into a new - * smear. So no part gets lost and all will be included eventually. - * 4.2 Check the resulting union for VALID geometries and create new - * smears for each of them. - * - * A VALID geometry is one that - * a. is large enough ( >= 3K sq. nautical miles ) - * b. intersects at least one of its associated snapshots (from - * which the smear polygon is generated) with an area >= 3K. - * c. intersects snapshot "6" with an area >= 3K, if it is a "6-6" smear - * and there are snapshots associated with it. - * - * @param smear the GFA smear to be clipped - * @param snapshots snapshots from where the input smear is created - * @return a list of clipped GFA smears. - */ - public ArrayList clipFARegions( Gfa smear, ArrayList snapshots ) { - - ArrayList clippedList = new ArrayList(); - if ( smear.getGfaHazard().equals( "FZLVL" ) ) { - return clippedList; - } - - /* - * If the smear size < AREA_LIMIT, stop. - */ - if ( !isBiggerInMap( gfaToPolygon( smear ) ) ) { - return clippedList; - } - - /* - * Do international clipping (in grid coordinate) - */ - boolean _clippingFlg = true; - - Geometry intlBound = getFaInternationalBound(); - Geometry intlBoundInGrid = getFaInternationalBoundInGrid() ; - - Polygon smearPoly = gfaToPolygon( smear ); - Polygon smearPolyInGrid = pointsToPolygon( PgenUtil.latlonToGrid( smear.getLinePoints() ) ); - - Geometry clipAgstIntlBnd = null; - - if ( smearPolyInGrid.intersects( intlBoundInGrid ) ) { - clipAgstIntlBnd = smearPolyInGrid.intersection( intlBoundInGrid ); - } - - if ( clipAgstIntlBnd == null || clipAgstIntlBnd.getNumGeometries() <= 0 || - !isBiggerInGrid( clipAgstIntlBnd ) ) { - return clippedList; - } - - - /* - * Find intersection points with the international bound and the common borders - * between West and Central, Central and East regions. Then insert and snap them - * for later replacement. - */ - HashMap intlPts = getIntlIntersectionPt( smearPoly, intlBound, clipAgstIntlBnd ); - - HashMap regionInterPts = getRegionIntersectionPt( smearPoly ); - - /* - * Build a list of non-reduce-able point, include all bound points and snapped - * intersection points - */ - HashMap rgbnds = getFaRegionBounds(); - HashMap rgbndsInGrid = getFaRegionBoundsInGrid(); - - CoordinateList nonReduceable = new CoordinateList(); - nonReduceable.addAll( intlPts.values(), false ); - nonReduceable.addAll( regionInterPts.values(), false ); - for ( Geometry gb : rgbnds.values() ) { - nonReduceable.addAll( Arrays.asList( gb.getCoordinates() ), false ); - } - - - //Build a map of all replaceable points - HashMap replacePts = new HashMap(); - replacePts.putAll( intlPts ); - replacePts.putAll( regionInterPts ); - - /* - * Regional clipping as following: - * - * 1. clip the smear polygon against international boundary. - * 2. clip the result against each FA region (WEST, CENTRAL, EAST) - * 3. create a list of parts bigger than/equal to 3K for each region - * 4. hold the parts smaller than 3K for all regions in another list. - */ - HashMap > clipWithRegions = new HashMap >(); - - ArrayList smallPoly = new ArrayList(); - - for ( String regionName : rgbnds.keySet() ) { - - clipWithRegions.put( regionName, new ArrayList() ); - - // Always start from the smear clipped within international bound - Geometry startPoly = intlBoundInGrid.intersection( smearPolyInGrid ); - - //Do regional clipping as described above. - if ( _clippingFlg ) { - - Geometry regionBnd = rgbndsInGrid.get( regionName ); - - if ( regionBnd.intersects( startPoly ) ) { - Geometry regionPoly = regionBnd.intersection( startPoly ); - - if ( regionPoly != null ) { - - for ( int kk = 0; kk < regionPoly.getNumGeometries(); kk++ ) { - Geometry bigPoly = regionPoly.getGeometryN( kk ); - - if ( isBiggerInGrid( bigPoly ) ) { - clipWithRegions.get( regionName ).add( bigPoly ); - } - else { - smallPoly.add( bigPoly ); - } - } - } - } - } - } - - /* - * Create smears from VALID parts and add into the return list - * - * 1. Union the parts in each FA region with the list of small parts - - * If a small part touches one of the bigs (only one, I believe), it - * will be united into that big and thus be included into a new - * smear. So no part gets lost and all will be included eventually. - * 2. When a small part is united into a big one (if they intersect), - * the common points are still retained in the result, we need to - * remove those extra point. The common points are resulted from the - * previous clipping with the regional boundaries. - * 3. check the resulting union for VALID geometries and create new - * smears for each of them. - */ - for ( String regionName : clipWithRegions.keySet() ) { - - ArrayList bigs = clipWithRegions.get( regionName ); - - ArrayList toBeUnioned = new ArrayList(); - toBeUnioned.addAll( bigs ); - toBeUnioned.addAll( smallPoly ); - Geometry result = quickUnion( toBeUnioned ); - - ArrayList commPts = getCommonPoints( bigs, smallPoly ); - - if ( result != null ) { - for ( int kk = 0; kk < result.getNumGeometries(); kk++ ) { - - Geometry one = result.getGeometryN( kk ); - - /* - * Remove residue points due to clipping followed by subsequent union. - * Done in grid coordinate. - */ - Geometry onePart = removeCommonPoints( one, commPts ); - - /* - * Clean up some improper cases - done in MAP coordinate. - */ - Coordinate[] gPts = PgenUtil.gridToLatlon( onePart.getCoordinates() ); - ArrayList points = new ArrayList(); - for ( Coordinate c : gPts ) { - points.add( c ); - } - points.remove( points.size() - 1 ); - - Geometry cleanPts = cleanupPoints( pointsToGeometry( points ) ); - - if ( isAddableAsSmear( cleanPts, snapshots, smear ) ) { - - //Replace intersection points with their pre-snapped pair - map - Geometry rplPts = replacePts( cleanPts, replacePts ); - - //Clean up duplicate point from point replacement - map - Geometry finalPts = cleanupPoints( rplPts ); - - if ( finalPts != null ) { - //Create a new GFA smear. - Gfa newElm = geometryToGfa( smear, finalPts ); - - //Mark non-reduce-able points. - addReduceFlags( newElm, nonReduceable ); - - newElm.addAttribute( "FA_REGION", new String(regionName) ); - - clippedList.add( newElm ); - } - } - } - } - - } - - return clippedList; - } - - - /** - * Check if a polygon is valid to be added as a new smear: - * - * Note: the input geometry is assumed to be in map coordinate. - * - * 1. it must be large enough ( >= 3K sq. nautical miles ) - * 2. it must intersect at least one of its associated snapshots (from - * which the smear polygon is generated) with an area >= 3K. - * 3. if it is "6-6" smear, it must intersect snapshot "6" with an - * area >= 3K. - * - * @param g A Geometry (polygon) in map coordinate. - * @param snapshots A list of associated snapshots - * @param smear Original GFA smear - * @return - */ - public boolean isAddableAsSmear( Geometry g, ArrayList snapshots, Gfa smear ) { - - return ( isBiggerInMap( g ) && - passed6_6Rule( g, snapshots, smear ) && - intersectBigWithSS( g, snapshots ) ) ; - - } - - - /** - * Check if a polygon intersects at least one of the snapshots with an area >= 3K. - * - * Note: the input is assumed in MAP coordinate. - * - * @param g A Geometry (polygon) - * @param snapshots A list of associated snapshots - * @return - */ - private boolean intersectBigWithSS( Geometry g, ArrayList snapshots ) { - - boolean addable = false; - - if ( snapshots == null || snapshots.size() <= 0 ) { - addable = true; - } - else { - Coordinate[] pts = PgenUtil.latlonToGrid( g.getCoordinates() ); - Geometry poly = pointsToGeometry( pts ); - for ( Gfa ss : snapshots ) { - if ( isBiggerInGrid( poly.intersection( gfaToPolygonInGrid( ss ) ) ) ) { - addable = true; - break; - } - } - } - - return addable; - - } - - /** - * Check if a 6-6 polygon intersect snapshot "6" with an area >= 3K. - * - * Note: if the smear is not a "6-6" smear or no snapshots, return true. - * if there are snapshots but no snapshot "6" somehow, return false; - * - * @param g A Geometry (polygon) - * @param snapshots A list of associated snapshots - * @return - */ - private boolean passed6_6Rule ( Geometry g, ArrayList snapshots, Gfa smear ) { - - boolean addable = true; - - if ( snapshots != null && snapshots.size() > 0 && - smear.getForecastHours().equals( "6-6" ) ) { - - Gfa ss_6 = null; - - for ( Gfa ss : snapshots ) { - if ( ss.getForecastHours().equals( "6" ) ) { - ss_6 = ss; - break; - } - } - - if ( ss_6 == null ) { - addable = false; - } - - if ( addable ) { - Coordinate[] pts = PgenUtil.latlonToGrid( g.getCoordinates() ); - Geometry poly = pointsToGeometry( pts ); - if ( !isBiggerInGrid( poly.intersection( gfaToPolygonInGrid( ss_6 ) ) ) ) { - addable = false; - } - } - - } - - return addable; - - } - - /** - * Check if a polygon is bigger than a value in unit of sq. nautical miles. - * @param g A Geometry - * @return - */ - private boolean isBigger( Geometry g, double limit ) { - return ( g != null && PgenUtil.getSphPolyArea( g ) >= limit ); - } - - /** - * Check if a polygon is bigger than the GFA AREA_LIMIT (3K sq. nautical miles). - * - * @param g A Geometry - * @return - */ - public boolean isBiggerInMap( Geometry g ) { - - return isBigger( g, GfaRules.AREA_LIMIT ); - - } - - /** - * Check if a polygon is bigger than the GFA AREA_LIMIT (3K sq. nautical miles). - * - * Note: the input is assumed to be in grid coordinate, not map coordinate. - * - * @param g A Geometry - * @return - */ - public boolean isBiggerInGrid( Geometry g ) { - - double area = 0.0; - if ( g instanceof Polygon ) { - area = PgenUtil.getSphPolyAreaInGrid( (Polygon)g ); - } else if ( g instanceof MultiPolygon ) { - MultiPolygon mp = (MultiPolygon)g; - for( int nn = 0; nn < mp.getNumGeometries(); nn++ ) { - area += PgenUtil.getSphPolyAreaInGrid( (Polygon)mp.getGeometryN( nn ) ); - } - } - - return ( area >= GfaRules.AREA_LIMIT ) ? true : false; - - } - - - /** - * Get a list of states that allows MT_OBSC hazard. - * @param - * @return - */ - public List getMtObscStates(){ - - if ( mtObscStates == null ) { - mtObscStates = new ArrayList(); - String xpath = MTOBSC_XPATH; - - Document dm = readMtObscTbl(); - - if ( dm != null ) { - Node mtObscInfo = dm.selectSingleNode(xpath); - List nodes = mtObscInfo.selectNodes( "area" ); - for (Node node : nodes) { - node.selectNodes("state"); - for ( Object nd : node.selectNodes("state") ) { - mtObscStates.add( ((Node)nd).getText() ); - } - } - } - } - - return mtObscStates; - } - - /** - * Read mt_obsc_states.xml - * @return - document - */ - private static Document readMtObscTbl() { - - if ( mtObscTbl == null) { - try { - String mtObscFile = PgenStaticDataProvider.getProvider().getFileAbsolutePath( - PgenStaticDataProvider.getProvider().getPgenLocalizationRoot() + "mt_obsc_states.xml"); - - SAXReader reader = new SAXReader(); - mtObscTbl = reader.read( mtObscFile ); - } catch ( Exception e ) { - e.printStackTrace(); - } - } - - return mtObscTbl; - } - - - /** - * This routine clips a GFA polygon against the international bound and - * finds the intersection points of the GFA polygon with the bound. - * Then the intersection points are snapped individually to points - * outside of the Clipped GFA polygon. Both the intersection points and - * their snapped matches are returned in map coordinate. - * - * The input is assumed to be in MAP coordinate. - * - * @param gfaPoly Polygon from GFA - * @param bndPoly Polygon of international boundary - * @param clipped Intersection Polygon of international boundary - * with the GFA polygon (in grid coordinate) - * + * 1. Check if the smear is big enough ( >= 3K sq. nautical miles ) 2. Clip + * against the international boundary and check if the intersection is big + * enough 3. Clip against FA region boundaries - 3.1 clip the smear polygon + * against international boundary. 3.2 clip the result against each FA + * region (WEST, CENTRAL, EAST) 3.3 create a list of parts bigger than/equal + * to 3K for each region 3.4 hold the parts smaller than 3K for all regions + * in another list. 4. Create smears from VALID parts and add into the + * return list 4.1 Union the parts in each FA region with the list of small + * parts - If a small part touches one of the bigs (only one, I believe), it + * will be united into that big and thus be included into a new smear. So no + * part gets lost and all will be included eventually. 4.2 Check the + * resulting union for VALID geometries and create new smears for each of + * them. + * + * A VALID geometry is one that a. is large enough ( >= 3K sq. nautical + * miles ) b. intersects at least one of its associated snapshots (from + * which the smear polygon is generated) with an area >= 3K. c. intersects + * snapshot "6" with an area >= 3K, if it is a "6-6" smear and there are + * snapshots associated with it. + * + * @param smear + * the GFA smear to be clipped + * @param snapshots + * snapshots from where the input smear is created + * @return a list of clipped GFA smears. */ - private HashMap getIntlIntersectionPt( Geometry gfaPoly, - Geometry bndPoly, Geometry clipped ) - { - HashMap interPts = new HashMap(); - - //Get points in clockwise order - do not repeat the first point at the end. - Coordinate[] pts = clipped.getGeometryN( 0 ).getCoordinates(); - Coordinate[] intlPoly = PgenUtil.gridToLatlon( pts ); - ArrayList intlList = new ArrayList(); - intlList.addAll( Arrays.asList( intlPoly ) ); - intlList.remove( intlList.size() - 1 ); - ArrayList cwPoly = GfaSnap.getInstance().reorderInClockwise( intlList , null ); + public ArrayList clipFARegions(Gfa smear, ArrayList snapshots) { + + ArrayList clippedList = new ArrayList(); + if (smear.getGfaHazard().equals("FZLVL")) { + return clippedList; + } /* - * Check out each point as either a new point, an international boundary point, - * or a point of the original polygon. - */ - int[] ptFlag = new int[ cwPoly.size() ]; - for ( int ii = 0; ii < cwPoly.size(); ii++ ) { - - ptFlag[ ii ] = NEW_POINT; - - for ( Coordinate bndc : bndPoly.getCoordinates() ) { - if ( isSamePoint( bndc, cwPoly.get( ii ), SMALLF ) ) { - ptFlag[ ii ] = BOUND_POINT; - break; - } - } - - if ( ptFlag[ ii ] != NEW_POINT ) continue; - - for ( Coordinate orgc : gfaPoly.getCoordinates() ) { - if ( isSamePoint( orgc, cwPoly.get( ii ), SMALLF ) ) { - ptFlag[ ii ] = ORIGINAL_POINT; - break; - } - } + * If the smear size < AREA_LIMIT, stop. + */ + if (!isBiggerInMap(gfaToPolygon(smear))) { + return clippedList; } - //Shift the array to let it start with an original point. - int eflag; - while ( ptFlag[ 0 ] != ORIGINAL_POINT ) { - - cwPoly = GfaSnap.getInstance().shiftArray( cwPoly ); - - eflag = ptFlag[ 0 ]; - for ( int jj = 0; jj < (ptFlag.length - 1); jj++ ) { - ptFlag[ jj ] = ptFlag[ jj + 1 ]; - } - - ptFlag[ ptFlag.length - 1 ] = eflag; - - } - - - //Snap and match any new points. - int snap_indx1; - int snap_indx2; - int status; - int np = cwPoly.size(); - Coordinate[] snapPt = new Coordinate[1]; - - ArrayList usedPts = new ArrayList(); - usedPts.addAll( cwPoly ); - - for ( int ii = 0; ii < cwPoly.size(); ii++ ) { - - if ( ptFlag[ ii ] != NEW_POINT ) { - continue; - } - - /* - * Handle NN case - a "small" triangle may be cut off when the smear intersects - * the international boundary. The two new close points by the intersection - * should be replaced by the original point in the smear. - */ - if ( (ii + 1) < cwPoly.size() ) { - if ( ptFlag[ ii + 1 ] == NEW_POINT && - GfaSnap.getInstance().isCluster( cwPoly.get( ii ), cwPoly.get( ii + 1 ) ) ) { - - int ptBefore = (ii - 1 + cwPoly.size() ) % cwPoly.size(); - int ptAfter = (ii + 2 + cwPoly.size() ) % cwPoly.size(); - - List gfaPts = Arrays.asList( gfaPoly.getCoordinates() ); - int indInGfa1 = findPoint( cwPoly.get( ptBefore ), gfaPts, SMALLF ); - int indInGfa2 = findPoint( cwPoly.get( ptAfter ), gfaPts, SMALLF ); - - if ( indInGfa1 >= 0 && indInGfa2 >= 0 && - (indInGfa2 - indInGfa1) == 2 ) { - - int indBtw = indInGfa1 + 1; //the original point between - if ( GfaSnap.getInstance().isCluster( cwPoly.get( ii ), gfaPts.get( indBtw ) ) && - GfaSnap.getInstance().isCluster( cwPoly.get( ii + 1 ), gfaPts.get( indBtw ) ) ) { + /* + * Do international clipping (in grid coordinate) + */ + boolean _clippingFlg = true; - interPts.put( cwPoly.get( ii ) , gfaPts.get( indBtw ) ); - interPts.put( cwPoly.get( ii + 1 ) , gfaPts.get( indBtw ) ); + Geometry intlBound = getFaInternationalBound(); + Geometry intlBoundInGrid = getFaInternationalBoundInGrid(); - ii++; //skip these two new points. - continue; - } - } - } - } - - /* - * All other cases - snap the intersection point to a point with a - * clustering distance away and outside the polygon. For clustering - * points, snap them to a single snap point. If fail to snap a cluster - * of points, try to snap them individually. - * - */ - snap_indx1 = ii; - snap_indx2 = ii; - - while ( snap_indx1 > 0 && - GfaSnap.getInstance().isCluster( cwPoly.get( ii ), - cwPoly.get( snap_indx1-1 ) ) ) { - snap_indx1--; - } - - while ( snap_indx2 < ( np - 1 ) && - GfaSnap.getInstance().isCluster( cwPoly.get( ii ), - cwPoly.get( snap_indx2+1 ) ) ) { - snap_indx2++; - } + Polygon smearPoly = gfaToPolygon(smear); + Polygon smearPolyInGrid = pointsToPolygon(PgenUtil.latlonToGrid(smear + .getLinePoints())); - status = GfaSnap.getInstance().snapPtGFA( snap_indx1, snap_indx2, - usedPts, null, cwPoly, true, true, 3.0F, snapPt ); - + Geometry clipAgstIntlBnd = null; - if ( status != 0 && ( snap_indx1 != snap_indx2 ) ) { - - snap_indx1 = ii; - snap_indx2 = ii; - - status = GfaSnap.getInstance().snapPtGFA( snap_indx1, snap_indx2, - usedPts, null, cwPoly, true, true, 3.0F, snapPt ); - } - - // Snap failed - use the original point. - if ( status != 0 ) { - snapPt[ 0 ].x = cwPoly.get( ii ).x; - snapPt[ 0 ].y = cwPoly.get( ii ).y; - } - - /* - * Pair the intersection point with its snapped counterpart. - * Also replace the intersection points with the snapped ones - * for snapping the next one. - */ - for ( int jj = snap_indx1; jj <= snap_indx2; jj++ ) { - interPts.put( cwPoly.get( jj ), snapPt[ 0 ] ); -// cwPoly.set( jj, new Coordinate( snapPt[ 0 ] ) );; - } - - ii += ( snap_indx2 - snap_indx1 ); //added to skip duplicate calculation. - - usedPts.add( snapPt[ 0 ] ); - + if (smearPolyInGrid.intersects(intlBoundInGrid)) { + clipAgstIntlBnd = smearPolyInGrid.intersection(intlBoundInGrid); } - - return interPts; - - } - - /** - * Check if two pints are within a given tie distance. If so, they are - * considered as the same point. - */ - private boolean isSamePoint( Coordinate p1, Coordinate p2, double tieDist ) { - - boolean sameP = false; - if ( p1 != null && p2 != null && - Math.abs( p1.x - p2.x ) < Math.abs( tieDist ) && - Math.abs( p1.y - p2.y ) < Math.abs( tieDist ) ) { - sameP = true; - } - - return sameP; - } - + + if (clipAgstIntlBnd == null || clipAgstIntlBnd.getNumGeometries() <= 0 + || !isBiggerInGrid(clipAgstIntlBnd)) { + return clippedList; + } + + /* + * Find intersection points with the international bound and the common + * borders between West and Central, Central and East regions. Then + * insert and snap them for later replacement. + */ + HashMap intlPts = getIntlIntersectionPt( + smearPoly, intlBound, clipAgstIntlBnd); + + HashMap regionInterPts = getRegionIntersectionPt(smearPoly); + + /* + * Build a list of non-reduce-able point, include all bound points and + * snapped intersection points + */ + HashMap rgbnds = getFaRegionBounds(); + HashMap rgbndsInGrid = getFaRegionBoundsInGrid(); + + CoordinateList nonReduceable = new CoordinateList(); + nonReduceable.addAll(intlPts.values(), false); + nonReduceable.addAll(regionInterPts.values(), false); + for (Geometry gb : rgbnds.values()) { + nonReduceable.addAll(Arrays.asList(gb.getCoordinates()), false); + } + + // Build a map of all replaceable points + HashMap replacePts = new HashMap(); + replacePts.putAll(intlPts); + replacePts.putAll(regionInterPts); + + /* + * Regional clipping as following: + * + * 1. clip the smear polygon against international boundary. 2. clip the + * result against each FA region (WEST, CENTRAL, EAST) 3. create a list + * of parts bigger than/equal to 3K for each region 4. hold the parts + * smaller than 3K for all regions in another list. + */ + HashMap> clipWithRegions = new HashMap>(); + + ArrayList smallPoly = new ArrayList(); + + for (String regionName : rgbnds.keySet()) { + + clipWithRegions.put(regionName, new ArrayList()); + + // Always start from the smear clipped within international bound + Geometry startPoly = intlBoundInGrid.intersection(smearPolyInGrid); + + // Do regional clipping as described above. + if (_clippingFlg) { + + Geometry regionBnd = rgbndsInGrid.get(regionName); + + if (regionBnd.intersects(startPoly)) { + Geometry regionPoly = regionBnd.intersection(startPoly); + + if (regionPoly != null) { + + for (int kk = 0; kk < regionPoly.getNumGeometries(); kk++) { + Geometry bigPoly = regionPoly.getGeometryN(kk); + + if (isBiggerInGrid(bigPoly)) { + clipWithRegions.get(regionName).add(bigPoly); + } else { + smallPoly.add(bigPoly); + } + } + } + } + } + } + + /* + * Create smears from VALID parts and add into the return list + * + * 1. Union the parts in each FA region with the list of small parts - + * If a small part touches one of the bigs (only one, I believe), it + * will be united into that big and thus be included into a new smear. + * So no part gets lost and all will be included eventually. 2. When a + * small part is united into a big one (if they intersect), the common + * points are still retained in the result, we need to remove those + * extra point. The common points are resulted from the previous + * clipping with the regional boundaries. 3. check the resulting union + * for VALID geometries and create new smears for each of them. + */ + for (String regionName : clipWithRegions.keySet()) { + + ArrayList bigs = clipWithRegions.get(regionName); + + ArrayList toBeUnioned = new ArrayList(); + toBeUnioned.addAll(bigs); + toBeUnioned.addAll(smallPoly); + Geometry result = quickUnion(toBeUnioned); + + ArrayList commPts = getCommonPoints(bigs, smallPoly); + + if (result != null) { + for (int kk = 0; kk < result.getNumGeometries(); kk++) { + + Geometry one = result.getGeometryN(kk); + + /* + * Remove residue points due to clipping followed by + * subsequent union. Done in grid coordinate. + */ + Geometry onePart = removeCommonPoints(one, commPts); + + /* + * Clean up some improper cases - done in MAP coordinate. + */ + Coordinate[] gPts = PgenUtil.gridToLatlon(onePart + .getCoordinates()); + ArrayList points = new ArrayList(); + for (Coordinate c : gPts) { + points.add(c); + } + points.remove(points.size() - 1); + + Geometry cleanPts = cleanupPoints(pointsToGeometry(points)); + + if (isAddableAsSmear(cleanPts, snapshots, smear)) { + + // Replace intersection points with their pre-snapped + // pair - map + Geometry rplPts = replacePts(cleanPts, replacePts); + + // Clean up duplicate point from point replacement - map + Geometry finalPts = cleanupPoints(rplPts); + + if (finalPts != null) { + // Create a new GFA smear. + Gfa newElm = geometryToGfa(smear, finalPts); + + // Mark non-reduce-able points. + addReduceFlags(newElm, nonReduceable); + + newElm.addAttribute("FA_REGION", new String( + regionName)); + + clippedList.add(newElm); + } + } + } + } + + } + + return clippedList; + } + /** - * This routine clips a GFA polygon against common border between FA regional - * bounds to find the intersection points of the GFA polygon with the bound. - * Then the intersection points are snapped individually to points outside - * of the polygon. Both the intersection points and their snapped matches - * are returned in map coordinate. + * Check if a polygon is valid to be added as a new smear: + * + * Note: the input geometry is assumed to be in map coordinate. + * + * 1. it must be large enough ( >= 3K sq. nautical miles ) 2. it must + * intersect at least one of its associated snapshots (from which the smear + * polygon is generated) with an area >= 3K. 3. if it is "6-6" smear, it + * must intersect snapshot "6" with an area >= 3K. + * + * @param g + * A Geometry (polygon) in map coordinate. + * @param snapshots + * A list of associated snapshots + * @param smear + * Original GFA smear + * @return + */ + public boolean isAddableAsSmear(Geometry g, ArrayList snapshots, + Gfa smear) { + + return (isBiggerInMap(g) && passed6_6Rule(g, snapshots, smear) && intersectBigWithSS( + g, snapshots)); + + } + + /** + * Check if a polygon intersects at least one of the snapshots with an area + * >= 3K. + * + * Note: the input is assumed in MAP coordinate. + * + * @param g + * A Geometry (polygon) + * @param snapshots + * A list of associated snapshots + * @return + */ + private boolean intersectBigWithSS(Geometry g, ArrayList snapshots) { + + boolean addable = false; + + if (snapshots == null || snapshots.size() <= 0) { + addable = true; + } else { + Coordinate[] pts = PgenUtil.latlonToGrid(g.getCoordinates()); + Geometry poly = pointsToGeometry(pts); + for (Gfa ss : snapshots) { + if (isBiggerInGrid(poly.intersection(gfaToPolygonInGrid(ss)))) { + addable = true; + break; + } + } + } + + return addable; + + } + + /** + * Check if a 6-6 polygon intersect snapshot "6" with an area >= 3K. + * + * Note: if the smear is not a "6-6" smear or no snapshots, return true. if + * there are snapshots but no snapshot "6" somehow, return false; + * + * @param g + * A Geometry (polygon) + * @param snapshots + * A list of associated snapshots + * @return + */ + private boolean passed6_6Rule(Geometry g, ArrayList snapshots, + Gfa smear) { + + boolean addable = true; + + if (snapshots != null && snapshots.size() > 0 + && smear.getForecastHours().equals("6-6")) { + + Gfa ss_6 = null; + + for (Gfa ss : snapshots) { + if (ss.getForecastHours().equals("6")) { + ss_6 = ss; + break; + } + } + + if (ss_6 == null) { + addable = false; + } + + if (addable) { + Coordinate[] pts = PgenUtil.latlonToGrid(g.getCoordinates()); + Geometry poly = pointsToGeometry(pts); + if (!isBiggerInGrid(poly.intersection(gfaToPolygonInGrid(ss_6)))) { + addable = false; + } + } + + } + + return addable; + + } + + /** + * Check if a polygon is bigger than a value in unit of sq. nautical miles. + * + * @param g + * A Geometry + * @return + */ + private boolean isBigger(Geometry g, double limit) { + return (g != null && PgenUtil.getSphPolyArea(g) >= limit); + } + + /** + * Check if a polygon is bigger than the GFA AREA_LIMIT (3K sq. nautical + * miles). + * + * @param g + * A Geometry + * @return + */ + public boolean isBiggerInMap(Geometry g) { + + return isBigger(g, GfaRules.AREA_LIMIT); + + } + + /** + * Check if a polygon is bigger than the GFA AREA_LIMIT (3K sq. nautical + * miles). + * + * Note: the input is assumed to be in grid coordinate, not map coordinate. + * + * @param g + * A Geometry + * @return + */ + public boolean isBiggerInGrid(Geometry g) { + + double area = 0.0; + if (g instanceof Polygon) { + area = PgenUtil.getSphPolyAreaInGrid((Polygon) g); + } else if (g instanceof MultiPolygon) { + MultiPolygon mp = (MultiPolygon) g; + for (int nn = 0; nn < mp.getNumGeometries(); nn++) { + area += PgenUtil.getSphPolyAreaInGrid((Polygon) mp + .getGeometryN(nn)); + } + } + + return (area >= GfaRules.AREA_LIMIT) ? true : false; + + } + + /** + * Get a list of states that allows MT_OBSC hazard. + * + * @param + * @return + */ + public List getMtObscStates() { + + if (mtObscStates == null) { + mtObscStates = new ArrayList(); + String xpath = MTOBSC_XPATH; + + Document dm = readMtObscTbl(); + + if (dm != null) { + Node mtObscInfo = dm.selectSingleNode(xpath); + List nodes = mtObscInfo.selectNodes("area"); + for (Node node : nodes) { + node.selectNodes("state"); + for (Object nd : node.selectNodes("state")) { + mtObscStates.add(((Node) nd).getText()); + } + } + } + } + + return mtObscStates; + } + + /** + * Read mt_obsc_states.xml + * + * @return - document + */ + private static Document readMtObscTbl() { + + if (mtObscTbl == null) { + try { + String mtObscFile = PgenStaticDataProvider.getProvider() + .getFileAbsolutePath( + PgenStaticDataProvider.getProvider() + .getPgenLocalizationRoot() + + "mt_obsc_states.xml"); + + SAXReader reader = new SAXReader(); + mtObscTbl = reader.read(mtObscFile); + } catch (Exception e) { + e.printStackTrace(); + } + } + + return mtObscTbl; + } + + /** + * This routine clips a GFA polygon against the international bound and + * finds the intersection points of the GFA polygon with the bound. Then the + * intersection points are snapped individually to points outside of the + * Clipped GFA polygon. Both the intersection points and their snapped + * matches are returned in map coordinate. + * + * The input is assumed to be in MAP coordinate. + * + * @param gfaPoly + * Polygon from GFA + * @param bndPoly + * Polygon of international boundary + * @param clipped + * Intersection Polygon of international boundary with the GFA + * polygon (in grid coordinate) + * + */ + private HashMap getIntlIntersectionPt( + Geometry gfaPoly, Geometry bndPoly, Geometry clipped) { + HashMap interPts = new HashMap(); + + // Get points in clockwise order - do not repeat the first point at the + // end. + Coordinate[] pts = clipped.getGeometryN(0).getCoordinates(); + Coordinate[] intlPoly = PgenUtil.gridToLatlon(pts); + ArrayList intlList = new ArrayList(); + intlList.addAll(Arrays.asList(intlPoly)); + intlList.remove(intlList.size() - 1); + ArrayList cwPoly = GfaSnap.getInstance() + .reorderInClockwise(intlList, null); + + /* + * Check out each point as either a new point, an international boundary + * point, or a point of the original polygon. + */ + boolean originalFound = false; + int[] ptFlag = new int[cwPoly.size()]; + for (int ii = 0; ii < cwPoly.size(); ii++) { + + ptFlag[ii] = NEW_POINT; + + for (Coordinate bndc : bndPoly.getCoordinates()) { + if (isSamePoint(bndc, cwPoly.get(ii), SMALLF)) { + ptFlag[ii] = BOUND_POINT; + break; + } + } + + if (ptFlag[ii] != NEW_POINT) + continue; + + for (Coordinate orgc : gfaPoly.getCoordinates()) { + if (isSamePoint(orgc, cwPoly.get(ii), SMALLF)) { + ptFlag[ii] = ORIGINAL_POINT; + originalFound = true; + break; + } + } + } + + /* + * Shift the array to let it start with an original point. Only do this + * if at least one original point found. + */ + int eflag; + if (originalFound) { + while (ptFlag[0] != ORIGINAL_POINT) { + + cwPoly = GfaSnap.getInstance().shiftArray(cwPoly); + + eflag = ptFlag[0]; + for (int jj = 0; jj < (ptFlag.length - 1); jj++) { + ptFlag[jj] = ptFlag[jj + 1]; + } + + ptFlag[ptFlag.length - 1] = eflag; + + } + } + + // Snap and match any new points. + int snap_indx1; + int snap_indx2; + int status; + int np = cwPoly.size(); + Coordinate[] snapPt = new Coordinate[1]; + + ArrayList usedPts = new ArrayList(); + usedPts.addAll(cwPoly); + + for (int ii = 0; ii < cwPoly.size(); ii++) { + + if (ptFlag[ii] != NEW_POINT) { + continue; + } + + /* + * Handle NN case - a "small" triangle may be cut off when the smear + * intersects the international boundary. The two new close points + * by the intersection should be replaced by the original point in + * the smear. + */ + if ((ii + 1) < cwPoly.size()) { + if (ptFlag[ii + 1] == NEW_POINT + && GfaSnap.getInstance().isCluster(cwPoly.get(ii), + cwPoly.get(ii + 1))) { + + int ptBefore = (ii - 1 + cwPoly.size()) % cwPoly.size(); + int ptAfter = (ii + 2 + cwPoly.size()) % cwPoly.size(); + + List gfaPts = Arrays.asList(gfaPoly + .getCoordinates()); + int indInGfa1 = findPoint(cwPoly.get(ptBefore), gfaPts, + SMALLF); + int indInGfa2 = findPoint(cwPoly.get(ptAfter), gfaPts, + SMALLF); + + if (indInGfa1 >= 0 && indInGfa2 >= 0 + && (indInGfa2 - indInGfa1) == 2) { + + int indBtw = indInGfa1 + 1; // the original point + // between + if (GfaSnap.getInstance().isCluster(cwPoly.get(ii), + gfaPts.get(indBtw)) + && GfaSnap.getInstance().isCluster( + cwPoly.get(ii + 1), gfaPts.get(indBtw))) { + + interPts.put(cwPoly.get(ii), gfaPts.get(indBtw)); + interPts.put(cwPoly.get(ii + 1), gfaPts.get(indBtw)); + + ii++; // skip these two new points. + continue; + } + } + } + } + + /* + * All other cases - snap the intersection point to a point with a + * clustering distance away and outside the polygon. For clustering + * points, snap them to a single snap point. If fail to snap a + * cluster of points, try to snap them individually. + */ + snap_indx1 = ii; + snap_indx2 = ii; + + while (snap_indx1 > 0 + && GfaSnap.getInstance().isCluster(cwPoly.get(ii), + cwPoly.get(snap_indx1 - 1))) { + snap_indx1--; + } + + while (snap_indx2 < (np - 1) + && GfaSnap.getInstance().isCluster(cwPoly.get(ii), + cwPoly.get(snap_indx2 + 1))) { + snap_indx2++; + } + + status = GfaSnap.getInstance().snapPtGFA(snap_indx1, snap_indx2, + usedPts, null, cwPoly, true, true, 3.0F, snapPt); + + if (status != 0 && (snap_indx1 != snap_indx2)) { + + snap_indx1 = ii; + snap_indx2 = ii; + + status = GfaSnap.getInstance().snapPtGFA(snap_indx1, + snap_indx2, usedPts, null, cwPoly, true, true, 3.0F, + snapPt); + } + + // Snap failed - use the original point. + if (status != 0) { + snapPt[0].x = cwPoly.get(ii).x; + snapPt[0].y = cwPoly.get(ii).y; + } + + /* + * Pair the intersection point with its snapped counterpart. Also + * replace the intersection points with the snapped ones for + * snapping the next one. + */ + for (int jj = snap_indx1; jj <= snap_indx2; jj++) { + interPts.put(cwPoly.get(jj), snapPt[0]); + // cwPoly.set( jj, new Coordinate( snapPt[ 0 ] ) );; + } + + ii += (snap_indx2 - snap_indx1); // added to skip duplicate + // calculation. + + usedPts.add(snapPt[0]); + + } + + return interPts; + + } + + /** + * Check if two pints are within a given tie distance. If so, they are + * considered as the same point. + */ + private boolean isSamePoint(Coordinate p1, Coordinate p2, double tieDist) { + + boolean sameP = false; + if (p1 != null && p2 != null + && Math.abs(p1.x - p2.x) < Math.abs(tieDist) + && Math.abs(p1.y - p2.y) < Math.abs(tieDist)) { + sameP = true; + } + + return sameP; + } + + /** + * This routine clips a GFA polygon against common border between FA + * regional bounds to find the intersection points of the GFA polygon with + * the bound. Then the intersection points are snapped individually to + * points outside of the polygon. Both the intersection points and their + * snapped matches are returned in map coordinate. * * Note: the input is assumed to be in MAP coordinate * - * @param gfaPoly Polygon from GFA - * + * @param gfaPoly + * Polygon from GFA + * */ - private HashMap getRegionIntersectionPt( Geometry gfaPoly ) - { - HashMap interPtsPair = new HashMap(); + private HashMap getRegionIntersectionPt( + Geometry gfaPoly) { + HashMap interPtsPair = new HashMap(); - ArrayList interPts = new ArrayList(); - ArrayList pts; - ArrayList interIndex = new ArrayList(); - ArrayList indx = new ArrayList(); - - //Reorder in clockwise - first point is repeated at the end. - ArrayList gfaPoints = new ArrayList(); - for ( Coordinate c : gfaPoly.getCoordinates() ) { - gfaPoints.add( c ); - } - - ArrayList cwGfaPts = GfaSnap.getInstance().reorderInClockwise( gfaPoints , null ); - - //Get all intersection point with FA region common border. - HashMap regionCommBnds = getFaRegionCommBounds(); - for ( Geometry bnd : regionCommBnds.values() ) { - pts = lineIntersect( cwGfaPts.toArray( new Coordinate[ cwGfaPts.size() ]), - bnd.getCoordinates(), indx ); - - if ( pts.size() > 0 ) { - interPts.addAll( pts ); - interIndex.addAll( indx ); - } - } + ArrayList interPts = new ArrayList(); + ArrayList pts; + ArrayList interIndex = new ArrayList(); + ArrayList indx = new ArrayList(); - if ( interPts.size() <= 0 ) { - return interPtsPair; - } + // Reorder in clockwise - first point is repeated at the end. + ArrayList gfaPoints = new ArrayList(); + for (Coordinate c : gfaPoly.getCoordinates()) { + gfaPoints.add(c); + } -/* - ArrayList closePts = new ArrayList(); - ArrayList closeIndex = new ArrayList(); - - for ( int ii = 0; ii < interPts.size(); ii++ ) { - - Coordinate interP = interPts.get( ii ); - Coordinate ptBefore = cwGfaPts.get( interIndex.get( ii ) ); - Coordinate ptAfter = cwGfaPts.get( interIndex.get( ii ) + 1 ); - - double qdist1 = GfaSnap.getInstance().distance( interP, ptBefore ); - double qdist2 = GfaSnap.getInstance().distance( interP, ptAfter ); - - double qdist = Math.min( qdist1, qdist2 ); - if ( ( qdist / PgenUtil.NM2M ) <= GfaSnap.CLUSTER_DIST ) { - closePts.add( interP ); - closeIndex.add( interIndex.get(ii) ); - } - } - - interPts.removeAll( closePts ); - interIndex.removeAll( closeIndex ); -*/ - /* - * Find the Central boundary points inside the polygon to ensure - * the new snap points will not cluster with these points. - */ - ArrayList checkPoints = new ArrayList(); - Geometry centralBnd = getFaRegionBounds().get( "CENTRAL" ); - for ( Coordinate c : centralBnd.getCoordinates() ) { - Geometry pp = pointsToGeometry( new Coordinate[]{ c } ); - if ( pp.within( gfaPoly ) ) { - checkPoints.add( c ); - } - } + ArrayList cwGfaPts = GfaSnap.getInstance() + .reorderInClockwise(gfaPoints, null); - /* - * Now insert each common intersection point into the el polygon - * and snap it outside of the el polygon. - * - * Note: the point cannot be any point of the el polygon or any - * snap point that has been used. - * - * If an intersection point is not within the clustering distance of - * the point before it (Pb) or point after it (Pa), simply insert it into - * the polygon and snap it. Otherwise, do the following: - * - * 1. Pick the closer one of Pb and Pa as Pn. - * 2. Check if Pn is within the clustering distance of the common boundary - * points inside the FROM line. - * 3. If so, snap Pn to the closest point not within the clustering distance - * and match the intersection point and Pn to the new point. - * 4. If not, match the intersection point with Pn. - */ - ArrayList usedPoints = new ArrayList(); - usedPoints.addAll( cwGfaPts ); - - ArrayList ePts = new ArrayList(); - for ( int ii = 0; ii < interPts.size(); ii++ ) { - - Coordinate interP = interPts.get( ii ); - Coordinate ptBefore = cwGfaPts.get( interIndex.get( ii ) ); - Coordinate ptAfter = cwGfaPts.get( interIndex.get( ii ) + 1 ); - - double qdist1 = GfaSnap.getInstance().distance( interP, ptBefore ); - double qdist2 = GfaSnap.getInstance().distance( interP, ptAfter ); + // Get all intersection point with FA region common border. + HashMap regionCommBnds = getFaRegionCommBounds(); + for (Geometry bnd : regionCommBnds.values()) { + pts = lineIntersect( + cwGfaPts.toArray(new Coordinate[cwGfaPts.size()]), + bnd.getCoordinates(), indx); - int addOne = -1; - int qmatch = -1; - double qdist; + if (pts.size() > 0) { + interPts.addAll(pts); + interIndex.addAll(indx); + } + } - if ( qdist1 < qdist2 ) { - qmatch = interIndex.get( ii ); - qdist = qdist1; - } - else { - qmatch = interIndex.get( ii ) + 1; - qdist = qdist2; - } + if (interPts.size() <= 0) { + return interPtsPair; + } - if ( ( qdist / PgenUtil.NM2M ) < GfaSnap.CLUSTER_DIST ) { + /* + * ArrayList closePts = new ArrayList(); + * ArrayList closeIndex = new ArrayList(); + * + * for ( int ii = 0; ii < interPts.size(); ii++ ) { + * + * Coordinate interP = interPts.get( ii ); Coordinate ptBefore = + * cwGfaPts.get( interIndex.get( ii ) ); Coordinate ptAfter = + * cwGfaPts.get( interIndex.get( ii ) + 1 ); + * + * double qdist1 = GfaSnap.getInstance().distance( interP, ptBefore ); + * double qdist2 = GfaSnap.getInstance().distance( interP, ptAfter ); + * + * double qdist = Math.min( qdist1, qdist2 ); if ( ( qdist / + * PgenUtil.NM2M ) <= GfaSnap.CLUSTER_DIST ) { closePts.add( interP ); + * closeIndex.add( interIndex.get(ii) ); } } + * + * interPts.removeAll( closePts ); interIndex.removeAll( closeIndex ); + */ + /* + * Find the Central boundary points inside the polygon to ensure the new + * snap points will not cluster with these points. + */ + ArrayList checkPoints = new ArrayList(); + Geometry centralBnd = getFaRegionBounds().get("CENTRAL"); + for (Coordinate c : centralBnd.getCoordinates()) { + Geometry pp = pointsToGeometry(new Coordinate[] { c }); + if (pp.within(gfaPoly)) { + checkPoints.add(c); + } + } - Coordinate ptMatch = cwGfaPts.get( qmatch ); - for ( Coordinate c : checkPoints ) { - if ( GfaSnap.getInstance().isCluster( c, ptMatch ) ) { - addOne = qmatch; - break; - } - } - - if ( addOne < 0 ) { - interPtsPair.put( new Coordinate( interP ), - new Coordinate( ptMatch ) ); - continue; //Done - ptMatch is a snapped point. - } - } - - // Snap - int kk, kk2; - if ( addOne >= 0 ) { - kk = addOne; - kk2 = kk; + /* + * Now insert each common intersection point into the el polygon and + * snap it outside of the el polygon. + * + * Note: the point cannot be any point of the el polygon or any snap + * point that has been used. + * + * If an intersection point is not within the clustering distance of the + * point before it (Pb) or point after it (Pa), simply insert it into + * the polygon and snap it. Otherwise, do the following: + * + * 1. Pick the closer one of Pb and Pa as Pn. 2. Check if Pn is within + * the clustering distance of the common boundary points inside the FROM + * line. 3. If so, snap Pn to the closest point not within the + * clustering distance and match the intersection point and Pn to the + * new point. 4. If not, match the intersection point with Pn. + */ + ArrayList usedPoints = new ArrayList(); + usedPoints.addAll(cwGfaPts); - ePts.clear(); -// ePts.addAll( cwGfaPts ); - //If the point to be added is at the end, need to insert in - JW - 10/2012. - if ( addOne == (cwGfaPts.size() - 1) ) { - ePts.addAll( GfaSnap.getInstance().insertArray( cwGfaPts, interIndex.get( ii ) + 1, interP ) ); - kk = interIndex.get( ii ) + 1; - kk2 = kk; - } - else { - ePts.addAll( cwGfaPts ); - } - } - else { - ePts.clear(); - ePts.addAll( GfaSnap.getInstance().insertArray( cwGfaPts, interIndex.get( ii ) + 1, interP ) ); - kk = interIndex.get( ii ) + 1; - kk2 = kk; - } + ArrayList ePts = new ArrayList(); + for (int ii = 0; ii < interPts.size(); ii++) { - - ePts.remove( ePts.size() - 1 ); - - Coordinate[] snapped = new Coordinate[1]; - - //snap.... - int status = GfaSnap.getInstance().snapPtGFA( kk, kk2, usedPoints, checkPoints, - ePts, true, true, 3.0F, snapped ); - - if ( status != 0 ) { - if ( addOne >= 0 ) { - snapped[ 0 ] = new Coordinate( ePts.get( kk ) ); - } - else { - snapped[ 0 ] = new Coordinate( interP ); - } - } - - interPtsPair.put( new Coordinate( interP ), - new Coordinate( snapped[ 0 ] ) ); - - if ( addOne >= 0 ) { - interPtsPair.put( new Coordinate( cwGfaPts.get( addOne ) ), - new Coordinate( snapped[ 0 ] ) ); - } - - usedPoints.add( snapped[ 0 ] ); - - } + Coordinate interP = interPts.get(ii); + Coordinate ptBefore = cwGfaPts.get(interIndex.get(ii)); + Coordinate ptAfter = cwGfaPts.get(interIndex.get(ii) + 1); + double qdist1 = GfaSnap.getInstance().distance(interP, ptBefore); + double qdist2 = GfaSnap.getInstance().distance(interP, ptAfter); - - return interPtsPair; - } + int addOne = -1; + int qmatch = -1; + double qdist; - /** - * Computes the intersection points of two multi-point lines. - * - * The input is assumed to be in MAP coordinate. - * - * Note: 1. the computation is done segment by segment, so if a line is closed - * it is the caller's responsibility to ensure the first point is repeated - * at the end of the line. - * 2. the index of the point before the intersection in line1 is retained. So - * the index is dependent the direction of the line1 (Clockwise or - * counterclockwise) - */ - public ArrayList lineIntersect( Coordinate[] line1, Coordinate[] line2, - ArrayList indexInLine1 ) { - - ArrayList interPts = new ArrayList(); - if ( indexInLine1 == null ) { - indexInLine1 = new ArrayList(); - } - else { - indexInLine1.clear(); - } + if (qdist1 < qdist2) { + qmatch = interIndex.get(ii); + qdist = qdist1; + } else { + qmatch = interIndex.get(ii) + 1; + qdist = qdist2; + } - Coordinate[] line1InGrid = PgenUtil.latlonToGrid( line1 ); - Coordinate[] line2InGrid = PgenUtil.latlonToGrid( line2 ); + if ((qdist / PgenUtil.NM2M) < GfaSnap.CLUSTER_DIST) { - Coordinate onePt; - for ( int ii = 0; ii < (line1.length - 1); ii++ ) { - for ( int jj = 0; jj < (line2.length - 1); jj++ ) { - - onePt = segmentIntersect( line1InGrid[ ii ], line1InGrid[ ii + 1 ], - line2InGrid[ jj ], line2InGrid[ jj + 1 ] ); - if ( onePt != null ) { - Coordinate[] onePtInMap = PgenUtil.gridToLatlon( new Coordinate[]{ onePt } ); - interPts.add( new Coordinate( onePtInMap[ 0 ] ) ); - indexInLine1.add( new Integer( ii ) ); - } - } - } - - return interPts; - } - - /** - * Computes the intersection points of two line segments (not extended lines). - * - * No coordinate system is assumed. - * - */ - public Coordinate segmentIntersect( Coordinate seg1_start, Coordinate seg1_end, - Coordinate seg2_start, Coordinate seg2_end ) { - Coordinate interPt = null; - - Geometry g1 = pointsToLineString( new Coordinate[]{seg1_start, seg1_end} ); - Geometry g2 = pointsToLineString( new Coordinate[]{seg2_start, seg2_end} ); - - if ( g1.intersects( g2 ) ) { - interPt = g1.intersection( g2 ).getCoordinates()[0]; - } - - return interPt; - } + Coordinate ptMatch = cwGfaPts.get(qmatch); + for (Coordinate c : checkPoints) { + if (GfaSnap.getInstance().isCluster(c, ptMatch)) { + addOne = qmatch; + break; + } + } - /** - * Get the common bounds between FA West and Central, Central and East. - */ - public HashMap getFaRegionCommBounds() - { - if ( faRegionCommBounds == null ){ - loadFaRegionCommBounds(); - } - - return faRegionCommBounds; - } - - /** - * Calculate the common bounds between FA West and Central, Central and East. - */ - private void loadFaRegionCommBounds() - { - faRegionCommBounds = new HashMap(); - HashMap rgbnds = getFaRegionBounds(); - ArrayList used = new ArrayList(); - - for ( String regionName1 : rgbnds.keySet() ) { - used.add( regionName1 ); - Geometry bnd1 = rgbnds.get( regionName1 ); - for ( String regionName2 : rgbnds.keySet() ) { - if ( !used.contains( regionName2 ) ) { - Geometry bnd2 = rgbnds.get( regionName2 ); - if ( bnd1.intersects( bnd2 ) ) { - String bname = new String( regionName1 + "-" + regionName2 ); - Geometry comm = bnd1.intersection( bnd2 ); - //Use CoordinateList to remove duplicate points - CoordinateList clist = new CoordinateList( ); - clist.add( comm.getCoordinates(), false ); - - faRegionCommBounds.put( bname, pointsToLineString( clist.toCoordinateArray() ) ); - } - } - } - } - } + if (addOne < 0) { + interPtsPair.put(new Coordinate(interP), new Coordinate( + ptMatch)); + continue; // Done - ptMatch is a snapped point. + } + } - /** - * Get the common bounds between extended SFO/SLC bounds, and - * extended CHI-BOS and DFW-MIA bounds. - */ - public HashMap getFaAreaXCommBounds() - { - if ( faAreaXCommBounds == null ){ - loadFaAreaXCommBounds(); - } - - return faAreaXCommBounds; - } - - /** - * Calculate the common bounds between extended FA area SLC and dSFC, - * CHI-BOS and DFW-MIA. - */ - private void loadFaAreaXCommBounds() - { - faAreaXCommBounds = new HashMap(); - HashMap areaxbnds = getFaAreaXBounds(); - - Geometry bnd1 = areaxbnds.get( "SLC" ); - Geometry bnd2 = areaxbnds.get( "SFO" ); - - if ( bnd1.intersects( bnd2 ) ) { - String bname = new String( "SLC-SFO" ); - Geometry comm = bnd1.intersection( bnd2 ); - //Use CoordinateList to remove duplicate points - CoordinateList clist = new CoordinateList( ); - clist.add( comm.getCoordinates(), false ); - - faAreaXCommBounds.put( bname, pointsToLineString( clist.toCoordinateArray() ) ); - } - - bnd1 = areaxbnds.get( "CHI" ); - bnd2 = areaxbnds.get( "DFW" ); - - if ( bnd1.intersects( bnd2 ) ) { - String bname = new String( "CHI-DFW" ); - Geometry comm = bnd1.intersection( bnd2 ); - //Use CoordinateList to remove duplicate points - CoordinateList clist = new CoordinateList( ); - clist.add( comm.getCoordinates(), false ); - - faAreaXCommBounds.put( bname, pointsToLineString( clist.toCoordinateArray() ) ); - - String bname2 = new String( "BOS-MIA" ); - faAreaXCommBounds.put( bname2, pointsToLineString( clist.toCoordinateArray() ) ); - - } - - - } + // Snap + int kk, kk2; + if (addOne >= 0) { + kk = addOne; + kk2 = kk; - /** - * Cleans up improper point sequence: - * - * Note: MAP coordinate is assumed. - * - * 1. compresses the consecutive duplicate points to single point - * 2. compress ABA point sequence to a single point A - * - */ - public Geometry cleanupPoints( Geometry geom ) - { - Coordinate[] gPts = geom.getCoordinates(); - ArrayList gList = new ArrayList(); + ePts.clear(); + // ePts.addAll( cwGfaPts ); + // If the point to be added is at the end, need to insert in - + // JW - 10/2012. + if (addOne == (cwGfaPts.size() - 1)) { + ePts.addAll(GfaSnap.getInstance().insertArray(cwGfaPts, + interIndex.get(ii) + 1, interP)); + kk = interIndex.get(ii) + 1; + kk2 = kk; + } else { + ePts.addAll(cwGfaPts); + } + } else { + ePts.clear(); + ePts.addAll(GfaSnap.getInstance().insertArray(cwGfaPts, + interIndex.get(ii) + 1, interP)); + kk = interIndex.get(ii) + 1; + kk2 = kk; + } - for ( Coordinate c : gPts ) { - gList.add( new Coordinate( Math.rint(c.x * 100) / 100, - Math.rint(c.y * 100) / 100 ) ); - } - - gList.remove( gList.size() - 1 ); //remove last point. - - //Compresses consecutive duplicate points to single point. + ePts.remove(ePts.size() - 1); + + Coordinate[] snapped = new Coordinate[1]; + + // snap.... + int status = GfaSnap.getInstance().snapPtGFA(kk, kk2, usedPoints, + checkPoints, ePts, true, true, 3.0F, snapped); + + if (status != 0) { + if (addOne >= 0) { + snapped[0] = new Coordinate(ePts.get(kk)); + } else { + snapped[0] = new Coordinate(interP); + } + } + + interPtsPair + .put(new Coordinate(interP), new Coordinate(snapped[0])); + + if (addOne >= 0) { + interPtsPair.put(new Coordinate(cwGfaPts.get(addOne)), + new Coordinate(snapped[0])); + } + + usedPoints.add(snapped[0]); + + } + + return interPtsPair; + } + + /** + * Computes the intersection points of two multi-point lines. + * + * The input is assumed to be in MAP coordinate. + * + * Note: 1. the computation is done segment by segment, so if a line is + * closed it is the caller's responsibility to ensure the first point is + * repeated at the end of the line. 2. the index of the point before the + * intersection in line1 is retained. So the index is dependent the + * direction of the line1 (Clockwise or counterclockwise) + */ + public ArrayList lineIntersect(Coordinate[] line1, + Coordinate[] line2, ArrayList indexInLine1) { + + ArrayList interPts = new ArrayList(); + if (indexInLine1 == null) { + indexInLine1 = new ArrayList(); + } else { + indexInLine1.clear(); + } + + Coordinate[] line1InGrid = PgenUtil.latlonToGrid(line1); + Coordinate[] line2InGrid = PgenUtil.latlonToGrid(line2); + + Coordinate onePt; + for (int ii = 0; ii < (line1.length - 1); ii++) { + for (int jj = 0; jj < (line2.length - 1); jj++) { + + onePt = segmentIntersect(line1InGrid[ii], line1InGrid[ii + 1], + line2InGrid[jj], line2InGrid[jj + 1]); + if (onePt != null) { + Coordinate[] onePtInMap = PgenUtil + .gridToLatlon(new Coordinate[] { onePt }); + interPts.add(new Coordinate(onePtInMap[0])); + indexInLine1.add(new Integer(ii)); + } + } + } + + return interPts; + } + + /** + * Computes the intersection points of two line segments (not extended + * lines). + * + * No coordinate system is assumed. + * + */ + public Coordinate segmentIntersect(Coordinate seg1_start, + Coordinate seg1_end, Coordinate seg2_start, Coordinate seg2_end) { + Coordinate interPt = null; + + Geometry g1 = pointsToLineString(new Coordinate[] { seg1_start, + seg1_end }); + Geometry g2 = pointsToLineString(new Coordinate[] { seg2_start, + seg2_end }); + + if (g1.intersects(g2)) { + interPt = g1.intersection(g2).getCoordinates()[0]; + } + + return interPt; + } + + /** + * Get the common bounds between FA West and Central, Central and East. + */ + public HashMap getFaRegionCommBounds() { + if (faRegionCommBounds == null) { + loadFaRegionCommBounds(); + } + + return faRegionCommBounds; + } + + /** + * Calculate the common bounds between FA West and Central, Central and + * East. + */ + private void loadFaRegionCommBounds() { + faRegionCommBounds = new HashMap(); + HashMap rgbnds = getFaRegionBounds(); + ArrayList used = new ArrayList(); + + for (String regionName1 : rgbnds.keySet()) { + used.add(regionName1); + Geometry bnd1 = rgbnds.get(regionName1); + for (String regionName2 : rgbnds.keySet()) { + if (!used.contains(regionName2)) { + Geometry bnd2 = rgbnds.get(regionName2); + if (bnd1.intersects(bnd2)) { + String bname = new String(regionName1 + "-" + + regionName2); + Geometry comm = bnd1.intersection(bnd2); + // Use CoordinateList to remove duplicate points + CoordinateList clist = new CoordinateList(); + clist.add(comm.getCoordinates(), false); + + faRegionCommBounds.put(bname, + pointsToLineString(clist.toCoordinateArray())); + } + } + } + } + } + + /** + * Get the common bounds between extended SFO/SLC bounds, and extended + * CHI-BOS and DFW-MIA bounds. + */ + public HashMap getFaAreaXCommBounds() { + if (faAreaXCommBounds == null) { + loadFaAreaXCommBounds(); + } + + return faAreaXCommBounds; + } + + /** + * Calculate the common bounds between extended FA area SLC and dSFC, + * CHI-BOS and DFW-MIA. + */ + private void loadFaAreaXCommBounds() { + faAreaXCommBounds = new HashMap(); + HashMap areaxbnds = getFaAreaXBounds(); + + Geometry bnd1 = areaxbnds.get("SLC"); + Geometry bnd2 = areaxbnds.get("SFO"); + + if (bnd1.intersects(bnd2)) { + String bname = new String("SLC-SFO"); + Geometry comm = bnd1.intersection(bnd2); + // Use CoordinateList to remove duplicate points + CoordinateList clist = new CoordinateList(); + clist.add(comm.getCoordinates(), false); + + faAreaXCommBounds.put(bname, + pointsToLineString(clist.toCoordinateArray())); + } + + bnd1 = areaxbnds.get("CHI"); + bnd2 = areaxbnds.get("DFW"); + + if (bnd1.intersects(bnd2)) { + String bname = new String("CHI-DFW"); + Geometry comm = bnd1.intersection(bnd2); + // Use CoordinateList to remove duplicate points + CoordinateList clist = new CoordinateList(); + clist.add(comm.getCoordinates(), false); + + faAreaXCommBounds.put(bname, + pointsToLineString(clist.toCoordinateArray())); + + String bname2 = new String("BOS-MIA"); + faAreaXCommBounds.put(bname2, + pointsToLineString(clist.toCoordinateArray())); + + } + + } + + /** + * Cleans up improper point sequence: + * + * Note: MAP coordinate is assumed. + * + * 1. compresses the consecutive duplicate points to single point 2. + * compress ABA point sequence to a single point A + * + */ + public Geometry cleanupPoints(Geometry geom) { + Coordinate[] gPts = geom.getCoordinates(); + ArrayList gList = new ArrayList(); + + for (Coordinate c : gPts) { + gList.add(new Coordinate(Math.rint(c.x * 100) / 100, Math + .rint(c.y * 100) / 100)); + } + + gList.remove(gList.size() - 1); // remove last point. + + // Compresses consecutive duplicate points to single point. int ii = 0, jj, nshift; - boolean done = false; - while ( !done ) { + boolean done = false; + while (!done) { - jj = ii; - while ( ( jj + 1 ) < gList.size() && - ( Math.abs( gList.get( ii ).x - gList.get( jj + 1 ).x ) < SMALLF && - Math.abs( gList.get( ii ).y - gList.get( jj + 1 ).y ) < SMALLF ) ) { - jj += 1; - } - nshift = jj - ii; + jj = ii; + while ((jj + 1) < gList.size() + && (Math.abs(gList.get(ii).x - gList.get(jj + 1).x) < SMALLF && Math + .abs(gList.get(ii).y - gList.get(jj + 1).y) < SMALLF)) { + jj += 1; + } + nshift = jj - ii; - if ( nshift != 0 ) { - gList = GfaSnap.getInstance().collapseArray( gList, ii, nshift ); - } + if (nshift != 0) { + gList = GfaSnap.getInstance().collapseArray(gList, ii, nshift); + } - ii++; + ii++; - if ( ii >= gList.size() ) done = true; + if (ii >= gList.size()) + done = true; } - //Reduce ABA case to A (line starts at A, goes to B and then back to A). + // Reduce ABA case to A (line starts at A, goes to B and then back to + // A). ii = 0; - done = false; - while ( !done ) { + done = false; + while (!done) { - if ( ( ii + 2) < gList.size() && - ( Math.abs( gList.get( ii ).x - gList.get( ii + 2 ).x ) < SMALLF && - Math.abs( gList.get( ii ).y - gList.get( ii + 2 ).y ) < SMALLF ) ) { - - gList = GfaSnap.getInstance().collapseArray( gList, ii, 2 ); - } + if ((ii + 2) < gList.size() + && (Math.abs(gList.get(ii).x - gList.get(ii + 2).x) < SMALLF && Math + .abs(gList.get(ii).y - gList.get(ii + 2).y) < SMALLF)) { - ii++; + gList = GfaSnap.getInstance().collapseArray(gList, ii, 2); + } + + ii++; + + if (ii >= gList.size()) + done = true; - if ( ii >= gList.size() ) done = true; - } - - - //Make sure the first point is not duplicated at the end. - if ( ( Math.abs( gList.get( 0 ).x - gList.get( gList.size() - 1 ).x ) < SMALLF && - Math.abs( gList.get( 0 ).y - gList.get( gList.size() - 1 ).y ) < SMALLF ) ) { - gList.remove( gList.size() - 1 ); - } - - Coordinate[] outp = gList.toArray( new Coordinate[ gList.size() ] ); - - return pointsToGeometry( outp ) ; - - } - - /** - * Finds and replaces the points in a Geometry with its pair. - */ - protected Geometry replacePts( Geometry geom, HashMap pairs ) { - - Coordinate[] poly = geom.getCoordinates(); - Coordinate[] pts = new Coordinate[ poly.length - 1 ]; //remove last point - - for ( int ii = 0; ii < ( poly.length - 1 ); ii++ ) { - - pts[ ii ] = new Coordinate( poly[ ii ] ); - - if ( pairs != null ) { - for ( Coordinate p : pairs.keySet() ) { - if ( Math.abs( poly[ ii ].x - p.x ) < SMALLF && - Math.abs( poly[ ii ].y - p.y ) < SMALLF ) { - pts[ ii ] = new Coordinate( pairs.get( p ) ); - break; - } - } - } - } - - return pointsToGeometry( pts ); - - } - - /** - * Flags a set of points in a GFA element as non-reduce-able they are in tie - * distance of one of the non-reduce-able points. This strategy helps to - * preserve the integrity of the boundary after clipping and point reduction. - * - * The non-reduce-able points includes: all the FA regional boundary points, the - * snapped intersection points of the original GFA with the FA international - * and common regional bounds, as well as the points immediately before and - * such a non-reduce-able point. - */ - private void addReduceFlags( Gfa elm, CoordinateList pts ) { - - // Note: the first point is not repeated at the end for a DrawableElement. - Coordinate[] poly = elm.getLinePoints(); - int np = poly.length; - boolean[] reduceable = new boolean[ np ]; - for ( int ii = 0; ii < np; ii++ ) { - reduceable[ ii ] = true; - } - - for ( int ii = 0; ii < np; ii++ ) { - for ( int jj = 0; jj < pts.size(); jj++ ) { - if ( Math.abs( poly[ ii ].x - pts.getCoordinate( jj ).x ) < SMALLF && - Math.abs( poly[ ii ].y - pts.getCoordinate( jj ).y ) < SMALLF ) { - reduceable[ ii ] = false; - reduceable[ ( ii - 1 + np ) % np ] = false; - reduceable[ ( ii + 1 + np ) % np ] = false; - break; - } - } - } - - elm.setReduceFlags( reduceable ); - - } - - /** - * Finds the common points between two sets of Geometries. - */ - public ArrayList getCommonPoints( ArrayList big, - ArrayList small ) { - - ArrayList commPts = new ArrayList(); - - for ( Geometry g1 : big ) { - for ( Geometry g2 : small ) { - if ( g1.intersects( g2 ) ) { - for ( Coordinate c : g1.intersection( g2 ).getCoordinates() ) { - if ( !commPts.contains( c ) ) { - commPts.add( new Coordinate( c ) ); - } - } - } - } - } - - return commPts; - } - - /** - * Remove a list of points from a Geometry and form a new Geometry. - */ - public Geometry removeCommonPoints( Geometry gm, ArrayList pts ) { - - if ( pts == null || pts.size() == 0 ) { - return gm; - } - - ArrayList newPts = new ArrayList(); - - Coordinate[] gPts = gm.getCoordinates(); - - for ( int ii = 0; ii < ( gPts.length - 1 ); ii++ ) { - if ( !pts.contains( gPts[ ii ] ) ) { - newPts.add( new Coordinate( gPts[ ii ] ) ); - } - } - - return pointsToGeometry( newPts ); - - } - - /** - * Load all bounds needed for Gfa processing. - */ - public void loadGfaBounds() { - - //States, FA Regions, FA Areas, Fa extended Areas. - getStateBounds(); - getFaRegionBounds(); - getFaAreaBounds(); - getFaAreaXBounds(); - - getGreatLakeBounds(); - getCoastalWaterBounds(); - getFaInternationalBound(); - getMtObscStates(); - - getFaRegionCommBounds(); - getFaAreaXCommBounds(); - - //Convert to grid coordinates. - updateGfaBoundsInGrid(); - - //Snap points - SnapVOR.getSnapStns( null, 16 ); - - } - - /** - * Update all bounds needed for Gfa processing. - */ - public void updateGfaBoundsInGrid() { - - faInternationalBoundInGrid = geometryInGrid( getFaInternationalBound() ); - - faRegionBoundsInGrid = updateBoundsInGrid( getFaRegionBounds() ); - faAreaBoundsInGrid = updateBoundsInGrid( getFaAreaBounds() ); - faAreaXBoundsInGrid = updateBoundsInGrid( getFaAreaXBounds() ); - - stateBoundsInGrid = updateBoundsInGrid( getStateBounds() ); - -/* - stateBoundsInGrid = updateBoundsInGrid( getStateBounds() ); - StringBuilder invalidSts = new StringBuilder(); - for ( String key : stateBoundsInGrid.keySet() ) { - Geometry g1 = stateBounds.get( key ); - Geometry g2 = stateBoundsInGrid.get( key ); - - if ( !g1.isValid() || (g1.isValid() && !g2.isValid()) ) { - invalidSts.append( " " + key ); - } - } - - System.out.println( "Invalid state = " + invalidSts ); - - for ( String key : stateBoundsInGrid.keySet() ) { - Geometry g1 = stateBounds.get( key ); - Geometry g2 = stateBoundsInGrid.get( key ); - System.out.println( "Original State Bound for " + key + " is " + g1.isValid() ); - System.out.println( "\tState Bound in Grid for " + key + " is " + g2.isValid() ); - } - stateBoundsInGrid = updateBoundsInGrid( getStateBounds() ); -*/ - greatLakesBoundsInGrid = updateBoundsInGrid( getGreatLakeBounds() ); - coastalWaterBoundsInGrid = updateBoundsInGrid( getCoastalWaterBounds() ); - faRegionCommBoundsInGrid = updateBoundsInGrid( getFaRegionCommBounds() ); - faAreaXCommBoundsInGrid = updateBoundsInGrid( getFaAreaXCommBounds() ); - - } - - /** - * Load all bounds in grid coordinate. - */ - private HashMap updateBoundsInGrid( HashMap bndInMap ) { - - HashMap bndInGrid = new HashMap(); - - for ( String bname : bndInMap.keySet() ) { - bndInGrid.put( bname , geometryInGrid( bndInMap.get( bname ) ) ); - } - - return bndInGrid; - - } - - - /** - * Getters for all bounds in grid coordinate. - */ - public Geometry getFaInternationalBoundInGrid() { - return faInternationalBoundInGrid; - } - - public HashMap getFaRegionBoundsInGrid() { - return faRegionBoundsInGrid; - } - - public HashMap getFaAreaBoundsInGrid() { - return faAreaBoundsInGrid; - } - - public HashMap getFaAreaXBoundsInGrid() { - return faAreaXBoundsInGrid; - } - - public HashMap getStateBoundsInGrid() { - return stateBoundsInGrid; - } - - public HashMap getGreatLakesBoundsInGrid() { - return greatLakesBoundsInGrid; - } - - public HashMap getCoastalWaterBoundsInGrid() { - return coastalWaterBoundsInGrid; - } - - public HashMap getFaRegionCommBoundsInGrid() { - return faRegionCommBoundsInGrid; - } - - public HashMap getFaAreaXCommBoundsInGrid() { - return faAreaXCommBoundsInGrid; - } - - /* - * Convert a Geometry in map coordinate into grid coordinate. - */ - private Geometry geometryInGrid( Geometry geomInMap ) { - - Geometry gout = null; - if ( geomInMap instanceof Polygon || geomInMap instanceof MultiPolygon ) { - - Polygon[] polygons = new Polygon[ geomInMap.getNumGeometries() ]; - - for ( int ii = 0; ii < geomInMap.getNumGeometries(); ii++ ) { - Geometry g = geomInMap.getGeometryN( ii ); - Coordinate[] gpts = g.getCoordinates(); - Coordinate[] gpts1 = Arrays.copyOf( gpts, gpts.length - 1 ); - Coordinate[] pts = PgenUtil.latlonToGrid( gpts1 ); - - polygons[ ii ] = pointsToPolygon( pts ); - } - - gout = geometryFactory.createMultiPolygon( polygons ); - } - else if ( geomInMap instanceof LineString ) { - Coordinate[] gpts = geomInMap.getCoordinates(); - Coordinate[] pts = PgenUtil.latlonToGrid( gpts ); - - gout = pointsToLineString( pts ); - } - - return gout; - - } - - - /** - * Try to write state bounds in error to a PGEN line element for visual check. - */ - public void validateGfaBounds() { - writeErrorBound( "FA_States_Map_Fixed", getStateBounds() ); - } - - /* - * check the invalid polygons in state bounds and write each state into - * a PGEN file. - */ - private void writeErrorBound( String bndName, HashMap bndMap ) { - - ArrayList errorStates = new ArrayList(); -// for ( String s : WRONG_STATES ) { -// errorStates.add( s ); -// } - - boolean isvalid = true; - - StringBuilder ss = new StringBuilder(); - for ( String key : bndMap.keySet() ) { - ss.append( key + " "); - } - - StringBuilder as = new StringBuilder(); - for ( String key : bndMap.keySet() ) { - - Product activeProduct = new Product("Default", "Default", "Default", - new ProductInfo(), new ProductTime(), new ArrayList() ); - - Layer activeLayer = new Layer(); - activeProduct.addLayer( activeLayer ); - - List productList = new ArrayList(); - productList.add( activeProduct ); - - Geometry g = bndMap.get( key ); - - ArrayList pts = new ArrayList(); - -// if ( errorStates.contains( key ) ) { - isvalid = g.isValid(); - if ( !isvalid ) { - as.append( " " + key ); - System.out.println( "\tInvalid Bound " + key + "\t " + g.getNumGeometries() ); - } - -// if ( !g.isValid() ) { - - - System.out.println( "\tProcess Bound " + key + "\t " + g.getNumGeometries() ); - - for ( int jk = 0; jk < g.getNumGeometries(); jk++ ) { - - pts.clear(); //!!! - - Geometry one = g.getGeometryN( jk ); - - for ( Coordinate c : one.getCoordinates() ) { - pts.add( new Coordinate( c ) ); - } - pts.remove( pts.size() - 1 ); - - Line cline = new Line( null, new Color[]{ Color.red }, - 2.0f, 1.0, true, false, pts, 0, FillPattern.SOLID, - "Lines", "LINE_SOLID" ); - String str = ""; - str = str + key + "_" + jk; - - Text lbl = new Text( null, "Courier", 14.0f, - TextJustification.CENTER, null, 0.0, - TextRotation.SCREEN_RELATIVE, new String[]{ str }, - FontStyle.REGULAR, Color.GREEN, 0, 0, true, DisplayType.NORMAL, - "Text", "General Text" ); - lbl.setLocation( cline.getLinePoints()[0] ); - -// activeLayer.add( lbl ); - activeLayer.add( cline ); - } - - /* - * Write into a file. - */ - if ( productList.get(0).getLayer(0).getDrawables().size() > 0 ) { - Products filePrds = ProductConverter.convert( productList ); - String a; - if ( isvalid ) { - a = "/export/cdbsrv/jwu/stateBnd/" + bndName + "_high_" + key + "_correct_nolabel.xml"; - } - else { - a = "/export/cdbsrv/jwu/stateBnd/" + bndName + "_high_" + key + "_icorrect_nolabel.xml"; - } - System.out.println( "Write to validation file: " + a ); - FileTools.write( a, filePrds ); - } - } - - System.out.println( "Invalid states are: " + as ); - -// } - } - - - /* - * Fixes the incorrect state bounds for a few states. - */ - private HashMap fixStateBounds( HashMap stateBnd ) { - - HashMap fixedBounds = new HashMap(); - - ArrayList errorStates = new ArrayList(); - for ( String s : WRONG_STATES ) { - errorStates.add( s ); + // Make sure the first point is not duplicated at the end. + if ((Math.abs(gList.get(0).x - gList.get(gList.size() - 1).x) < SMALLF && Math + .abs(gList.get(0).y - gList.get(gList.size() - 1).y) < SMALLF)) { + gList.remove(gList.size() - 1); } - - for ( String key : stateBnd.keySet() ) { - - Geometry g = stateBnd.get( key ); - - if ( !errorStates.contains( key ) ) { - fixedBounds.put( key, g ); - } - else { - ArrayList pts = new ArrayList(); - - Polygon[] polygons = new Polygon[ g.getNumGeometries() ]; - - for ( int jk = 0; jk < g.getNumGeometries(); jk++ ) { - - pts.clear(); //!!! - - Geometry one = g.getGeometryN( jk ); - Coordinate[] bpts = one.getCoordinates(); - Coordinate firstPt = bpts[0]; - pts.add( firstPt ); - int nn = 1; - while ( ! bpts[ nn ].equals( firstPt ) && nn < bpts.length ) { - pts.add( bpts[ nn ] ); - nn++; - } - - polygons[ jk ] = pointsToPolygon( pts.toArray( new Coordinate[ pts.size() ] ) ); - } - - MultiPolygon multipolygon = geometryFactory.createMultiPolygon( polygons ); - - fixedBounds.put( key, multipolygon ); - } - } - - return fixedBounds; - } - - /* - * Find the first occurrence of a point in an array. - * - * @param pt - * @param list - * @param tie - */ - private int findPoint( Coordinate pt, List list, double tie ) { - - int indx = -1; - - if ( pt != null && list != null ) { - for ( int ii = 0; ii < list.size(); ii++ ) { - if ( isSamePoint( pt, list.get( ii ), tie ) ) { - indx = ii; - break; - } - } - } - - return indx; - - } - - /* - * Some tests for JTS, could be removed later. - */ - public void testJTS() { - Coordinate[] polyPts = new Coordinate[]{ new Coordinate(-110.0, 40.0), - new Coordinate(-110.0, 50.0), - new Coordinate(-90.0, 50.0), - new Coordinate(-90.0, 40.0) }; - Geometry poly = pointsToGeometry( polyPts ); - Geometry bndPts = pointsToGeometry( new Coordinate[]{ new Coordinate(-110.0, 50.0) } ); - Geometry inPts = pointsToGeometry( new Coordinate[]{ new Coordinate(-100.0, 45.0) } ); - Geometry outPts = pointsToGeometry( new Coordinate[]{ new Coordinate(-100.0, 30.0) } ); - - Geometry a1 = bndPts.intersection( poly ); - Geometry a2 = inPts.intersection( poly ); - Geometry a3 = outPts.intersection( poly ); - - Geometry bndlin = pointsToGeometry( new Coordinate[]{ new Coordinate(-110.0, 50.0), - new Coordinate(-110.0, 40.0) } ); - - Geometry inlin = pointsToGeometry( new Coordinate[]{ new Coordinate(-110.0, 50.0), - new Coordinate(-100.0, 45.0) } ); - - Geometry outlin = pointsToGeometry( new Coordinate[]{ new Coordinate(-110.0, 50.0), - new Coordinate(-100.0, 30.0) } ); - Geometry a4 = bndlin.intersection( poly ); - Geometry a5 = inlin.intersection( poly ); - Geometry a6 = outlin.intersection( poly ); - - System.out.println( "\n\na1="+ a1.getCoordinates().length ); - System.out.println( "a2="+ a2.getCoordinates().length ); - System.out.println( "a3="+ a3.getCoordinates().length ); - System.out.println( "a4="+ a4.getCoordinates().length ); - System.out.println( "a5="+ a5.getCoordinates().length ); - System.out.println( "a6="+ a6.getCoordinates().length ); - - Geometry l1 = pointsToGeometry( new Coordinate[]{ new Coordinate(-110.0, 40.0), - new Coordinate(-110.0, 50.0) } ); - Geometry l2 = pointsToGeometry( new Coordinate[]{ new Coordinate(-90., 40.0), - new Coordinate(-100.0, 45.0) } ); - Geometry l3 = pointsToGeometry( new Coordinate[]{ new Coordinate(-90., 40.0), - new Coordinate(-115.0, 40.0) } ); - - Geometry a7 = l1.intersection( l2 ); - System.out.println( "a7="+ a7.getCoordinates().length ); - - Geometry a8 = l1.intersection( l3 ); - System.out.println( "a8="+ a8.getCoordinates().length ); - Geometry g1 = pointsToGeometry( new Coordinate[]{ - new Coordinate(-110.0, 47.9), - new Coordinate(-104.0, 46.85), - new Coordinate(-104.0, 42.80), - new Coordinate(-110.0, 43.0)} ); - - Geometry g2 = pointsToGeometry( new Coordinate[]{ - new Coordinate(-104.0, 46.85), - new Coordinate(-97.0, 46.4), - new Coordinate(-98, 42.8), - new Coordinate(-104.0, 42.80) }); - - Geometry u1 = g1.union( g2 ); - System.out.println( "\nTest union of two polygons clipped from one polygon:" ); - for ( Coordinate c : u1.getCoordinates() ) { - System.out.println( c.y+","+c.x); + Coordinate[] outp = gList.toArray(new Coordinate[gList.size()]); + + return pointsToGeometry(outp); + + } + + /** + * Finds and replaces the points in a Geometry with its pair. + */ + protected Geometry replacePts(Geometry geom, + HashMap pairs) { + + Coordinate[] poly = geom.getCoordinates(); + Coordinate[] pts = new Coordinate[poly.length - 1]; // remove last point + + for (int ii = 0; ii < (poly.length - 1); ii++) { + + pts[ii] = new Coordinate(poly[ii]); + + if (pairs != null) { + for (Coordinate p : pairs.keySet()) { + if (Math.abs(poly[ii].x - p.x) < SMALLF + && Math.abs(poly[ii].y - p.y) < SMALLF) { + pts[ii] = new Coordinate(pairs.get(p)); + break; + } + } + } } - - ArrayList uniquePts = new ArrayList(); - for ( Coordinate c : u1.getCoordinates() ) { - if ( Arrays.asList( g1.getCoordinates() ).contains( c ) && - Arrays.asList( g2.getCoordinates() ).contains( c ) ) { - } - else { - uniquePts.add( c ); - } - } - - System.out.println( "\nUnique points found:" ); - for ( Coordinate c : uniquePts ) { - System.out.println( c.y+","+c.x); - } - - Geometry p1 = pointsToGeometry( new Coordinate[]{ new Coordinate(20, 10), new Coordinate(30, 20), - new Coordinate(40,10) } ); - Geometry p2 = pointsToGeometry( new Coordinate[]{ new Coordinate(20, 10) } ); - System.out.println( "\nTest:" ); - - if ( p1.covers( p2 )) { - System.out.println( "Covered"); - } - else { - System.out.println( "Not Covered"); - } - - if ( p2.intersects( p1 )) { - System.out.println( "Intersect"); - } - else { - System.out.println( "Not Intersect"); - } - /* - Coordinate s1 = new Coordinate( 0, 0); - Coordinate s2 = new Coordinate( 100, 100); - - Coordinate t1 = new Coordinate( 0, 0); - Coordinate t2 = new Coordinate( -100, -100); - - Coordinate o1 = new Coordinate( 0, 100 ); - Coordinate o2 = new Coordinate( 0, -100 ); - - if ( onLeft( o1, s1, s2 ) ) { - System.out.println( "o1 is at left of s1s2 " ); - } - else { - System.out.println( "o1 is at right of s1s2 " ); - } - - if ( onLeft( o2, s1, s2 ) ) { - System.out.println( "o2 is at left of s1s2 " ); - } - else { - System.out.println( "o2 is at right of s1s2 " ); - } - - if ( onLeft( o1, t1, t2 ) ) { - System.out.println( "o1 is at left of t1t2 " ); - } - else { - System.out.println( "o1 is at right of t1t2 " ); // - } - - if ( onLeft( o2, t1, t2 ) ) { - System.out.println( "o2 is at left of t1t2 " ); - } - else { - System.out.println( "o2 is at right of t1t2 " ); - } - */ - - } + return pointsToGeometry(pts); + + } + + /** + * Flags a set of points in a GFA element as non-reduce-able they are in tie + * distance of one of the non-reduce-able points. This strategy helps to + * preserve the integrity of the boundary after clipping and point + * reduction. + * + * The non-reduce-able points includes: all the FA regional boundary points, + * the snapped intersection points of the original GFA with the FA + * international and common regional bounds, as well as the points + * immediately before and such a non-reduce-able point. + */ + private void addReduceFlags(Gfa elm, CoordinateList pts) { + + // Note: the first point is not repeated at the end for a + // DrawableElement. + Coordinate[] poly = elm.getLinePoints(); + int np = poly.length; + boolean[] reduceable = new boolean[np]; + for (int ii = 0; ii < np; ii++) { + reduceable[ii] = true; + } + + for (int ii = 0; ii < np; ii++) { + for (int jj = 0; jj < pts.size(); jj++) { + if (Math.abs(poly[ii].x - pts.getCoordinate(jj).x) < SMALLF + && Math.abs(poly[ii].y - pts.getCoordinate(jj).y) < SMALLF) { + reduceable[ii] = false; + reduceable[(ii - 1 + np) % np] = false; + reduceable[(ii + 1 + np) % np] = false; + break; + } + } + } + + elm.setReduceFlags(reduceable); + + } + + /** + * Finds the common points between two sets of Geometries. + */ + public ArrayList getCommonPoints(ArrayList big, + ArrayList small) { + + ArrayList commPts = new ArrayList(); + + for (Geometry g1 : big) { + for (Geometry g2 : small) { + if (g1.intersects(g2)) { + for (Coordinate c : g1.intersection(g2).getCoordinates()) { + if (!commPts.contains(c)) { + commPts.add(new Coordinate(c)); + } + } + } + } + } + + return commPts; + } + + /** + * Remove a list of points from a Geometry and form a new Geometry. + */ + public Geometry removeCommonPoints(Geometry gm, ArrayList pts) { + + if (pts == null || pts.size() == 0) { + return gm; + } + + ArrayList newPts = new ArrayList(); + + Coordinate[] gPts = gm.getCoordinates(); + + for (int ii = 0; ii < (gPts.length - 1); ii++) { + if (!pts.contains(gPts[ii])) { + newPts.add(new Coordinate(gPts[ii])); + } + } + + return pointsToGeometry(newPts); + + } + + /** + * Load all bounds needed for Gfa processing. + */ + public void loadGfaBounds() { + + // States, FA Regions, FA Areas, Fa extended Areas. + getStateBounds(); + getFaRegionBounds(); + getFaAreaBounds(); + getFaAreaXBounds(); + + getGreatLakeBounds(); + getCoastalWaterBounds(); + getFaInternationalBound(); + getMtObscStates(); + + getFaRegionCommBounds(); + getFaAreaXCommBounds(); + + // Convert to grid coordinates. + updateGfaBoundsInGrid(); + + // Snap points + SnapVOR.getSnapStns(null, 16); + + } + + /** + * Update all bounds needed for Gfa processing. + */ + public void updateGfaBoundsInGrid() { + + faInternationalBoundInGrid = geometryInGrid(getFaInternationalBound()); + + faRegionBoundsInGrid = updateBoundsInGrid(getFaRegionBounds()); + faAreaBoundsInGrid = updateBoundsInGrid(getFaAreaBounds()); + faAreaXBoundsInGrid = updateBoundsInGrid(getFaAreaXBounds()); + + stateBoundsInGrid = updateBoundsInGrid(getStateBounds()); + + /* + * stateBoundsInGrid = updateBoundsInGrid( getStateBounds() ); + * StringBuilder invalidSts = new StringBuilder(); for ( String key : + * stateBoundsInGrid.keySet() ) { Geometry g1 = stateBounds.get( key ); + * Geometry g2 = stateBoundsInGrid.get( key ); + * + * if ( !g1.isValid() || (g1.isValid() && !g2.isValid()) ) { + * invalidSts.append( " " + key ); } } + * + * System.out.println( "Invalid state = " + invalidSts ); + * + * for ( String key : stateBoundsInGrid.keySet() ) { Geometry g1 = + * stateBounds.get( key ); Geometry g2 = stateBoundsInGrid.get( key ); + * System.out.println( "Original State Bound for " + key + " is " + + * g1.isValid() ); System.out.println( "\tState Bound in Grid for " + + * key + " is " + g2.isValid() ); } stateBoundsInGrid = + * updateBoundsInGrid( getStateBounds() ); + */ + greatLakesBoundsInGrid = updateBoundsInGrid(getGreatLakeBounds()); + coastalWaterBoundsInGrid = updateBoundsInGrid(getCoastalWaterBounds()); + faRegionCommBoundsInGrid = updateBoundsInGrid(getFaRegionCommBounds()); + faAreaXCommBoundsInGrid = updateBoundsInGrid(getFaAreaXCommBounds()); + + } + + /** + * Load all bounds in grid coordinate. + */ + private HashMap updateBoundsInGrid( + HashMap bndInMap) { + + HashMap bndInGrid = new HashMap(); + + for (String bname : bndInMap.keySet()) { + bndInGrid.put(bname, geometryInGrid(bndInMap.get(bname))); + } + + return bndInGrid; + + } + + /** + * Getters for all bounds in grid coordinate. + */ + public Geometry getFaInternationalBoundInGrid() { + return faInternationalBoundInGrid; + } + + public HashMap getFaRegionBoundsInGrid() { + return faRegionBoundsInGrid; + } + + public HashMap getFaAreaBoundsInGrid() { + return faAreaBoundsInGrid; + } + + public HashMap getFaAreaXBoundsInGrid() { + return faAreaXBoundsInGrid; + } + + public HashMap getStateBoundsInGrid() { + return stateBoundsInGrid; + } + + public HashMap getGreatLakesBoundsInGrid() { + return greatLakesBoundsInGrid; + } + + public HashMap getCoastalWaterBoundsInGrid() { + return coastalWaterBoundsInGrid; + } + + public HashMap getFaRegionCommBoundsInGrid() { + return faRegionCommBoundsInGrid; + } + + public HashMap getFaAreaXCommBoundsInGrid() { + return faAreaXCommBoundsInGrid; + } + + /* + * Convert a Geometry in map coordinate into grid coordinate. + */ + private Geometry geometryInGrid(Geometry geomInMap) { + + Geometry gout = null; + if (geomInMap instanceof Polygon || geomInMap instanceof MultiPolygon) { + + Polygon[] polygons = new Polygon[geomInMap.getNumGeometries()]; + + for (int ii = 0; ii < geomInMap.getNumGeometries(); ii++) { + Geometry g = geomInMap.getGeometryN(ii); + Coordinate[] gpts = g.getCoordinates(); + Coordinate[] gpts1 = Arrays.copyOf(gpts, gpts.length - 1); + Coordinate[] pts = PgenUtil.latlonToGrid(gpts1); + + polygons[ii] = pointsToPolygon(pts); + } + + gout = geometryFactory.createMultiPolygon(polygons); + } else if (geomInMap instanceof LineString) { + Coordinate[] gpts = geomInMap.getCoordinates(); + Coordinate[] pts = PgenUtil.latlonToGrid(gpts); + + gout = pointsToLineString(pts); + } + + return gout; + + } + + /** + * Try to write state bounds in error to a PGEN line element for visual + * check. + */ + public void validateGfaBounds() { + writeErrorBound("FA_States_Map_Fixed", getStateBounds()); + } + + /* + * check the invalid polygons in state bounds and write each state into a + * PGEN file. + */ + private void writeErrorBound(String bndName, + HashMap bndMap) { + + ArrayList errorStates = new ArrayList(); + // for ( String s : WRONG_STATES ) { + // errorStates.add( s ); + // } + + boolean isvalid = true; + + StringBuilder ss = new StringBuilder(); + for (String key : bndMap.keySet()) { + ss.append(key + " "); + } + + StringBuilder as = new StringBuilder(); + for (String key : bndMap.keySet()) { + + Product activeProduct = new Product("Default", "Default", + "Default", new ProductInfo(), new ProductTime(), + new ArrayList()); + + Layer activeLayer = new Layer(); + activeProduct.addLayer(activeLayer); + + List productList = new ArrayList(); + productList.add(activeProduct); + + Geometry g = bndMap.get(key); + + ArrayList pts = new ArrayList(); + + // if ( errorStates.contains( key ) ) { + isvalid = g.isValid(); + if (!isvalid) { + as.append(" " + key); + System.out.println("\tInvalid Bound " + key + "\t " + + g.getNumGeometries()); + } + + // if ( !g.isValid() ) { + + System.out.println("\tProcess Bound " + key + "\t " + + g.getNumGeometries()); + + for (int jk = 0; jk < g.getNumGeometries(); jk++) { + + pts.clear(); // !!! + + Geometry one = g.getGeometryN(jk); + + for (Coordinate c : one.getCoordinates()) { + pts.add(new Coordinate(c)); + } + pts.remove(pts.size() - 1); + + Line cline = new Line(null, new Color[] { Color.red }, 2.0f, + 1.0, true, false, pts, 0, FillPattern.SOLID, "Lines", + "LINE_SOLID"); + String str = ""; + str = str + key + "_" + jk; + + Text lbl = new Text(null, "Courier", 14.0f, + TextJustification.CENTER, null, 0.0, + TextRotation.SCREEN_RELATIVE, new String[] { str }, + FontStyle.REGULAR, Color.GREEN, 0, 0, true, + DisplayType.NORMAL, "Text", "General Text"); + lbl.setLocation(cline.getLinePoints()[0]); + + // activeLayer.add( lbl ); + activeLayer.add(cline); + } + + /* + * Write into a file. + */ + if (productList.get(0).getLayer(0).getDrawables().size() > 0) { + Products filePrds = ProductConverter.convert(productList); + String a; + if (isvalid) { + a = "/export/cdbsrv/jwu/stateBnd/" + bndName + "_high_" + + key + "_correct_nolabel.xml"; + } else { + a = "/export/cdbsrv/jwu/stateBnd/" + bndName + "_high_" + + key + "_icorrect_nolabel.xml"; + } + System.out.println("Write to validation file: " + a); + FileTools.write(a, filePrds); + } + } + + System.out.println("Invalid states are: " + as); + + // } + } + + /* + * Fixes the incorrect state bounds for a few states. + */ + private HashMap fixStateBounds( + HashMap stateBnd) { + + HashMap fixedBounds = new HashMap(); + + ArrayList errorStates = new ArrayList(); + for (String s : WRONG_STATES) { + errorStates.add(s); + } + + for (String key : stateBnd.keySet()) { + + Geometry g = stateBnd.get(key); + + if (!errorStates.contains(key)) { + fixedBounds.put(key, g); + } else { + ArrayList pts = new ArrayList(); + + Polygon[] polygons = new Polygon[g.getNumGeometries()]; + + for (int jk = 0; jk < g.getNumGeometries(); jk++) { + + pts.clear(); // !!! + + Geometry one = g.getGeometryN(jk); + Coordinate[] bpts = one.getCoordinates(); + Coordinate firstPt = bpts[0]; + pts.add(firstPt); + int nn = 1; + while (!bpts[nn].equals(firstPt) && nn < bpts.length) { + pts.add(bpts[nn]); + nn++; + } + + polygons[jk] = pointsToPolygon(pts + .toArray(new Coordinate[pts.size()])); + } + + MultiPolygon multipolygon = geometryFactory + .createMultiPolygon(polygons); + + fixedBounds.put(key, multipolygon); + } + } + + return fixedBounds; + } + + /* + * Find the first occurrence of a point in an array. + * + * @param pt + * + * @param list + * + * @param tie + */ + private int findPoint(Coordinate pt, List list, double tie) { + + int indx = -1; + + if (pt != null && list != null) { + for (int ii = 0; ii < list.size(); ii++) { + if (isSamePoint(pt, list.get(ii), tie)) { + indx = ii; + break; + } + } + } + + return indx; + + } + + /* + * Some tests for JTS, could be removed later. + */ + public void testJTS() { + Coordinate[] polyPts = new Coordinate[] { new Coordinate(-110.0, 40.0), + new Coordinate(-110.0, 50.0), new Coordinate(-90.0, 50.0), + new Coordinate(-90.0, 40.0) }; + Geometry poly = pointsToGeometry(polyPts); + Geometry bndPts = pointsToGeometry(new Coordinate[] { new Coordinate( + -110.0, 50.0) }); + Geometry inPts = pointsToGeometry(new Coordinate[] { new Coordinate( + -100.0, 45.0) }); + Geometry outPts = pointsToGeometry(new Coordinate[] { new Coordinate( + -100.0, 30.0) }); + + Geometry a1 = bndPts.intersection(poly); + Geometry a2 = inPts.intersection(poly); + Geometry a3 = outPts.intersection(poly); + + Geometry bndlin = pointsToGeometry(new Coordinate[] { + new Coordinate(-110.0, 50.0), new Coordinate(-110.0, 40.0) }); + + Geometry inlin = pointsToGeometry(new Coordinate[] { + new Coordinate(-110.0, 50.0), new Coordinate(-100.0, 45.0) }); + + Geometry outlin = pointsToGeometry(new Coordinate[] { + new Coordinate(-110.0, 50.0), new Coordinate(-100.0, 30.0) }); + Geometry a4 = bndlin.intersection(poly); + Geometry a5 = inlin.intersection(poly); + Geometry a6 = outlin.intersection(poly); + + System.out.println("\n\na1=" + a1.getCoordinates().length); + System.out.println("a2=" + a2.getCoordinates().length); + System.out.println("a3=" + a3.getCoordinates().length); + System.out.println("a4=" + a4.getCoordinates().length); + System.out.println("a5=" + a5.getCoordinates().length); + System.out.println("a6=" + a6.getCoordinates().length); + + Geometry l1 = pointsToGeometry(new Coordinate[] { + new Coordinate(-110.0, 40.0), new Coordinate(-110.0, 50.0) }); + Geometry l2 = pointsToGeometry(new Coordinate[] { + new Coordinate(-90., 40.0), new Coordinate(-100.0, 45.0) }); + Geometry l3 = pointsToGeometry(new Coordinate[] { + new Coordinate(-90., 40.0), new Coordinate(-115.0, 40.0) }); + + Geometry a7 = l1.intersection(l2); + System.out.println("a7=" + a7.getCoordinates().length); + + Geometry a8 = l1.intersection(l3); + System.out.println("a8=" + a8.getCoordinates().length); + + Geometry g1 = pointsToGeometry(new Coordinate[] { + new Coordinate(-110.0, 47.9), new Coordinate(-104.0, 46.85), + new Coordinate(-104.0, 42.80), new Coordinate(-110.0, 43.0) }); + + Geometry g2 = pointsToGeometry(new Coordinate[] { + new Coordinate(-104.0, 46.85), new Coordinate(-97.0, 46.4), + new Coordinate(-98, 42.8), new Coordinate(-104.0, 42.80) }); + + Geometry u1 = g1.union(g2); + System.out + .println("\nTest union of two polygons clipped from one polygon:"); + for (Coordinate c : u1.getCoordinates()) { + System.out.println(c.y + "," + c.x); + } + + ArrayList uniquePts = new ArrayList(); + for (Coordinate c : u1.getCoordinates()) { + if (Arrays.asList(g1.getCoordinates()).contains(c) + && Arrays.asList(g2.getCoordinates()).contains(c)) { + } else { + uniquePts.add(c); + } + } + + System.out.println("\nUnique points found:"); + for (Coordinate c : uniquePts) { + System.out.println(c.y + "," + c.x); + } + + Geometry p1 = pointsToGeometry(new Coordinate[] { + new Coordinate(20, 10), new Coordinate(30, 20), + new Coordinate(40, 10) }); + Geometry p2 = pointsToGeometry(new Coordinate[] { new Coordinate(20, 10) }); + System.out.println("\nTest:"); + + if (p1.covers(p2)) { + System.out.println("Covered"); + } else { + System.out.println("Not Covered"); + } + + if (p2.intersects(p1)) { + System.out.println("Intersect"); + } else { + System.out.println("Not Intersect"); + } + + /* + * Coordinate s1 = new Coordinate( 0, 0); Coordinate s2 = new + * Coordinate( 100, 100); + * + * Coordinate t1 = new Coordinate( 0, 0); Coordinate t2 = new + * Coordinate( -100, -100); + * + * Coordinate o1 = new Coordinate( 0, 100 ); Coordinate o2 = new + * Coordinate( 0, -100 ); + * + * if ( onLeft( o1, s1, s2 ) ) { System.out.println( + * "o1 is at left of s1s2 " ); } else { System.out.println( + * "o1 is at right of s1s2 " ); } + * + * if ( onLeft( o2, s1, s2 ) ) { System.out.println( + * "o2 is at left of s1s2 " ); } else { System.out.println( + * "o2 is at right of s1s2 " ); } + * + * if ( onLeft( o1, t1, t2 ) ) { System.out.println( + * "o1 is at left of t1t2 " ); } else { System.out.println( + * "o1 is at right of t1t2 " ); // } + * + * if ( onLeft( o2, t1, t2 ) ) { System.out.println( + * "o2 is at left of t1t2 " ); } else { System.out.println( + * "o2 is at right of t1t2 " ); } + */ + + } - } diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/graphtogrid/ContoursToGrid.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/graphtogrid/ContoursToGrid.java index c4f5e562ec..e846a50f29 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/graphtogrid/ContoursToGrid.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/graphtogrid/ContoursToGrid.java @@ -58,6 +58,7 @@ import com.vividsolutions.jts.geom.impl.CoordinateArraySequence; * a GEMPAK grid file * 09/10 #215 J. Wu Checked working directory and PATH. * 11/10 #345 J. Wu Added support for circle. + * 05/14 TTR989 J. Wu Allow environmental variable in PATH. * * * @@ -418,26 +419,61 @@ public class ContoursToGrid extends GraphToGrid { } } - String fullFile = new String(path + "/" + gdoutf); - /* + * GEMPAK cannot accept a PATH with upper case letter, however, it takes + * environmental variables (which is UPPER CASE!). So we need to parse + * the environmental variables in the PATH before checking upper case + * characters. + * * Check if the PATH is valid and exists */ - File grdfile = new File(path); - - Pattern ptn = Pattern.compile("[A-Z]"); - Matcher mt = ptn.matcher(path); - String msg = null; - if (mt.find()) { - msg = new String("The PATH cannot have upper case in it"); - } else { - if (!grdfile.exists()) { - msg = new String( - "The PATH does not exist, please create it first"); + + String[] dirs = path.split(File.separator); + StringBuilder rpath = new StringBuilder(); + for (String str : dirs) { + if (str.trim().startsWith("$")) { + String val = System.getenv(str.substring(1)); + if (val != null) { + rpath.append(val); + rpath.append(File.separator); + } else { + msg = new String(str + " is not defined."); + rpath = new StringBuilder(path); + break; + } + } else if (str.trim().startsWith("~")) { + rpath.append(System.getProperty("user.home")); + rpath.append(File.separator); + } else { + rpath.append(str); + rpath.append(File.separator); } } + String fpath = rpath.toString(); + if (fpath.endsWith(File.separator)) { + fpath = fpath.substring(0, fpath.length() - 1); + } + + Pattern ptn = Pattern.compile("[A-Z]"); + Matcher mt = ptn.matcher(fpath); + + File grdfile = new File(fpath); + + if (msg == null) { + if (mt.find()) { + msg = new String("The PATH cannot have upper case in it"); + } else { + if (!grdfile.exists()) { + msg = new String( + "The PATH does not exist, please create it first"); + } + } + } + + String fullFile = new String(fpath + "/" + gdoutf); + if (msg != null) { MessageDialog msgDlg = new MessageDialog(PlatformUI.getWorkbench() @@ -893,4 +929,4 @@ public class ContoursToGrid extends GraphToGrid { return points; } -} +} \ No newline at end of file diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/graphtogrid/GraphToGridParamDialog.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/graphtogrid/GraphToGridParamDialog.java index 4cf2d9a353..355e409c71 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/graphtogrid/GraphToGridParamDialog.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/graphtogrid/GraphToGridParamDialog.java @@ -19,8 +19,10 @@ import gov.noaa.nws.ncep.ui.pgen.contours.ContourLine; import gov.noaa.nws.ncep.ui.pgen.contours.ContourMinmax; import gov.noaa.nws.ncep.ui.pgen.contours.Contours; import gov.noaa.nws.ncep.ui.pgen.contours.IContours; +import gov.noaa.nws.ncep.ui.pgen.elements.AbstractDrawableComponent; import gov.noaa.nws.ncep.ui.pgen.elements.DECollection; import gov.noaa.nws.ncep.ui.pgen.elements.DrawableElement; +import gov.noaa.nws.ncep.ui.pgen.elements.Outlook; import gov.noaa.nws.ncep.ui.pgen.rsc.PgenResource; import gov.noaa.nws.ncep.viz.gempak.nativelib.LibraryLoader; @@ -30,6 +32,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.HashMap; +import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.TimeZone; @@ -70,6 +73,7 @@ import com.raytheon.viz.ui.editor.AbstractEditor; * 10/11 ? J. Wu Remove entry if the given table does not exist. * 08/13 TTR778 J. Wu Load libg2g when this dialog is created. * 12/13 1090 J. Wu Allow either table or element applied to g2g. + * 05/14 TTR989 J. Wu Find current contour via contour parameters. * * * @@ -858,11 +862,12 @@ public class GraphToGridParamDialog extends CaveJFACEDialog { if (cntAttrDlg instanceof ContoursAttrDlg) { + // First try to get from dialog curCnt = ((ContoursAttrDlg) cntAttrDlg).getCurrentContours(); + // Then try to get from the selected DE's parent.... if (curCnt == null) { DrawableElement de = drawingLayer.getSelectedDE(); - if (de != null && (de.getParent() instanceof ContourLine || de.getParent() instanceof ContourMinmax || de @@ -871,6 +876,27 @@ public class GraphToGridParamDialog extends CaveJFACEDialog { curCnt = (Contours) de.getParent().getParent(); } } + + // Finally try to get from PgenResource - matching this contour + // dialog's attributes. + if (curCnt == null) { + Iterator it = drawingLayer + .getActiveLayer().getComponentIterator(); + while (it.hasNext()) { + AbstractDrawableComponent de = it.next(); + if (de instanceof Contours && !(de instanceof Outlook)) { + Contours thisContour = (Contours) de; + ContoursAttrDlg thisDlg = (ContoursAttrDlg) cntAttrDlg; + + if (thisContour.getKey().equals( + Contours.getKey(thisDlg))) { + curCnt = (Contours) de; + break; + } + } + } + } + } else if (cntAttrDlg instanceof OutlookAttrDlg) { curCnt = ((OutlookAttrDlg) cntAttrDlg).getCurrentOtlk(); } @@ -1076,4 +1102,4 @@ public class GraphToGridParamDialog extends CaveJFACEDialog { return cints; } -} +} \ No newline at end of file diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/tools/PgenModifyTool.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/tools/PgenModifyTool.java index dace184fc5..4c9945b74e 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/tools/PgenModifyTool.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/tools/PgenModifyTool.java @@ -1,4 +1,3 @@ - /* * gov.noaa.nws.ncep.ui.pgen.rsc.PgenModifyTool * @@ -9,25 +8,25 @@ package gov.noaa.nws.ncep.ui.pgen.tools; -import java.util.ArrayList; -import java.awt.Color; +import gov.noaa.nws.ncep.ui.pgen.PgenUtil; +import gov.noaa.nws.ncep.ui.pgen.annotation.Operation; +import gov.noaa.nws.ncep.ui.pgen.elements.Arc; +import gov.noaa.nws.ncep.ui.pgen.elements.DrawableElement; +import gov.noaa.nws.ncep.ui.pgen.elements.Jet; +import gov.noaa.nws.ncep.ui.pgen.elements.Line; +import gov.noaa.nws.ncep.ui.pgen.elements.MultiPointElement; +import gov.noaa.nws.ncep.ui.pgen.filter.OperationFilter; +import gov.noaa.nws.ncep.ui.pgen.gfa.Gfa; +import gov.noaa.nws.ncep.ui.pgen.gfa.GfaReducePoint; +import java.awt.Color; +import java.util.ArrayList; + +import com.raytheon.uf.viz.core.map.IMapDescriptor; import com.raytheon.uf.viz.core.rsc.IInputHandler; import com.vividsolutions.jts.geom.Coordinate; //import gov.noaa.nws.ncep.ui.display.InputHandlerDefaultImpl; -import gov.noaa.nws.ncep.ui.pgen.PgenUtil; -import gov.noaa.nws.ncep.ui.pgen.annotation.Operation; -import gov.noaa.nws.ncep.ui.pgen.elements.Jet; -import gov.noaa.nws.ncep.ui.pgen.elements.Line; -import gov.noaa.nws.ncep.ui.pgen.elements.Arc; -import gov.noaa.nws.ncep.ui.pgen.elements.MultiPointElement; -import gov.noaa.nws.ncep.ui.pgen.elements.DrawableElement; -import gov.noaa.nws.ncep.ui.pgen.filter.OperationFilter; -import gov.noaa.nws.ncep.ui.pgen.gfa.Gfa; -import gov.noaa.nws.ncep.ui.pgen.gfa.GfaReducePoint; -import gov.noaa.nws.ncep.ui.pgen.tools.PgenModifyLine; - /** * Implements a modal map tool for PGEN Line Modification function. @@ -44,372 +43,434 @@ import gov.noaa.nws.ncep.ui.pgen.tools.PgenModifyLine; * Moved snap functionalities to SnapUtil from SigmetInfo. * 05/12 #808 J. Wu Update GFA vor text * 05/12 #610 J. Wu Add warning when GFA FROM lines > 3 - * + * 05/12 TTR 998 J. Wu Use mapDescriptor's pixelToWorld instead of PaneManager's + * translateClick() to convert point - translateClick() may + * fail to convert if a point is outside of Grid coverage. + * * * - * @author J. Wu + * @author J. Wu */ public class PgenModifyTool extends AbstractPgenTool { - + /** * Input handler for mouse events. - */ + */ protected IInputHandler modifyHandler = null; - - + public PgenModifyTool() { - - super(); - + + super(); + } - + /** * Returns the current mouse handler. + * * @return - */ - public IInputHandler getMouseHandler() { - - if ( this.modifyHandler == null ) { - - this.modifyHandler = new PgenModifyHandler(); - + */ + public IInputHandler getMouseHandler() { + + if (this.modifyHandler == null) { + + this.modifyHandler = new PgenModifyHandler(); + } return this.modifyHandler; - + } - + /** * Implements input handler for mouse events. + * * @author bingfan - * + * */ public class PgenModifyHandler extends InputHandlerDefaultImpl { - - private boolean preempt; - OperationFilter modifyFilter = new OperationFilter( Operation.MODIFY ); - - /** - * Array list to hold clicked points. - */ + + private boolean preempt; + + OperationFilter modifyFilter = new OperationFilter(Operation.MODIFY); + + /** + * Array list to hold clicked points. + */ ArrayList clickPts = null; - - /** - * Ghost element that shows the modified element. - */ - MultiPointElement ghostEl = null; - - /** - * Instance for performing modification. - */ - PgenModifyLine pml = null; - - /** - * Color of the ghost element. - */ - Color ghostColor = new java.awt.Color( 255,255,255); - + + /** + * Ghost element that shows the modified element. + */ + MultiPointElement ghostEl = null; + + /** + * Instance for performing modification. + */ + PgenModifyLine pml = null; + + /** + * Color of the ghost element. + */ + Color ghostColor = new java.awt.Color(255, 255, 255); + /* * (non-Javadoc) * * @see com.raytheon.viz.ui.input.IInputHandler#handleMouseDown(int, - * int, int) + * int, int) */ - @Override - public boolean handleMouseDown( int anX, int aY, int button ) { - if ( !isResourceEditable() ) return false; + @Override + public boolean handleMouseDown(int anX, int aY, int button) { + if (!isResourceEditable()) + return false; - preempt = false; - // Check if mouse is in geographic extent - Coordinate loc = mapEditor.translateClick(anX, aY); - if ( loc == null || shiftDown ) return false; - - if ( button == 1 ) { + preempt = false; + // Check if mouse is in geographic extent + Coordinate loc = mapEditor.translateClick(anX, aY); + if (loc == null || shiftDown) + return false; - if ( drawingLayer.getSelectedDE() == null ) { - - // Get the nearest element and set it as the selected element. - DrawableElement elSelected = drawingLayer.getNearestElement( loc, modifyFilter); - if (( (elSelected instanceof Line) && !(elSelected instanceof Arc ) ) || isModifiableSigmet(elSelected)) { - drawingLayer.setSelected( elSelected ); - mapEditor.refresh(); - preempt = true; - } - else { - return false; - } - } - else { - preempt = true; - - if ( clickPts == null ) { - clickPts = new ArrayList(); - } - - clickPts.add( loc ); - - if ( pml == null ) { - pml = new PgenModifyLine(); - } - - pml.setClickPts( latlonToPixel( clickPts.toArray( new Coordinate[clickPts.size()] ) ) ); - - ModifyLine(); - - ghostEl.setColors(new Color[]{ ghostColor, new java.awt.Color( 255,255,255)}); + if (button == 1) { - drawingLayer.setGhostLine( ghostEl) ; - mapEditor.refresh(); - - } - - return preempt; - - } - else if ( button == 3 ) { - - if ( drawingLayer.getSelectedDE() != null ) { - - if ( clickPts != null && !clickPts.isEmpty() ) { - - pml.setClickPts( latlonToPixel( clickPts.toArray( new Coordinate[clickPts.size()] ) ) ); - - ModifyLine(); - - if ( ! ( ((Line)drawingLayer.getSelectedDE()).isClosedLine() && - ((MultiPointElement)ghostEl).getLinePoints().length < 3 ) ) { - - MultiPointElement selected = (MultiPointElement)drawingLayer.getSelectedDE(); - - if ( selected instanceof Jet.JetLine ){ - - Jet jet = (Jet)drawingLayer.getActiveLayer().search(selected); - Jet newJet = jet.copy(); - drawingLayer.replaceElement(jet, newJet); - newJet.getPrimaryDE().setPoints( ghostEl.getPoints()); - drawingLayer.setSelected(newJet.getPrimaryDE()); - } - else { - MultiPointElement mpe = (MultiPointElement)drawingLayer.getSelectedDE().copy(); + if (drawingLayer.getSelectedDE() == null) { - drawingLayer.replaceElement( drawingLayer.getSelectedDE(), mpe ); - - //need snapping, get ghostEl's points with mpe's pgenType - /*if( isModifiableSigmet(mpe)){ - ArrayList list = SigmetInfo.getSnapWithStation( - ghostEl.getPoints(), - SigmetInfo.VOR_STATION_LIST, - 10, - SigmetInfo.getNumOfCompassPts(mpe)); - //ArrayList list2 = SigmetInfo.getNonDplicList(list); - mpe.setPoints(list);//2); - }else*/ - - mpe.setPoints(ghostEl.getPoints()); - if ( mpe instanceof Gfa ) { - if( ((Gfa)mpe).getGfaFcstHr().indexOf("-") > -1 ){ - // snap - ((Gfa)mpe).snap(); - - GfaReducePoint.WarningForOverThreeLines( (Gfa)mpe ); - } - + // Get the nearest element and set it as the selected + // element. + DrawableElement elSelected = drawingLayer + .getNearestElement(loc, modifyFilter); + if (((elSelected instanceof Line) && !(elSelected instanceof Arc)) + || isModifiableSigmet(elSelected)) { + drawingLayer.setSelected(elSelected); + mapEditor.refresh(); + preempt = true; + } else { + return false; + } + } else { + preempt = true; + + if (clickPts == null) { + clickPts = new ArrayList(); + } + + clickPts.add(loc); + + if (pml == null) { + pml = new PgenModifyLine(); + } + + pml.setClickPts(latlonToPixel(clickPts + .toArray(new Coordinate[clickPts.size()]))); + + ModifyLine(); + + ghostEl.setColors(new Color[] { ghostColor, + new java.awt.Color(255, 255, 255) }); + + drawingLayer.setGhostLine(ghostEl); + mapEditor.refresh(); - ((Gfa)mpe).setGfaVorText( Gfa.buildVorText( (Gfa)mpe )); - } - - drawingLayer.setSelected( mpe ); - } - } - - drawingLayer.removeGhostLine(); - clickPts.clear(); - - mapEditor.refresh(); - - } - else { - - ghostEl = null; - - drawingLayer.removeGhostLine(); - drawingLayer.removeSelected(); - mapEditor.refresh(); - - } - } - else { - - drawingLayer.removeSelected(); - mapEditor.refresh(); - - // set selecting mode - PgenUtil.setSelectingMode(); - + + return preempt; + + } else if (button == 3) { + + if (drawingLayer.getSelectedDE() != null) { + + if (clickPts != null && !clickPts.isEmpty()) { + + pml.setClickPts(latlonToPixel(clickPts + .toArray(new Coordinate[clickPts.size()]))); + + ModifyLine(); + + if (!(((Line) drawingLayer.getSelectedDE()) + .isClosedLine() && ((MultiPointElement) ghostEl) + .getLinePoints().length < 3)) { + + MultiPointElement selected = (MultiPointElement) drawingLayer + .getSelectedDE(); + + if (selected instanceof Jet.JetLine) { + + Jet jet = (Jet) drawingLayer.getActiveLayer() + .search(selected); + Jet newJet = jet.copy(); + drawingLayer.replaceElement(jet, newJet); + newJet.getPrimaryDE().setPoints( + ghostEl.getPoints()); + drawingLayer.setSelected(newJet.getPrimaryDE()); + } else { + MultiPointElement mpe = (MultiPointElement) drawingLayer + .getSelectedDE().copy(); + + drawingLayer.replaceElement( + drawingLayer.getSelectedDE(), mpe); + + // need snapping, get ghostEl's points with + // mpe's pgenType + /* + * if( isModifiableSigmet(mpe)){ + * ArrayList list = + * SigmetInfo.getSnapWithStation( + * ghostEl.getPoints(), + * SigmetInfo.VOR_STATION_LIST, 10, + * SigmetInfo.getNumOfCompassPts(mpe)); + * //ArrayList list2 = + * SigmetInfo.getNonDplicList(list); + * mpe.setPoints(list);//2); }else + */ + + mpe.setPoints(ghostEl.getPoints()); + if (mpe instanceof Gfa) { + if (((Gfa) mpe).getGfaFcstHr().indexOf("-") > -1) { + // snap + ((Gfa) mpe).snap(); + + GfaReducePoint + .WarningForOverThreeLines((Gfa) mpe); + } + + ((Gfa) mpe).setGfaVorText(Gfa + .buildVorText((Gfa) mpe)); + } + + drawingLayer.setSelected(mpe); + } + } + + drawingLayer.removeGhostLine(); + clickPts.clear(); + + mapEditor.refresh(); + + } else { + + ghostEl = null; + + drawingLayer.removeGhostLine(); + drawingLayer.removeSelected(); + mapEditor.refresh(); + + } + + } else { + + drawingLayer.removeSelected(); + mapEditor.refresh(); + + // set selecting mode + PgenUtil.setSelectingMode(); + } - - return true; + + return true; } - - else { - return false; + + else { + return false; } - + } /* * (non-Javadoc) * * @see com.raytheon.viz.ui.input.IInputHandler#handleMouseMove(int, - * int) + * int) */ @Override public boolean handleMouseMove(int x, int y) { - if ( !isResourceEditable() ) return false; + if (!isResourceEditable()) + return false; + + // Check if mouse is in geographic extent + Coordinate loc = mapEditor.translateClick(x, y); + if (loc == null) + return false; + + // create the ghost element and put it in the drawing layer + if (clickPts != null && clickPts.size() >= 1) { + + ArrayList newPts = new ArrayList( + clickPts); + newPts.add(loc); + + pml.setClickPts(latlonToPixel(newPts + .toArray(new Coordinate[newPts.size()]))); + + ModifyLine(); + + ghostEl.setColors(new Color[] { ghostColor, + new java.awt.Color(255, 255, 255) }); + drawingLayer.setGhostLine(ghostEl); + mapEditor.refresh(); - // Check if mouse is in geographic extent - Coordinate loc = mapEditor.translateClick(x, y); - if ( loc == null ) return false; - - // create the ghost element and put it in the drawing layer - if ( clickPts != null && clickPts.size() >= 1 ) { - - ArrayList newPts = new ArrayList( clickPts ); - newPts.add( loc ); - - pml.setClickPts( latlonToPixel( newPts.toArray( new Coordinate[newPts.size()] ) ) ); - - ModifyLine(); - - ghostEl.setColors(new Color[]{ ghostColor, new java.awt.Color( 255,255,255)}); - drawingLayer.setGhostLine( ghostEl) ; - mapEditor.refresh(); - } - - return true; - + + return true; + } /* * (non-Javadoc) * * @see com.raytheon.viz.ui.input.IInputHandler#handleMouseUp(int, int, - * int) + * int) */ @Override - public boolean handleMouseUp( int x, int y, int button) { - + public boolean handleMouseUp(int x, int y, int button) { + return false; - + } - - @Override - public boolean handleMouseDownMove(int x, int y, int mouseButton) { - if ( !isResourceEditable() || shiftDown ) return false; - else return preempt; - } - /** - * Set up a "modify" instance, perform modification and - * build a new modified element - */ - private void ModifyLine( ) { - - pml.setOriginalPts( latlonToPixel( ((Line)drawingLayer.getSelectedDE()).getLinePoints() ) ); - - pml.setSmoothLevel ( ((Line)drawingLayer.getSelectedDE()).getSmoothFactor() ); + @Override + public boolean handleMouseDownMove(int x, int y, int mouseButton) { + if (!isResourceEditable() || shiftDown) + return false; + else + return preempt; + } - pml.setClosed ( ((Line)drawingLayer.getSelectedDE()).isClosedLine() ); - - pml.PerformModify(); - - buildNewElement(); - - } - - /** - * Converts an array of lat/lons to pixel coordinates - * @param pts An array of points in lat/lon coordinates - * @return The array of points in pixel coordinates - */ - private double[][] latlonToPixel( Coordinate[] pts ) { - - double[] point = new double[2]; - double[][] pixels = new double[pts.length][2]; - - int ii = 0; - for ( Coordinate crd : pts ) { - - point = mapEditor.translateInverseClick( crd ); - pixels[ii][0] = point[0]; - pixels[ii][1] = point[1]; - - ii++; - } - - return pixels; - } + /** + * Set up a "modify" instance, perform modification and build a new + * modified element + */ + private void ModifyLine() { - - /** - * Converts an array of pixel coordinates to lat/lons - * @param pts An array of points in pixel coordinates - * @return The array of points in Lat/Lons - */ - private ArrayList pixelToLatlon( double[][] pixels ) { - - ArrayList crd = new ArrayList(); - - for ( int ii = 0; ii < pixels.length; ii++ ) { - crd.add( mapEditor.translateClick( pixels[ii][0], pixels[ii][1] ) ); - } - - return crd; - - } - - /** - * Build a new modified DrawableElement from a set of lat/lons - * @param pts An array of points in pixel coordinates - * @return The array of points in Lat/Lons - */ - private void buildNewElement() { - - ghostEl = (MultiPointElement)( drawingLayer.getSelectedDE().copy() ); - - if ( ghostEl != null && pml.getModifiedPts() != null && pml.getModifiedPts().length > 1 ) { - - ghostEl.setLinePoints( pixelToLatlon( pml.getModifiedPts() ) ); - - if ( ((Line)drawingLayer.getSelectedDE()).isClosedLine() ) { - if ( pml.getModifiedPts().length < 3 ) { - ghostEl.setClosed( false ); - } - } - } - } + pml.setOriginalPts(latlonToPixel(((Line) drawingLayer + .getSelectedDE()).getLinePoints())); + + pml.setSmoothLevel(((Line) drawingLayer.getSelectedDE()) + .getSmoothFactor()); + + pml.setClosed(((Line) drawingLayer.getSelectedDE()).isClosedLine()); + + pml.PerformModify(); + + buildNewElement(); + + } + + /** + * Converts an array of lat/lons to pixel coordinates + * + * @param pts + * An array of points in lat/lon coordinates + * @return The array of points in pixel coordinates + */ + private double[][] latlonToPixelOld(Coordinate[] pts) { + + double[] point = new double[2]; + double[][] pixels = new double[pts.length][2]; + + int ii = 0; + for (Coordinate crd : pts) { + + point = mapEditor.translateInverseClick(crd); + pixels[ii][0] = point[0]; + pixels[ii][1] = point[1]; + + ii++; + } + + return pixels; + } + + /** + * Converts an array of pixel coordinates to lat/lons + * + * @param pts + * An array of points in pixel coordinates + * @return The array of points in Lat/Lons + */ + private ArrayList pixelToLatlonOld(double[][] pixels) { + + ArrayList crd = new ArrayList(); + + for (int ii = 0; ii < pixels.length; ii++) { + crd.add(mapEditor.translateClick(pixels[ii][0], pixels[ii][1])); + } + + return crd; + + } + + /** + * Build a new modified DrawableElement from a set of lat/lons + * + * @param pts + * An array of points in pixel coordinates + * @return The array of points in Lat/Lons + */ + private void buildNewElement() { + + ghostEl = (MultiPointElement) (drawingLayer.getSelectedDE().copy()); + + if (ghostEl != null && pml.getModifiedPts() != null + && pml.getModifiedPts().length > 1) { + + ghostEl.setLinePoints(pixelToLatlon(pml.getModifiedPts())); + + if (((Line) drawingLayer.getSelectedDE()).isClosedLine()) { + if (pml.getModifiedPts().length < 3) { + ghostEl.setClosed(false); + } + } + } + } + + /** + * Converts an array of pixel coordinates to lat/lons + * + * @param pts + * An array of points in pixel coordinates + * @return The array of points in Lat/Lons + */ + private ArrayList pixelToLatlon(double[][] pixels) { + + return PgenUtil.pixelToLatlon(pixels, (IMapDescriptor) mapEditor + .getActiveDisplayPane().getRenderableDisplay() + .getDescriptor()); + + } + + /** + * Converts an array of lat/lons to pixel coordinates + * + * @param pts + * An array of points in lat/lon coordinates + * @return The array of points in pixel coordinates + */ + private double[][] latlonToPixel(Coordinate[] pts) { + return PgenUtil.latlonToPixel(pts, (IMapDescriptor) mapEditor + .getActiveDisplayPane().getRenderableDisplay() + .getDescriptor()); + } } - + /** * check if the DE is modifiable Sigmet. - * @param DrawableElement: DE to be checked. + * + * @param DrawableElement + * : DE to be checked. * @return boolean: true: the Sigmet is Modifiable. */ - private boolean isModifiableSigmet(DrawableElement el){ - - if(el instanceof gov.noaa.nws.ncep.ui.pgen.sigmet.Sigmet){ - gov.noaa.nws.ncep.ui.pgen.sigmet.Sigmet sig = (gov.noaa.nws.ncep.ui.pgen.sigmet.Sigmet) el; - - if( ! sig.getType().contains("Text") && ! sig.getType().contains("Isolated")) - return true; - } - - return false; - } - -} + private boolean isModifiableSigmet(DrawableElement el) { + if (el instanceof gov.noaa.nws.ncep.ui.pgen.sigmet.Sigmet) { + gov.noaa.nws.ncep.ui.pgen.sigmet.Sigmet sig = (gov.noaa.nws.ncep.ui.pgen.sigmet.Sigmet) el; + + if (!sig.getType().contains("Text") + && !sig.getType().contains("Isolated")) + return true; + } + + return false; + } + +} diff --git a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAM32-standard.xml b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAM32-standard.xml new file mode 100644 index 0000000000..e284e019a7 --- /dev/null +++ b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAM32-standard.xml @@ -0,0 +1,6 @@ + + + NAM32 + standard + 1000-500_thkn,1000-850_thkn,1000mb_hght_tmp_wind,100mb_hght_wind,200mb_hght_wind,250mb_ageo_div_isotachs,250mb_hght_wind,300mb_hght_wind,500mb_hght_absv_wnd,500mb_hght_color,500mb_hght_wind,500mb_hght_tmp_wind,700mb_hght_rh_omega,700mb_hght_tmp_wind,850-700_thkn,850mb_hght_tmp_wind,pmsl,pmsl_thkn + diff --git a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAM40-standard.xml b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAM40-standard.xml new file mode 100644 index 0000000000..a56dcaad00 --- /dev/null +++ b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAM40-standard.xml @@ -0,0 +1,6 @@ + + + NAM40 + standard + 1000-500_thkn,1000-850_thkn,1000mb_hght_tmp_wind,100mb_hght_wind,200mb_hght_wind,250mb_ageo_div_isotachs,250mb_hght_wind,300mb_hght_wind,500mb_hght_absv_wnd,500mb_hght_color,500mb_hght_wind,500mb_hght_tmp_wind,700mb_hght_rh_omega,700mb_hght_tmp_wind,850-700_thkn,850mb_hght_tmp_wind,pmsl,pmsl_thkn + diff --git a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAM5-standard.xml b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAM5-standard.xml new file mode 100644 index 0000000000..ee730ff096 --- /dev/null +++ b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAM5-standard.xml @@ -0,0 +1,6 @@ + + + NAM5 + standard + 1000-500_thkn,1000-850_thkn,1000mb_hght_tmp_wind,100mb_hght_wind,200mb_hght_wind,250mb_ageo_div_isotachs,250mb_hght_wind,300mb_hght_wind,500mb_hght_absv_wnd,500mb_hght_color,500mb_hght_wind,500mb_hght_tmp_wind,700mb_hght_rh_omega,700mb_hght_tmp_wind,850-700_thkn,850mb_hght_tmp_wind,pmsl,pmsl_thkn + diff --git a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-exp_marine.xml b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-exp_marine.xml new file mode 100644 index 0000000000..da1088eeac --- /dev/null +++ b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-exp_marine.xml @@ -0,0 +1,6 @@ + + + NAVGEM + exp_marine + 1000-850thk_only,500_vort_only,pmsl_1000-850thk,pmsl_1000-500thk,pmsl_only,bl_winds_only_nogaps + diff --git a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-loops.xml b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-loops.xml new file mode 100644 index 0000000000..bc4fea9721 --- /dev/null +++ b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-loops.xml @@ -0,0 +1,6 @@ + + + NAVGEM + loops + 24-hr_obs_pcpn_al,24-hr_obs_pcpn_spc_al + diff --git a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-marine.xml b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-marine.xml new file mode 100644 index 0000000000..45aa872f20 --- /dev/null +++ b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-marine.xml @@ -0,0 +1,6 @@ + + + NAVGEM + marine + 1000mb_hght_absv,850mb_hght_absv,pmsl_1000-850_thk_global,pmsl_and_bl_wind_nogaps + diff --git a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-medr.xml b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-medr.xml new file mode 100644 index 0000000000..2498a9844f --- /dev/null +++ b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-medr.xml @@ -0,0 +1,6 @@ + + + NAVGEM + medr + 1000-500_thkn + diff --git a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-no_col-fill.xml b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-no_col-fill.xml new file mode 100644 index 0000000000..aed7585d10 --- /dev/null +++ b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-no_col-fill.xml @@ -0,0 +1,6 @@ + + + NAVGEM + no_col-fill + 500mb_absv_ncf + diff --git a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-precip.xml b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-precip.xml new file mode 100644 index 0000000000..e3b93d4e4a --- /dev/null +++ b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-precip.xml @@ -0,0 +1,6 @@ + + + NAVGEM + precip + precip_12hr_nogaps,precip_12hr_mm_nogaps + diff --git a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-standard.xml b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-standard.xml new file mode 100644 index 0000000000..19ded8efce --- /dev/null +++ b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-standard.xml @@ -0,0 +1,6 @@ + + + NAVGEM + standard + 1000-500_thkn,1000-850_thkn,1000mb_hght_tmp_wind,200mb_div_isotachs,200mb_hght_wind,250mb_hght_wind,250mb_wind_and_rel_vort,300mb_div_isotachs,300mb_hght_absv_adv,300mb_hght_wind,300mb_hght_tmp_wind,500mb_hght_absv,500mb_hght_absv_adv,500mb_hght_absv_wnd,500mb_hght_color,500mb_hght_geoabsv,500mb_hght_rh_omega,500mb_hght_wind,500mb_hght_tmp_wind,700mb_hght_rh_omega,700mb_hght_tmp_wind,850-700_thkn,850mb_hght_tmp_wind,850mb_hgt_wind,pmsl,pmsl_thkn,pmsl_and_bl_wind_nogaps,300-200mb_pv,400-200mb_pv,400-250mb_pv_global,500-250mb_pv,500-300mb_pv + diff --git a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-surface.xml b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-surface.xml new file mode 100644 index 0000000000..43712713a5 --- /dev/null +++ b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-surface.xml @@ -0,0 +1,6 @@ + + + NAVGEM + surface + 1000-500_thkn,1000-850_thkn,500mb_absv_ncf,500mb_hght,850-700_thkn,pmsl + diff --git a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-tropical.xml b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-tropical.xml new file mode 100644 index 0000000000..765f62d4fb --- /dev/null +++ b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/AttributeSetGroups/ModelFcstGridContours/NAVGEM-tropical.xml @@ -0,0 +1,6 @@ + + + NAVGEM + tropical + 500mb_hght_absv + diff --git a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/GRID/NAM11/NAM11.xml b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/GRID/NAM32/NAM32.xml similarity index 92% rename from ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/GRID/NAM11/NAM11.xml rename to ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/GRID/NAM32/NAM32.xml index 510ecb956b..f2afdbdf00 100644 --- a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/GRID/NAM11/NAM11.xml +++ b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/GRID/NAM32/NAM32.xml @@ -1,6 +1,6 @@ - NAM11 + NAM32 GRID ModelFcstGridContours @@ -13,7 +13,7 @@ BasicWX_US pluginName=grid -GDFILE=ETA242 +GDFILE=nam32 true diff --git a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/GRID/NAM40/NAM40.xml b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/GRID/NAM40/NAM40.xml new file mode 100644 index 0000000000..653fa1c1db --- /dev/null +++ b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/GRID/NAM40/NAM40.xml @@ -0,0 +1,20 @@ + + + NAM40 + GRID + ModelFcstGridContours + + + CLOSEST_BEFORE_OR_AFTER + 60 + USE_CYCLE_TIME_FCST_HOURS + 999 + 96 + BasicWX_US + +pluginName=grid +GDFILE=mesoEta212 + + + true + diff --git a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/GRID/NMM40/NMM40.xml b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/GRID/NAM40_SFC/NAM40_SFC.xml similarity index 93% rename from ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/GRID/NMM40/NMM40.xml rename to ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/GRID/NAM40_SFC/NAM40_SFC.xml index c225545fd4..50675ebb6e 100644 --- a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/GRID/NMM40/NMM40.xml +++ b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/GRID/NAM40_SFC/NAM40_SFC.xml @@ -1,6 +1,6 @@ - NMM40 + NAM40_SFC GRID ModelFcstGridContours diff --git a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/GRID/NAM5/NAM5.xml b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/GRID/NAM5/NAM5.xml new file mode 100644 index 0000000000..91ed83c8cc --- /dev/null +++ b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/GRID/NAM5/NAM5.xml @@ -0,0 +1,20 @@ + + + NAM5 + GRID + ModelFcstGridContours + + + CLOSEST_BEFORE_OR_AFTER + 60 + USE_CYCLE_TIME_FCST_HOURS + 999 + 96 + BasicWX_US + +pluginName=grid +GDFILE=NAM227 + + + true + diff --git a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/GRID/NAVGEM/NAVGEM.xml b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/GRID/NAVGEM/NAVGEM.xml new file mode 100644 index 0000000000..fc1180c420 --- /dev/null +++ b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/GRID/NAVGEM/NAVGEM.xml @@ -0,0 +1,19 @@ + + + true + NAVGEM + GRID + +GDFILE=nogaps +pluginName=grid + + ModelFcstGridContours + + + CLOSEST_BEFORE_OR_AFTER + 60 + USE_CYCLE_TIME_FCST_HOURS + 999 + 240 + BasicWX_US + \ No newline at end of file diff --git a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/NTRANS/HYSPLIT_NT/HYSPLIT_NT.xml b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/NTRANS/HYSPLIT_NT/HYSPLIT_NT.xml new file mode 100644 index 0000000000..742381bd6a --- /dev/null +++ b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/NTRANS/HYSPLIT_NT/HYSPLIT_NT.xml @@ -0,0 +1,19 @@ + + + HYSPLIT_NT + false + NTRANS + +pluginName=ntrans +modelName=HYSPLIT + + NTRANS + metafileName,productName + + CLOSEST_BEFORE_OR_AFTER + 60 + USE_CYCLE_TIME_FCST_HOURS + 10 + 48 + XY + diff --git a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/NTRANS/HYSPLIT_NT/default.attr b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/NTRANS/HYSPLIT_NT/default.attr new file mode 100644 index 0000000000..94588adb75 --- /dev/null +++ b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/NTRANS/HYSPLIT_NT/default.attr @@ -0,0 +1,2 @@ +! No real attributes for NTRANS +color= RGB {255,255,255} diff --git a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/RADAR/LocalRadar/LocalRadar.xml b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/RADAR/LocalRadar/LocalRadar.xml index 83e44106b1..feeda45fd5 100644 --- a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/RADAR/LocalRadar/LocalRadar.xml +++ b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/RADAR/LocalRadar/LocalRadar.xml @@ -1,6 +1,6 @@ - true + false LocalRadar RADAR diff --git a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/ResourceFilters.xml b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/ResourceFilters.xml index f49155fd4c..b94d84e167 100644 --- a/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/ResourceFilters.xml +++ b/ncep/gov.noaa.nws.ncep.viz.localization/localization/ncep/ResourceDefns/ResourceFilters.xml @@ -318,6 +318,9 @@ Forecast,NTRANS + +Forecast,NTRANS + Forecast,NTRANS @@ -702,7 +705,13 @@ Forecast - + +Forecast,Regional,SBN + + +Forecast,Regional,SBN + + Forecast,Regional,SBN @@ -1077,6 +1086,9 @@ Forecast,Global + +Forecast,Global,NSBN + Forecast,SBN @@ -1158,6 +1170,9 @@ Forecast + +Forecast,Regional,NSBN + Forecast,Regional,SBN @@ -1410,4 +1425,4 @@ Forecast,SWPC - \ No newline at end of file + diff --git a/ncep/gov.noaa.nws.ncep.viz.overlays/src/gov/noaa/nws/ncep/viz/overlays/resources/LatLonOverlayResource.java b/ncep/gov.noaa.nws.ncep.viz.overlays/src/gov/noaa/nws/ncep/viz/overlays/resources/LatLonOverlayResource.java index 945cc4e2d4..0f9cd3ab7a 100644 --- a/ncep/gov.noaa.nws.ncep.viz.overlays/src/gov/noaa/nws/ncep/viz/overlays/resources/LatLonOverlayResource.java +++ b/ncep/gov.noaa.nws.ncep.viz.overlays/src/gov/noaa/nws/ncep/viz/overlays/resources/LatLonOverlayResource.java @@ -1,25 +1,25 @@ -package gov.noaa.nws.ncep.viz.overlays.resources; +package gov.noaa.nws.ncep.viz.overlays.resources; + +import gov.noaa.nws.ncep.viz.resources.INatlCntrsResource; import java.util.ArrayList; import java.util.List; -import gov.noaa.nws.ncep.viz.resources.INatlCntrsResource; - import org.opengis.referencing.crs.CoordinateReferenceSystem; -import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.IGraphicsTarget; import com.raytheon.uf.viz.core.PixelExtent; -import com.raytheon.uf.viz.core.rsc.LoadProperties; +import com.raytheon.uf.viz.core.drawables.IFont; import com.raytheon.uf.viz.core.drawables.IWireframeShape; import com.raytheon.uf.viz.core.drawables.PaintProperties; +import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.map.IMapDescriptor; import com.raytheon.uf.viz.core.rsc.AbstractVizResource; - +import com.raytheon.uf.viz.core.rsc.LoadProperties; import com.vividsolutions.jts.geom.Coordinate; /** - * Implements a drawing layer to draw lat/lon lines + * Implements a drawing layer to draw lat/lon lines * *
  * SOFTWARE HISTORY
@@ -31,58 +31,70 @@ import com.vividsolutions.jts.geom.Coordinate;
  *   11/18/09                Greg Hull   Incorporate to11d6 changes 
  *   11/04/13    #880        Xiaochuan   set one wireframeShape for one lat or Lon lines.
  *                                       Set spatialChopFlag to be false.
+ *   05/23/2014  #970        P.Swamy     Lat/lon label sizes need to be larger
  * 
* * @author mgao * */ -public class LatLonOverlayResource extends AbstractVizResource - implements INatlCntrsResource { +public class LatLonOverlayResource extends + AbstractVizResource + implements INatlCntrsResource { - private final static org.apache.log4j.Logger log = - org.apache.log4j.Logger.getLogger(LatLonOverlayResource.class); - - private LatLonOverlayResourceData latLonOverlayResourceData; - - /** The wireframe object for drawing Latitude lines*/ + private final static org.apache.log4j.Logger log = org.apache.log4j.Logger + .getLogger(LatLonOverlayResource.class); + + private LatLonOverlayResourceData latLonOverlayResourceData; + + /** The wireframe object for drawing Latitude lines */ private IWireframeShape wireframeShapeForLatLineArray; - /** The wireframe object for drawing Longitude lines*/ + /** The wireframe object for drawing Longitude lines */ private IWireframeShape wireframeShapeForLonLineArray; - - private List latitudeCoordinatePointArrayList; - private List longitudeCoordinatePointArrayList; - - private double offset = 0; //50000; - - private double mapMinX; - private double mapMaxY; - private double mapMinY; - private double mapMaxX; - - private double viewMinX; - private double viewMaxY; - private double viewMinY; - private double viewMaxX; - - /* - * The four minimum and maximum of X and Y used to paint label - */ - private double effectiveMinX; - private double effectiveMaxY; - private double effectiveMinY; - private double effectiveMaxX; - - private double latLonDrawingPointInterval = 1.0; //0.7; //1.0; //0.5 - - private boolean needsUpdate = true; - - protected LatLonOverlayResource(LatLonOverlayResourceData llRscData, LoadProperties props) { + private List latitudeCoordinatePointArrayList; + + private List longitudeCoordinatePointArrayList; + + private double offset = 0; // 50000; + + private double mapMinX; + + private double mapMaxY; + + private double mapMinY; + + private double mapMaxX; + + private double viewMinX; + + private double viewMaxY; + + private double viewMinY; + + private double viewMaxX; + + /* + * The four minimum and maximum of X and Y used to paint label + */ + private double effectiveMinX; + + private double effectiveMaxY; + + private double effectiveMinY; + + private double effectiveMaxX; + + private double latLonDrawingPointInterval = 1.0; // 0.7; //1.0; //0.5 + + private boolean needsUpdate = true; + + protected LatLonOverlayResource(LatLonOverlayResourceData llRscData, + LoadProperties props) { super(llRscData, props); latLonOverlayResourceData = llRscData; } - + /* * (non-Javadoc) * @@ -90,7 +102,7 @@ public class LatLonOverlayResource extends AbstractVizResource(latitudeDrawingLineNumber); - longitudeCoordinatePointArrayList = new ArrayList(longitudeDrawingLineNumber); - - wireframeShapeForLatLineArray = target.createWireframeShape(false, - descriptor, 4.0f, false, new PixelExtent( - getViewMinX()+offset, getViewMaxX()-offset, getViewMinY()+offset, getViewMaxY()-offset)); - - double latitudeValue = -90; - for(int i=0; i( + latitudeDrawingLineNumber); + longitudeCoordinatePointArrayList = new ArrayList( + longitudeDrawingLineNumber); - for(int i=0; i minXOfCurrentView && minXOfMap < maxXOfCurrentView) - isInsideResult = true; - return isInsideResult; - } - - private void updateEffectiveMaxY(double mapMaxYValue, double viewMinYValue, double viewMaxYValue) { - if(isBottomEdgeOfMapInsideCurrentView(mapMaxYValue, viewMinYValue, viewMaxYValue)) - effectiveMaxY = mapMaxYValue; - } - - private boolean isBottomEdgeOfMapInsideCurrentView(double maxYOfMap, double minYOfCurrentView, double maxYOfCurrentView) { - boolean isInsideResult = false; - if(maxYOfMap > minYOfCurrentView && maxYOfMap < maxYOfCurrentView) { - isInsideResult = true; - } - return isInsideResult; - } - - private int getPointLabelIndexForAddingLongitudeLabel(Coordinate[] latLonCoordinateArray, - float zoomFactor, double minX, double maxX, double minY, double maxY) { - int pointIndex = -1; - if(latLonCoordinateArray == null || latLonCoordinateArray.length == 0) - return pointIndex; - - double positionOffset = 120; - for(int i=0; i minX && pixelValueArray[0] < maxX && - pixelValueArray[1] > minY && pixelValueArray[1] < maxY) { - if(Math.abs(pixelValueArray[1] - maxY) < delta) { - isPointForLabel = true; - } - } - } - return isPointForLabel; + effectiveMinX = viewMinX; + effectiveMaxX = viewMaxX; + effectiveMinY = viewMinY; + effectiveMaxY = viewMaxY; } - private boolean isPointForPlacingLatituteLabel(double[] pixelValueArray, double positionOffset, float zoomFactor, - double minX, double maxX, double minY, double maxY) { - double delta = 200; - double adjustedOffset = positionOffset * zoomFactor; - boolean isPointForLabel = false; - if(pixelValueArray != null) { - if(pixelValueArray[0] > (minX + adjustedOffset) && pixelValueArray[0] < maxX && - pixelValueArray[1] > minY && pixelValueArray[1] < maxY) { - if(Math.abs(pixelValueArray[0] - minX - (positionOffset * zoomFactor)) < delta) { - isPointForLabel = true; - } - } - } - return isPointForLabel; + private void updateEffectiveMinX(double mapMinXValue, double viewMinXValue, + double viewMaxXValue) { + if (isLeftEdgeOfMapInsideCurrentView(mapMinXValue, viewMinXValue, + viewMaxXValue)) { + effectiveMinX = mapMinXValue; + } } - private int getLatitudeDrawingLineNumber(int latInterval) { - int latLineNumber = 180/15; // set a default value - if(latInterval>0 && latInterval<=180) { - latLineNumber = 180/latInterval; - } - return latLineNumber + 1; - } - - private int getLongitudeDrawingLineNumber(int lonInterval) { - int lonLineNumber = 360/15; // set a default value - if(lonInterval>0 && lonInterval<=360) { - lonLineNumber = 360 / lonInterval; - if(lonLineNumber > 360) - lonLineNumber = 360; // if we draw 360 lines, the last line will overlap with the first line - } - return lonLineNumber + 1; - } - - private Coordinate[] createCoordinateArrayForLatitudeLine(double latitudeValue, double latLonPointInterval) { - int coordinateArrayLength = (int)(360 / latLonPointInterval) + 1; - Coordinate[] coordinateArray = new Coordinate[coordinateArrayLength]; - double longitude = -180; - for(int i=0; i minXOfCurrentView && minXOfMap < maxXOfCurrentView) + isInsideResult = true; + return isInsideResult; + } + + private void updateEffectiveMaxY(double mapMaxYValue, double viewMinYValue, + double viewMaxYValue) { + if (isBottomEdgeOfMapInsideCurrentView(mapMaxYValue, viewMinYValue, + viewMaxYValue)) + effectiveMaxY = mapMaxYValue; + } + + private boolean isBottomEdgeOfMapInsideCurrentView(double maxYOfMap, + double minYOfCurrentView, double maxYOfCurrentView) { + boolean isInsideResult = false; + if (maxYOfMap > minYOfCurrentView && maxYOfMap < maxYOfCurrentView) { + isInsideResult = true; + } + return isInsideResult; + } + + private int getPointLabelIndexForAddingLongitudeLabel( + Coordinate[] latLonCoordinateArray, float zoomFactor, double minX, + double maxX, double minY, double maxY) { + int pointIndex = -1; + if (latLonCoordinateArray == null || latLonCoordinateArray.length == 0) + return pointIndex; + + double positionOffset = 120; + for (int i = 0; i < latLonCoordinateArray.length; i++) { + double[] tmp = { latLonCoordinateArray[i].x, + latLonCoordinateArray[i].y }; + double[] screenPixel = descriptor.worldToPixel(tmp); + if (isPointForPlacingLongituteLabel(screenPixel, positionOffset, + zoomFactor, minX, maxX, minY, maxY)) { + pointIndex = i; + break; + } + } + return pointIndex; + } + + private int getPointLabelIndexForAddingLatitudeLabel( + Coordinate[] latLonCoordinateArray, float zoomFactor, double minX, + double maxX, double minY, double maxY) { + int pointIndex = -1; + if (latLonCoordinateArray == null || latLonCoordinateArray.length == 0) + return pointIndex; + + double positionOffset = 120; + for (int i = 0; i < latLonCoordinateArray.length; i++) { + double[] tmp = { latLonCoordinateArray[i].x, + latLonCoordinateArray[i].y }; + double[] screenPixel = descriptor.worldToPixel(tmp); + if (isPointForPlacingLatituteLabel(screenPixel, positionOffset, + zoomFactor, minX, maxX, minY, maxY)) { + pointIndex = i; + break; + } + } + return pointIndex; + } + + private void addDefaultLabelByPointIndex(IWireframeShape wireframeShape, + String labelValue, Coordinate[] latLonCoordinateArray, + int defaultPointIndex) { + double[] tmp = { latLonCoordinateArray[defaultPointIndex].x, + latLonCoordinateArray[defaultPointIndex].y }; + double[] screenPixel = descriptor.worldToPixel(tmp); + if (screenPixel != null) + wireframeShape.addLabel(labelValue, screenPixel); + } + + private boolean isPointForPlacingLongituteLabel(double[] pixelValueArray, + double positionOffset, float zoomFactor, double minX, double maxX, + double minY, double maxY) { + double delta = 200; + boolean isPointForLabel = false; + if (pixelValueArray != null) { + if (pixelValueArray[0] > minX && pixelValueArray[0] < maxX + && pixelValueArray[1] > minY && pixelValueArray[1] < maxY) { + if (Math.abs(pixelValueArray[1] - maxY) < delta) { + isPointForLabel = true; + } + } + } + return isPointForLabel; + } + + private boolean isPointForPlacingLatituteLabel(double[] pixelValueArray, + double positionOffset, float zoomFactor, double minX, double maxX, + double minY, double maxY) { + double delta = 200; + double adjustedOffset = positionOffset * zoomFactor; + boolean isPointForLabel = false; + if (pixelValueArray != null) { + if (pixelValueArray[0] > (minX + adjustedOffset) + && pixelValueArray[0] < maxX && pixelValueArray[1] > minY + && pixelValueArray[1] < maxY) { + if (Math.abs(pixelValueArray[0] - minX + - (positionOffset * zoomFactor)) < delta) { + isPointForLabel = true; + } + } + } + return isPointForLabel; + } + + private int getLatitudeDrawingLineNumber(int latInterval) { + int latLineNumber = 180 / 15; // set a default value + if (latInterval > 0 && latInterval <= 180) { + latLineNumber = 180 / latInterval; + } + return latLineNumber + 1; + } + + private int getLongitudeDrawingLineNumber(int lonInterval) { + int lonLineNumber = 360 / 15; // set a default value + if (lonInterval > 0 && lonInterval <= 360) { + lonLineNumber = 360 / lonInterval; + if (lonLineNumber > 360) + lonLineNumber = 360; // if we draw 360 lines, the last line will + // overlap with the first line + } + return lonLineNumber + 1; + } + + private Coordinate[] createCoordinateArrayForLatitudeLine( + double latitudeValue, double latLonPointInterval) { + int coordinateArrayLength = (int) (360 / latLonPointInterval) + 1; + Coordinate[] coordinateArray = new Coordinate[coordinateArrayLength]; + double longitude = -180; + for (int i = 0; i < coordinateArray.length && longitude <= 180; i++) { + coordinateArray[i] = new Coordinate(longitude, latitudeValue); + longitude += latLonPointInterval; + } + return coordinateArray; + } + + private Coordinate[] createCoordinateArrayLongitudeLine( + double longitudeValue, double latLonPointInterval) { + int coordinateArrayLength = (int) ((180 - 10) / latLonPointInterval); + Coordinate[] coordinateArray = new Coordinate[coordinateArrayLength]; + double latitude = -90 + latLonPointInterval; + for (int i = 0; i < coordinateArray.length && latitude <= 90; i++) { + coordinateArray[i] = new Coordinate(longitudeValue, latitude); + latitude += latLonPointInterval; + } + return coordinateArray; + } /* * (non-Javadoc) @@ -368,91 +432,92 @@ public class LatLonOverlayResource extends AbstractVizResource coordinatePointArrayList) { - if(coordinatePointArrayList != null) { - for(Coordinate[] eachCoordinateArray : coordinatePointArrayList) { - eachCoordinateArray = null; - } - coordinatePointArrayList = null; - } + if (wireframeShapeArray != null) { + wireframeShapeArray.dispose(); + wireframeShapeArray = null; + } } - /* - * the getters for Map's Min and Max X and Y, View's Min and Max X and Y - */ - public double getViewMinX() { - return viewMinX; - } + private void clearCoordinatePointArrayList( + List coordinatePointArrayList) { + if (coordinatePointArrayList != null) { + for (Coordinate[] eachCoordinateArray : coordinatePointArrayList) { + eachCoordinateArray = null; + } + coordinatePointArrayList = null; + } + } - public double getViewMaxY() { - return viewMaxY; - } + /* + * the getters for Map's Min and Max X and Y, View's Min and Max X and Y + */ + public double getViewMinX() { + return viewMinX; + } - public double getViewMinY() { - return viewMinY; - } + public double getViewMaxY() { + return viewMaxY; + } - public double getViewMaxX() { - return viewMaxX; - } + public double getViewMinY() { + return viewMinY; + } + + public double getViewMaxX() { + return viewMaxX; + } public double getMapMinX() { - return mapMinX; - } - - public double getMapMaxY() { - return mapMaxY; - } - - public double getMapMinY() { - return mapMinY; - } - - public double getMapMaxX() { - return mapMaxX; - } - - public double getEffectiveMinX() { - return effectiveMinX; - } - - public double getEffectiveMaxY() { - return effectiveMaxY; - } - - public double getEffectiveMinY() { - return effectiveMinY; - } - - public double getEffectiveMaxX() { - return effectiveMaxX; - } - -// @Override - public void resourceAttrsModified() { - needsUpdate = true; + return mapMinX; } -// @Override - public boolean isProjectable(CoordinateReferenceSystem mapData) { - return true; - } + public double getMapMaxY() { + return mapMaxY; + } - // TODO : This has not been tested. - @Override - public void project(CoordinateReferenceSystem mapData) throws VizException { - needsUpdate = true; - } + public double getMapMinY() { + return mapMinY; + } + + public double getMapMaxX() { + return mapMaxX; + } + + public double getEffectiveMinX() { + return effectiveMinX; + } + + public double getEffectiveMaxY() { + return effectiveMaxY; + } + + public double getEffectiveMinY() { + return effectiveMinY; + } + + public double getEffectiveMaxX() { + return effectiveMaxX; + } + + // @Override + public void resourceAttrsModified() { + needsUpdate = true; + } + + // @Override + public boolean isProjectable(CoordinateReferenceSystem mapData) { + return true; + } + + // TODO : This has not been tested. + @Override + public void project(CoordinateReferenceSystem mapData) throws VizException { + needsUpdate = true; + } } diff --git a/ncep/gov.noaa.nws.ncep.viz.resourceManager/src/gov/noaa/nws/ncep/viz/resourceManager/ui/createRbd/CreateRbdControl.java b/ncep/gov.noaa.nws.ncep.viz.resourceManager/src/gov/noaa/nws/ncep/viz/resourceManager/ui/createRbd/CreateRbdControl.java index 30fc64099f..39bf72fa3e 100644 --- a/ncep/gov.noaa.nws.ncep.viz.resourceManager/src/gov/noaa/nws/ncep/viz/resourceManager/ui/createRbd/CreateRbdControl.java +++ b/ncep/gov.noaa.nws.ncep.viz.resourceManager/src/gov/noaa/nws/ncep/viz/resourceManager/ui/createRbd/CreateRbdControl.java @@ -25,6 +25,7 @@ import gov.noaa.nws.ncep.viz.resources.manager.ResourceName; import gov.noaa.nws.ncep.viz.resources.manager.RscBundleDisplayMngr; import gov.noaa.nws.ncep.viz.resources.manager.SpfsManager; import gov.noaa.nws.ncep.viz.resources.time_match.NCTimeMatcher; +import gov.noaa.nws.ncep.viz.ui.display.NatlCntrsEditor; import gov.noaa.nws.ncep.viz.ui.display.NcDisplayMngr; import gov.noaa.nws.ncep.viz.ui.display.NcEditorUtil; import gov.noaa.nws.ncep.viz.ui.display.NcPaneID; @@ -43,7 +44,6 @@ import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.viewers.CellEditor.LayoutData; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.LabelProvider; @@ -83,6 +83,9 @@ import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.swt.widgets.ToolItem; +import org.eclipse.ui.IPartListener2; +import org.eclipse.ui.IWorkbenchPartReference; +import org.eclipse.ui.PlatformUI; import com.raytheon.uf.viz.core.VizApp; import com.raytheon.uf.viz.core.exception.VizException; @@ -134,170 +137,210 @@ import com.raytheon.viz.ui.editor.AbstractEditor; * 05/24/2013 #862 Greg Hull get areas from menus file and change combo to a cascading menu * 06/03/2013 #1001 Greg Hull allow multiple Remove/TurnOff of resources * 10/22/2013 #1043 Greg Hull setSelectedResource() if rsc sel dlg is already up. - * 11/25/2013 #1079 Greg Hull adjust size/font of area toolbar based on the text + * 11/25/2013 #1079 Greg Hull adjust size/font of area toolbar based on the text + * 05/07/2014 TTR991 D. Sushon if a different NCP editor is selected, the CreateRDB tab should now adjust. * * * * @author ghull * @version 1 */ -public class CreateRbdControl extends Composite { - - private ResourceSelectionDialog rscSelDlg = null; +public class CreateRbdControl extends Composite implements IPartListener2 { + + private ResourceSelectionDialog rscSelDlg = null; + + private RscBundleDisplayMngr rbdMngr; + + private Shell shell; - private RscBundleDisplayMngr rbdMngr; - private Shell shell; - private SashForm sash_form = null; + private Group rbd_grp = null; - + private Text rbd_name_txt = null; + private Label rbd_name_lbl = null; - - private Combo disp_type_combo = null; - private Label disp_type_lbl = null; - + + private Combo disp_type_combo = null; + + private Label disp_type_lbl = null; + private Button sel_rsc_btn = null; - + private Button multi_pane_tog = null; + private Button auto_update_btn = null; + private Button geo_sync_panes = null; private Group seld_rscs_grp = null; - private ListViewer seld_rscs_lviewer = null; + private ListViewer seld_rscs_lviewer = null; private Button replace_rsc_btn = null; + private Button edit_rsc_btn = null; + private Button del_rsc_btn = null; + private Button disable_rsc_btn = null; - - private ToolItem areaTItm; + + private ToolItem areaTItm; + private AreaMenuItem seldAreaMenuItem = null; + private Font areaFont = null; // dispose if new Font created - + private Group geo_area_grp = null; + private MenuManager areaMenuMngr = null; - - private Composite geo_area_info_comp = null; // only one of these visible at a time - private Composite rsc_area_opts_comp = null; // depending on if a satellite area is selected - - private Text proj_info_txt = null; // view-only projection and map center info - private Text map_center_txt = null; // view-only projection and map center info - private Button fit_to_screen_btn = null; + + private Composite geo_area_info_comp = null; // only one of these visible at + // a time + + private Composite rsc_area_opts_comp = null; // depending on if a satellite + // area is selected + + private Text proj_info_txt = null; // view-only projection and map center + // info + + private Text map_center_txt = null; // view-only projection and map center + // info + + private Button fit_to_screen_btn = null; + private Button size_of_image_btn = null; - + private Button custom_area_btn = null; - - private Group pane_layout_grp = null; + + private Group pane_layout_grp = null; private Button pane_sel_btns[][] = null; - private Button import_pane_btn = null; - private Button load_pane_btn = null; - private Button clr_pane_btn = null; - - private Label import_lbl = null; - private Combo import_rbd_combo = null; - private Button load_rbd_btn = null; - private Button load_and_close_btn = null; - private Button save_rbd_btn = null; - private Button clear_rbd_btn = null; - private Button cancel_edit_btn = null; // when part of the 'Edit Rbd' dialog these will - private Button ok_edit_btn = null; // replace the Clear, Save, and Load buttons - private AbstractRBD editedRbd = null; // set on OK when this is an 'Edit Rbd' dialog + private Button import_pane_btn = null; + + private Button load_pane_btn = null; + + private Button clr_pane_btn = null; + + private Label import_lbl = null; + + private Combo import_rbd_combo = null; + + private Button load_rbd_btn = null; + + private Button load_and_close_btn = null; + + private Button save_rbd_btn = null; + + private Button clear_rbd_btn = null; + + private Button cancel_edit_btn = null; // when part of the 'Edit Rbd' dialog + // these will + + private Button ok_edit_btn = null; // replace the Clear, Save, and Load + // buttons + + private AbstractRBD editedRbd = null; // set on OK when this is an 'Edit + // Rbd' dialog // used to initialize the Save Dialog private String savedSpfGroup = null; - private String savedSpfName = null; - - private Point initDlgSize = new Point( 750, 860 ); - private int singlePaneDlgWidth = 750; - private int multiPaneDlgWidth = 950; - + + private String savedSpfName = null; + + private Point initDlgSize = new Point(750, 860); + + private int singlePaneDlgWidth = 750; + + private int multiPaneDlgWidth = 950; + private TimelineControl timelineControl = null; - + private final String ImportFromSPF = "From SPF..."; -// private final String[] StandardZoomLevels = {"1", "1.5","2","3","5","7.5","10","15","20","30"}; - - private static Map gempakProjMap = - GempakProjectionValuesUtil.initializeProjectionNameMap(); - - // the rbdMngr will be used to set the gui so it should either be initialized/cleared - // or set with the initial RBD. - public CreateRbdControl(Composite parent, RscBundleDisplayMngr mngr ) throws VizException { + + // private final String[] StandardZoomLevels = {"1", + // "1.5","2","3","5","7.5","10","15","20","30"}; + + private static Map gempakProjMap = GempakProjectionValuesUtil + .initializeProjectionNameMap(); + + // the rbdMngr will be used to set the gui so it should either be + // initialized/cleared or set with the initial RBD. + public CreateRbdControl(Composite parent, RscBundleDisplayMngr mngr) + throws VizException { super(parent, SWT.NONE); shell = parent.getShell(); rbdMngr = mngr; - - rscSelDlg = new ResourceSelectionDialog( shell ); - - Composite top_comp = this; - top_comp.setLayout( new GridLayout(1,true) ); - -// top_comp.setSize( 400, 400 ); - - sash_form = new SashForm( top_comp, SWT.VERTICAL ); + + rscSelDlg = new ResourceSelectionDialog(shell); + + Composite top_comp = this; + top_comp.setLayout(new GridLayout(1, true)); + + // top_comp.setSize( 400, 400 ); + + sash_form = new SashForm(top_comp, SWT.VERTICAL); GridData gd = new GridData(); gd.grabExcessHorizontalSpace = true; gd.grabExcessVerticalSpace = true; gd.horizontalAlignment = SWT.FILL; gd.verticalAlignment = SWT.FILL; - - sash_form.setLayoutData( gd ); + + sash_form.setLayoutData(gd); sash_form.setSashWidth(10); - - rbd_grp = new Group( sash_form, SWT.SHADOW_NONE ); - rbd_grp.setText( "Resource Bundle Display" ); + + rbd_grp = new Group(sash_form, SWT.SHADOW_NONE); + rbd_grp.setText("Resource Bundle Display"); gd = new GridData(); gd.grabExcessHorizontalSpace = true; gd.grabExcessVerticalSpace = true; gd.horizontalAlignment = SWT.FILL; gd.verticalAlignment = SWT.FILL; - rbd_grp.setLayoutData( gd ); + rbd_grp.setLayoutData(gd); + + rbd_grp.setLayout(new FormLayout()); - rbd_grp.setLayout( new FormLayout() ); - createRBDGroup(); - Group timeline_grp = new Group( sash_form, SWT.SHADOW_NONE ); - timeline_grp.setText( "Select Timeline" ); + Group timeline_grp = new Group(sash_form, SWT.SHADOW_NONE); + timeline_grp.setText("Select Timeline"); gd = new GridData(); gd.grabExcessHorizontalSpace = true; gd.grabExcessVerticalSpace = true; gd.horizontalAlignment = SWT.FILL; gd.verticalAlignment = SWT.FILL; - timeline_grp.setLayoutData( gd ); + timeline_grp.setLayoutData(gd); - timeline_grp.setLayout( new GridLayout() ); + timeline_grp.setLayout(new GridLayout()); - timelineControl = new TimelineControl( timeline_grp ); - - timelineControl.addDominantResourceChangedListener( new IDominantResourceChangedListener() { - @Override - public void dominantResourceChanged( - AbstractNatlCntrsRequestableResourceData newDomRsc ) { - if( newDomRsc == null ) { - auto_update_btn.setSelection( rbdMngr.isAutoUpdate() ); - auto_update_btn.setEnabled( false ); - } - else if( newDomRsc.isAutoUpdateable() ){ - auto_update_btn.setEnabled( true ); - //auto_update_btn.setSelection( rbdMngr.isAutoUpdate() ); - auto_update_btn.setSelection( true ); - } - else { - auto_update_btn.setSelection(false); - auto_update_btn.setEnabled( false ); - } - } - }); - - timelineControl.setTimeMatcher( new NCTimeMatcher( ) ); - - Composite loadSaveComp = new Composite( top_comp, SWT.NONE ); + timelineControl = new TimelineControl(timeline_grp); + + timelineControl + .addDominantResourceChangedListener(new IDominantResourceChangedListener() { + @Override + public void dominantResourceChanged( + AbstractNatlCntrsRequestableResourceData newDomRsc) { + if (newDomRsc == null) { + auto_update_btn.setSelection(rbdMngr.isAutoUpdate()); + auto_update_btn.setEnabled(false); + } else if (newDomRsc.isAutoUpdateable()) { + auto_update_btn.setEnabled(true); + // auto_update_btn.setSelection( + // rbdMngr.isAutoUpdate() ); + auto_update_btn.setSelection(true); + } else { + auto_update_btn.setSelection(false); + auto_update_btn.setEnabled(false); + } + } + }); + + timelineControl.setTimeMatcher(new NCTimeMatcher()); + + Composite loadSaveComp = new Composite(top_comp, SWT.NONE); gd = new GridData(); gd.minimumHeight = 40; gd.grabExcessHorizontalSpace = true; @@ -305,2238 +348,2470 @@ public class CreateRbdControl extends Composite { gd.horizontalAlignment = SWT.FILL; gd.verticalAlignment = SWT.FILL; - loadSaveComp.setLayoutData( gd ); + loadSaveComp.setLayoutData(gd); - loadSaveComp.setLayout( new FormLayout() ); + loadSaveComp.setLayout(new FormLayout()); - clear_rbd_btn = new Button( loadSaveComp, SWT.PUSH ); - clear_rbd_btn.setText(" Reset To Default "); - FormData fd = new FormData(); - fd.width = 130; - fd.top = new FormAttachment( 0, 7 ); - fd.left = new FormAttachment( 17, -65 ); - clear_rbd_btn.setLayoutData( fd ); + clear_rbd_btn = new Button(loadSaveComp, SWT.PUSH); + clear_rbd_btn.setText(" Reset To Default "); + FormData fd = new FormData(); + fd.width = 130; + fd.top = new FormAttachment(0, 7); + fd.left = new FormAttachment(17, -65); + clear_rbd_btn.setLayoutData(fd); - save_rbd_btn = new Button( loadSaveComp, SWT.PUSH ); - save_rbd_btn.setText(" Save RBD "); - fd = new FormData(); - fd.width = 100; - fd.top = new FormAttachment( 0, 7 ); - fd.left = new FormAttachment( 40, -50 ); - save_rbd_btn.setLayoutData( fd ); + save_rbd_btn = new Button(loadSaveComp, SWT.PUSH); + save_rbd_btn.setText(" Save RBD "); + fd = new FormData(); + fd.width = 100; + fd.top = new FormAttachment(0, 7); + fd.left = new FormAttachment(40, -50); + save_rbd_btn.setLayoutData(fd); - load_rbd_btn = new Button( loadSaveComp, SWT.PUSH ); - load_rbd_btn.setText("Load RBD"); - fd = new FormData(); - fd.width = 100; - fd.top = new FormAttachment( 0, 7 ); -// fd.bottom = new FormAttachment( 100, -7 ); - fd.left = new FormAttachment( 63, -50 ); - load_rbd_btn.setLayoutData( fd ); + load_rbd_btn = new Button(loadSaveComp, SWT.PUSH); + load_rbd_btn.setText("Load RBD"); + fd = new FormData(); + fd.width = 100; + fd.top = new FormAttachment(0, 7); + // fd.bottom = new FormAttachment( 100, -7 ); + fd.left = new FormAttachment(63, -50); + load_rbd_btn.setLayoutData(fd); - load_and_close_btn = new Button( loadSaveComp, SWT.PUSH ); - load_and_close_btn.setText("Load And Close"); - fd = new FormData(); - fd.width = 120; - fd.top = new FormAttachment( 0, 7 ); -// fd.bottom = new FormAttachment( 100, -7 ); - fd.left = new FormAttachment( 83, -50 ); - load_and_close_btn.setLayoutData( fd ); + load_and_close_btn = new Button(loadSaveComp, SWT.PUSH); + load_and_close_btn.setText("Load And Close"); + fd = new FormData(); + fd.width = 120; + fd.top = new FormAttachment(0, 7); + // fd.bottom = new FormAttachment( 100, -7 ); + fd.left = new FormAttachment(83, -50); + load_and_close_btn.setLayoutData(fd); - cancel_edit_btn = new Button( loadSaveComp, SWT.PUSH ); - cancel_edit_btn.setText(" Cancel "); - fd = new FormData(); - fd.width = 80; - fd.top = new FormAttachment( 0, 7 ); -// fd.bottom = new FormAttachment( 100, -7 ); - fd.right = new FormAttachment( 45, 0 ); - cancel_edit_btn.setLayoutData( fd ); + cancel_edit_btn = new Button(loadSaveComp, SWT.PUSH); + cancel_edit_btn.setText(" Cancel "); + fd = new FormData(); + fd.width = 80; + fd.top = new FormAttachment(0, 7); + // fd.bottom = new FormAttachment( 100, -7 ); + fd.right = new FormAttachment(45, 0); + cancel_edit_btn.setLayoutData(fd); - ok_edit_btn = new Button( loadSaveComp, SWT.PUSH ); - ok_edit_btn.setText(" Ok "); - fd = new FormData(); - fd.width = 80; - fd.top = new FormAttachment( 0, 7 ); -// fd.bottom = new FormAttachment( 100, -7 ); - fd.left = new FormAttachment( 55, 0 ); - ok_edit_btn.setLayoutData( fd ); + ok_edit_btn = new Button(loadSaveComp, SWT.PUSH); + ok_edit_btn.setText(" Ok "); + fd = new FormData(); + fd.width = 80; + fd.top = new FormAttachment(0, 7); + // fd.bottom = new FormAttachment( 100, -7 ); + fd.left = new FormAttachment(55, 0); + ok_edit_btn.setLayoutData(fd); + + cancel_edit_btn.setVisible(false); // only visible if + // configureForEditRbd is called + ok_edit_btn.setVisible(false); + + sash_form.setWeights(new int[] { 50, 35 }); - cancel_edit_btn.setVisible( false ); // only visible if configureForEditRbd is called - ok_edit_btn.setVisible( false ); - - sash_form.setWeights( new int[] { 50, 35 } ); - // set up the content providers for the ListViewers setContentProviders(); addSelectionListeners(); - + initWidgets(); + + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() + .addPartListener(this); + this.addDisposeListener(new DisposeListener() { + @Override + public void widgetDisposed(DisposeEvent e) { + try { + PlatformUI.getWorkbench().getActiveWorkbenchWindow() + .getActivePage() + .removePartListener(CreateRbdControl.this); + + CreateRbdControl.this.dispose(); // now mark for disposal + } catch (NullPointerException npe) { + // do nothing if already disposed, another thread already + // swept it up.. + // System.out.println(this.getClass().getCanonicalName() + + // ":" + npe.getMessage()); + } + } + }); + } - // create all the widgets in the Resource Bundle Definition (bottom) section of the sashForm. - // + // create all the widgets in the Resource Bundle Definition (bottom) section + // of the sashForm. + // private void createRBDGroup() { - - import_rbd_combo = new Combo( rbd_grp, SWT.DROP_DOWN | SWT.READ_ONLY ); - FormData form_data = new FormData();//195,20); - form_data.left = new FormAttachment( 0, 15 ); - form_data.top = new FormAttachment( 0, 30 ); - form_data.right= new FormAttachment( 24, 0 ); - import_rbd_combo.setLayoutData( form_data ); - import_rbd_combo.setEnabled(true); - import_lbl = new Label( rbd_grp, SWT.None ); + import_rbd_combo = new Combo(rbd_grp, SWT.DROP_DOWN | SWT.READ_ONLY); + FormData form_data = new FormData();// 195,20); + form_data.left = new FormAttachment(0, 15); + form_data.top = new FormAttachment(0, 30); + form_data.right = new FormAttachment(24, 0); + import_rbd_combo.setLayoutData(form_data); + import_rbd_combo.setEnabled(true); + + import_lbl = new Label(rbd_grp, SWT.None); import_lbl.setText("Import"); form_data = new FormData(); - form_data.left = new FormAttachment( import_rbd_combo, 0, SWT.LEFT ); - form_data.bottom = new FormAttachment( import_rbd_combo, -3, SWT.TOP ); - import_lbl.setLayoutData( form_data ); + form_data.left = new FormAttachment(import_rbd_combo, 0, SWT.LEFT); + form_data.bottom = new FormAttachment(import_rbd_combo, -3, SWT.TOP); + import_lbl.setLayoutData(form_data); + rbd_name_txt = new Text(rbd_grp, SWT.SINGLE | SWT.BORDER); + form_data = new FormData(200, 20); + form_data.left = new FormAttachment(import_rbd_combo, 25, SWT.RIGHT); + form_data.top = new FormAttachment(import_rbd_combo, 0, SWT.TOP); + rbd_name_txt.setLayoutData(form_data); - rbd_name_txt = new Text( rbd_grp, SWT.SINGLE | SWT.BORDER ); - form_data = new FormData(200,20); - form_data.left = new FormAttachment( import_rbd_combo, 25, SWT.RIGHT ); - form_data.top = new FormAttachment( import_rbd_combo, 0, SWT.TOP ); - rbd_name_txt.setLayoutData( form_data ); - - rbd_name_lbl = new Label( rbd_grp, SWT.None ); + rbd_name_lbl = new Label(rbd_grp, SWT.None); rbd_name_lbl.setText("RBD Name"); form_data = new FormData(); form_data.width = 180; - form_data.left = new FormAttachment( rbd_name_txt, 0, SWT.LEFT ); - form_data.bottom = new FormAttachment( rbd_name_txt, -3, SWT.TOP ); - rbd_name_lbl.setLayoutData( form_data ); - - - disp_type_combo = new Combo( rbd_grp, SWT.DROP_DOWN | SWT.READ_ONLY ); - form_data = new FormData(120,20); - form_data.left = new FormAttachment( import_rbd_combo, 0, SWT.LEFT ); - form_data.top = new FormAttachment( import_rbd_combo, 45, SWT.BOTTOM ); - disp_type_combo.setLayoutData( form_data ); - disp_type_combo.setEnabled(true); - - disp_type_combo.setItems( new String[] { - NcDisplayType.NMAP_DISPLAY.getName(), - NcDisplayType.NTRANS_DISPLAY.getName(), - NcDisplayType.SOLAR_DISPLAY.getName()} ); + form_data.left = new FormAttachment(rbd_name_txt, 0, SWT.LEFT); + form_data.bottom = new FormAttachment(rbd_name_txt, -3, SWT.TOP); + rbd_name_lbl.setLayoutData(form_data); - - disp_type_lbl = new Label( rbd_grp, SWT.None ); + disp_type_combo = new Combo(rbd_grp, SWT.DROP_DOWN | SWT.READ_ONLY); + form_data = new FormData(120, 20); + form_data.left = new FormAttachment(import_rbd_combo, 0, SWT.LEFT); + form_data.top = new FormAttachment(import_rbd_combo, 45, SWT.BOTTOM); + disp_type_combo.setLayoutData(form_data); + disp_type_combo.setEnabled(true); + + disp_type_combo.setItems(new String[] { + NcDisplayType.NMAP_DISPLAY.getName(), + NcDisplayType.NTRANS_DISPLAY.getName(), + NcDisplayType.SOLAR_DISPLAY.getName() }); + + disp_type_lbl = new Label(rbd_grp, SWT.None); disp_type_lbl.setText("RBD Type"); form_data = new FormData(); - form_data.left = new FormAttachment( disp_type_combo, 0, SWT.LEFT ); - form_data.bottom = new FormAttachment( disp_type_combo, -3, SWT.TOP ); - disp_type_lbl.setLayoutData( form_data ); + form_data.left = new FormAttachment(disp_type_combo, 0, SWT.LEFT); + form_data.bottom = new FormAttachment(disp_type_combo, -3, SWT.TOP); + disp_type_lbl.setLayoutData(form_data); - - multi_pane_tog = new Button( rbd_grp, SWT.CHECK ); - multi_pane_tog.setText("Multi-Pane Display"); - form_data = new FormData(); - form_data.top = new FormAttachment( rbd_name_txt, -10, SWT.TOP ); - form_data.left = new FormAttachment( rbd_name_txt, 35, SWT.RIGHT ); - multi_pane_tog.setLayoutData( form_data ); + multi_pane_tog = new Button(rbd_grp, SWT.CHECK); + multi_pane_tog.setText("Multi-Pane Display"); + form_data = new FormData(); + form_data.top = new FormAttachment(rbd_name_txt, -10, SWT.TOP); + form_data.left = new FormAttachment(rbd_name_txt, 35, SWT.RIGHT); + multi_pane_tog.setLayoutData(form_data); - auto_update_btn = new Button( rbd_grp, SWT.CHECK ); + auto_update_btn = new Button(rbd_grp, SWT.CHECK); form_data = new FormData(); auto_update_btn.setText("Auto Update"); - form_data.top = new FormAttachment( multi_pane_tog, 10, SWT.BOTTOM ); - form_data.left = new FormAttachment( multi_pane_tog, 0, SWT.LEFT ); - auto_update_btn.setLayoutData( form_data ); + form_data.top = new FormAttachment(multi_pane_tog, 10, SWT.BOTTOM); + form_data.left = new FormAttachment(multi_pane_tog, 0, SWT.LEFT); + auto_update_btn.setLayoutData(form_data); auto_update_btn.setEnabled(false); - - geo_sync_panes = new Button( rbd_grp, SWT.CHECK ); + + geo_sync_panes = new Button(rbd_grp, SWT.CHECK); form_data = new FormData(); geo_sync_panes.setText("Geo-Sync Panes"); - form_data.top = new FormAttachment( auto_update_btn, 10, SWT.BOTTOM ); - form_data.left = new FormAttachment( auto_update_btn, 0, SWT.LEFT ); - geo_sync_panes.setLayoutData( form_data ); - - createAreaGroup(); - - // create all the widgets used to show and edit the Selected Resources - seld_rscs_grp = createSeldRscsGroup( ); + form_data.top = new FormAttachment(auto_update_btn, 10, SWT.BOTTOM); + form_data.left = new FormAttachment(auto_update_btn, 0, SWT.LEFT); + geo_sync_panes.setLayoutData(form_data); - createPaneLayoutGroup(); + createAreaGroup(); + + // create all the widgets used to show and edit the Selected Resources + seld_rscs_grp = createSeldRscsGroup(); + + createPaneLayoutGroup(); } - - private void createAreaGroup( ) { - geo_area_grp = new Group( rbd_grp, SWT.SHADOW_NONE ); - geo_area_grp.setText("Area" ); - geo_area_grp.setLayout( new FormLayout() ); - FormData form_data = new FormData(); - form_data.top = new FormAttachment( disp_type_combo, 25, SWT.BOTTOM ); - // form_data.bottom = new FormAttachment( 100, -60 ); // if offset for room for the Load and Save buttons - form_data.bottom = new FormAttachment( 100, -10 ); - form_data.left = new FormAttachment( 0, 10 ); - form_data.right = new FormAttachment( 24, 0 ); - - geo_area_grp.setLayoutData( form_data ); - ToolBar areaTBar = new ToolBar(geo_area_grp, SWT.SHADOW_OUT|SWT.HORIZONTAL|SWT.RIGHT|SWT.WRAP); - form_data = new FormData(); - form_data.left = new FormAttachment( 0, 10 ); - form_data.top = new FormAttachment( 0, 15 ); - form_data.right = new FormAttachment( 100, -10 ); - form_data.height = 30; - areaTBar.setLayoutData( form_data ); - - this.addDisposeListener( new DisposeListener() { - @Override - public void widgetDisposed(DisposeEvent e) { - if( areaFont != null ) { - areaFont.dispose(); - } - } - }); - - areaTItm = new ToolItem(areaTBar, SWT.DROP_DOWN); - areaMenuMngr = new MenuManager("CreateRbdControl"); - areaMenuMngr.setRemoveAllWhenShown( true ); - final Menu areaCtxMenu = areaMenuMngr.createContextMenu( shell ); - - areaCtxMenu.setVisible( false ); - geo_area_grp.setMenu( areaCtxMenu ); - - areaMenuMngr.addMenuListener( new IMenuListener() { - @Override - public void menuAboutToShow(IMenuManager amngr) { - createAvailAreaMenuItems( amngr ); - } - }); - - // Main toolbar button clicked: show the areas popup menu at - // the location of the toolbar so it appears like a combo - // dropdown. This will also trigger the menu manager to create - // the menu items for the available areas. - areaTItm.addListener(SWT.Selection, new Listener() { - public void handleEvent(Event event) { - ToolItem ti = ((ToolItem)event.widget); - Rectangle bounds = ti.getBounds(); - Point point = ((ToolBar)ti.getParent()).toDisplay(bounds.x, bounds.y + bounds.height); - - areaCtxMenu.setLocation(point); - areaCtxMenu.setVisible(true); - } + private void createAreaGroup() { + geo_area_grp = new Group(rbd_grp, SWT.SHADOW_NONE); + geo_area_grp.setText("Area"); + geo_area_grp.setLayout(new FormLayout()); + FormData form_data = new FormData(); + form_data.top = new FormAttachment(disp_type_combo, 25, SWT.BOTTOM); + // form_data.bottom = new FormAttachment( 100, -60 ); // if offset for + // room for the Load and Save buttons + form_data.bottom = new FormAttachment(100, -10); + form_data.left = new FormAttachment(0, 10); + form_data.right = new FormAttachment(24, 0); + + geo_area_grp.setLayoutData(form_data); + + ToolBar areaTBar = new ToolBar(geo_area_grp, SWT.SHADOW_OUT + | SWT.HORIZONTAL | SWT.RIGHT | SWT.WRAP); + form_data = new FormData(); + form_data.left = new FormAttachment(0, 10); + form_data.top = new FormAttachment(0, 15); + form_data.right = new FormAttachment(100, -10); + form_data.height = 30; + areaTBar.setLayoutData(form_data); + + this.addDisposeListener(new DisposeListener() { + @Override + public void widgetDisposed(DisposeEvent e) { + if (areaFont != null) { + areaFont.dispose(); + } + } }); - - // 2 Composites. 1 for when a predefined area is selected which will show the - // projection and map center. And 1 for when a satellite resource is selecte which - // will let the user select either FitToScreen or SizeOfImage - // - geo_area_info_comp = new Composite( geo_area_grp, SWT.NONE ); - geo_area_info_comp.setLayout( new FormLayout() ); - rsc_area_opts_comp = new Composite( geo_area_grp, SWT.NONE ); - rsc_area_opts_comp.setLayout( new GridLayout(1,true) ); - - geo_area_info_comp.setVisible( true ); - rsc_area_opts_comp.setVisible( false ); - - form_data = new FormData(); - form_data.left = new FormAttachment( 0, 10 ); - form_data.top = new FormAttachment( areaTBar, 15, SWT.BOTTOM ); - form_data.right = new FormAttachment( 100, -10 ); - // both overlap each other since only one visible at a time - geo_area_info_comp.setLayoutData( form_data ); - - form_data.top = new FormAttachment( areaTBar, 30, SWT.BOTTOM ); - rsc_area_opts_comp.setLayoutData( form_data ); - - fit_to_screen_btn = new Button( rsc_area_opts_comp, SWT.RADIO ); - fit_to_screen_btn.setText( "Fit To Screen"); + areaTItm = new ToolItem(areaTBar, SWT.DROP_DOWN); + areaMenuMngr = new MenuManager("CreateRbdControl"); + areaMenuMngr.setRemoveAllWhenShown(true); + final Menu areaCtxMenu = areaMenuMngr.createContextMenu(shell); - size_of_image_btn = new Button( rsc_area_opts_comp, SWT.RADIO ); - size_of_image_btn.setText("Size Of Image"); + areaCtxMenu.setVisible(false); + geo_area_grp.setMenu(areaCtxMenu); - fit_to_screen_btn.setSelection( true ); // radio behaviour - size_of_image_btn.setSelection( false ); + areaMenuMngr.addMenuListener(new IMenuListener() { + @Override + public void menuAboutToShow(IMenuManager amngr) { + createAvailAreaMenuItems(amngr); + } + }); - - Label proj_lbl = new Label( geo_area_info_comp, SWT.None ); + // Main toolbar button clicked: show the areas popup menu at + // the location of the toolbar so it appears like a combo + // dropdown. This will also trigger the menu manager to create + // the menu items for the available areas. + areaTItm.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event event) { + ToolItem ti = ((ToolItem) event.widget); + Rectangle bounds = ti.getBounds(); + Point point = ((ToolBar) ti.getParent()).toDisplay(bounds.x, + bounds.y + bounds.height); + + areaCtxMenu.setLocation(point); + areaCtxMenu.setVisible(true); + } + }); + + // 2 Composites. 1 for when a predefined area is selected which will + // show the + // projection and map center. And 1 for when a satellite resource is + // selecte which + // will let the user select either FitToScreen or SizeOfImage + // + geo_area_info_comp = new Composite(geo_area_grp, SWT.NONE); + geo_area_info_comp.setLayout(new FormLayout()); + rsc_area_opts_comp = new Composite(geo_area_grp, SWT.NONE); + rsc_area_opts_comp.setLayout(new GridLayout(1, true)); + + geo_area_info_comp.setVisible(true); + rsc_area_opts_comp.setVisible(false); + + form_data = new FormData(); + form_data.left = new FormAttachment(0, 10); + form_data.top = new FormAttachment(areaTBar, 15, SWT.BOTTOM); + form_data.right = new FormAttachment(100, -10); + + // both overlap each other since only one visible at a time + geo_area_info_comp.setLayoutData(form_data); + + form_data.top = new FormAttachment(areaTBar, 30, SWT.BOTTOM); + rsc_area_opts_comp.setLayoutData(form_data); + + fit_to_screen_btn = new Button(rsc_area_opts_comp, SWT.RADIO); + fit_to_screen_btn.setText("Fit To Screen"); + + size_of_image_btn = new Button(rsc_area_opts_comp, SWT.RADIO); + size_of_image_btn.setText("Size Of Image"); + + fit_to_screen_btn.setSelection(true); // radio behaviour + size_of_image_btn.setSelection(false); + + Label proj_lbl = new Label(geo_area_info_comp, SWT.None); proj_lbl.setText("Projection"); form_data = new FormData(); - form_data.left = new FormAttachment( 0, 0 ); - form_data.top = new FormAttachment( 0, 0 ); - form_data.right = new FormAttachment( 100, 0 ); - proj_lbl.setLayoutData( form_data ); + form_data.left = new FormAttachment(0, 0); + form_data.top = new FormAttachment(0, 0); + form_data.right = new FormAttachment(100, 0); + proj_lbl.setLayoutData(form_data); - proj_info_txt = new Text( geo_area_info_comp, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY ); - form_data = new FormData(); - form_data.left = new FormAttachment( 0, 0 ); - form_data.top = new FormAttachment( proj_lbl, 2, SWT.BOTTOM ); - form_data.right = new FormAttachment( 100, 0 ); - proj_info_txt.setLayoutData( form_data ); - proj_info_txt.setText(""); - proj_info_txt.setBackground(rbd_grp.getBackground() ); // indicate Read-only + proj_info_txt = new Text(geo_area_info_comp, SWT.SINGLE | SWT.BORDER + | SWT.READ_ONLY); + form_data = new FormData(); + form_data.left = new FormAttachment(0, 0); + form_data.top = new FormAttachment(proj_lbl, 2, SWT.BOTTOM); + form_data.right = new FormAttachment(100, 0); + proj_info_txt.setLayoutData(form_data); + proj_info_txt.setText(""); + proj_info_txt.setBackground(rbd_grp.getBackground()); // indicate + // Read-only - Label map_center_lbl = new Label( geo_area_info_comp, SWT.None ); + Label map_center_lbl = new Label(geo_area_info_comp, SWT.None); map_center_lbl.setText("Map Center"); form_data = new FormData(); - form_data.left = new FormAttachment( 0, 0 ); - form_data.top = new FormAttachment( proj_info_txt, 15, SWT.BOTTOM ); - form_data.right = new FormAttachment( 100, 0 ); - map_center_lbl.setLayoutData( form_data ); + form_data.left = new FormAttachment(0, 0); + form_data.top = new FormAttachment(proj_info_txt, 15, SWT.BOTTOM); + form_data.right = new FormAttachment(100, 0); + map_center_lbl.setLayoutData(form_data); - map_center_txt = new Text( geo_area_info_comp, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY ); - form_data = new FormData(); - form_data.left = new FormAttachment( 0, 0 ); - form_data.top = new FormAttachment( map_center_lbl, 2, SWT.BOTTOM ); - form_data.right = new FormAttachment( 100, 0 ); - map_center_txt.setLayoutData( form_data ); - map_center_txt.setText(" "); - map_center_txt.setBackground(rbd_grp.getBackground() ); // indicate Read-only + map_center_txt = new Text(geo_area_info_comp, SWT.SINGLE | SWT.BORDER + | SWT.READ_ONLY); + form_data = new FormData(); + form_data.left = new FormAttachment(0, 0); + form_data.top = new FormAttachment(map_center_lbl, 2, SWT.BOTTOM); + form_data.right = new FormAttachment(100, 0); + map_center_txt.setLayoutData(form_data); + map_center_txt.setText(" "); + map_center_txt.setBackground(rbd_grp.getBackground()); // indicate + // Read-only - // TODO : move this to be a Tool from main menu to create and name predefined areas - // and move this button to be an option under the predefined areas list - // - custom_area_btn = new Button( geo_area_grp, SWT.PUSH ); - form_data = new FormData(); - form_data.left = new FormAttachment( 0, 40 ); - form_data.right = new FormAttachment( 100, -40 ); - form_data.bottom = new FormAttachment( 100, -15 ); + // TODO : move this to be a Tool from main menu to create and name + // predefined areas + // and move this button to be an option under the predefined areas list + // + custom_area_btn = new Button(geo_area_grp, SWT.PUSH); + form_data = new FormData(); + form_data.left = new FormAttachment(0, 40); + form_data.right = new FormAttachment(100, -40); + form_data.bottom = new FormAttachment(100, -15); - custom_area_btn.setLayoutData( form_data ); - custom_area_btn.setText(" Custom ... "); - custom_area_btn.setEnabled(false); // not implemented - custom_area_btn.setVisible( false ); + custom_area_btn.setLayoutData(form_data); + custom_area_btn.setText(" Custom ... "); + custom_area_btn.setEnabled(false); // not implemented + custom_area_btn.setVisible(false); } - + // create the Selected Resources List, the Edit, Delete and Clear buttons // - private Group createSeldRscsGroup( ) { - Group seld_rscs_grp = new Group( rbd_grp, SWT.SHADOW_NONE ); - seld_rscs_grp.setText("Selected Resources" ); - seld_rscs_grp.setLayout( new FormLayout() ); - FormData form_data = new FormData(); - - // NOTE : This is reset in updateGUIforMultipane() -// form_data.left = new FormAttachment( 30, 2 ); -// form_data.top = new FormAttachment( rbd_name_txt, 25, SWT.BOTTOM ); - form_data.top = new FormAttachment( auto_update_btn, 15, SWT.BOTTOM ); - form_data.left = new FormAttachment( geo_area_grp, 10, SWT.RIGHT ); - form_data.right = new FormAttachment( 100, -10 ); - form_data.bottom = new FormAttachment( geo_area_grp, 0, SWT.BOTTOM ); - seld_rscs_grp.setLayoutData( form_data ); + private Group createSeldRscsGroup() { + Group seld_rscs_grp = new Group(rbd_grp, SWT.SHADOW_NONE); + seld_rscs_grp.setText("Selected Resources"); + seld_rscs_grp.setLayout(new FormLayout()); + FormData form_data = new FormData(); - // This is multi-select to make Deleting resources easier. - seld_rscs_lviewer = new ListViewer( seld_rscs_grp, - SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL ); - form_data = new FormData(); - form_data.top = new FormAttachment( 0, 5 ); - form_data.left = new FormAttachment( 0, 5 ); - form_data.right = new FormAttachment( 100, -95);//-110 ); //80, 0 ); - form_data.bottom = new FormAttachment( 100, -47 ); - seld_rscs_lviewer.getList().setLayoutData( form_data ); + // NOTE : This is reset in updateGUIforMultipane() + // form_data.left = new FormAttachment( 30, 2 ); + // form_data.top = new FormAttachment( rbd_name_txt, 25, SWT.BOTTOM ); + form_data.top = new FormAttachment(auto_update_btn, 15, SWT.BOTTOM); + form_data.left = new FormAttachment(geo_area_grp, 10, SWT.RIGHT); + form_data.right = new FormAttachment(100, -10); + form_data.bottom = new FormAttachment(geo_area_grp, 0, SWT.BOTTOM); + seld_rscs_grp.setLayoutData(form_data); - // - edit_rsc_btn = new Button( seld_rscs_grp, SWT.PUSH ); - edit_rsc_btn.setText(" Edit ..."); - form_data = new FormData(); - form_data.width = 90; - form_data.bottom = new FormAttachment( 100, -10 ); + // This is multi-select to make Deleting resources easier. + seld_rscs_lviewer = new ListViewer(seld_rscs_grp, SWT.MULTI + | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); + form_data = new FormData(); + form_data.top = new FormAttachment(0, 5); + form_data.left = new FormAttachment(0, 5); + form_data.right = new FormAttachment(100, -95);// -110 ); //80, 0 ); + form_data.bottom = new FormAttachment(100, -47); + seld_rscs_lviewer.getList().setLayoutData(form_data); -// if( enableReplaceBtnFromCreateRbd ) { -// form_data.left = new FormAttachment( 42, -45 ); -// } -// else { - form_data.left = new FormAttachment( 40, 20 ); -// } - - edit_rsc_btn.setLayoutData( form_data ); - edit_rsc_btn.setEnabled(false); + // + edit_rsc_btn = new Button(seld_rscs_grp, SWT.PUSH); + edit_rsc_btn.setText(" Edit ..."); + form_data = new FormData(); + form_data.width = 90; + form_data.bottom = new FormAttachment(100, -10); + // if( enableReplaceBtnFromCreateRbd ) { + // form_data.left = new FormAttachment( 42, -45 ); + // } + // else { + form_data.left = new FormAttachment(40, 20); + // } - sel_rsc_btn = new Button( seld_rscs_grp, SWT.PUSH ); - sel_rsc_btn.setText(" New ... "); - form_data = new FormData(); - form_data.width = 90; - form_data.bottom = new FormAttachment( 100, -10 ); -// if( enableReplaceBtnFromCreateRbd ) { -// form_data.right = new FormAttachment( edit_rsc_btn, -30, SWT.LEFT ); -// } -// else { - form_data.right = new FormAttachment( 40, -20 ); -// } - sel_rsc_btn.setLayoutData( form_data ); - - replace_rsc_btn = new Button( seld_rscs_grp, SWT.PUSH ); - replace_rsc_btn.setText(" Replace ..."); - form_data = new FormData(); - form_data.width = 90; - form_data.bottom = new FormAttachment( 100, -10 ); - form_data.left = new FormAttachment( edit_rsc_btn, 30, SWT.RIGHT ); - replace_rsc_btn.setLayoutData( form_data ); - replace_rsc_btn.setEnabled(false); + edit_rsc_btn.setLayoutData(form_data); + edit_rsc_btn.setEnabled(false); - - replace_rsc_btn.setVisible( false ); //enableReplaceBtnFromCreateRbd ); + sel_rsc_btn = new Button(seld_rscs_grp, SWT.PUSH); + sel_rsc_btn.setText(" New ... "); + form_data = new FormData(); + form_data.width = 90; + form_data.bottom = new FormAttachment(100, -10); + // if( enableReplaceBtnFromCreateRbd ) { + // form_data.right = new FormAttachment( edit_rsc_btn, -30, SWT.LEFT ); + // } + // else { + form_data.right = new FormAttachment(40, -20); + // } + sel_rsc_btn.setLayoutData(form_data); - - del_rsc_btn = new Button( seld_rscs_grp, SWT.PUSH ); - del_rsc_btn.setText("Remove"); - form_data = new FormData(); - form_data.width = 75; - form_data.top = new FormAttachment( 10, -10 ); - form_data.right = new FormAttachment( 100, -10 ); - del_rsc_btn.setLayoutData( form_data ); - del_rsc_btn.setEnabled(false); + replace_rsc_btn = new Button(seld_rscs_grp, SWT.PUSH); + replace_rsc_btn.setText(" Replace ..."); + form_data = new FormData(); + form_data.width = 90; + form_data.bottom = new FormAttachment(100, -10); + form_data.left = new FormAttachment(edit_rsc_btn, 30, SWT.RIGHT); + replace_rsc_btn.setLayoutData(form_data); + replace_rsc_btn.setEnabled(false); - disable_rsc_btn = new Button( seld_rscs_grp, SWT.TOGGLE ); - disable_rsc_btn.setText("Turn Off"); - form_data = new FormData(); - form_data.width = 75; - form_data.right = new FormAttachment( 100, -10 ); - form_data.top = new FormAttachment( 30, -10 ); - disable_rsc_btn.setLayoutData( form_data ); + replace_rsc_btn.setVisible(false); // enableReplaceBtnFromCreateRbd ); - - Button move_down_btn = new Button( seld_rscs_grp, SWT.ARROW | SWT.DOWN ); - move_down_btn.setToolTipText("Move Down"); - form_data = new FormData(); - form_data.width = 35; - form_data.top = new FormAttachment( 50, -10 ); - form_data.right = new FormAttachment( 100, -10 ); - move_down_btn.setLayoutData( form_data ); - move_down_btn.setEnabled(false); + del_rsc_btn = new Button(seld_rscs_grp, SWT.PUSH); + del_rsc_btn.setText("Remove"); + form_data = new FormData(); + form_data.width = 75; + form_data.top = new FormAttachment(10, -10); + form_data.right = new FormAttachment(100, -10); + del_rsc_btn.setLayoutData(form_data); + del_rsc_btn.setEnabled(false); - Button move_up_btn = new Button( seld_rscs_grp, SWT.ARROW | SWT.UP ); - move_up_btn.setToolTipText("Move Up"); - form_data = new FormData(); - form_data.width = 35; - form_data.top = new FormAttachment( move_down_btn, 0, SWT.TOP ); - form_data.left = new FormAttachment( disable_rsc_btn, 0, SWT.LEFT); - move_up_btn.setLayoutData( form_data ); - move_up_btn.setEnabled(false); + disable_rsc_btn = new Button(seld_rscs_grp, SWT.TOGGLE); + disable_rsc_btn.setText("Turn Off"); + form_data = new FormData(); + form_data.width = 75; + form_data.right = new FormAttachment(100, -10); + form_data.top = new FormAttachment(30, -10); + disable_rsc_btn.setLayoutData(form_data); - Button edit_span_btn = new Button( seld_rscs_grp, SWT.PUSH ); - edit_span_btn.setText(" Bin ... "); - form_data = new FormData(); - form_data.width = 75; - form_data.top = new FormAttachment( 70, -10 ); - form_data.right = new FormAttachment( 100, -10 ); - edit_span_btn.setLayoutData( form_data ); - edit_span_btn.setEnabled(false); + Button move_down_btn = new Button(seld_rscs_grp, SWT.ARROW | SWT.DOWN); + move_down_btn.setToolTipText("Move Down"); + form_data = new FormData(); + form_data.width = 35; + form_data.top = new FormAttachment(50, -10); + form_data.right = new FormAttachment(100, -10); + move_down_btn.setLayoutData(form_data); + move_down_btn.setEnabled(false); + Button move_up_btn = new Button(seld_rscs_grp, SWT.ARROW | SWT.UP); + move_up_btn.setToolTipText("Move Up"); + form_data = new FormData(); + form_data.width = 35; + form_data.top = new FormAttachment(move_down_btn, 0, SWT.TOP); + form_data.left = new FormAttachment(disable_rsc_btn, 0, SWT.LEFT); + move_up_btn.setLayoutData(form_data); + move_up_btn.setEnabled(false); -// seld_rscs_grp.pack(true); + Button edit_span_btn = new Button(seld_rscs_grp, SWT.PUSH); + edit_span_btn.setText(" Bin ... "); + form_data = new FormData(); + form_data.width = 75; + form_data.top = new FormAttachment(70, -10); + form_data.right = new FormAttachment(100, -10); + edit_span_btn.setLayoutData(form_data); + edit_span_btn.setEnabled(false); - return seld_rscs_grp; - } + // seld_rscs_grp.pack(true); - private void createPaneLayoutGroup() { - pane_layout_grp = new Group( rbd_grp, SWT.SHADOW_NONE ); - pane_layout_grp.setText("Pane Layout" ); - pane_layout_grp.setLayout( new FormLayout() ); - FormData fd = new FormData(); - fd.left = new FormAttachment( seld_rscs_grp, 10, SWT.RIGHT ); - fd.top = new FormAttachment( 0, 3); - fd.right = new FormAttachment( 100, -10 ); - fd.bottom = new FormAttachment( 100, -15 ); - pane_layout_grp.setLayoutData( fd ); - - Composite num_rows_cols_comp = new Composite( pane_layout_grp, SWT.NONE ); - GridLayout gl = new GridLayout(rbdMngr.getMaxPaneLayout().getColumns(), false); - // gl.horizontalSpacing = 4; - - num_rows_cols_comp.setLayout( gl ); + return seld_rscs_grp; + } - fd = new FormData(); - fd.left = new FormAttachment( 0, 80 ); - fd.top = new FormAttachment( 0, 3 ); - fd.right = new FormAttachment( 100, -10 ); - num_rows_cols_comp.setLayoutData( fd ); + private void createPaneLayoutGroup() { + pane_layout_grp = new Group(rbd_grp, SWT.SHADOW_NONE); + pane_layout_grp.setText("Pane Layout"); + pane_layout_grp.setLayout(new FormLayout()); + FormData fd = new FormData(); + fd.left = new FormAttachment(seld_rscs_grp, 10, SWT.RIGHT); + fd.top = new FormAttachment(0, 3); + fd.right = new FormAttachment(100, -10); + fd.bottom = new FormAttachment(100, -15); + pane_layout_grp.setLayoutData(fd); - Button num_rows_btns[] = new Button[rbdMngr.getMaxPaneLayout().getRows()]; - Button num_cols_btns[] = new Button[rbdMngr.getMaxPaneLayout().getColumns()]; - - for( int r=0 ; r dfltRbd = AbstractRBD.getDefaultRBD( rbdMngr.getRbdType() ); - - rbdMngr.initFromRbdBundle( dfltRbd ); - - } catch (VizException ve) { - MessageDialog errDlg = new MessageDialog( - shell, "Error", null, - ve.getMessage(), MessageDialog.ERROR, new String[]{"OK"}, 0); - errDlg.open(); - - rbdMngr.init( rbdMngr.getRbdType() ); - } - updateGUI(); - } - } - }); - - sel_rsc_btn.addSelectionListener( new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - StructuredSelection sel_elems = (StructuredSelection) seld_rscs_lviewer.getSelection(); - List seldRscsList = (List) sel_elems.toList(); - int numSeldRscs = seld_rscs_lviewer.getList().getSelectionCount(); + if (confirmDlg.getReturnCode() != MessageDialog.OK) { + return; + } + } - Boolean isBaseLevelRscSeld = false; - // the initially selected resource is the first non-baselevel rsc - ResourceName initRscName = null; + try { + rbdMngr.setRbdType(selDispType); - for( ResourceSelection rscSel : seldRscsList ) { - isBaseLevelRscSeld |= rscSel.isBaseLevelResource(); - if( initRscName == null && !rscSel.isBaseLevelResource() ) { - initRscName = rscSel.getResourceName(); - } - } - - // the replace button is enabled if there is only 1 resource selected and - // it is not the base resource - if( rscSelDlg.isOpen() ) { - if( initRscName != null ) { - rscSelDlg.setSelectedResource( initRscName ); - } - } - else { - rscSelDlg.open( true, // Replace button is visible - (numSeldRscs == 1 && !isBaseLevelRscSeld), // replace enabled - initRscName, - multi_pane_tog.getSelection(), - rbdMngr.getRbdType(), - SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MODELESS); - } - } - }); + AbstractRBD dfltRbd = AbstractRBD + .getDefaultRBD(rbdMngr.getRbdType()); - // may be invisible, if implementing the Replace on the Select Resource Dialog - replace_rsc_btn.addSelectionListener( new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - if (! rscSelDlg.isOpen()) { - StructuredSelection sel_elems = (StructuredSelection) seld_rscs_lviewer.getSelection(); - ResourceSelection rscSel = (ResourceSelection)sel_elems.getFirstElement(); + rbdMngr.initFromRbdBundle(dfltRbd); - rscSelDlg.open( true, // Replace button is visible - (rscSel != null ? true : false), - rscSel.getResourceName(), - multi_pane_tog.getSelection(), - rbdMngr.getRbdType(), - //SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MODELESS); - SWT.DIALOG_TRIM | SWT.RESIZE | SWT.APPLICATION_MODAL ); - } - } - }); - - rscSelDlg.addResourceSelectionListener( new IResourceSelectedListener() { - @Override - public void resourceSelected( ResourceName rscName, boolean replace, - boolean addAllPanes, boolean done ) { - - try { - ResourceSelection rbt = ResourceFactory.createResource( rscName ); - - rbdMngr.getSelectedArea(); + } catch (VizException ve) { + MessageDialog errDlg = new MessageDialog(shell, + "Error", null, ve.getMessage(), + MessageDialog.ERROR, new String[] { "OK" }, 0); + errDlg.open(); - - // if replacing existing resources, get the selected resources - // (For now just replace the 1st if more than one selected.) - // - if( replace ) { - StructuredSelection sel_elems = - (StructuredSelection) seld_rscs_lviewer.getSelection(); - ResourceSelection rscSel = (ResourceSelection)sel_elems.getFirstElement(); - - if( !rbdMngr.replaceSelectedResource( rscSel, rbt ) ) { -// return; - } - - // remove this from the list of available dominant resources. - if( rscSel.getResourceData() instanceof AbstractNatlCntrsRequestableResourceData ) { - timelineControl.removeAvailDomResource( - (AbstractNatlCntrsRequestableResourceData) rscSel.getResourceData() ); - } - - // if replacing a resource which is set to provide the geographic area - // check to see if the current area has been reset to the default because - // it was not available -// String seldArea = rbdMngr.getSelectedArea().getProviderName(); -// -// if( !seldAreaMenuItem.getAreaName().equals( seldArea ) ) { - updateAreaGUI( ); -// } - } - else { - if( addAllPanes ) { - if( !rbdMngr.addSelectedResourceToAllPanes( rbt ) ) { - if( done ) { - rscSelDlg.close(); - } - return; - } - } - else if( !rbdMngr.addSelectedResource( rbt ) ) { - if( done ) { - rscSelDlg.close(); - } - return; - } - } + rbdMngr.init(rbdMngr.getRbdType()); + } + updateGUI(); + } + } + }); - // add the new resource to the timeline as a possible dominant resource - if( rbt.getResourceData() instanceof AbstractNatlCntrsRequestableResourceData ) { - timelineControl.addAvailDomResource( - (AbstractNatlCntrsRequestableResourceData) rbt.getResourceData() ); - - // if there is not a dominant resource selected then select this one - if( timelineControl.getDominantResource() == null ) { - timelineControl.setDominantResource( - (AbstractNatlCntrsRequestableResourceData) rbt.getResourceData() ); - // timelineControl.selectDominantResource(); -// (AbstractNatlCntrsRequestableResourceData) rbt.getResourceData() ); - } - } - } - catch (VizException e ) { - System.out.println( "Error Adding Resource to List: " + e.getMessage() ); - MessageDialog errDlg = new MessageDialog( - shell, "Error", null, - "Error Creating Resource:"+rscName.toString()+"\n\n"+e.getMessage(), - MessageDialog.ERROR, new String[]{"OK"}, 0); - errDlg.open(); - } - - updateSelectedResourcesView( true ); - - if( done ) { - rscSelDlg.close(); - } - } - }); + sel_rsc_btn.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + StructuredSelection sel_elems = (StructuredSelection) seld_rscs_lviewer + .getSelection(); + List seldRscsList = (List) sel_elems + .toList(); + int numSeldRscs = seld_rscs_lviewer.getList() + .getSelectionCount(); - size_of_image_btn.addSelectionListener( new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - rbdMngr.setZoomLevel( - (size_of_image_btn.getSelection() ? // -1.0 : 1.0 ) ); - ZoomLevelStrings.SizeOfImage.toString() : - ZoomLevelStrings.FitToScreen.toString() ) ); + Boolean isBaseLevelRscSeld = false; + // the initially selected resource is the first non-baselevel + // rsc + ResourceName initRscName = null; - } - }); + for (ResourceSelection rscSel : seldRscsList) { + isBaseLevelRscSeld |= rscSel.isBaseLevelResource(); + if (initRscName == null && !rscSel.isBaseLevelResource()) { + initRscName = rscSel.getResourceName(); + } + } - fit_to_screen_btn.addSelectionListener( new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - rbdMngr.setZoomLevel( - (fit_to_screen_btn.getSelection() ? //1.0 : -1.0 ) ); - ZoomLevelStrings.FitToScreen.toString() : - ZoomLevelStrings.SizeOfImage.toString() ) ); - } - }); - - // TODO: if single pane and there are resources selected - // in other panes then should we prompt the user on whether - // to clear them? We can ignore them if Loading/Saving a - // single pane, but if they reset multi-pane then should the - // resources in other panes still be selected. - multi_pane_tog.addSelectionListener( new SelectionAdapter() { - public void widgetSelected(SelectionEvent ev) { - rbdMngr.setMultiPane( multi_pane_tog.getSelection() ); - - updateGUIforMultipane( multi_pane_tog.getSelection() ); - - if( multi_pane_tog.getSelection() ) { - updatePaneLayout(); - } - else { - selectPane( new NcPaneID() ); // 0,0 - } - - if( rscSelDlg != null && rscSelDlg.isOpen() ) { - rscSelDlg.setMultiPaneEnabled( multi_pane_tog.getSelection() ); - } - } - }); - - // if syncing the panes - geo_sync_panes.addSelectionListener( new SelectionAdapter() { - public void widgetSelected(SelectionEvent ev) { - - if( geo_sync_panes.getSelection() ) { - - MessageDialog confirmDlg = new MessageDialog( shell, - "Confirm Geo-Sync Panes", null, - "This will set the Area for all panes to the currently\n"+ - "selected Area: "+ rbdMngr.getSelectedArea().getProviderName() + "\n\n"+ - "Continue?", - MessageDialog.QUESTION, new String[]{"Yes", "No"}, 0); - confirmDlg.open(); + // the replace button is enabled if there is only 1 resource + // selected and + // it is not the base resource + if (rscSelDlg.isOpen()) { + if (initRscName != null) { + rscSelDlg.setSelectedResource(initRscName); + } + } else { + rscSelDlg.open( + true, // Replace button is visible + (numSeldRscs == 1 && !isBaseLevelRscSeld), // replace + // enabled + initRscName, multi_pane_tog.getSelection(), + rbdMngr.getRbdType(), SWT.DIALOG_TRIM | SWT.RESIZE + | SWT.MODELESS); + } + } + }); - if( confirmDlg.getReturnCode() != MessageDialog.OK ) { - geo_sync_panes.setSelection( false ); - return; - } - - rbdMngr.syncPanesToArea( ); - } - else { - rbdMngr.setGeoSyncPanes( false ); - } - } - }); + // may be invisible, if implementing the Replace on the Select Resource + // Dialog + replace_rsc_btn.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + if (!rscSelDlg.isOpen()) { + StructuredSelection sel_elems = (StructuredSelection) seld_rscs_lviewer + .getSelection(); + ResourceSelection rscSel = (ResourceSelection) sel_elems + .getFirstElement(); - custom_area_btn.addSelectionListener( new SelectionAdapter() { - public void widgetSelected(SelectionEvent ev) { -// Shell shell = NcDisplayMngr.getCaveShell(); -// CreateCustomProjectionDialog dlg = CreateCustomProjectionDialog(shell); -// dlg.open(); - - } - }); - - // only 1 should be selected or this button should be greyed out - edit_rsc_btn.addSelectionListener( new SelectionAdapter() { - public void widgetSelected( SelectionEvent ev ) { - editResourceData(); - } - }); - - del_rsc_btn.addSelectionListener( new SelectionAdapter() { - public void widgetSelected( SelectionEvent ev ) { - StructuredSelection sel_elems = (StructuredSelection) seld_rscs_lviewer.getSelection(); - Iterator itr = sel_elems.iterator(); - - // note: the base may be selected if there are multi selected with others. - while( itr.hasNext() ) { - ResourceSelection rscSel = (ResourceSelection)itr.next(); - if( !rscSel.isBaseLevelResource() ) { - removeSelectedResource( rscSel ); - } - } - - updateSelectedResourcesView( true ); - - // check to see if the current area has been reset to the default because - // it was the -// String seldArea = rbdMngr.getSelectedArea().getProviderName(); -// -// if( seldAreaMenuItem.getAreaName().equals( seldArea) ) { - updateAreaGUI( ); -// } - } - }); + rscSelDlg.open( + true, // Replace button is visible + (rscSel != null ? true : false), + rscSel.getResourceName(), + multi_pane_tog.getSelection(), + rbdMngr.getRbdType(), + // SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MODELESS); + SWT.DIALOG_TRIM | SWT.RESIZE + | SWT.APPLICATION_MODAL); + } + } + }); - disable_rsc_btn.addSelectionListener( new SelectionAdapter() { - public void widgetSelected( SelectionEvent ev ) { - StructuredSelection sel_elems = (StructuredSelection) seld_rscs_lviewer.getSelection(); - Iterator itr = sel_elems.iterator(); - - while( itr.hasNext() ) { - ResourceSelection rscSel = (ResourceSelection)itr.next(); - rscSel.setIsVisible( !disable_rsc_btn.getSelection() ); - } - - - seld_rscs_lviewer.refresh( true ); - - updateSelectedResourcesView( false ); // true - } - }); + rscSelDlg.addResourceSelectionListener(new IResourceSelectedListener() { + @Override + public void resourceSelected(ResourceName rscName, boolean replace, + boolean addAllPanes, boolean done) { - clr_pane_btn.addSelectionListener( new SelectionAdapter() { - public void widgetSelected( SelectionEvent ev ) { - clearSeldResources(); - } - }); + try { + ResourceSelection rbt = ResourceFactory + .createResource(rscName); + rbdMngr.getSelectedArea(); - clear_rbd_btn.addSelectionListener( new SelectionAdapter() { - public void widgetSelected( SelectionEvent ev ) { - clearRBD(); - } - }); + // if replacing existing resources, get the selected + // resources + // (For now just replace the 1st if more than one selected.) + // + if (replace) { + StructuredSelection sel_elems = (StructuredSelection) seld_rscs_lviewer + .getSelection(); + ResourceSelection rscSel = (ResourceSelection) sel_elems + .getFirstElement(); - - load_rbd_btn.addSelectionListener( new SelectionAdapter() { - public void widgetSelected( SelectionEvent ev ) { - loadRBD( false ); - } - }); + if (!rbdMngr.replaceSelectedResource(rscSel, rbt)) { + // return; + } - load_and_close_btn.addSelectionListener( new SelectionAdapter() { - public void widgetSelected( SelectionEvent ev ) { - loadRBD( true ); - } - }); + // remove this from the list of available dominant + // resources. + if (rscSel.getResourceData() instanceof AbstractNatlCntrsRequestableResourceData) { + timelineControl + .removeAvailDomResource((AbstractNatlCntrsRequestableResourceData) rscSel + .getResourceData()); + } - load_pane_btn.addSelectionListener( new SelectionAdapter() { - public void widgetSelected( SelectionEvent ev ) { - loadPane(); - } - }); + // if replacing a resource which is set to provide the + // geographic area + // check to see if the current area has been reset to + // the default because + // it was not available + // String seldArea = + // rbdMngr.getSelectedArea().getProviderName(); + // + // if( !seldAreaMenuItem.getAreaName().equals( seldArea + // ) ) { + updateAreaGUI(); + // } + } else { + if (addAllPanes) { + if (!rbdMngr.addSelectedResourceToAllPanes(rbt)) { + if (done) { + rscSelDlg.close(); + } + return; + } + } else if (!rbdMngr.addSelectedResource(rbt)) { + if (done) { + rscSelDlg.close(); + } + return; + } + } - save_rbd_btn.addSelectionListener( new SelectionAdapter() { - public void widgetSelected( SelectionEvent ev ) { - saveRBD( false ); - } - }); - - import_rbd_combo.addSelectionListener( new SelectionAdapter() { - public void widgetSelected( SelectionEvent ev ) { - importRBD( import_rbd_combo.getText() ); - } - }); - - // TODO : Currently we can't detect if the user clicks on the import combo and then clicks on the currently selected - // item which means the users can't re-import the current selection (or import another from an spf.) The following may - // allow a hackish work around later.... (I tried virtually every listener and these where the only ones to trigger.) - // ....update...with new Eclipse this seems to be working; ie. triggering a selection when - // combo is clicked on but selection isn't changed. - import_rbd_combo.addFocusListener( new FocusListener() { - @Override - public void focusGained(FocusEvent e) { -// System.out.println("focusGained: "); - } - @Override - public void focusLost(FocusEvent e) { -// System.out.println("focusLost: " ); - } - }); - import_rbd_combo.addListener( SWT.MouseDown, new Listener() { // and SWT.MouseUp - @Override - public void handleEvent(Event event) { -// System.out.println("SWT.MouseDown: " ); - } - }); - import_rbd_combo.addListener( SWT.Activate, new Listener() { - @Override - public void handleEvent(Event event) { - updateImportCombo(); - } - }); - import_rbd_combo.addListener( SWT.Deactivate, new Listener() { - @Override - public void handleEvent(Event event) { -// System.out.println("SWT.Deactivate: " ); - } - }); - - import_pane_btn.addSelectionListener( new SelectionAdapter() { - public void widgetSelected( SelectionEvent ev ) { - SelectRbdsDialog impDlg = - new SelectRbdsDialog( shell, "Import Pane", - true, false, true ); - - if( !impDlg.open() ) { - return; - } + // add the new resource to the timeline as a possible + // dominant resource + if (rbt.getResourceData() instanceof AbstractNatlCntrsRequestableResourceData) { + timelineControl + .addAvailDomResource((AbstractNatlCntrsRequestableResourceData) rbt + .getResourceData()); - AbstractRBD impRbd = impDlg.getSelectedRBD(); + // if there is not a dominant resource selected then + // select this one + if (timelineControl.getDominantResource() == null) { + timelineControl + .setDominantResource((AbstractNatlCntrsRequestableResourceData) rbt + .getResourceData()); + // timelineControl.selectDominantResource(); + // (AbstractNatlCntrsRequestableResourceData) + // rbt.getResourceData() ); + } + } + } catch (VizException e) { + System.out.println("Error Adding Resource to List: " + + e.getMessage()); + MessageDialog errDlg = new MessageDialog(shell, "Error", + null, "Error Creating Resource:" + + rscName.toString() + "\n\n" + + e.getMessage(), MessageDialog.ERROR, + new String[] { "OK" }, 0); + errDlg.open(); + } - if( impRbd != null ) { - // if any selections have been made then popup a confirmation msg - // TODO:add support for determining if only this pane has been modified. -// boolean confirm = ( rbdMngr.getSelectedRscs().length > 1 ); -// if( confirm ) { -// MessageDialog confirmDlg = new MessageDialog( -// NcDisplayMngr.getCaveShell(), "Confirm", null, -// "Do you want to remove all currently selected Resources?", -// MessageDialog.QUESTION, new String[]{"Yes", "No"}, 0); -// confirmDlg.open(); -// -// if( confirmDlg.getReturnCode() != MessageDialog.OK ) { -// return; -// } -// } - - impRbd.resolveLatestCycleTimes(); - - try { - importPane( impRbd, impRbd.getSelectedPaneId() ); - } - catch (VizException e) { - MessageDialog errDlg = new MessageDialog( - shell, "Error", null, - "Error Importing Rbd, "+impRbd.getRbdName()+".\n"+e.getMessage(), - MessageDialog.ERROR, new String[]{"OK"}, 0); - errDlg.open(); - } - } - } - }); + updateSelectedResourcesView(true); - } - - // import the current editor or initialize the widgets. - // - public void initWidgets() { - - rbd_name_txt.setText(""); - - updateAreaGUI( );// should be the default area - - shell.setSize( initDlgSize ); + if (done) { + rscSelDlg.close(); + } + } + }); - updateGUIforMultipane( rbdMngr.isMultiPane() ); + size_of_image_btn.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + rbdMngr.setZoomLevel((size_of_image_btn.getSelection() ? // -1.0 + // : + // 1.0 + // ) ); + ZoomLevelStrings.SizeOfImage.toString() + : ZoomLevelStrings.FitToScreen.toString())); - timelineControl.clearTimeline(); - } - - // if this is called from the Edit Rbd Dialog (from the LoadRbd tab), then - // remove widgets that don't apply. (ie, import, Save, and Load) - // - public void configureForEditRbd() { -// allow the user to change the name -// rbd_name_txt.setEditable( false ); -// rbd_name_txt.setBackground( rbd_name_txt.getParent().getBackground() ); - import_lbl.setVisible( false ); - import_rbd_combo.setVisible( false ); - clear_rbd_btn.setVisible( false ); - save_rbd_btn.setVisible( false ); - load_pane_btn.setVisible( false ); - load_rbd_btn.setVisible( false ); - load_and_close_btn.setVisible( false ); - - cancel_edit_btn.setVisible( true ); - ok_edit_btn.setVisible( true ); - - cancel_edit_btn.addSelectionListener( new SelectionAdapter() { - public void widgetSelected( SelectionEvent ev ) { - editedRbd = null; - shell.dispose(); - } - }); + } + }); - // dispose and leave the edited RBD in - ok_edit_btn.addSelectionListener( new SelectionAdapter() { - public void widgetSelected( SelectionEvent ev ) { - createEditedRbd(); - shell.dispose(); - } - }); - - FormData fd = (FormData) rbd_name_txt.getLayoutData(); - fd.left = new FormAttachment( 20, 0 ); - rbd_name_txt.setLayoutData( fd ); + fit_to_screen_btn.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + rbdMngr.setZoomLevel((fit_to_screen_btn.getSelection() ? // 1.0 + // : + // -1.0 + // ) ); + ZoomLevelStrings.FitToScreen.toString() + : ZoomLevelStrings.SizeOfImage.toString())); + } + }); - timelineControl.getParent().setVisible( false ); - sash_form.setWeights( new int[] { 10, 1 } ); - shell.setSize( shell.getSize().x-100, 350 ); + // TODO: if single pane and there are resources selected + // in other panes then should we prompt the user on whether + // to clear them? We can ignore them if Loading/Saving a + // single pane, but if they reset multi-pane then should the + // resources in other panes still be selected. + multi_pane_tog.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent ev) { + rbdMngr.setMultiPane(multi_pane_tog.getSelection()); + + updateGUIforMultipane(multi_pane_tog.getSelection()); + + if (multi_pane_tog.getSelection()) { + updatePaneLayout(); + } else { + selectPane(new NcPaneID()); // 0,0 + } + + if (rscSelDlg != null && rscSelDlg.isOpen()) { + rscSelDlg.setMultiPaneEnabled(multi_pane_tog.getSelection()); + } + } + }); + + // if syncing the panes + geo_sync_panes.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent ev) { + + if (geo_sync_panes.getSelection()) { + + MessageDialog confirmDlg = new MessageDialog(shell, + "Confirm Geo-Sync Panes", null, + "This will set the Area for all panes to the currently\n" + + "selected Area: " + + rbdMngr.getSelectedArea() + .getProviderName() + "\n\n" + + "Continue?", MessageDialog.QUESTION, + new String[] { "Yes", "No" }, 0); + confirmDlg.open(); + + if (confirmDlg.getReturnCode() != MessageDialog.OK) { + geo_sync_panes.setSelection(false); + return; + } + + rbdMngr.syncPanesToArea(); + } else { + rbdMngr.setGeoSyncPanes(false); + } + } + }); + + custom_area_btn.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent ev) { + // Shell shell = NcDisplayMngr.getCaveShell(); + // CreateCustomProjectionDialog dlg = + // CreateCustomProjectionDialog(shell); + // dlg.open(); + + } + }); + + // only 1 should be selected or this button should be greyed out + edit_rsc_btn.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent ev) { + editResourceData(); + } + }); + + del_rsc_btn.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent ev) { + StructuredSelection sel_elems = (StructuredSelection) seld_rscs_lviewer + .getSelection(); + Iterator itr = sel_elems.iterator(); + + // note: the base may be selected if there are multi selected + // with others. + while (itr.hasNext()) { + ResourceSelection rscSel = (ResourceSelection) itr.next(); + if (!rscSel.isBaseLevelResource()) { + removeSelectedResource(rscSel); + } + } + + updateSelectedResourcesView(true); + + // check to see if the current area has been reset to the + // default because + // it was the + // String seldArea = + // rbdMngr.getSelectedArea().getProviderName(); + // + // if( seldAreaMenuItem.getAreaName().equals( seldArea) ) { + updateAreaGUI(); + // } + } + }); + + disable_rsc_btn.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent ev) { + StructuredSelection sel_elems = (StructuredSelection) seld_rscs_lviewer + .getSelection(); + Iterator itr = sel_elems.iterator(); + + while (itr.hasNext()) { + ResourceSelection rscSel = (ResourceSelection) itr.next(); + rscSel.setIsVisible(!disable_rsc_btn.getSelection()); + } + + seld_rscs_lviewer.refresh(true); + + updateSelectedResourcesView(false); // true + } + }); + + clr_pane_btn.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent ev) { + clearSeldResources(); + } + }); + + clear_rbd_btn.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent ev) { + clearRBD(); + } + }); + + load_rbd_btn.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent ev) { + loadRBD(false); + } + }); + + load_and_close_btn.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent ev) { + loadRBD(true); + } + }); + + load_pane_btn.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent ev) { + loadPane(); + } + }); + + save_rbd_btn.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent ev) { + saveRBD(false); + } + }); + + import_rbd_combo.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent ev) { + importRBD(import_rbd_combo.getText()); + AbstractEditor seldEditor = NcDisplayMngr + .findDisplayByID(NcDisplayName + .parseNcDisplayNameString(import_rbd_combo + .getText())); + + if (seldEditor != null) { + NcDisplayMngr.bringToTop(seldEditor); + } + + } + }); + + // TODO : Currently we can't detect if the user clicks on the import + // combo and then clicks on the currently selected + // item which means the users can't re-import the current selection (or + // import another from an spf.) The following may + // allow a hackish work around later.... (I tried virtually every + // listener and these where the only ones to trigger.) + // ....update...with new Eclipse this seems to be working; ie. + // triggering a selection when + // combo is clicked on but selection isn't changed. + import_rbd_combo.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + // System.out.println("focusGained: "); + } + + @Override + public void focusLost(FocusEvent e) { + // System.out.println("focusLost: " ); + } + }); + import_rbd_combo.addListener(SWT.MouseDown, new Listener() { // and + // SWT.MouseUp + @Override + public void handleEvent(Event event) { + // System.out.println("SWT.MouseDown: " ); + } + }); + import_rbd_combo.addListener(SWT.Activate, new Listener() { + @Override + public void handleEvent(Event event) { + updateImportCombo(); + } + }); + import_rbd_combo.addListener(SWT.Deactivate, new Listener() { + @Override + public void handleEvent(Event event) { + // System.out.println("SWT.Deactivate: " ); + } + }); + + import_pane_btn.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent ev) { + SelectRbdsDialog impDlg = new SelectRbdsDialog(shell, + "Import Pane", true, false, true); + + if (!impDlg.open()) { + return; + } + + AbstractRBD impRbd = impDlg.getSelectedRBD(); + + if (impRbd != null) { + // if any selections have been made then popup a + // confirmation msg + // TODO:add support for determining if only this pane has + // been modified. + // boolean confirm = ( rbdMngr.getSelectedRscs().length > 1 + // ); + // if( confirm ) { + // MessageDialog confirmDlg = new MessageDialog( + // NcDisplayMngr.getCaveShell(), "Confirm", null, + // "Do you want to remove all currently selected Resources?", + // MessageDialog.QUESTION, new String[]{"Yes", "No"}, 0); + // confirmDlg.open(); + // + // if( confirmDlg.getReturnCode() != MessageDialog.OK ) { + // return; + // } + // } + + impRbd.resolveLatestCycleTimes(); + + try { + importPane(impRbd, impRbd.getSelectedPaneId()); + } catch (VizException e) { + MessageDialog errDlg = new MessageDialog(shell, + "Error", null, "Error Importing Rbd, " + + impRbd.getRbdName() + ".\n" + + e.getMessage(), MessageDialog.ERROR, + new String[] { "OK" }, 0); + errDlg.open(); + } + } + } + }); + + } + + // import the current editor or initialize the widgets. + // + public void initWidgets() { + + rbd_name_txt.setText(""); + + updateAreaGUI();// should be the default area + + shell.setSize(initDlgSize); + + updateGUIforMultipane(rbdMngr.isMultiPane()); + + timelineControl.clearTimeline(); + } + + // if this is called from the Edit Rbd Dialog (from the LoadRbd tab), then + // remove widgets that don't apply. (ie, import, Save, and Load) + // + public void configureForEditRbd() { + // allow the user to change the name + // rbd_name_txt.setEditable( false ); + // rbd_name_txt.setBackground( rbd_name_txt.getParent().getBackground() + // ); + import_lbl.setVisible(false); + import_rbd_combo.setVisible(false); + clear_rbd_btn.setVisible(false); + save_rbd_btn.setVisible(false); + load_pane_btn.setVisible(false); + load_rbd_btn.setVisible(false); + load_and_close_btn.setVisible(false); + + cancel_edit_btn.setVisible(true); + ok_edit_btn.setVisible(true); + + cancel_edit_btn.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent ev) { + editedRbd = null; + shell.dispose(); + } + }); + + // dispose and leave the edited RBD in + ok_edit_btn.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent ev) { + createEditedRbd(); + shell.dispose(); + } + }); + + FormData fd = (FormData) rbd_name_txt.getLayoutData(); + fd.left = new FormAttachment(20, 0); + rbd_name_txt.setLayoutData(fd); + + timelineControl.getParent().setVisible(false); + sash_form.setWeights(new int[] { 10, 1 }); + shell.setSize(shell.getSize().x - 100, 350); shell.pack(true); - } - - private void updateImportCombo() { - // check for possible new Displays that may be imported. - NcDisplayName seldImport = NcDisplayName.parseNcDisplayNameString( import_rbd_combo.getText() ); - - import_rbd_combo.removeAll(); - for( AbstractEditor ncDisplay : NcDisplayMngr.getAllNcDisplays() ) { //rbdMngr.getRbdType() ) ) { - - NcDisplayName displayName = NcEditorUtil.getDisplayName( ncDisplay ); - import_rbd_combo.add( displayName.toString() ); - - // if this was selected before, select it again - if( seldImport == null || //seldImport.isEmpty() || - seldImport.equals( displayName ) ) { - import_rbd_combo.select( import_rbd_combo.getItemCount()-1 ); - } - } + } - // if the previous selection wasn't found then select 'from SPF' - import_rbd_combo.add( ImportFromSPF ); - - if( import_rbd_combo.getSelectionIndex() == -1 ) { - import_rbd_combo.select( import_rbd_combo.getItemCount()-1 ); - } - } - - // Note: if the text set for the ToolItem doesn't fit on the size of the item then - // it will become blank and unselectable. Need to make sure this doesn't happen so - // create a multi-line text string for the tool item and make sure it is wide and high - // enough to hold the string. - // - public void setAreaTextOnMenuItem( AreaName areaName ) { - seldAreaMenuItem = new AreaMenuItem( areaName ); + public void updateImportCombo() { + // check for possible new Displays that may be imported. + NcDisplayName seldImport = NcDisplayName + .parseNcDisplayNameString(import_rbd_combo.getText()); - // based on the starting width of the dialog and current attachments, the - // ToolItem has a width of 136. This will display up to 13 characters. - // - Point toolBarSize = areaTItm.getParent().getSize(); // current width and height - - if( toolBarSize.x == 0 ) { // gui not initialized yet - return; - } + import_rbd_combo.removeAll(); + for (AbstractEditor ncDisplay : NcDisplayMngr.getAllNcDisplays()) { // rbdMngr.getRbdType() + // ) + // ) + // { - int maxChars = toolBarSize.x * 13 / 136; - int fontSize = 10; // normal font - boolean truncated = false; - String menuText = seldAreaMenuItem.getMenuName(); // string that will be used to set the menuItem - - // if greater than 13 then we will have to figure out how to make it fit - // - if( menuText.length() > maxChars ) { - // if its close then just change the font size - // - if( menuText.length() <= maxChars+1 ) { - fontSize = 8; - } - else if( menuText.length() <= maxChars+2 ) { - fontSize = 7; - } - else if( menuText.length() <= maxChars+3 ) { - fontSize = 7; - } - // if this is a Display-defined area then just truncate it since the - // display id should be enough to let the user know what the area is - else if( areaName.getSource() == AreaSource.DISPLAY_AREA ) { - fontSize = 8; - menuText = menuText.substring( 0, maxChars+3 ); - truncated = true; - } - // - else if( areaName.getSource().isImagedBased() ) { - // if a Mcidas or Gini satellite then the name is the satellite name and area or sector name - // separated with '/' - // in this case we can leave off the satelliteName - int sepIndx = menuText.indexOf( File.separator ); - if( sepIndx == -1 ) { - System.out.println("Expecting '/' in satellite defined area???? "); - menuText = menuText.substring( 0, maxChars ); - truncated = true; - } - else { -// StringBuffer menuName = new StringBuffer( menuText ); -// menuName.insert( sepIndx+1, "\n" ); - String satName = menuText.substring(0,sepIndx); - String area = menuText.substring(sepIndx+1); + NcDisplayName displayName = NcEditorUtil.getDisplayName(ncDisplay); + import_rbd_combo.add(displayName.toString()); - // if the areaName is close then change the font size - if( area.length() > maxChars ) { - if( area.length() <= maxChars+1 ) { - fontSize = 8; - } - else if( area.length() <= maxChars+2 ) { - fontSize = 7; - } - else if( area.length() <= maxChars+3 ) { - fontSize = 7; - } - else { // else have to truncate - fontSize = 7; - area = area.substring(0,maxChars+3); - truncated = true; - } - } - if( satName.length() > maxChars+10-fontSize ) { - satName = satName.substring(0,maxChars+10-fontSize ); - truncated = true; - } - - menuText = satName + "\n" + area; - } - } - else { - fontSize = 8; - menuText = menuText.substring( 0, maxChars+1 ); - truncated = true; - } - } - - // change the font and set the text. - // (don't dispose the original font) - Font curFont = areaTItm.getParent().getFont(); - FontData[] fd = curFont.getFontData(); + // if this was selected before, select it again + if (seldImport == null || // seldImport.isEmpty() || + seldImport.equals(displayName)) { + import_rbd_combo.select(import_rbd_combo.getItemCount() - 1); + } + } - if( fd[0].getHeight() != fontSize ) { - fd[0].setHeight( fontSize ); - Device dev = curFont.getDevice(); - - if( areaFont != null ) { - areaFont.dispose(); - } - areaFont = new Font( dev, fd ); - areaTItm.getParent().setFont( areaFont ); - } - - int tbHght = ( menuText.indexOf("\n") > 0 ? 47 : 30 ); - - if( tbHght != toolBarSize.y ) { - toolBarSize.y = ( menuText.indexOf("\n") > 0 ? 47 : 30 ); - // without this the size will revert back when the dialog is resized for multi-pane - FormData formData = (FormData)areaTItm.getParent().getLayoutData(); - formData.height = tbHght; - areaTItm.getParent().getLayoutData(); - areaTItm.getParent().getParent().layout( true ); -// areaTItm.getParent().setSize( toolBarSize ); // don't need this anymore with changing the layout - } - areaTItm.setText( menuText ); - - // if truncated then show the menuname in the tooltips - areaTItm.setToolTipText( truncated ? seldAreaMenuItem.getMenuName() : "" ); - - } - - // set the area and update the proj/center field - // the - public void updateAreaGUI() { - - PredefinedArea area = rbdMngr.getSelectedArea(); - - setAreaTextOnMenuItem( new AreaName( area.getSource(), area.getAreaName() ) ); - - geo_area_info_comp.setVisible( false ); - rsc_area_opts_comp.setVisible( false ); - - if( area.getSource().isImagedBased() ) { + // if the previous selection wasn't found then select 'from SPF' + import_rbd_combo.add(ImportFromSPF); - rsc_area_opts_comp.setVisible( true ); - - if( area.getZoomLevel().equals( ZoomLevelStrings.FitToScreen.toString() ) ) { - fit_to_screen_btn.setSelection( true ); - size_of_image_btn.setSelection( false ); - } - else if( area.getZoomLevel().equals( ZoomLevelStrings.SizeOfImage.toString() ) ) { - fit_to_screen_btn.setSelection( false ); - size_of_image_btn.setSelection( true ); - } - else { - /// ???? - area.setZoomLevel( "1.0" ); - fit_to_screen_btn.setSelection( true ); - size_of_image_btn.setSelection( false ); - } - } - else { - geo_area_info_comp.setVisible( true ); - - String projStr = rbdMngr.getSelectedArea().getGridGeometry(). - getCoordinateReferenceSystem().getName().toString(); - - proj_info_txt.setText( projStr ); - proj_info_txt.setToolTipText( projStr ); - - // use the GEMPAK name if possible. - for( String gemProj : gempakProjMap.keySet() ) { - - if( gempakProjMap.get( gemProj ).equals( projStr ) ) { - proj_info_txt.setText( gemProj.toUpperCase() ); - break; - } - } + if (import_rbd_combo.getSelectionIndex() == -1) { + import_rbd_combo.select(import_rbd_combo.getItemCount() - 1); + } + } - if( area.getMapCenter() != null ) { - Integer lat = (int)(area.getMapCenter()[1] *1000.0); - Integer lon = (int)(area.getMapCenter()[0] *1000.0); - - map_center_txt.setText( - Double.toString((double)lat/1000.0) +"/" + Double.toString((double)lon/1000.0) ); - } - else { - map_center_txt.setText( "N/A" ); - } - } - -// if( seldAreaMenuItem == null ) { -// try { -// rbdMngr.setAreaProviderName( -// new AreaName( AreaSource.PREDEFINED_AREA, -// rbdMngr.getRbdType().getDefaultMap() )); -// updateAreaGUI(); -// } catch (VizException e) { -// } -// } - } - - private class SelectAreaAction extends Action { - private AreaMenuItem ami; - - public SelectAreaAction( AreaMenuItem a ) { - super( a.getMenuName() ); - ami = a; - } - - @Override - public void run() { - try { - rbdMngr.setSelectedAreaName( - new AreaName( AreaSource.getAreaSource( ami.getSource() ), - ami.getAreaName() ) ); - updateAreaGUI(); - } - catch (VizException e) { - MessageDialog errDlg = new MessageDialog( - NcDisplayMngr.getCaveShell(), "Error", null, - e.getMessage(), MessageDialog.ERROR, new String[]{"OK"}, 0); - errDlg.open(); - } - } - } -// private void setSeldAreaMenuItem( AreaMenuItem ami ) { -// areaTItm.setText(ami.getAreaName()); -// -// seldAreaMenuItem = ami; -// -// } - - public void createAvailAreaMenuItems( IMenuManager aMenuMngr ) { - // a map from the sub-menu name to a list of menu item - List> availMenuItems = rbdMngr.getAvailAreaMenuItems(); + // Note: if the text set for the ToolItem doesn't fit on the size of the + // item then it will become blank and unselectable. Need to make sure this + // doesn't happen so create a multi-line text string for the tool item and + // make sure it is wide and high enough to hold the string. + // + public void setAreaTextOnMenuItem(AreaName areaName) { + seldAreaMenuItem = new AreaMenuItem(areaName); - for( List amiList : availMenuItems ) { - if( amiList == null || amiList.isEmpty() ) { - continue; - } - - // all the submenu name in the list should be the same. - String subMenuName = amiList.get(0).getSubMenuName(); - IMenuManager menuMngrToAddTo = aMenuMngr; - - if( subMenuName != null && !subMenuName.isEmpty() ) { - IMenuManager subMenu = new MenuManager( subMenuName, - areaMenuMngr.getId() + "." + subMenuName); - aMenuMngr.add( subMenu ); - menuMngrToAddTo = subMenu; - } - - for( AreaMenuItem ami : amiList ) { - menuMngrToAddTo.add( new SelectAreaAction( ami ) ); - } - } - } - - // called when the user switches to this tab in the ResourceManagerDialog or when - // the EditRbd Dialog initializes + // based on the starting width of the dialog and current attachments, + // the ToolItem has a width of 136. This will display up to 13 + // characters. + // + Point toolBarSize = areaTItm.getParent().getSize(); // current width and + // height + + if (toolBarSize.x == 0) { // gui not initialized yet + return; + } + + int maxChars = toolBarSize.x * 13 / 136; + int fontSize = 10; // normal font + boolean truncated = false; + String menuText = seldAreaMenuItem.getMenuName(); // string that will be + // used to set the + // menuItem + + // if greater than 13 then we will have to figure out how to make it fit + // + if (menuText.length() > maxChars) { + // if its close then just change the font size + // + if (menuText.length() <= maxChars + 1) { + fontSize = 8; + } else if (menuText.length() <= maxChars + 2) { + fontSize = 7; + } else if (menuText.length() <= maxChars + 3) { + fontSize = 7; + } + // if this is a Display-defined area then just truncate it since the + // display id should be enough to let the user know what the area is + else if (areaName.getSource() == AreaSource.DISPLAY_AREA) { + fontSize = 8; + menuText = menuText.substring(0, maxChars + 3); + truncated = true; + } + // + else if (areaName.getSource().isImagedBased()) { + // if a Mcidas or Gini satellite then the name is the satellite + // name and area or sector name + // separated with '/' + // in this case we can leave off the satelliteName + int sepIndx = menuText.indexOf(File.separator); + if (sepIndx == -1) { + System.out + .println("Expecting '/' in satellite defined area???? "); + menuText = menuText.substring(0, maxChars); + truncated = true; + } else { + // StringBuffer menuName = new StringBuffer( menuText ); + // menuName.insert( sepIndx+1, "\n" ); + String satName = menuText.substring(0, sepIndx); + String area = menuText.substring(sepIndx + 1); + + // if the areaName is close then change the font size + if (area.length() > maxChars) { + if (area.length() <= maxChars + 1) { + fontSize = 8; + } else if (area.length() <= maxChars + 2) { + fontSize = 7; + } else if (area.length() <= maxChars + 3) { + fontSize = 7; + } else { // else have to truncate + fontSize = 7; + area = area.substring(0, maxChars + 3); + truncated = true; + } + } + if (satName.length() > maxChars + 10 - fontSize) { + satName = satName + .substring(0, maxChars + 10 - fontSize); + truncated = true; + } + + menuText = satName + "\n" + area; + } + } else { + fontSize = 8; + menuText = menuText.substring(0, maxChars + 1); + truncated = true; + } + } + + // change the font and set the text. + // (don't dispose the original font) + Font curFont = areaTItm.getParent().getFont(); + FontData[] fd = curFont.getFontData(); + + if (fd[0].getHeight() != fontSize) { + fd[0].setHeight(fontSize); + Device dev = curFont.getDevice(); + + if (areaFont != null) { + areaFont.dispose(); + } + areaFont = new Font(dev, fd); + areaTItm.getParent().setFont(areaFont); + } + + int tbHght = (menuText.indexOf("\n") > 0 ? 47 : 30); + + if (tbHght != toolBarSize.y) { + toolBarSize.y = (menuText.indexOf("\n") > 0 ? 47 : 30); + // without this the size will revert back when the dialog is resized + // for multi-pane + FormData formData = (FormData) areaTItm.getParent().getLayoutData(); + formData.height = tbHght; + areaTItm.getParent().getLayoutData(); + areaTItm.getParent().getParent().layout(true); + // areaTItm.getParent().setSize( toolBarSize ); // don't need this + // anymore with changing the layout + } + areaTItm.setText(menuText); + + // if truncated then show the menuname in the tooltips + areaTItm.setToolTipText(truncated ? seldAreaMenuItem.getMenuName() : ""); + + } + + // set the area and update the proj/center field + // the + public void updateAreaGUI() { + + PredefinedArea area = rbdMngr.getSelectedArea(); + + setAreaTextOnMenuItem(new AreaName(area.getSource(), area.getAreaName())); + + geo_area_info_comp.setVisible(false); + rsc_area_opts_comp.setVisible(false); + + if (area.getSource().isImagedBased()) { + + rsc_area_opts_comp.setVisible(true); + + if (area.getZoomLevel().equals( + ZoomLevelStrings.FitToScreen.toString())) { + fit_to_screen_btn.setSelection(true); + size_of_image_btn.setSelection(false); + } else if (area.getZoomLevel().equals( + ZoomLevelStrings.SizeOfImage.toString())) { + fit_to_screen_btn.setSelection(false); + size_of_image_btn.setSelection(true); + } else { + // / ???? + area.setZoomLevel("1.0"); + fit_to_screen_btn.setSelection(true); + size_of_image_btn.setSelection(false); + } + } else { + geo_area_info_comp.setVisible(true); + + String projStr = rbdMngr.getSelectedArea().getGridGeometry() + .getCoordinateReferenceSystem().getName().toString(); + + proj_info_txt.setText(projStr); + proj_info_txt.setToolTipText(projStr); + + // use the GEMPAK name if possible. + for (String gemProj : gempakProjMap.keySet()) { + + if (gempakProjMap.get(gemProj).equals(projStr)) { + proj_info_txt.setText(gemProj.toUpperCase()); + break; + } + } + + if (area.getMapCenter() != null) { + Integer lat = (int) (area.getMapCenter()[1] * 1000.0); + Integer lon = (int) (area.getMapCenter()[0] * 1000.0); + + map_center_txt.setText(Double.toString((double) lat / 1000.0) + + "/" + Double.toString((double) lon / 1000.0)); + } else { + map_center_txt.setText("N/A"); + } + } + + // if( seldAreaMenuItem == null ) { + // try { + // rbdMngr.setAreaProviderName( + // new AreaName( AreaSource.PREDEFINED_AREA, + // rbdMngr.getRbdType().getDefaultMap() )); + // updateAreaGUI(); + // } catch (VizException e) { + // } + // } + } + + private class SelectAreaAction extends Action { + private AreaMenuItem ami; + + public SelectAreaAction(AreaMenuItem a) { + super(a.getMenuName()); + ami = a; + } + + @Override + public void run() { + try { + rbdMngr.setSelectedAreaName(new AreaName(AreaSource + .getAreaSource(ami.getSource()), ami.getAreaName())); + updateAreaGUI(); + } catch (VizException e) { + MessageDialog errDlg = new MessageDialog( + NcDisplayMngr.getCaveShell(), "Error", null, + e.getMessage(), MessageDialog.ERROR, + new String[] { "OK" }, 0); + errDlg.open(); + } + } + } + + // private void setSeldAreaMenuItem( AreaMenuItem ami ) { + // areaTItm.setText(ami.getAreaName()); + // + // seldAreaMenuItem = ami; + // + // } + + public void createAvailAreaMenuItems(IMenuManager aMenuMngr) { + // a map from the sub-menu name to a list of menu item + List> availMenuItems = rbdMngr + .getAvailAreaMenuItems(); + + for (List amiList : availMenuItems) { + if (amiList == null || amiList.isEmpty()) { + continue; + } + + // all the submenu name in the list should be the same. + String subMenuName = amiList.get(0).getSubMenuName(); + IMenuManager menuMngrToAddTo = aMenuMngr; + + if (subMenuName != null && !subMenuName.isEmpty()) { + IMenuManager subMenu = new MenuManager(subMenuName, + areaMenuMngr.getId() + "." + subMenuName); + aMenuMngr.add(subMenu); + menuMngrToAddTo = subMenu; + } + + for (AreaMenuItem ami : amiList) { + menuMngrToAddTo.add(new SelectAreaAction(ami)); + } + } + } + + // called when the user switches to this tab in the ResourceManagerDialog or + // when the EditRbd Dialog initializes // public void updateDialog() { - - updateImportCombo(); - - // If the gui has not been set with the current rbdMngr then do it now. - updateGUI(); - // updateGUI triggers the spinner which ends up calling rbdMngr.setPaneLayout(), - // so we need to reset this here. - rbdMngr.setRbdModified( false ); + updateImportCombo(); + + // If the gui has not been set with the current rbdMngr then do it now. + updateGUI(); + + // updateGUI triggers the spinner which ends up calling + // rbdMngr.setPaneLayout(), + // so we need to reset this here. + rbdMngr.setRbdModified(false); } - - // set widgets based on rbdMngr - public void updateGUI( ) { - // update the display type combo - for( int i=0 ; i