Omaha #4354: Modify Damage Path tool so each polygon has its own properties, demo bug fixes.
Change-Id: Ib69c19fa518f5e89638af1eba391ee6954f7891d Former-commit-id: affaf23ed435cd3dc62e074cf19a8c4c478d7295
This commit is contained in:
parent
372f7b5362
commit
744b5c3c5b
12 changed files with 320 additions and 120 deletions
|
@ -3,12 +3,6 @@
|
|||
<plugin>
|
||||
<extension
|
||||
point="com.raytheon.viz.ui.contextualMenu">
|
||||
<contextualMenu
|
||||
actionClass="com.raytheon.uf.viz.damagepath.OpenGeoJsonPropertiesDlgAction"
|
||||
capabilityClass="com.raytheon.uf.viz.damagepath.DamagePathLayer"
|
||||
name="Set Properties"
|
||||
sortID="3">
|
||||
</contextualMenu>
|
||||
<contextualMenu
|
||||
actionClass="com.raytheon.uf.viz.damagepath.ImportFromDistanceSpeedAction"
|
||||
capabilityClass="com.raytheon.uf.viz.damagepath.DamagePathLayer"
|
||||
|
|
|
@ -23,7 +23,6 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -32,6 +31,9 @@ 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.eclipse.jface.action.IMenuManager;
|
||||
import org.geotools.data.DataUtilities;
|
||||
import org.geotools.data.simple.SimpleFeatureCollection;
|
||||
import org.geotools.feature.simple.SimpleFeatureBuilder;
|
||||
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
|
||||
import org.opengis.feature.simple.SimpleFeature;
|
||||
|
@ -49,15 +51,16 @@ import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
|
|||
import com.raytheon.uf.common.localization.LocalizationFile;
|
||||
import com.raytheon.uf.common.localization.LocalizationFileOutputStream;
|
||||
import com.raytheon.uf.common.localization.PathManagerFactory;
|
||||
import com.raytheon.uf.common.util.Pair;
|
||||
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.core.rsc.LoadProperties;
|
||||
import com.raytheon.uf.viz.core.rsc.capabilities.EditableCapability;
|
||||
import com.raytheon.uf.viz.drawing.polygon.DrawablePolygon;
|
||||
import com.raytheon.uf.viz.drawing.polygon.PolygonLayer;
|
||||
import com.raytheon.uf.viz.drawing.polygon.PolygonUtil;
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.geom.GeometryCollection;
|
||||
import com.vividsolutions.jts.geom.Polygon;
|
||||
|
||||
/**
|
||||
|
@ -78,6 +81,8 @@ import com.vividsolutions.jts.geom.Polygon;
|
|||
* Jun 08, 2015 4355 dgilling Fix NullPointerException in loadJob.
|
||||
* Jun 12, 2015 4375 dgilling Fix ConcurrentModificationException in
|
||||
* initInternal.
|
||||
* Jun 18, 2015 4354 dgilling Allow each polygon to have their own
|
||||
* properties.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -111,8 +116,6 @@ public class DamagePathLayer<T extends DamagePathResourceData> extends
|
|||
|
||||
private static final String PATH = DIR + IPathManager.SEPARATOR + FILE;
|
||||
|
||||
private Map<String, String> featureProperties = Collections.emptyMap();
|
||||
|
||||
/**
|
||||
* JVM property to specify the localization level to attempt to save/load
|
||||
* with. Falls back to USER if not defined.
|
||||
|
@ -171,7 +174,7 @@ public class DamagePathLayer<T extends DamagePathResourceData> extends
|
|||
private void setDefaultPolygon() {
|
||||
Polygon polygon = PolygonUtil.makeDefaultPolygon(getResourceContainer()
|
||||
.getActiveDisplayPane().getRenderableDisplay());
|
||||
DrawablePolygon drawablePolygon = new DrawablePolygon(polygon, this);
|
||||
DrawablePolygon drawablePolygon = new DamagePathPolygon(polygon, this);
|
||||
polygons.add(0, drawablePolygon);
|
||||
}
|
||||
|
||||
|
@ -250,18 +253,24 @@ public class DamagePathLayer<T extends DamagePathResourceData> extends
|
|||
protected void loadDamagePath(LocalizationFile file) {
|
||||
try {
|
||||
DamagePathLoader loader = new DamagePathLoader(file);
|
||||
Collection<Polygon> newPolygons = loader.getPolygons();
|
||||
if (!newPolygons.isEmpty()) {
|
||||
Collection<Pair<Polygon, Map<String, String>>> newData = loader
|
||||
.getDamagePathData();
|
||||
if (!newData.isEmpty()) {
|
||||
Collection<DrawablePolygon> newDamagePaths = new ArrayList<>(
|
||||
newData.size());
|
||||
for (Pair<Polygon, Map<String, String>> data : newData) {
|
||||
newDamagePaths.add(new DamagePathPolygon(data.getFirst(),
|
||||
data.getSecond(), this));
|
||||
}
|
||||
|
||||
/*
|
||||
* specifically call super.resetPolygon() cause
|
||||
* this.resetPolygon() will save the file and we don't want to
|
||||
* do that or we could infinite loop of load, save, load,
|
||||
* save...
|
||||
*/
|
||||
super.resetPolygons(newPolygons);
|
||||
super.resetPolygons(newDamagePaths);
|
||||
}
|
||||
|
||||
featureProperties = loader.getProperties();
|
||||
} catch (Exception e) {
|
||||
statusHandler.error(
|
||||
"Error loading damage path file " + file.getName(), e);
|
||||
|
@ -273,8 +282,8 @@ public class DamagePathLayer<T extends DamagePathResourceData> extends
|
|||
try {
|
||||
fos = file.openOutputStream();
|
||||
IGeoJsonService json = new SimpleGeoJsonService();
|
||||
SimpleFeature feature = buildFeature();
|
||||
json.serialize(feature, fos);
|
||||
SimpleFeatureCollection featureCollection = buildFeatureCollection();
|
||||
json.serialize(featureCollection, fos);
|
||||
fos.closeAndSave();
|
||||
} catch (Throwable t) {
|
||||
if (fos != null) {
|
||||
|
@ -289,18 +298,16 @@ public class DamagePathLayer<T extends DamagePathResourceData> extends
|
|||
}
|
||||
}
|
||||
|
||||
public SimpleFeature buildFeature() {
|
||||
Map<String, String> jsonProps = getFeatureProperties();
|
||||
private SimpleFeature buildFeature(final DamagePathPolygon damagePath) {
|
||||
Map<String, String> jsonProps = damagePath.getProperties();
|
||||
|
||||
String id = jsonProps.get(GeoJsonMapUtil.ID_KEY);
|
||||
SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder();
|
||||
typeBuilder.setName("feature");
|
||||
|
||||
Collection<Polygon> polygons = getPolygons();
|
||||
GeometryCollection geomCollection = PolygonUtil.FACTORY
|
||||
.createGeometryCollection(polygons.toArray(new Geometry[0]));
|
||||
Geometry polygon = damagePath.getPolygon();
|
||||
typeBuilder.setDefaultGeometry("the_geom");
|
||||
typeBuilder.add("the_geom", geomCollection.getClass());
|
||||
typeBuilder.add("the_geom", polygon.getClass());
|
||||
|
||||
Collection<String> keysToIgnore = Arrays.asList(GeoJsonMapUtil.ID_KEY);
|
||||
Set<String> keySet = jsonProps.keySet();
|
||||
|
@ -315,25 +322,25 @@ public class DamagePathLayer<T extends DamagePathResourceData> extends
|
|||
|
||||
SimpleFeatureType type = typeBuilder.buildFeatureType();
|
||||
SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(type);
|
||||
if (geomCollection != null) {
|
||||
featureBuilder.add(geomCollection);
|
||||
if (polygon != null) {
|
||||
featureBuilder.add(polygon);
|
||||
}
|
||||
featureBuilder.addAll(values);
|
||||
return featureBuilder.buildFeature(id);
|
||||
}
|
||||
|
||||
public Map<String, String> getFeatureProperties() {
|
||||
return featureProperties;
|
||||
public SimpleFeatureCollection buildFeatureCollection() {
|
||||
List<SimpleFeature> features = new ArrayList<>(polygons.size());
|
||||
for (DrawablePolygon polygon : polygons) {
|
||||
features.add(buildFeature((DamagePathPolygon) polygon));
|
||||
}
|
||||
|
||||
public void setFeatureProperties(Map<String, String> featureProperties) {
|
||||
this.featureProperties = featureProperties;
|
||||
saveJob.schedule();
|
||||
return DataUtilities.collection(features);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPolygon(Coordinate[] coords) {
|
||||
super.addPolygon(coords);
|
||||
super.addPolygon(new DamagePathPolygon(coords, this));
|
||||
saveJob.schedule();
|
||||
}
|
||||
|
||||
|
@ -342,4 +349,28 @@ public class DamagePathLayer<T extends DamagePathResourceData> extends
|
|||
super.deletePolygon(index);
|
||||
saveJob.schedule();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addContextMenuItems(IMenuManager menuManager, int x, int y) {
|
||||
if (!getCapability(EditableCapability.class).isEditable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
super.addContextMenuItems(menuManager, x, y);
|
||||
|
||||
int onPolygonIdx = uiInput.pointOnPolygon(x, y);
|
||||
if (onPolygonIdx >= 0) {
|
||||
menuManager.add(new OpenGeoJsonPropertiesDlgAction(
|
||||
(DamagePathPolygon) polygons.get(onPolygonIdx)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DrawablePolygon getNewDrawable() {
|
||||
return new DamagePathPolygon(this);
|
||||
}
|
||||
|
||||
protected void scheduleSaveJob() {
|
||||
saveJob.schedule();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,11 +26,15 @@ import java.nio.file.Path;
|
|||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.geotools.feature.FeatureCollection;
|
||||
import org.geotools.feature.FeatureIterator;
|
||||
import org.opengis.feature.Property;
|
||||
import org.opengis.feature.simple.SimpleFeature;
|
||||
import org.opengis.feature.simple.SimpleFeatureType;
|
||||
import org.opengis.feature.type.Name;
|
||||
|
||||
import com.raytheon.uf.common.json.JsonException;
|
||||
|
@ -40,6 +44,7 @@ import com.raytheon.uf.common.json.geo.IGeoJsonService;
|
|||
import com.raytheon.uf.common.json.geo.SimpleGeoJsonService;
|
||||
import com.raytheon.uf.common.localization.LocalizationFile;
|
||||
import com.raytheon.uf.common.localization.exception.LocalizationException;
|
||||
import com.raytheon.uf.common.util.Pair;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.geom.Polygon;
|
||||
import com.vividsolutions.jts.operation.valid.IsValidOp;
|
||||
|
@ -55,6 +60,8 @@ import com.vividsolutions.jts.operation.valid.IsValidOp;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 05, 2015 #4375 dgilling Initial creation
|
||||
* Jun 18, 2015 #4354 dgilling Support FeatureCollections so each polygon
|
||||
* can have its own properties.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -70,9 +77,7 @@ public final class DamagePathLoader {
|
|||
|
||||
private static final String INVALID_POLYGON = "Damage path file contains an invalid Polyon at index %d: %s";
|
||||
|
||||
private final Collection<Polygon> polygons;
|
||||
|
||||
private final Map<String, String> properties;
|
||||
private final Collection<Pair<Polygon, Map<String, String>>> damagePathData;
|
||||
|
||||
public DamagePathLoader(LocalizationFile locFile)
|
||||
throws LocalizationException, IOException, JsonException {
|
||||
|
@ -86,8 +91,7 @@ public final class DamagePathLoader {
|
|||
|
||||
private DamagePathLoader(LocalizationFile locFileSource, Path realFileSource)
|
||||
throws LocalizationException, IOException, JsonException {
|
||||
this.polygons = new ArrayList<>();
|
||||
this.properties = new LinkedHashMap<>();
|
||||
this.damagePathData = new ArrayList<>();
|
||||
|
||||
if (locFileSource != null) {
|
||||
loadFromLocalizationFile(locFileSource);
|
||||
|
@ -96,12 +100,8 @@ public final class DamagePathLoader {
|
|||
}
|
||||
}
|
||||
|
||||
public Collection<Polygon> getPolygons() {
|
||||
return polygons;
|
||||
}
|
||||
|
||||
public Map<String, String> getProperties() {
|
||||
return properties;
|
||||
public Collection<Pair<Polygon, Map<String, String>>> getDamagePathData() {
|
||||
return damagePathData;
|
||||
}
|
||||
|
||||
private void loadFromLocalizationFile(final LocalizationFile locFile)
|
||||
|
@ -120,29 +120,36 @@ public final class DamagePathLoader {
|
|||
|
||||
private void loadFromInputStream(final InputStream is) throws JsonException {
|
||||
Geometry deserializedGeom = null;
|
||||
Map<String, String> deserializedProps = Collections.emptyMap();
|
||||
GeoJsonMapUtil geoJsonUtil = new GeoJsonMapUtil();
|
||||
|
||||
/*
|
||||
* For compatibility with any users that may have an autosaved damage
|
||||
* path file from build 15.1, we'll support deserializing both Geometry
|
||||
* and Feature GeoJSON types.
|
||||
* path file from previous builds, we'll support deserializing Geometry,
|
||||
* Feature and FeatureCollection GeoJSON types.
|
||||
*
|
||||
* TODO: remove this code for code that just expects the file to always
|
||||
* be a Feature.
|
||||
* be a FeatureCollection.
|
||||
*/
|
||||
Map<String, Object> jsonObject = (Map<String, Object>) new BasicJsonService()
|
||||
.deserialize(is, LinkedHashMap.class);
|
||||
String geoJsonType = jsonObject.get(GeoJsonMapUtil.TYPE_KEY).toString();
|
||||
if (geoJsonType.equals(GeoJsonMapUtil.FEATURE_TYPE)) {
|
||||
if (geoJsonType.equals(GeoJsonMapUtil.FEATURE_COLL_TYPE)) {
|
||||
FeatureCollection<SimpleFeatureType, SimpleFeature> featureCollection = geoJsonUtil
|
||||
.populateFeatureCollection(jsonObject);
|
||||
populateDataFromFeatureCollection(featureCollection);
|
||||
return;
|
||||
} else if (geoJsonType.equals(GeoJsonMapUtil.FEATURE_TYPE)) {
|
||||
SimpleFeature feature = geoJsonUtil.populateFeature(jsonObject);
|
||||
deserializedGeom = (Geometry) feature.getDefaultGeometry();
|
||||
|
||||
Name defaultGeomAttrib = feature.getDefaultGeometryProperty()
|
||||
.getName();
|
||||
properties.put(GeoJsonMapUtil.ID_KEY, feature.getID());
|
||||
deserializedProps = new LinkedHashMap<>();
|
||||
deserializedProps.put(GeoJsonMapUtil.ID_KEY, feature.getID());
|
||||
for (Property p : feature.getProperties()) {
|
||||
if (!defaultGeomAttrib.equals(p.getName())) {
|
||||
properties.put(p.getName().toString(), p.getValue()
|
||||
deserializedProps.put(p.getName().toString(), p.getValue()
|
||||
.toString());
|
||||
}
|
||||
}
|
||||
|
@ -160,7 +167,9 @@ public final class DamagePathLoader {
|
|||
Polygon newPolygon = (Polygon) geomN;
|
||||
IsValidOp validator = new IsValidOp(newPolygon);
|
||||
if (validator.isValid()) {
|
||||
polygons.add(newPolygon);
|
||||
Pair<Polygon, Map<String, String>> polygonAndProps = new Pair<>(
|
||||
newPolygon, deserializedProps);
|
||||
damagePathData.add(polygonAndProps);
|
||||
} else {
|
||||
throw new JsonException(String.format(INVALID_POLYGON, i,
|
||||
validator.getValidationError()));
|
||||
|
@ -190,32 +199,49 @@ public final class DamagePathLoader {
|
|||
private void loadFromInputStreamFuture(final InputStream is)
|
||||
throws JsonException {
|
||||
IGeoJsonService json = new SimpleGeoJsonService();
|
||||
SimpleFeature feature = json.deserializeFeature(is);
|
||||
Geometry featureGeom = (Geometry) feature.getDefaultGeometry();
|
||||
FeatureCollection<SimpleFeatureType, SimpleFeature> featureCollection = json
|
||||
.deserializeFeatureCollection(is);
|
||||
populateDataFromFeatureCollection(featureCollection);
|
||||
}
|
||||
|
||||
int numGeometries = featureGeom.getNumGeometries();
|
||||
for (int i = 0; i < numGeometries; i++) {
|
||||
Geometry geomN = featureGeom.getGeometryN(i);
|
||||
if (geomN instanceof Polygon) {
|
||||
Polygon newPolygon = (Polygon) geomN;
|
||||
private void populateDataFromFeatureCollection(
|
||||
FeatureCollection<SimpleFeatureType, SimpleFeature> featureCollection)
|
||||
throws JsonException {
|
||||
try (FeatureIterator<SimpleFeature> iter = featureCollection.features()) {
|
||||
int featureIdx = 0;
|
||||
while (iter.hasNext()) {
|
||||
SimpleFeature feature = iter.next();
|
||||
|
||||
Geometry geom = (Geometry) feature.getDefaultGeometry();
|
||||
if (geom instanceof Polygon) {
|
||||
Polygon newPolygon = (Polygon) geom;
|
||||
IsValidOp validator = new IsValidOp(newPolygon);
|
||||
if (validator.isValid()) {
|
||||
polygons.add(newPolygon);
|
||||
} else {
|
||||
throw new JsonException(String.format(INVALID_POLYGON, i,
|
||||
validator.getValidationError()));
|
||||
}
|
||||
} else {
|
||||
throw new JsonException(String.format(UNSUPPORTED_GEOM_TYPE,
|
||||
geomN.getGeometryType(), i));
|
||||
}
|
||||
if (!validator.isValid()) {
|
||||
throw new JsonException(String.format(INVALID_POLYGON,
|
||||
featureIdx, validator.getValidationError()));
|
||||
}
|
||||
|
||||
Name defaultGeomAttrib = feature.getDefaultGeometryProperty().getName();
|
||||
Map<String, String> properties = new LinkedHashMap<>();
|
||||
Name defaultGeomAttrib = feature
|
||||
.getDefaultGeometryProperty().getName();
|
||||
properties.put(GeoJsonMapUtil.ID_KEY, feature.getID());
|
||||
for (Property p : feature.getProperties()) {
|
||||
if (!defaultGeomAttrib.equals(p.getName())) {
|
||||
properties.put(p.getName().toString(), p.getValue().toString());
|
||||
properties.put(p.getName().toString(), p.getValue()
|
||||
.toString());
|
||||
}
|
||||
}
|
||||
|
||||
Pair<Polygon, Map<String, String>> polygonAndProps = new Pair<>(
|
||||
newPolygon, properties);
|
||||
damagePathData.add(polygonAndProps);
|
||||
} else {
|
||||
throw new JsonException(String.format(
|
||||
UNSUPPORTED_GEOM_TYPE, geom.getGeometryType(),
|
||||
featureIdx));
|
||||
}
|
||||
|
||||
featureIdx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.uf.viz.damagepath;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import com.raytheon.uf.viz.drawing.polygon.DrawablePolygon;
|
||||
import com.raytheon.uf.viz.drawing.polygon.PolygonLayer;
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.Polygon;
|
||||
|
||||
/**
|
||||
* Extension of {@code DrawablePolygon} to support GeoJSON properties.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 18, 2015 #4354 dgilling Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author dgilling
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class DamagePathPolygon extends DrawablePolygon {
|
||||
|
||||
private static final Map<String, String> DEFAULT_PROPS = Collections
|
||||
.emptyMap();
|
||||
|
||||
private Map<String, String> properties;
|
||||
|
||||
public DamagePathPolygon(PolygonLayer<?> polygonLayer) {
|
||||
super(polygonLayer);
|
||||
this.properties = DEFAULT_PROPS;
|
||||
}
|
||||
|
||||
public DamagePathPolygon(Polygon polygon, PolygonLayer<?> polygonLayer) {
|
||||
this(polygon, DEFAULT_PROPS, polygonLayer);
|
||||
}
|
||||
|
||||
public DamagePathPolygon(Polygon polygon, Map<String, String> properties,
|
||||
PolygonLayer<?> polygonLayer) {
|
||||
super(polygon, polygonLayer);
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public DamagePathPolygon(Coordinate[] coords, PolygonLayer<?> polygonLayer) {
|
||||
super(coords, polygonLayer);
|
||||
this.properties = DEFAULT_PROPS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetPolygon(DrawablePolygon newPolygon) {
|
||||
super.resetPolygon(newPolygon);
|
||||
|
||||
if (newPolygon instanceof DamagePathPolygon) {
|
||||
DamagePathPolygon newDamagePath = (DamagePathPolygon) newPolygon;
|
||||
properties = newDamagePath.getProperties();
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, String> getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public void setProperties(Map<String, String> properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
}
|
|
@ -25,7 +25,7 @@ import org.eclipse.jface.dialogs.MessageDialog;
|
|||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.widgets.FileDialog;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
import org.opengis.feature.simple.SimpleFeature;
|
||||
import org.geotools.data.simple.SimpleFeatureCollection;
|
||||
|
||||
import com.raytheon.uf.common.json.geo.IGeoJsonService;
|
||||
import com.raytheon.uf.common.json.geo.SimpleGeoJsonService;
|
||||
|
@ -34,7 +34,6 @@ import com.raytheon.uf.common.status.UFStatus;
|
|||
import com.raytheon.uf.viz.core.VizApp;
|
||||
import com.raytheon.viz.ui.VizWorkbenchManager;
|
||||
import com.raytheon.viz.ui.cmenu.AbstractRightClickAction;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
|
||||
/**
|
||||
* Action to export a damage path as GeoJSON to a file specified by the user.
|
||||
|
@ -50,6 +49,8 @@ import com.vividsolutions.jts.geom.Geometry;
|
|||
* Jun 05, 2015 4375 dgilling Prompt user before exporting feature
|
||||
* with no polygons.
|
||||
* Jun 09, 2015 4355 dgilling Rename action for UI.
|
||||
* Jun 18, 2015 #4354 dgilling Support FeatureCollections so each
|
||||
* polygon can have its own properties.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -85,11 +86,10 @@ public class ExportDamagePathAction extends AbstractRightClickAction {
|
|||
|
||||
if (filename != null) {
|
||||
DamagePathLayer<?> layer = (DamagePathLayer<?>) getSelectedRsc();
|
||||
SimpleFeature feature = layer.buildFeature();
|
||||
SimpleFeatureCollection featureCollection = layer
|
||||
.buildFeatureCollection();
|
||||
|
||||
Geometry defaultGeometry = (Geometry) feature
|
||||
.getDefaultGeometry();
|
||||
if (defaultGeometry.getNumGeometries() < 1) {
|
||||
if (featureCollection.size() < 1) {
|
||||
boolean export = MessageDialog.openConfirm(shell,
|
||||
CONFIRM_DLG_TITLE, CONFIRM_DLG_MSG);
|
||||
if (!export) {
|
||||
|
@ -101,7 +101,7 @@ public class ExportDamagePathAction extends AbstractRightClickAction {
|
|||
|
||||
try (FileOutputStream fos = new FileOutputStream(filename)) {
|
||||
IGeoJsonService json = new SimpleGeoJsonService();
|
||||
json.serialize(feature, fos);
|
||||
json.serialize(featureCollection, fos);
|
||||
} catch (Exception e) {
|
||||
statusHandler.error(
|
||||
"Error exporting damage path file to "
|
||||
|
|
|
@ -22,7 +22,7 @@ package com.raytheon.uf.viz.damagepath;
|
|||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.opengis.feature.simple.SimpleFeature;
|
||||
import org.geotools.data.simple.SimpleFeatureCollection;
|
||||
|
||||
import com.raytheon.uf.common.damagepath.request.ExportToLdadRequest;
|
||||
import com.raytheon.uf.common.json.JsonException;
|
||||
|
@ -46,6 +46,8 @@ import com.raytheon.viz.ui.cmenu.AbstractRightClickAction;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 08, 2015 #4355 dgilling Initial creation
|
||||
* Jun 18, 2015 #4354 dgilling Support FeatureCollections so each
|
||||
* polygon can have its own properties.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -69,9 +71,10 @@ public class ExportToLdadAction extends AbstractRightClickAction {
|
|||
|
||||
try (ByteArrayOutputStream outStream = new ByteArrayOutputStream()) {
|
||||
DamagePathLayer<?> layer = (DamagePathLayer<?>) getSelectedRsc();
|
||||
SimpleFeature feature = layer.buildFeature();
|
||||
SimpleFeatureCollection featureCollection = layer
|
||||
.buildFeatureCollection();
|
||||
|
||||
new SimpleGeoJsonService().serialize(feature, outStream);
|
||||
new SimpleGeoJsonService().serialize(featureCollection, outStream);
|
||||
jsonData = outStream.toByteArray();
|
||||
} catch (JsonException | IOException e) {
|
||||
statusHandler.error(
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
**/
|
||||
package com.raytheon.uf.viz.damagepath;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.widgets.FileDialog;
|
||||
|
@ -28,7 +30,11 @@ import org.eclipse.swt.widgets.Shell;
|
|||
import com.raytheon.uf.common.json.JsonException;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.util.Pair;
|
||||
import com.raytheon.uf.viz.core.VizApp;
|
||||
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
|
||||
import com.raytheon.uf.viz.core.rsc.capabilities.EditableCapability;
|
||||
import com.raytheon.uf.viz.drawing.polygon.DrawablePolygon;
|
||||
import com.raytheon.viz.ui.VizWorkbenchManager;
|
||||
import com.raytheon.viz.ui.cmenu.AbstractRightClickAction;
|
||||
import com.vividsolutions.jts.geom.Polygon;
|
||||
|
@ -47,6 +53,8 @@ import com.vividsolutions.jts.geom.Polygon;
|
|||
* Apr 23, 2015 4354 dgilling Support GeoJSON Feature objects.
|
||||
* Jun 03, 2015 4375 dgilling Support multiple polygons.
|
||||
* Jun 09, 2015 4355 dgilling Rename action for UI.
|
||||
* Jun 18, 2015 4354 dgilling Support modifications to loader so each
|
||||
* polygon can have its own properties.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -80,10 +88,16 @@ public class ImportDamagePathAction extends AbstractRightClickAction {
|
|||
try {
|
||||
DamagePathLoader loader = new DamagePathLoader(filename);
|
||||
|
||||
Collection<Polygon> newPolygons = loader.getPolygons();
|
||||
if (!newPolygons.isEmpty()) {
|
||||
layer.resetPolygons(newPolygons);
|
||||
layer.setFeatureProperties(loader.getProperties());
|
||||
Collection<Pair<Polygon, Map<String, String>>> newData = loader
|
||||
.getDamagePathData();
|
||||
if (!newData.isEmpty()) {
|
||||
Collection<DrawablePolygon> newDamagePaths = new ArrayList<>(
|
||||
newData.size());
|
||||
for (Pair<Polygon, Map<String, String>> data : newData) {
|
||||
newDamagePaths.add(new DamagePathPolygon(data
|
||||
.getFirst(), data.getSecond(), layer));
|
||||
}
|
||||
layer.resetPolygons(newDamagePaths);
|
||||
} else {
|
||||
throw new JsonException(
|
||||
"Damage path file contains no polygons.");
|
||||
|
@ -96,4 +110,10 @@ public class ImportDamagePathAction extends AbstractRightClickAction {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
AbstractVizResource<?, ?> layer = getSelectedRsc();
|
||||
return layer.getCapability(EditableCapability.class).isEditable();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import com.raytheon.uf.viz.core.VizApp;
|
|||
import com.raytheon.uf.viz.core.drawables.ResourcePair;
|
||||
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
|
||||
import com.raytheon.uf.viz.core.rsc.ResourceList;
|
||||
import com.raytheon.uf.viz.core.rsc.capabilities.EditableCapability;
|
||||
import com.raytheon.viz.awipstools.ui.layer.DistanceSpeedLayer;
|
||||
import com.raytheon.viz.ui.cmenu.AbstractRightClickAction;
|
||||
import com.vividsolutions.jts.geom.Polygon;
|
||||
|
@ -41,6 +42,8 @@ import com.vividsolutions.jts.geom.Polygon;
|
|||
* Mar 23, 2015 3977 nabowle Initial creation
|
||||
* Jun 01, 2015 3975 dgilling Update for DamageLayer changes for
|
||||
* multiple polygon support.
|
||||
* Jun 18, 2015 4354 dgilling Update isEnabled to consider editable
|
||||
* capability.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -85,9 +88,10 @@ public class ImportFromDistanceSpeedAction extends AbstractRightClickAction {
|
|||
*/
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
boolean enabled = super.isEnabled();
|
||||
if (enabled) {
|
||||
AbstractVizResource<?, ?> rsc = getSelectedRsc();
|
||||
boolean enabled = rsc.getCapability(EditableCapability.class)
|
||||
.isEditable();
|
||||
if (enabled) {
|
||||
if (rsc != null) {
|
||||
enabled = findImportLayer(rsc) != null;
|
||||
}
|
||||
|
@ -111,5 +115,4 @@ public class ImportFromDistanceSpeedAction extends AbstractRightClickAction {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -39,6 +39,8 @@ import com.raytheon.viz.ui.dialogs.ICloseCallback;
|
|||
* ------------ ---------- ----------- --------------------------
|
||||
* Apr 23, 2015 #4354 dgilling Initial creation
|
||||
* Jun 09, 2015 #4355 dgilling Rename action for UI.
|
||||
* Jun 18, 2015 #4354 dgilling Allow individual properties object for
|
||||
* each polygon.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -48,8 +50,11 @@ import com.raytheon.viz.ui.dialogs.ICloseCallback;
|
|||
|
||||
public class OpenGeoJsonPropertiesDlgAction extends AbstractRightClickAction {
|
||||
|
||||
public OpenGeoJsonPropertiesDlgAction() {
|
||||
private final DamagePathPolygon damagePath;
|
||||
|
||||
public OpenGeoJsonPropertiesDlgAction(final DamagePathPolygon damagePath) {
|
||||
super("Set Properties...");
|
||||
this.damagePath = damagePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -59,10 +64,10 @@ public class OpenGeoJsonPropertiesDlgAction extends AbstractRightClickAction {
|
|||
public void run() {
|
||||
Shell shell = VizWorkbenchManager.getInstance()
|
||||
.getCurrentWindow().getShell();
|
||||
final DamagePathLayer<?> layer = (DamagePathLayer<?>) getSelectedRsc();
|
||||
final Map<String, String> geoJsonProps = layer
|
||||
.getFeatureProperties();
|
||||
|
||||
final DamagePathLayer<?> layer = (DamagePathLayer<?>) getSelectedRsc();
|
||||
final Map<String, String> geoJsonProps = damagePath
|
||||
.getProperties();
|
||||
EditGeoJsonPropertiesDlg dlg = new EditGeoJsonPropertiesDlg(
|
||||
shell, geoJsonProps);
|
||||
dlg.setCloseCallback(new ICloseCallback() {
|
||||
|
@ -72,7 +77,8 @@ public class OpenGeoJsonPropertiesDlgAction extends AbstractRightClickAction {
|
|||
if ((returnValue != null)
|
||||
&& (!geoJsonProps.equals(returnValue))) {
|
||||
Map<String, String> updatedProperties = (Map<String, String>) returnValue;
|
||||
layer.setFeatureProperties(updatedProperties);
|
||||
damagePath.setProperties(updatedProperties);
|
||||
layer.scheduleSaveJob();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -50,6 +50,7 @@ import com.vividsolutions.jts.geom.Polygon;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* May 27, 2015 #4375 dgilling Initial creation
|
||||
* Jun 18, 2015 #4354 dgilling Correct behavior of project.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -168,6 +169,23 @@ public class DrawablePolygon implements IRenderable2 {
|
|||
if (coords != null && coords.length > 0) {
|
||||
polygon = PolygonUtil.FACTORY.createPolygon(coords);
|
||||
}
|
||||
|
||||
resetPolygon();
|
||||
}
|
||||
}
|
||||
|
||||
public void resetPolygon(DrawablePolygon newPolygon) {
|
||||
synchronized (lock) {
|
||||
if ((newPolygon != null) && (newPolygon.getPolygon() != null)) {
|
||||
polygon = newPolygon.getPolygon();
|
||||
}
|
||||
|
||||
resetPolygon();
|
||||
}
|
||||
}
|
||||
|
||||
public void resetPolygon() {
|
||||
synchronized (lock) {
|
||||
if (wireframeShape != null) {
|
||||
wireframeShape.reset();
|
||||
}
|
||||
|
@ -193,7 +211,7 @@ public class DrawablePolygon implements IRenderable2 {
|
|||
public void project(CoordinateReferenceSystem crs) {
|
||||
synchronized (lock) {
|
||||
dispose();
|
||||
polygon = null;
|
||||
resetPolygon();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ import com.vividsolutions.jts.geom.util.AffineTransformation;
|
|||
* Mar 04, 2015 4194 njensen Block other input on middle click drag on edges
|
||||
* Jun 03, 2015 4375 dgilling Add methods for adding/deleting polygons,
|
||||
* support multiple polygons in PolygonLayer.
|
||||
* Jun 18, 2015 4354 dgilling Changed visibility of pointOnPolygon.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -306,7 +307,7 @@ public class PolygonInputAdapter extends RscInputAdapter<PolygonLayer<?>> {
|
|||
* @return Index of the polygon this screen point is on or -1 if it is not
|
||||
* on any polygons.
|
||||
*/
|
||||
protected int pointOnPolygon(int screenX, int screenY) {
|
||||
public int pointOnPolygon(int screenX, int screenY) {
|
||||
int polygonIdx = -1;
|
||||
Coordinate worldCoord = screenToLatLon(screenX, screenY);
|
||||
if (worldCoord != null) {
|
||||
|
|
|
@ -22,7 +22,6 @@ package com.raytheon.uf.viz.drawing.polygon;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jface.action.IMenuManager;
|
||||
import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
||||
|
@ -59,6 +58,9 @@ import com.vividsolutions.jts.geom.Polygon;
|
|||
* May 15, 2015 4375 dgilling Support multiple polygons.
|
||||
* Jun 12, 2015 4375 dgilling Only show AddVertexAction when on polygon's
|
||||
* edge and not near a current vertex.
|
||||
* Jun 17, 2015 4354 dgilling Fix bugs that would clear polygons on
|
||||
* capability change or reproject.
|
||||
*
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -75,7 +77,7 @@ public class PolygonLayer<T extends AbstractResourceData> extends
|
|||
|
||||
protected PolygonInputAdapter uiInput = new PolygonInputAdapter(this);
|
||||
|
||||
protected final List<DrawablePolygon> polygons;
|
||||
protected final LinkedList<DrawablePolygon> polygons;
|
||||
|
||||
public PolygonLayer(T resourceData, LoadProperties loadProperties) {
|
||||
super(resourceData, loadProperties);
|
||||
|
@ -128,7 +130,7 @@ public class PolygonLayer<T extends AbstractResourceData> extends
|
|||
if ((index < polygons.size()) && (coords != null && coords.length > 0)) {
|
||||
DrawablePolygon polygon = polygons.remove(index);
|
||||
polygon.resetPolygon(coords);
|
||||
polygons.add(0, polygon);
|
||||
polygons.push(polygon);
|
||||
issueRefresh();
|
||||
}
|
||||
}
|
||||
|
@ -136,7 +138,12 @@ public class PolygonLayer<T extends AbstractResourceData> extends
|
|||
@Override
|
||||
protected void resourceDataChanged(ChangeType type, Object updateObject) {
|
||||
if (type.equals(ChangeType.CAPABILITY)) {
|
||||
clearPolygons();
|
||||
if (polygons != null) {
|
||||
for (DrawablePolygon polygon : polygons) {
|
||||
polygon.resetPolygon();
|
||||
}
|
||||
}
|
||||
issueRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,6 +152,7 @@ public class PolygonLayer<T extends AbstractResourceData> extends
|
|||
for (DrawablePolygon drawPolygon : polygons) {
|
||||
drawPolygon.project(crs);
|
||||
}
|
||||
issueRefresh();
|
||||
}
|
||||
|
||||
public Polygon getPolygon(int index) {
|
||||
|
@ -155,24 +163,13 @@ public class PolygonLayer<T extends AbstractResourceData> extends
|
|||
resetPolygon(index, polygon.getExteriorRing().getCoordinates());
|
||||
}
|
||||
|
||||
protected void clearPolygons() {
|
||||
if (polygons != null) {
|
||||
for (DrawablePolygon polygon : polygons) {
|
||||
polygon.dispose();
|
||||
}
|
||||
polygons.clear();
|
||||
issueRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void resetPolygons(Collection<Polygon> newPolygons) {
|
||||
public void resetPolygons(Collection<DrawablePolygon> newPolygons) {
|
||||
if ((polygons != null) && (!newPolygons.isEmpty())) {
|
||||
resizePolygonStack(newPolygons.size());
|
||||
|
||||
int i = 0;
|
||||
for (Polygon newPolygon : newPolygons) {
|
||||
polygons.get(i).resetPolygon(
|
||||
newPolygon.getExteriorRing().getCoordinates());
|
||||
for (DrawablePolygon newPolygon : newPolygons) {
|
||||
polygons.get(i).resetPolygon(newPolygon);
|
||||
i++;
|
||||
}
|
||||
|
||||
|
@ -185,21 +182,27 @@ public class PolygonLayer<T extends AbstractResourceData> extends
|
|||
if (newSize > currentSize) {
|
||||
int toAdd = newSize - currentSize;
|
||||
for (int i = 0; i < toAdd; i++) {
|
||||
polygons.add(new DrawablePolygon(this));
|
||||
polygons.add(getNewDrawable());
|
||||
}
|
||||
} else if (currentSize > newSize) {
|
||||
int toDelete = currentSize - newSize;
|
||||
for (int i = 0; i < toDelete; i++) {
|
||||
DrawablePolygon polygonToDelete = polygons.remove(polygons
|
||||
.size() - 1);
|
||||
DrawablePolygon polygonToDelete = polygons.removeLast();
|
||||
polygonToDelete.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected DrawablePolygon getNewDrawable() {
|
||||
return new DrawablePolygon(this);
|
||||
}
|
||||
|
||||
public void addPolygon(Coordinate[] coords) {
|
||||
DrawablePolygon polygon = new DrawablePolygon(coords, this);
|
||||
polygons.add(0, polygon);
|
||||
addPolygon(new DrawablePolygon(coords, this));
|
||||
}
|
||||
|
||||
protected void addPolygon(DrawablePolygon newPolygon) {
|
||||
polygons.push(newPolygon);
|
||||
}
|
||||
|
||||
public void deletePolygon(int index) {
|
||||
|
@ -224,6 +227,10 @@ public class PolygonLayer<T extends AbstractResourceData> extends
|
|||
*/
|
||||
@Override
|
||||
public void addContextMenuItems(IMenuManager menuManager, int x, int y) {
|
||||
if (!getCapability(EditableCapability.class).isEditable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int edgePolygonIdx = uiInput.pointOnEdge(x, y);
|
||||
boolean onEdge = (edgePolygonIdx >= 0);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue