itemToCheck : items) {
+ if (itemToCheck.getItem().getLocation()
+ .equals(item.getLocation())) {
+ info.setDistance(0);
+ break;
+ }
+ }
+ }
+ if (!info.hasDistance() || info.getDistance() > 0) {
+ items.add(info);
+
+ }
+ }
+ waitingTasks.decrementAndGet();
+ return info.getDistance();
+ }
+
+ /**
+ * Convert any items within the disclosure that are using the dynamic
+ * algorithm to be able to use the static algorithm. This will result in
+ * more consistent disclosure and faster execution of
+ * {@link #runDisclosure(IExtent, double)}. If there are alot of items this
+ * method can be slow and should not be run on a thread that is sensitive to
+ * delays.
+ *
+ * Running the calculation requires an exclusive lock that can block other
+ * methods. to avoid causing problems this method will return early if there
+ * is another thread using this object. The early return will often occur
+ * after some items have been converted so future calls will have less work
+ * to do. If the return value indicates an early return then the calling
+ * code should generally {@link Thread#sleep(long)}, {@link Thread#yield()},
+ * or do other tasks before calling this method again. Calling this method
+ * again before other threads have a chance to run will return immediately
+ * after doing no work.
+ *
+ * @return false if the calculation was interrupted and there are more
+ * dynamic items, true if this disclosure is now 100% static.
+ */
+ public boolean calculateStaticDistances() {
+ if (waitingTasks.get() > 0) {
+ return false;
+ }
+ synchronized (items) {
+ while (staticCount < items.size()) {
+ ItemInfo item = items.get(staticCount);
+ double distance = getMinDistance(getStaticItems(), item);
+ if (distance > 0) {
+ item.setDistance(distance);
+ staticCount += 1;
+ } else {
+ items.remove(staticCount);
+ }
+ if (waitingTasks.get() > 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ protected List> getStaticItems() {
+ return items.subList(0, staticCount);
+ }
+
+ protected List> getDynamicItems() {
+ return items.subList(staticCount, items.size());
+ }
+
+ private double getMinDistance(List> list, ItemInfo item) {
+ double min_dist = Double.MAX_VALUE;
+ for (ItemInfo existing : list) {
+ double dist = existing.getItem().getLocation()
+ .distance(item.getItem().getLocation());
+ if (dist < min_dist
+ && (Double.isNaN(existing.getDistance()) || dist < existing
+ .getDistance())) {
+ min_dist = dist;
+ }
+ }
+ return min_dist;
+
+ }
+
+ public static interface PlotItem {
+
+ public Coordinate getLocation();
+ }
+
+ private static class ItemInfo {
+
+ private final T item;
+
+ private double distance;
+
+ public ItemInfo(T item) {
+ this.item = item;
+ this.distance = Double.NaN;
+ }
+
+ public T getItem() {
+ return item;
+ }
+
+ public boolean within(IExtent extent) {
+ Coordinate location = item.getLocation();
+ return extent.contains(new double[] { location.x, location.y });
+ }
+
+ public boolean hasDistance() {
+ return !Double.isNaN(distance);
+ }
+
+ public double getDistance() {
+ return distance;
+ }
+
+ public void setDistance(double distance) {
+ this.distance = distance;
+ }
+
+ }
+}
diff --git a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/wind/WindPlotConfig.java b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/wind/WindPlotConfig.java
new file mode 100644
index 0000000000..ee9174b1da
--- /dev/null
+++ b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/wind/WindPlotConfig.java
@@ -0,0 +1,152 @@
+/**
+ * This software was developed and / or modified by Raytheon Company,
+ * pursuant to Contract DG133W-05-CQ-1067 with the US Government.
+ *
+ * U.S. EXPORT CONTROLLED TECHNICAL DATA
+ * This software product contains export-restricted data whose
+ * export/transfer/disclosure is restricted by U.S. law. Dissemination
+ * to non-U.S. persons whether in the United States or abroad requires
+ * an export license or other authorization.
+ *
+ * Contractor Name: Raytheon Company
+ * Contractor Address: 6825 Pine Street, Suite 340
+ * Mail Stop B8
+ * Omaha, NE 68106
+ * 402.291.0100
+ *
+ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
+ * further licensing information.
+ **/
+package com.raytheon.viz.pointdata.rsc.wind;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+
+/**
+ *
+ * JAXB compatible representation of all the configuration options needed to
+ * request data and sampling information for wind vectors.
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------- -------- --------- -----------------
+ * Nov 13, 2015 4903 bsteffen Initial creation
+ *
+ *
+ *
+ * @author bsteffen
+ * @version 1.0
+ */
+@XmlAccessorType(XmlAccessType.NONE)
+public class WindPlotConfig {
+
+ @XmlElement
+ private WindPlotParameter longitude = new WindPlotParameter("longitude");
+
+ @XmlElement
+ private WindPlotParameter latitude = new WindPlotParameter("latitude");
+
+ @XmlElement
+ private WindPlotParameter speed = new WindPlotParameter("windSpd", "kn");
+
+ @XmlElement
+ private WindPlotParameter direction = new WindPlotParameter("windDir");
+
+ @XmlElement
+ private SampleFormat sample;
+
+ public WindPlotParameter getLongitude() {
+ return longitude;
+ }
+
+ public void setLongitude(WindPlotParameter longitude) {
+ this.longitude = longitude;
+ }
+
+ public WindPlotParameter getLatitude() {
+ return latitude;
+ }
+
+ public void setLatitude(WindPlotParameter latitude) {
+ this.latitude = latitude;
+ }
+
+ public WindPlotParameter getSpeed() {
+ return speed;
+ }
+
+ public void setSpeed(WindPlotParameter speed) {
+ this.speed = speed;
+ }
+
+ public WindPlotParameter getDirection() {
+ return direction;
+ }
+
+ public void setDirection(WindPlotParameter direction) {
+ this.direction = direction;
+ }
+
+ public SampleFormat getSample() {
+ return sample;
+ }
+
+ public void setSample(SampleFormat sample) {
+ this.sample = sample;
+ }
+
+ public Set getUniqueParameters() {
+ Set result = new HashSet<>(5);
+ result.add(longitude.getParameter());
+ result.add(latitude.getParameter());
+ result.add(speed.getParameter());
+ result.add(direction.getParameter());
+ if (sample != null) {
+ result.addAll(sample.getUniqueParameters());
+ }
+ return result;
+ }
+
+ @XmlAccessorType(XmlAccessType.NONE)
+ public static class SampleFormat {
+
+ @XmlAttribute
+ private String text;
+
+ @XmlElement(name = "field")
+ private WindPlotParameter[] fields;
+
+ public String getText() {
+ return text;
+ }
+
+ public void setText(String text) {
+ this.text = text;
+ }
+
+ public WindPlotParameter[] getFields() {
+ return fields;
+ }
+
+ public void setFields(WindPlotParameter[] fields) {
+ this.fields = fields;
+ }
+
+ public Set getUniqueParameters() {
+ Set result = new HashSet<>();
+ for (WindPlotParameter p : fields) {
+ result.add(p.getParameter());
+ }
+ return result;
+ }
+
+ }
+}
diff --git a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/wind/WindPlotParameter.java b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/wind/WindPlotParameter.java
new file mode 100644
index 0000000000..273eb2d726
--- /dev/null
+++ b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/wind/WindPlotParameter.java
@@ -0,0 +1,236 @@
+/**
+ * This software was developed and / or modified by Raytheon Company,
+ * pursuant to Contract DG133W-05-CQ-1067 with the US Government.
+ *
+ * U.S. EXPORT CONTROLLED TECHNICAL DATA
+ * This software product contains export-restricted data whose
+ * export/transfer/disclosure is restricted by U.S. law. Dissemination
+ * to non-U.S. persons whether in the United States or abroad requires
+ * an export license or other authorization.
+ *
+ * Contractor Name: Raytheon Company
+ * Contractor Address: 6825 Pine Street, Suite 340
+ * Mail Stop B8
+ * Omaha, NE 68106
+ * 402.291.0100
+ *
+ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
+ * further licensing information.
+ **/
+package com.raytheon.viz.pointdata.rsc.wind;
+
+import java.text.ParseException;
+import java.text.ParsePosition;
+import java.util.Date;
+
+import javax.measure.unit.Unit;
+import javax.measure.unit.UnitFormat;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import com.raytheon.uf.common.pointdata.PointDataDescription.Type;
+import com.raytheon.uf.common.pointdata.PointDataView;
+import com.raytheon.uf.common.status.IUFStatusHandler;
+import com.raytheon.uf.common.status.UFStatus;
+import com.raytheon.uf.common.status.UFStatus.Priority;
+import com.raytheon.uf.common.time.util.TimeUtil;
+
+/**
+ *
+ * Configuration information for a single parameter that is part of a
+ * {@link WindPlotConfig}.
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------- -------- --------- -----------------
+ * Nov 13, 2015 4903 bsteffen Initial creation
+ *
+ *
+ *
+ * @author bsteffen
+ * @version 1.0
+ */
+@XmlAccessorType(XmlAccessType.NONE)
+public class WindPlotParameter {
+
+ private static final transient IUFStatusHandler statusHandler = UFStatus
+ .getHandler(WindPlotParameter.class);
+
+ @XmlAttribute
+ private String parameter;
+
+ @XmlAttribute
+ private String unit;
+
+ @XmlAttribute
+ private Boolean time;
+
+ @XmlElement(name = "format")
+ private FormatValue[] formats;
+
+ @XmlTransient
+ private Unit> parsedUnit;
+
+ /* Avoid spamming logs. */
+ @XmlTransient
+ private boolean unitParseFailed = false;
+
+ public WindPlotParameter() {
+
+ }
+
+ public WindPlotParameter(String parameter) {
+ this.parameter = parameter;
+ }
+
+ public WindPlotParameter(String parameter, String unit) {
+ this.parameter = parameter;
+ this.unit = unit;
+ }
+
+ public String getParameter() {
+ return parameter;
+ }
+
+ public void setParameter(String parameter) {
+ this.parameter = parameter;
+ }
+
+ public String getUnit() {
+ return unit;
+ }
+
+ public void setUnit(String unit) {
+ this.unit = unit;
+ }
+
+ public Boolean getTime() {
+ return time;
+ }
+
+ public void setTime(Boolean time) {
+ this.time = time;
+ }
+
+ public FormatValue[] getFormats() {
+ return formats;
+ }
+
+ public void setFormats(FormatValue[] formats) {
+ this.formats = formats;
+ }
+
+ public Unit> getParsedUnit() {
+ if (!unitParseFailed && parsedUnit == null) {
+ try {
+ parsedUnit = UnitFormat.getUCUMInstance().parseProductUnit(
+ unit, new ParsePosition(0));
+ } catch (ParseException e) {
+ statusHandler.handle(Priority.WARN,
+ "Error retrieving wind data.", e);
+ unitParseFailed = true;
+ }
+ }
+ return parsedUnit;
+ }
+
+ public double getNumericValue(PointDataView view) {
+ double value = view.getNumber(parameter).doubleValue();
+ if (unit != null) {
+ Unit> desired = getParsedUnit();
+ Unit> current = view.getUnit(parameter);
+ if (desired != null && current.isCompatible(desired)) {
+ value = current.getConverterTo(desired).convert(value);
+ }
+ }
+ return value;
+ }
+
+ public Object getValue(PointDataView view) {
+ if (view.getType(parameter) == Type.STRING) {
+ return view.getString(parameter);
+ } else if (Boolean.TRUE.equals(time)) {
+ return TimeUtil.newGmtCalendar(new Date(view.getNumber(parameter)
+ .longValue()));
+ } else if (formats != null) {
+ Number value = view.getNumber(parameter);
+ for (FormatValue format : formats) {
+ if (format.matches(value)) {
+ return format.getText();
+ }
+ }
+ return value.toString();
+ } else if (unit != null) {
+ return getNumericValue(view);
+ }
+ return view.getNumber(parameter);
+ }
+
+ @XmlAccessorType(XmlAccessType.NONE)
+ public static class FormatValue {
+
+ @XmlAttribute
+ private Double high;
+
+ @XmlAttribute
+ private Double low;
+
+ @XmlAttribute
+ private Double value;
+
+ @XmlAttribute
+ private String text;
+
+ public boolean matches(Number value) {
+ if (this.value != null
+ && value.doubleValue() == this.value.doubleValue()) {
+ return true;
+ } else if (high != null && low != null
+ && high.doubleValue() >= value.doubleValue()
+ && low.doubleValue() < value.doubleValue()) {
+ return true;
+ }
+ return false;
+ }
+
+ public Double getHigh() {
+ return high;
+ }
+
+ public void setHigh(Double high) {
+ this.high = high;
+ }
+
+ public Double getLow() {
+ return low;
+ }
+
+ public void setLow(Double low) {
+ this.low = low;
+ }
+
+ public Double getValue() {
+ return value;
+ }
+
+ public void setValue(Double value) {
+ this.value = value;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ public void setText(String text) {
+ this.text = text;
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/wind/WindPlotRenderable.java b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/wind/WindPlotRenderable.java
new file mode 100644
index 0000000000..c797b42865
--- /dev/null
+++ b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/wind/WindPlotRenderable.java
@@ -0,0 +1,268 @@
+/**
+ * This software was developed and / or modified by Raytheon Company,
+ * pursuant to Contract DG133W-05-CQ-1067 with the US Government.
+ *
+ * U.S. EXPORT CONTROLLED TECHNICAL DATA
+ * This software product contains export-restricted data whose
+ * export/transfer/disclosure is restricted by U.S. law. Dissemination
+ * to non-U.S. persons whether in the United States or abroad requires
+ * an export license or other authorization.
+ *
+ * Contractor Name: Raytheon Company
+ * Contractor Address: 6825 Pine Street, Suite 340
+ * Mail Stop B8
+ * Omaha, NE 68106
+ * 402.291.0100
+ *
+ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
+ * further licensing information.
+ **/
+package com.raytheon.viz.pointdata.rsc.wind;
+
+import java.util.Collection;
+
+import org.eclipse.swt.graphics.RGB;
+import org.geotools.referencing.GeodeticCalculator;
+
+import com.raytheon.uf.viz.core.IExtent;
+import com.raytheon.uf.viz.core.IGraphicsTarget;
+import com.raytheon.uf.viz.core.drawables.IDescriptor;
+import com.raytheon.uf.viz.core.drawables.PaintProperties;
+import com.raytheon.uf.viz.core.exception.VizException;
+import com.raytheon.uf.viz.core.point.display.VectorGraphicsConfig;
+import com.raytheon.uf.viz.core.point.display.VectorGraphicsRenderable;
+import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
+import com.raytheon.uf.viz.core.rsc.IResourceDataChanged;
+import com.raytheon.uf.viz.core.rsc.capabilities.ColorableCapability;
+import com.raytheon.uf.viz.core.rsc.capabilities.DensityCapability;
+import com.raytheon.uf.viz.core.rsc.capabilities.MagnificationCapability;
+import com.raytheon.viz.pointdata.rsc.progdisc.GenericProgressiveDisclosure;
+import com.raytheon.viz.pointdata.rsc.progdisc.GenericProgressiveDisclosure.PlotItem;
+import com.vividsolutions.jts.geom.Coordinate;
+
+/**
+ *
+ * Combines a {@link VectorGraphicsRenderable} with a
+ * {@link GenericProgressiveDisclosure} to generate progressively disclosed wind
+ * displays.
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------- -------- --------- -----------------
+ * Nov 13, 2015 4903 bsteffen Initial creation
+ *
+ *
+ *
+ * @author bsteffen
+ * @version 1.0
+ */
+public class WindPlotRenderable {
+
+ protected final AbstractVizResource, ?> resource;
+
+ private final IResourceDataChanged changeListener = new IResourceDataChanged() {
+
+ @Override
+ public void resourceChanged(ChangeType type, Object object) {
+ if (type == ChangeType.CAPABILITY) {
+ lastPaintedExtent = null;
+ }
+ }
+ };
+
+ protected VectorGraphicsConfig config = new VectorGraphicsConfig();
+
+ protected double baseDensity = 1.0;
+
+ protected GenericProgressiveDisclosure barbs = new GenericProgressiveDisclosure<>();
+
+ private VectorGraphicsRenderable renderable;
+
+ private double lastPaintedDistance = Double.POSITIVE_INFINITY;
+
+ private IExtent lastPaintedExtent;
+
+ public WindPlotRenderable(AbstractVizResource, ?> resource) {
+ this.resource = resource;
+ resource.getResourceData().addChangeListener(changeListener);
+ }
+
+ public VectorGraphicsConfig getConfig() {
+ return config;
+ }
+
+ public void reconfigure() {
+ if (lastPaintedExtent != null) {
+ lastPaintedExtent = null;
+ resource.issueRefresh();
+ }
+ }
+
+ public void dispose() {
+ if (renderable != null) {
+ renderable.dispose();
+ renderable = null;
+ }
+ resource.getResourceData().removeChangeListener(changeListener);
+ }
+
+ public void paint(IGraphicsTarget target, PaintProperties paintProps)
+ throws VizException {
+ IExtent extent = paintProps.getView().getExtent();
+ if (renderable != null
+ && (lastPaintedExtent == null || !lastPaintedExtent
+ .equals(extent))) {
+ renderable.dispose();
+ renderable = null;
+ }
+ if (renderable == null) {
+
+ double magnification = resource.getCapability(
+ MagnificationCapability.class).getMagnification();
+ double ratio = magnification * extent.getWidth()
+ / paintProps.getCanvasBounds().width;
+ config.setSizeScaler(ratio);
+ renderable = new VectorGraphicsRenderable(getDescriptor(), target,
+ config);
+ lastPaintedExtent = extent.clone();
+ double density = resource.getCapability(DensityCapability.class)
+ .getDensity();
+ double minDist = config.getScaledSize() / baseDensity / density;
+ lastPaintedDistance = minDist;
+ Collection barbs = this.barbs.runDisclosure(extent, minDist);
+ GeodeticCalculator gc = new GeodeticCalculator();
+ for (Barb barb : barbs) {
+ double dir = barb.getDirection();
+ Coordinate lonLat = barb.getLonLat();
+ Coordinate plotLoc = barb.getLocation();
+ gc.setStartingGeographicPoint(lonLat.x, lonLat.y);
+ double[] world = getDescriptor().pixelToWorld(
+ new double[] { plotLoc.x, plotLoc.y - 1 });
+ gc.setDestinationGeographicPoint(world[0], world[1]);
+ dir -= gc.getAzimuth();
+ dir = Math.toRadians(dir);
+ renderable.paintBarb(plotLoc, barb.getMagnitude(), dir);
+ }
+ }
+ renderable.setColor(getColor());
+ renderable.paint(target);
+ }
+
+ public String getText(Coordinate pixelLoc) {
+ String text = null;
+ double bestDist = 100;
+ if (renderable != null) {
+ bestDist = renderable.getConfig().getScaledSize() * 2;
+ }
+ for (Barb barb : barbs.getAll()) {
+ double dist = barb.getLocation().distance(pixelLoc);
+ if (dist < bestDist) {
+ bestDist = dist;
+ text = barb.getText();
+ }
+ }
+ return text;
+ }
+
+ protected RGB getColor() {
+ return resource.getCapability(ColorableCapability.class).getColor();
+ }
+
+ public synchronized boolean optimizeDisclosure() {
+ return barbs.calculateStaticDistances();
+ }
+
+ public void addBarb(Coordinate lonLat, double magnitude, double direction) {
+ addBarb(lonLat, magnitude, direction, null, false);
+ }
+
+ public void addBarb(Coordinate lonLat, double magnitude, double direction,
+ boolean checkDuplicate) {
+ addBarb(lonLat, magnitude, direction, null, checkDuplicate);
+ }
+
+ public void addBarb(Coordinate lonLat, double magnitude, double direction,
+ String text) {
+ addBarb(lonLat, magnitude, direction, text, false);
+ }
+
+ public synchronized void addBarb(Coordinate lonLat, double magnitude,
+ double direction, String text, boolean checkDuplicate) {
+ double[] pixel = getDescriptor().worldToPixel(
+ new double[] { lonLat.x, lonLat.y });
+ Coordinate plotLoc = new Coordinate(pixel[0], pixel[1]);
+ double distance = barbs.add(new Barb(lonLat, plotLoc, magnitude,
+ direction, text), checkDuplicate);
+ if (Double.isNaN(distance) || distance > lastPaintedDistance) {
+ IExtent extent = lastPaintedExtent;
+ if (extent != null && extent.contains(pixel)) {
+ resource.issueRefresh();
+ lastPaintedExtent = null;
+ }
+ }
+ }
+
+ public synchronized void reproject() {
+ GenericProgressiveDisclosure barbs = this.barbs;
+ this.barbs = new GenericProgressiveDisclosure<>();
+ for (Barb barb : barbs.getAll()) {
+ addBarb(barb.getLonLat(), barb.getMagnitude(), barb.getDirection());
+ }
+ }
+
+ protected IDescriptor getDescriptor() {
+ return resource.getDescriptor();
+ }
+
+ private class Barb implements PlotItem {
+
+ public final Coordinate lonLat;
+
+ public final Coordinate plotLoc;
+
+ public final double magnitude;
+
+ public final double direction;
+
+ public final String text;
+
+ public Barb(Coordinate lonLat, Coordinate plotLoc, double magnitude,
+ double direction, String text) {
+ this.lonLat = lonLat;
+ this.plotLoc = plotLoc;
+ this.magnitude = magnitude;
+ this.direction = direction;
+ this.text = text;
+ }
+
+ public Coordinate getLonLat() {
+ return lonLat;
+ }
+
+ @Override
+ public Coordinate getLocation() {
+ return plotLoc;
+ }
+
+ public double getMagnitude() {
+ return magnitude;
+ }
+
+ public double getDirection() {
+ return direction;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ }
+
+ public void setBaseDensity(double baseDensity) {
+ this.baseDensity = baseDensity;
+ }
+
+}
diff --git a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/wind/WindPlotResource.java b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/wind/WindPlotResource.java
new file mode 100644
index 0000000000..4bada49793
--- /dev/null
+++ b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/wind/WindPlotResource.java
@@ -0,0 +1,404 @@
+/**
+ * This software was developed and / or modified by Raytheon Company,
+ * pursuant to Contract DG133W-05-CQ-1067 with the US Government.
+ *
+ * U.S. EXPORT CONTROLLED TECHNICAL DATA
+ * This software product contains export-restricted data whose
+ * export/transfer/disclosure is restricted by U.S. law. Dissemination
+ * to non-U.S. persons whether in the United States or abroad requires
+ * an export license or other authorization.
+ *
+ * Contractor Name: Raytheon Company
+ * Contractor Address: 6825 Pine Street, Suite 340
+ * Mail Stop B8
+ * Omaha, NE 68106
+ * 402.291.0100
+ *
+ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
+ * further licensing information.
+ **/
+package com.raytheon.viz.pointdata.rsc.wind;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.opengis.referencing.FactoryException;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.TransformException;
+
+import com.raytheon.uf.common.dataplugin.PluginDataObject;
+import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
+import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
+import com.raytheon.uf.common.pointdata.PointDataContainer;
+import com.raytheon.uf.common.pointdata.PointDataServerRequest;
+import com.raytheon.uf.common.pointdata.PointDataView;
+import com.raytheon.uf.common.time.BinOffset;
+import com.raytheon.uf.common.time.DataTime;
+import com.raytheon.uf.common.time.TimeRange;
+import com.raytheon.uf.viz.core.IGraphicsTarget;
+import com.raytheon.uf.viz.core.drawables.PaintProperties;
+import com.raytheon.uf.viz.core.exception.VizException;
+import com.raytheon.uf.viz.core.jobs.JobPool;
+import com.raytheon.uf.viz.core.map.IMapDescriptor;
+import com.raytheon.uf.viz.core.point.display.VectorGraphicsConfig;
+import com.raytheon.uf.viz.core.requests.ThriftClient;
+import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
+import com.raytheon.uf.viz.core.rsc.IResourceDataChanged.ChangeType;
+import com.raytheon.uf.viz.core.rsc.LoadProperties;
+import com.raytheon.viz.pointdata.rsc.wind.WindPlotConfig.SampleFormat;
+import com.vividsolutions.jts.geom.Coordinate;
+
+/**
+ *
+ * Resource for displaying wind barbs of point data.
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------- -------- --------- -----------------
+ * Nov 13, 2015 4903 bsteffen Initial creation
+ *
+ *
+ *
+ * @author bsteffen
+ * @version 1.0
+ */
+public class WindPlotResource extends
+ AbstractVizResource {
+
+ private JobPool primaryLoadPool;
+
+ private Job secondaryLoadJob;
+
+ private final Object framesLock = new Object();
+
+ private Map frames;
+
+ protected WindPlotResource(WindPlotResourceData resourceData,
+ LoadProperties loadProperties) {
+ super(resourceData, loadProperties);
+ }
+
+ @Override
+ protected void initInternal(IGraphicsTarget target) throws VizException {
+ synchronized (framesLock) {
+ dataTimes = new CopyOnWriteArrayList<>();
+ frames = new HashMap();
+ primaryLoadPool = new JobPool("Loading Wind Data", 4, false);
+ secondaryLoadJob = new SecondaryUpdateJob();
+ secondaryLoadJob.setSystem(true);
+ secondaryLoadJob.schedule();
+ }
+ }
+
+ @Override
+ protected void disposeInternal() {
+ secondaryLoadJob.cancel();
+ secondaryLoadJob = null;
+ primaryLoadPool.cancel();
+ primaryLoadPool = null;
+ synchronized (framesLock) {
+ for (DataFrame frame : frames.values()) {
+ frame.getRenderable().dispose();
+ }
+ this.frames = null;
+ }
+
+ }
+
+ @Override
+ protected void paintInternal(IGraphicsTarget target,
+ PaintProperties paintProps) throws VizException {
+ DataTime time = paintProps.getDataTime();
+ if (time == null) {
+ return;
+ }
+ DataFrame frame;
+ synchronized (framesLock) {
+ frame = frames.get(time);
+ if (frame == null) {
+ frame = addFrame(time);
+ }
+ }
+ primaryLoadPool.schedule(frame);
+ frame.getRenderable().paint(target, paintProps);
+ }
+
+ protected DataFrame addFrame(DataTime dataTime) {
+ synchronized (framesLock) {
+ DataFrame frame = frames.get(dataTime);
+ if (frame == null) {
+ frame = new DataFrame(dataTime);
+ int index = Collections.binarySearch(dataTimes, dataTime);
+ if (index < 0) {
+ /* Keep the list sorted. */
+ dataTimes.add(-1 * index - 1, dataTime);
+ }
+ frames.put(dataTime, frame);
+ }
+ return frame;
+ }
+ }
+
+ @Override
+ public void remove(DataTime dataTime) {
+ synchronized (framesLock) {
+ frames.remove(dataTime);
+ super.remove(dataTime);
+ }
+ }
+
+ @Override
+ public String inspect(ReferencedCoordinate coord) throws VizException {
+ if (resourceData.getConfig().getSample() == null) {
+ return null;
+ }
+ DataTime time = descriptor.getTimeForResource(this);
+ if (time == null) {
+ return null;
+ }
+ DataFrame frame;
+ synchronized (framesLock) {
+ frame = frames.get(time);
+ }
+ if (frame == null) {
+ return null;
+ }
+ try {
+ String text = frame.getRenderable().getText(
+ coord.asPixel(descriptor.getGridGeometry()));
+ if (text == null) {
+ text = "NO DATA";
+ }
+ return text;
+ } catch (TransformException | FactoryException e) {
+ throw new VizException("Unable to transform point for inspect.", e);
+ }
+ }
+
+ @Override
+ public void project(CoordinateReferenceSystem crs) throws VizException {
+ synchronized (framesLock) {
+ for (DataFrame frame : frames.values()) {
+ frame.reproject();
+ }
+ }
+ }
+
+ @Override
+ public String getName() {
+ String name = resourceData.getLegend();
+ if (name == null) {
+ name = "Wind";
+ }
+ return name;
+ }
+
+ protected void loadData(DataTime dataTime, WindPlotRenderable renderable,
+ boolean initialLoad) {
+ WindPlotConfig config = resourceData.getConfig();
+ SampleFormat sample = config.getSample();
+ Map constraints = new HashMap<>(
+ resourceData.getFullDataMetadataMap());
+ constraints.put(PointDataServerRequest.REQUEST_MODE_KEY,
+ new RequestConstraint(PointDataServerRequest.REQUEST_MODE_2D));
+ constraints.put(PointDataServerRequest.REQUEST_PARAMETERS_KEY,
+ new RequestConstraint(config.getUniqueParameters()));
+
+ BinOffset binOffset = resourceData.getBinOffset();
+ if (binOffset == null) {
+ constraints.put(PluginDataObject.DATATIME_ID,
+ new RequestConstraint(dataTime.toString()));
+ } else {
+ TimeRange range = binOffset.getTimeRange(dataTime);
+ constraints.put(PluginDataObject.REFTIME_ID, new RequestConstraint(
+ new DataTime(range.getStart()).toString(), new DataTime(
+ range.getEnd()).toString()));
+ }
+ PointDataServerRequest request = new PointDataServerRequest();
+ request.setRcMap(constraints);
+ try {
+ PointDataContainer container = (PointDataContainer) ThriftClient
+ .sendRequest(request);
+ if (container == null) {
+ return;
+ }
+ for (int i = 0; i < container.getAllocatedSz(); i += 1) {
+ PointDataView view = container.readRandom(i);
+ double longitude = config.getLongitude().getNumericValue(view);
+ double latitude = config.getLatitude().getNumericValue(view);
+ double magnitude = config.getSpeed().getNumericValue(view);
+ double direction = config.getDirection().getNumericValue(view);
+ Coordinate lonLat = new Coordinate(longitude, latitude);
+ if (sample == null) {
+ renderable.addBarb(lonLat, magnitude, direction,
+ !initialLoad);
+ } else {
+ WindPlotParameter[] fields = sample.getFields();
+ Object[] args = new Object[fields.length];
+ for (int c = 0; c < args.length; c += 1) {
+ args[c] = fields[c].getValue(view);
+ }
+ String text = String.format(sample.getText(), args)
+ .toString();
+ renderable.addBarb(lonLat, magnitude, direction, text,
+ !initialLoad);
+ }
+
+ }
+ } catch (VizException e) {
+ statusHandler.error("Error retrieving wind data.", e);
+ }
+ }
+
+ @Override
+ protected void resourceDataChanged(ChangeType type, Object updateObject) {
+ if (type == ChangeType.DATA_UPDATE
+ && updateObject instanceof PluginDataObject[]) {
+ synchronized (framesLock) {
+ BinOffset binOffset = resourceData.getBinOffset();
+ for (PluginDataObject pdo : (PluginDataObject[]) updateObject) {
+ DataTime time = pdo.getDataTime();
+ if (binOffset != null) {
+ time = binOffset.getNormalizedTime(time);
+ }
+ DataFrame frame = frames.get(time);
+ if (frame != null) {
+ frame.update();
+ }
+ }
+ secondaryLoadJob.schedule();
+ }
+ }
+ }
+
+
+ private class DataFrame implements Runnable {
+
+ private final DataTime time;
+
+ private final WindPlotRenderable renderable;
+
+ private boolean needsReproject = false;
+
+ private boolean needsData = true;
+
+ private boolean initialLoad = true;
+
+ public DataFrame(DataTime time) {
+ this.time = time;
+ this.renderable = new WindPlotRenderable(WindPlotResource.this);
+ renderable.setBaseDensity(resourceData.getBaseDensity());
+ VectorGraphicsConfig config = renderable.getConfig();
+ config.setBaseSize(20);
+ config.setCalmCircleSizeRatio(0.3);
+ }
+
+ public WindPlotRenderable getRenderable() {
+ return renderable;
+ }
+
+ public void update() {
+ needsData = true;
+ }
+
+ public void reproject() {
+ needsReproject = true;
+ }
+
+ @Override
+ public void run() {
+ asyncUpdate();
+ }
+
+ public synchronized boolean asyncUpdate() {
+ boolean result = needsReproject | needsData;
+ if (needsReproject) {
+ needsReproject = false;
+ renderable.reproject();
+ }
+ if (needsData) {
+ needsData = false;
+ loadData(time, renderable, initialLoad);
+ initialLoad = false;
+ }
+ return result;
+ }
+
+ }
+
+ private class SecondaryUpdateJob extends Job {
+
+ public SecondaryUpdateJob() {
+ super("Updating wind data.");
+ setSystem(true);
+ }
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ List frameList;
+ synchronized (framesLock) {
+ if (frames == null) {
+ return Status.OK_STATUS;
+ }
+ frameList = new ArrayList<>(frames.values());
+ }
+ for (DataFrame frame : frameList) {
+ if (frame.asyncUpdate()) {
+ /*
+ * Restart after every frame to make sure frames haven't
+ * been added or removed while it was updating.
+ */
+ schedule();
+ return Status.OK_STATUS;
+ }
+ }
+ DataTime[] times = descriptor.getFramesInfo().getTimeMap()
+ .get(WindPlotResource.this);
+ if (times == null) {
+ return Status.OK_STATUS;
+ }
+ boolean added = false;
+ for (DataTime time : times) {
+ if (time == null) {
+ continue;
+ }
+ synchronized (framesLock) {
+ if (!frames.containsKey(time)) {
+ addFrame(time);
+ added = true;
+ }
+ }
+ }
+ if (added) {
+ /*
+ * Restart to ensure data is requested before optimization.
+ */
+ schedule();
+ return Status.OK_STATUS;
+ }
+ boolean finished = true;
+ for (DataFrame frame : frameList) {
+ if (!frame.getRenderable().optimizeDisclosure()) {
+ finished = false;
+ }
+ }
+ if (!finished) {
+ schedule();
+ }
+ return Status.OK_STATUS;
+ }
+
+ }
+
+}
diff --git a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/wind/WindPlotResourceData.java b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/wind/WindPlotResourceData.java
new file mode 100644
index 0000000000..d451e1bf2c
--- /dev/null
+++ b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/wind/WindPlotResourceData.java
@@ -0,0 +1,199 @@
+/**
+ * This software was developed and / or modified by Raytheon Company,
+ * pursuant to Contract DG133W-05-CQ-1067 with the US Government.
+ *
+ * U.S. EXPORT CONTROLLED TECHNICAL DATA
+ * This software product contains export-restricted data whose
+ * export/transfer/disclosure is restricted by U.S. law. Dissemination
+ * to non-U.S. persons whether in the United States or abroad requires
+ * an export license or other authorization.
+ *
+ * Contractor Name: Raytheon Company
+ * Contractor Address: 6825 Pine Street, Suite 340
+ * Mail Stop B8
+ * Omaha, NE 68106
+ * 402.291.0100
+ *
+ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
+ * further licensing information.
+ **/
+package com.raytheon.viz.pointdata.rsc.wind;
+
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.bind.JAXB;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlTransient;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+import com.raytheon.uf.common.dataplugin.PluginDataObject;
+import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
+import com.raytheon.uf.common.dataquery.requests.RequestableMetadataMarshaller;
+import com.raytheon.uf.common.localization.IPathManager;
+import com.raytheon.uf.common.localization.LocalizationFile;
+import com.raytheon.uf.common.localization.PathManagerFactory;
+import com.raytheon.uf.viz.core.exception.VizException;
+import com.raytheon.uf.viz.core.rsc.AbstractRequestableResourceData;
+import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
+import com.raytheon.uf.viz.core.rsc.LoadProperties;
+
+/**
+ *
+ * Resource data for displaying wind barbs of point data.
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------- -------- --------- -----------------
+ * Nov 13, 2015 4903 bsteffen Initial creation
+ *
+ *
+ *
+ * @author bsteffen
+ * @version 1.0
+ */
+@XmlAccessorType(XmlAccessType.NONE)
+public class WindPlotResourceData extends AbstractRequestableResourceData {
+
+ @XmlAttribute
+ private String legend;
+
+ @XmlAttribute
+ private String windFile;
+
+ @XmlAttribute
+ private double baseDensity = 1.0;
+
+ @XmlJavaTypeAdapter(value = RequestableMetadataMarshaller.class)
+ protected HashMap dataMetadataMap;
+
+ @XmlTransient
+ protected WindPlotConfig config;
+
+ public WindPlotResourceData() {
+ /*
+ * Resource data should never instigate a trip to the DB, the resource
+ * is responsible for requesting its own stuff.
+ */
+ setRetrieveData(false);
+ setUpdatingOnMetadataOnly(true);
+ }
+
+ @Override
+ protected AbstractVizResource, ?> constructResource(
+ LoadProperties loadProperties, PluginDataObject[] objects)
+ throws VizException {
+ if (config == null) {
+ IPathManager pathManager = PathManagerFactory.getPathManager();
+ String path = "plotWind" + IPathManager.SEPARATOR + windFile;
+ LocalizationFile localizedFile = pathManager
+ .getStaticLocalizationFile(path);
+ try (InputStream is = localizedFile.openInputStream()) {
+ config = JAXB.unmarshal(is, WindPlotConfig.class);
+ } catch (Exception e) {
+ throw new VizException("Error loading " + path, e);
+ }
+ }
+ return new WindPlotResource(this, loadProperties);
+ }
+
+ public String getLegend() {
+ return legend;
+ }
+
+ public void setLegend(String legend) {
+ this.legend = legend;
+ }
+
+ public String getWindFile() {
+ return windFile;
+ }
+
+ public void setWindFile(String windFile) {
+ this.windFile = windFile;
+ }
+
+ public double getBaseDensity() {
+ return baseDensity;
+ }
+
+ public void setBaseDensity(double baseDensity) {
+ this.baseDensity = baseDensity;
+ }
+
+ public HashMap getDataMetadataMap() {
+ return dataMetadataMap;
+ }
+
+ public void setDataMetadataMap(
+ HashMap dataMetadataMap) {
+ this.dataMetadataMap = dataMetadataMap;
+ }
+
+ public Map getFullDataMetadataMap() {
+ Map result = new HashMap<>(getMetadataMap());
+ if (dataMetadataMap != null) {
+ result.putAll(dataMetadataMap);
+ }
+ return result;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result
+ + ((dataMetadataMap == null) ? 0 : dataMetadataMap.hashCode());
+ result = prime * result + ((legend == null) ? 0 : legend.hashCode());
+ result = prime * result
+ + ((windFile == null) ? 0 : windFile.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ WindPlotResourceData other = (WindPlotResourceData) obj;
+ if (dataMetadataMap == null) {
+ if (other.dataMetadataMap != null) {
+ return false;
+ }
+ } else if (!dataMetadataMap.equals(other.dataMetadataMap)) {
+ return false;
+ }
+ if (legend == null) {
+ if (other.legend != null) {
+ return false;
+ }
+ } else if (!legend.equals(other.legend)) {
+ return false;
+ }
+ if (windFile == null) {
+ if (other.windFile != null) {
+ return false;
+ }
+ } else if (!windFile.equals(other.windFile)) {
+ return false;
+ }
+ return true;
+ }
+
+ public WindPlotConfig getConfig() {
+ return config;
+ }
+
+}
diff --git a/cave/com.raytheon.viz.satellite/localization/bundles/Satellite3_9WindPlots.xml b/cave/com.raytheon.viz.satellite/localization/bundles/Satellite3_9WindPlots.xml
index 53153e3770..5f91331f3d 100644
--- a/cave/com.raytheon.viz.satellite/localization/bundles/Satellite3_9WindPlots.xml
+++ b/cave/com.raytheon.viz.satellite/localization/bundles/Satellite3_9WindPlots.xml
@@ -1,52 +1,43 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/cave/com.raytheon.viz.satellite/localization/bundles/SatelliteLayerPlot.xml b/cave/com.raytheon.viz.satellite/localization/bundles/SatelliteLayerPlot.xml
index c669e5d6be..3da444bea2 100644
--- a/cave/com.raytheon.viz.satellite/localization/bundles/SatelliteLayerPlot.xml
+++ b/cave/com.raytheon.viz.satellite/localization/bundles/SatelliteLayerPlot.xml
@@ -1,52 +1,43 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/cave/com.raytheon.viz.satellite/localization/bundles/SatelliteWV7_0WindPlots.xml b/cave/com.raytheon.viz.satellite/localization/bundles/SatelliteWV7_0WindPlots.xml
index 70094eeb22..248ff3bc22 100644
--- a/cave/com.raytheon.viz.satellite/localization/bundles/SatelliteWV7_0WindPlots.xml
+++ b/cave/com.raytheon.viz.satellite/localization/bundles/SatelliteWV7_0WindPlots.xml
@@ -1,185 +1,136 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/cave/com.raytheon.viz.satellite/localization/bundles/SatelliteWV7_4WindPlots.xml b/cave/com.raytheon.viz.satellite/localization/bundles/SatelliteWV7_4WindPlots.xml
index 6978c1b829..8a7fa984bd 100644
--- a/cave/com.raytheon.viz.satellite/localization/bundles/SatelliteWV7_4WindPlots.xml
+++ b/cave/com.raytheon.viz.satellite/localization/bundles/SatelliteWV7_4WindPlots.xml
@@ -1,211 +1,154 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/cave/com.raytheon.viz.satellite/localization/bundles/SatelliteWindPlots.xml b/cave/com.raytheon.viz.satellite/localization/bundles/SatelliteWindPlots.xml
index 17060a0485..45bb8eeeb5 100644
--- a/cave/com.raytheon.viz.satellite/localization/bundles/SatelliteWindPlots.xml
+++ b/cave/com.raytheon.viz.satellite/localization/bundles/SatelliteWindPlots.xml
@@ -1,237 +1,172 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/cave/com.raytheon.viz.satellite/localization/bundles/Scatterometer.xml b/cave/com.raytheon.viz.satellite/localization/bundles/Scatterometer.xml
new file mode 100644
index 0000000000..a284d1373d
--- /dev/null
+++ b/cave/com.raytheon.viz.satellite/localization/bundles/Scatterometer.xml
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/cave/com.raytheon.viz.pointdata/localization/plotModels/ascatPlotDesign.svg b/cave/com.raytheon.viz.satellite/localization/plotModels/ascatPlotDesign.svg
similarity index 100%
rename from cave/com.raytheon.viz.pointdata/localization/plotModels/ascatPlotDesign.svg
rename to cave/com.raytheon.viz.satellite/localization/plotModels/ascatPlotDesign.svg
diff --git a/cave/com.raytheon.viz.pointdata/localization/plotModels/hdwTypePlotDesign.svg b/cave/com.raytheon.viz.satellite/localization/plotModels/hdwTypePlotDesign.svg
similarity index 100%
rename from cave/com.raytheon.viz.pointdata/localization/plotModels/hdwTypePlotDesign.svg
rename to cave/com.raytheon.viz.satellite/localization/plotModels/hdwTypePlotDesign.svg
diff --git a/cave/com.raytheon.viz.pointdata/localization/plotModels/hdw_sat_lookup.txt b/cave/com.raytheon.viz.satellite/localization/plotModels/hdw_sat_lookup.txt
similarity index 100%
rename from cave/com.raytheon.viz.pointdata/localization/plotModels/hdw_sat_lookup.txt
rename to cave/com.raytheon.viz.satellite/localization/plotModels/hdw_sat_lookup.txt
diff --git a/cave/com.raytheon.viz.pointdata/localization/plotModels/sat_name_lookup.txt b/cave/com.raytheon.viz.satellite/localization/plotModels/sat_name_lookup.txt
similarity index 100%
rename from cave/com.raytheon.viz.pointdata/localization/plotModels/sat_name_lookup.txt
rename to cave/com.raytheon.viz.satellite/localization/plotModels/sat_name_lookup.txt
diff --git a/cave/com.raytheon.viz.pointdata/localization/plotModels/sat_type_lookup.txt b/cave/com.raytheon.viz.satellite/localization/plotModels/sat_type_lookup.txt
similarity index 100%
rename from cave/com.raytheon.viz.pointdata/localization/plotModels/sat_type_lookup.txt
rename to cave/com.raytheon.viz.satellite/localization/plotModels/sat_type_lookup.txt
diff --git a/cave/com.raytheon.viz.pointdata/localization/plotModels/sat_type_lookup_ascat.txt b/cave/com.raytheon.viz.satellite/localization/plotModels/sat_type_lookup_ascat.txt
similarity index 100%
rename from cave/com.raytheon.viz.pointdata/localization/plotModels/sat_type_lookup_ascat.txt
rename to cave/com.raytheon.viz.satellite/localization/plotModels/sat_type_lookup_ascat.txt
diff --git a/cave/com.raytheon.viz.pointdata/localization/plotModels/ssmiPWPlotDesign.svg b/cave/com.raytheon.viz.satellite/localization/plotModels/ssmiPWPlotDesign.svg
similarity index 100%
rename from cave/com.raytheon.viz.pointdata/localization/plotModels/ssmiPWPlotDesign.svg
rename to cave/com.raytheon.viz.satellite/localization/plotModels/ssmiPWPlotDesign.svg
diff --git a/cave/com.raytheon.viz.pointdata/localization/plotModels/ssmiSTPlotDesign.svg b/cave/com.raytheon.viz.satellite/localization/plotModels/ssmiSTPlotDesign.svg
similarity index 100%
rename from cave/com.raytheon.viz.pointdata/localization/plotModels/ssmiSTPlotDesign.svg
rename to cave/com.raytheon.viz.satellite/localization/plotModels/ssmiSTPlotDesign.svg
diff --git a/cave/com.raytheon.viz.pointdata/localization/plotModels/ssmiVILPlotDesign.svg b/cave/com.raytheon.viz.satellite/localization/plotModels/ssmiVILPlotDesign.svg
similarity index 100%
rename from cave/com.raytheon.viz.pointdata/localization/plotModels/ssmiVILPlotDesign.svg
rename to cave/com.raytheon.viz.satellite/localization/plotModels/ssmiVILPlotDesign.svg
diff --git a/cave/com.raytheon.viz.pointdata/localization/plotModels/ssmiVILPlotDesign.txt b/cave/com.raytheon.viz.satellite/localization/plotModels/ssmiVILPlotDesign.txt
similarity index 100%
rename from cave/com.raytheon.viz.pointdata/localization/plotModels/ssmiVILPlotDesign.txt
rename to cave/com.raytheon.viz.satellite/localization/plotModels/ssmiVILPlotDesign.txt
diff --git a/cave/com.raytheon.viz.pointdata/localization/plotModels/ssmiWindPlotDesign.svg b/cave/com.raytheon.viz.satellite/localization/plotModels/ssmiWindPlotDesign.svg
similarity index 100%
rename from cave/com.raytheon.viz.pointdata/localization/plotModels/ssmiWindPlotDesign.svg
rename to cave/com.raytheon.viz.satellite/localization/plotModels/ssmiWindPlotDesign.svg
diff --git a/cave/com.raytheon.viz.satellite/localization/plotWind/ascat_wind.xml b/cave/com.raytheon.viz.satellite/localization/plotWind/ascat_wind.xml
new file mode 100644
index 0000000000..7ece70ea3a
--- /dev/null
+++ b/cave/com.raytheon.viz.satellite/localization/plotWind/ascat_wind.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/cave/com.raytheon.viz.satellite/localization/plotWind/hdw_wind.xml b/cave/com.raytheon.viz.satellite/localization/plotWind/hdw_wind.xml
new file mode 100644
index 0000000000..2dd21d8b0d
--- /dev/null
+++ b/cave/com.raytheon.viz.satellite/localization/plotWind/hdw_wind.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file