Omaha #4354: Support GeoJSON Feature objects in damage path tool.

Change-Id: I62733373cb5da690ff03aebbb9826020b24e2585

Former-commit-id: 28845ce71a8d94b03bd4389f3cfdadbb29d06b3a
This commit is contained in:
David Gillingham 2015-04-24 13:21:22 -05:00
parent 944c2e0863
commit e25a35f1e3
10 changed files with 686 additions and 38 deletions

View file

@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Damage Path
Bundle-SymbolicName: com.raytheon.uf.viz.damagepath;singleton:=true
Bundle-Version: 1.15.1.qualifier
Bundle-Version: 1.15.2.qualifier
Bundle-Vendor: RAYTHEON
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Require-Bundle: com.raytheon.uf.viz.core;bundle-version="1.14.6",
@ -14,5 +14,6 @@ Require-Bundle: com.raytheon.uf.viz.core;bundle-version="1.14.6",
com.raytheon.viz.ui;bundle-version="1.14.1",
com.raytheon.viz.awipstools;bundle-version="1.14.0",
com.raytheon.viz.radar;bundle-version="1.14.0",
javax.measure;bundle-version="1.0.0"
javax.measure;bundle-version="1.0.0",
com.raytheon.uf.common.util;bundle-version="1.14.1"
Export-Package: com.raytheon.uf.viz.damagepath

View file

@ -3,23 +3,29 @@
<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 GeoJSON Properties"
sortID="3">
</contextualMenu>
<contextualMenu
actionClass="com.raytheon.uf.viz.damagepath.ExportDamagePathAction"
capabilityClass="com.raytheon.uf.viz.damagepath.DamagePathLayer"
name="Export GeoJSON"
sortID="3">
sortID="4">
</contextualMenu>
<contextualMenu
actionClass="com.raytheon.uf.viz.damagepath.ImportDamagePathAction"
capabilityClass="com.raytheon.uf.viz.damagepath.DamagePathLayer"
name="Import GeoJSON"
sortID="4">
sortID="5">
</contextualMenu>
<contextualMenu
actionClass="com.raytheon.uf.viz.damagepath.ImportFromDistanceSpeedAction"
capabilityClass="com.raytheon.uf.viz.damagepath.DamagePathLayer"
name="Import from Distance Speed Tool"
sortID="5">
sortID="6">
</contextualMenu>
</extension>
</plugin>

View file

@ -0,0 +1,173 @@
package com.raytheon.uf.viz.damagepath;
import java.util.Collection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import com.raytheon.uf.common.util.Pair;
import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
/**
* Dialog to add new property key/value pairs for the
* {@code EditGeoJsonPropertiesDlg}.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 23, 2015 #4354 dgilling Initial creation based on dialog from
* lvenable.
*
* </pre>
*
* @author lvenable
* @version 1.0
*/
public class AddKeyValueDlg extends CaveSWTDialog {
private static final String EMPTY_STRING = "";
private static final String EMPTY_KEY_MSG = "Enter a key.";
private static final String USED_KEY_MSG = "Key %s is already in use.";
private Text keyTF;
private Text valueTF;
private Button okBtn;
private Label verificationLbl;
private final Collection<String> reservedKeys;
public AddKeyValueDlg(Shell parentShell, Collection<String> reservedKeys) {
super(parentShell, SWT.DIALOG_TRIM, CAVE.DO_NOT_BLOCK
| CAVE.MODE_INDEPENDENT);
this.reservedKeys = reservedKeys;
}
@Override
protected Layout constructShellLayout() {
GridLayout mainLayout = new GridLayout(1, false);
return mainLayout;
}
@Override
protected Object constructShellLayoutData() {
GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
return gd;
}
@Override
protected void initializeComponents(Shell shell) {
setText("Add GeoJSON Property");
createKeyValueControls();
createBottomButtons();
}
private void createKeyValueControls() {
Composite keyValueComp = new Composite(shell, SWT.NONE);
keyValueComp.setLayout(new GridLayout(2, false));
keyValueComp.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true,
false));
Label keyLbl = new Label(keyValueComp, SWT.NONE);
keyLbl.setText("Key:");
GridData gd = new GridData(130, SWT.DEFAULT);
keyTF = new Text(keyValueComp, SWT.BORDER);
keyTF.setLayoutData(gd);
keyTF.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
String newKey = keyTF.getText().trim();
if (reservedKeys.contains(newKey)) {
verificationLbl.setText(String.format(USED_KEY_MSG, newKey));
okBtn.setEnabled(false);
} else if (newKey.isEmpty()) {
verificationLbl.setText(EMPTY_KEY_MSG);
okBtn.setEnabled(false);
} else {
verificationLbl.setText(EMPTY_STRING);
okBtn.setEnabled(true);
}
getShell().pack();
getShell().layout();
}
});
Label valueLbl = new Label(keyValueComp, SWT.NONE);
valueLbl.setText("Value:");
gd = new GridData(130, SWT.DEFAULT);
valueTF = new Text(keyValueComp, SWT.BORDER);
valueTF.setLayoutData(gd);
verificationLbl = new Label(keyValueComp, SWT.NONE);
verificationLbl.setText(EMPTY_KEY_MSG);
gd = new GridData(SWT.FILL, SWT.DEFAULT, true, true);
gd.horizontalSpan = 2;
verificationLbl.setLayoutData(gd);
}
private void createBottomButtons() {
Composite buttonComp = new Composite(shell, SWT.NONE);
buttonComp.setLayout(new GridLayout(2, false));
buttonComp.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true,
false));
int buttonWidth = 70;
GridData gd = new GridData(SWT.RIGHT, SWT.DEFAULT, true, false);
gd.widthHint = buttonWidth;
okBtn = new Button(buttonComp, SWT.PUSH);
okBtn.setText(" OK ");
okBtn.setLayoutData(gd);
okBtn.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
handleOkAction();
}
});
okBtn.setEnabled(false);
gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false);
gd.widthHint = buttonWidth;
Button cancelBtn = new Button(buttonComp, SWT.PUSH);
cancelBtn.setText(" Cancel ");
cancelBtn.setLayoutData(gd);
cancelBtn.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
setReturnValue(null);
close();
}
});
}
private void handleOkAction() {
Pair<String, String> pair = new Pair<>(keyTF.getText().trim(), valueTF
.getText().trim());
setReturnValue(pair);
close();
}
}

View file

@ -22,14 +22,31 @@ package com.raytheon.uf.viz.damagepath;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
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.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
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.geo.GeoJsonUtil;
import com.raytheon.uf.common.json.geo.GeoJsonUtilSimpleImpl;
import com.raytheon.uf.common.json.JsonException;
import com.raytheon.uf.common.json.geo.BasicJsonService;
import com.raytheon.uf.common.json.geo.GeoJsonMapUtil;
import com.raytheon.uf.common.json.geo.IGeoJsonService;
import com.raytheon.uf.common.json.geo.SimpleGeoJsonService;
import com.raytheon.uf.common.localization.FileUpdatedMessage;
import com.raytheon.uf.common.localization.ILocalizationFileObserver;
import com.raytheon.uf.common.localization.IPathManager;
@ -45,23 +62,25 @@ import com.raytheon.uf.viz.core.rsc.LoadProperties;
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.Polygon;
/**
* A layer for displaying and customizing a weather event's damage path.
*
*
* <pre>
*
*
* SOFTWARE HISTORY
*
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 19, 2015 3974 njensen Initial creation
* Mar 31, 2015 3977 nabowle Reset polygon when initializing from the
* localization file fails.
*
* Apr 23, 2015 4354 dgilling Support GeoJSON Feature properties.
*
* </pre>
*
*
* @author njensen
* @version 1.0
*/
@ -77,6 +96,8 @@ 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.
@ -181,7 +202,7 @@ public class DamagePathLayer<T extends DamagePathResourceData> extends
* TODO create a new InputAdapter that takes highest priority and blocks
* other inputs. left clicking adds vertices, right click indicates the
* last point on the polygon, then connect the first and last point.
*
*
* afterwards, remove and dispose of that input adapter
*/
return null;
@ -226,8 +247,46 @@ public class DamagePathLayer<T extends DamagePathResourceData> extends
protected void loadDamagePath(LocalizationFile file) {
try (InputStream is = file.openInputStream()) {
GeoJsonUtil json = new GeoJsonUtilSimpleImpl();
Polygon geometry = (Polygon) json.deserializeGeom(is);
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.
*
* TODO: remove this code for code that just expects the file to
* always be a Feature.
*/
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)) {
SimpleFeature feature = geoJsonUtil.populateFeature(jsonObject);
deserializedGeom = (Geometry) feature.getDefaultGeometry();
Name defaultGeomAttrib = feature.getDefaultGeometryProperty()
.getName();
deserializedProps = new LinkedHashMap<>();
deserializedProps.put(GeoJsonMapUtil.ID_KEY, feature.getID());
for (Property p : feature.getProperties()) {
if (!defaultGeomAttrib.equals(p.getName())) {
deserializedProps.put(p.getName().toString(), p
.getValue().toString());
}
}
} else if (isGeometryType(geoJsonType)) {
deserializedGeom = geoJsonUtil.populateGeometry(jsonObject);
} else {
String message = "Unexpected GeoJSON object type "
+ geoJsonType
+ ". This tool only supports Feature and Geometry objects.";
throw new JsonException(message);
}
Polygon geometry = (Polygon) deserializedGeom;
/*
* specifically call super.resetPolygon() cause this.resetPolygon()
* will save the file and we don't want to do that or we could
@ -237,6 +296,8 @@ public class DamagePathLayer<T extends DamagePathResourceData> extends
if (current == null || !current.equals(geometry)) {
super.resetPolygon(geometry.getExteriorRing().getCoordinates());
}
featureProperties = deserializedProps;
} catch (Exception e) {
statusHandler.error(
"Error loading damage path file " + file.getName(), e);
@ -247,8 +308,9 @@ public class DamagePathLayer<T extends DamagePathResourceData> extends
LocalizationFileOutputStream fos = null;
try {
fos = file.openOutputStream();
GeoJsonUtil json = new GeoJsonUtilSimpleImpl();
json.serialize(this.getPolygon(), fos);
IGeoJsonService json = new SimpleGeoJsonService();
SimpleFeature feature = buildFeature();
json.serialize(feature, fos);
fos.closeAndSave();
} catch (Throwable t) {
if (fos != null) {
@ -262,4 +324,55 @@ public class DamagePathLayer<T extends DamagePathResourceData> extends
"Error saving damage path file " + file.getName(), t);
}
}
public SimpleFeature buildFeature() {
Map<String, String> jsonProps = getFeatureProperties();
String id = jsonProps.get(GeoJsonMapUtil.ID_KEY);
SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder();
typeBuilder.setName("feature");
Geometry geom = getPolygon();
if (geom != null) {
typeBuilder.setDefaultGeometry("the_geom");
typeBuilder.add("the_geom", geom.getClass());
}
Collection<String> keysToIgnore = Arrays.asList(GeoJsonMapUtil.ID_KEY);
Set<String> keySet = jsonProps.keySet();
List<Object> values = new ArrayList<Object>(keySet.size());
for (String key : keySet) {
if (!keysToIgnore.contains(key)) {
Object val = jsonProps.get(key);
typeBuilder.add(key, val.getClass());
values.add(val);
}
}
SimpleFeatureType type = typeBuilder.buildFeatureType();
SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(type);
if (geom != null) {
featureBuilder.add(geom);
}
featureBuilder.addAll(values);
return featureBuilder.buildFeature(id);
}
public Map<String, String> getFeatureProperties() {
return featureProperties;
}
public void setFeatureProperties(Map<String, String> featureProperties) {
this.featureProperties = featureProperties;
saveJob.schedule();
}
public boolean isGeometryType(String geoJsonType) {
return ((GeoJsonMapUtil.GEOM_COLL_TYPE.equals(geoJsonType))
|| (GeoJsonMapUtil.LINE_STR_TYPE.equals(geoJsonType))
|| (GeoJsonMapUtil.MULT_LINE_STR_TYPE.equals(geoJsonType))
|| (GeoJsonMapUtil.MULT_POINT_TYPE.equals(geoJsonType))
|| (GeoJsonMapUtil.MULT_POLY_TYPE.equals(geoJsonType))
|| (GeoJsonMapUtil.POINT_TYPE.equals(geoJsonType)) || (GeoJsonMapUtil.POLY_TYPE
.equals(geoJsonType)));
}
}

View file

@ -0,0 +1,247 @@
package com.raytheon.uf.viz.damagepath;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import com.raytheon.uf.common.util.Pair;
import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
import com.raytheon.viz.ui.dialogs.ICloseCallback;
/**
* Dialog to add/remove the key/value pairs that are part of the "properties"
* member object in GeoJSON Feature objects.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 23, 2015 #4354 dgilling Initial creation based on dialog from
* lvenable.
*
* </pre>
*
* @author lvenable
* @version 1.0
*/
public class EditGeoJsonPropertiesDlg extends CaveSWTDialog {
private Table table;
private Button deleteBtn;
private Map<String, String> properties;
public EditGeoJsonPropertiesDlg(Shell parentShell,
Map<String, String> properties) {
super(parentShell, SWT.DIALOG_TRIM, CAVE.DO_NOT_BLOCK);
this.properties = new LinkedHashMap<>(properties);
}
@Override
protected Layout constructShellLayout() {
// Create the main layout for the shell.
GridLayout mainLayout = new GridLayout(1, false);
mainLayout.marginHeight = 2;
mainLayout.marginWidth = 2;
return mainLayout;
}
@Override
protected Object constructShellLayoutData() {
GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
return gd;
}
@Override
protected void initializeComponents(Shell shell) {
setText("GeoJSON Properties Editor");
shell.addShellListener(new ShellAdapter() {
@Override
public void shellClosed(ShellEvent e) {
setReturnValue(properties);
}
});
createTableComp();
createAddDeleteButtons();
addSeparator(shell, SWT.HORIZONTAL);
createBottomButtons();
populateTable();
}
private void createTableComp() {
int columnWidth = 150;
GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
gd.heightHint = 250;
gd.widthHint = columnWidth * 2;
table = new Table(shell, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL
| SWT.SINGLE);
table.setLayoutData(gd);
table.setHeaderVisible(true);
table.setLinesVisible(true);
TableColumn column = new TableColumn(table, SWT.NONE);
column.setText("Key");
column = new TableColumn(table, SWT.NONE);
column.setText("Value");
for (int i = 0; i < table.getColumnCount(); i++) {
table.getColumn(i).setWidth(columnWidth);
}
}
private void createAddDeleteButtons() {
Composite buttonComp = new Composite(shell, SWT.NONE);
buttonComp.setLayout(new GridLayout(2, false));
buttonComp.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true,
false));
int buttonWidth = 70;
GridData gd = new GridData(SWT.RIGHT, SWT.DEFAULT, true, false);
gd.widthHint = buttonWidth;
Button addBtn = new Button(buttonComp, SWT.PUSH);
addBtn.setText(" Add ");
addBtn.setLayoutData(gd);
addBtn.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
AddKeyValueDlg akvd = new AddKeyValueDlg(shell, properties
.keySet());
akvd.setCloseCallback(new ICloseCallback() {
@Override
public void dialogClosed(Object returnValue) {
if (returnValue == null) {
return;
}
if (returnValue instanceof Pair) {
Pair<String, String> newProperty = (Pair<String, String>) returnValue;
properties.put(newProperty.getFirst(),
newProperty.getSecond());
populateTable();
}
}
});
akvd.open();
}
});
gd = new GridData(SWT.LEFT, SWT.DEFAULT, true, false);
gd.widthHint = buttonWidth;
deleteBtn = new Button(buttonComp, SWT.PUSH);
deleteBtn.setText(" Delete ");
deleteBtn.setLayoutData(gd);
deleteBtn.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
handleDeleteAction();
}
});
}
private void createBottomButtons() {
Composite buttonComp = new Composite(shell, SWT.NONE);
buttonComp.setLayout(new GridLayout(1, false));
buttonComp.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true,
false));
int buttonWidth = 70;
GridData gd = new GridData(SWT.CENTER, SWT.DEFAULT, true, false);
gd.widthHint = buttonWidth;
Button okBtn = new Button(buttonComp, SWT.PUSH);
okBtn.setText(" Close ");
okBtn.setLayoutData(gd);
okBtn.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
setReturnValue(properties);
close();
}
});
}
public void addSeparator(Composite comp, int orientation) {
GridData gd;
if (orientation == SWT.HORIZONTAL) {
gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
if (comp.getLayout() instanceof GridLayout) {
int columns = ((GridLayout) comp.getLayout()).numColumns;
gd.horizontalSpan = columns;
}
} else {
gd = new GridData(SWT.DEFAULT, SWT.FILL, false, true);
}
Label sepLbl = new Label(comp, SWT.SEPARATOR | orientation);
sepLbl.setLayoutData(gd);
}
private void populateTable() {
table.removeAll();
for (Entry<String, String> entry : properties.entrySet()) {
TableItem ti = new TableItem(table, SWT.NONE);
ti.setText(0, entry.getKey());
ti.setText(1, entry.getValue());
}
if (table.getItemCount() > 0) {
table.select(0);
}
enableDeleteButton();
}
private void handleDeleteAction() {
int index = table.getSelectionIndex();
if (index < 0) {
return;
}
properties.remove(table.getItem(index).getText(0));
populateTable();
if (index < table.getItemCount()) {
table.select(index);
} else if (table.getItemCount() > 0) {
table.select(table.getItemCount() - 1);
}
}
private void enableDeleteButton() {
if ((table.getItemCount() > 0) && (table.getSelectionIndex() >= 0)) {
deleteBtn.setEnabled(true);
} else {
deleteBtn.setEnabled(false);
}
}
}

View file

@ -24,9 +24,10 @@ import java.io.FileOutputStream;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Shell;
import org.opengis.feature.simple.SimpleFeature;
import com.raytheon.uf.common.json.geo.GeoJsonUtil;
import com.raytheon.uf.common.json.geo.GeoJsonUtilSimpleImpl;
import com.raytheon.uf.common.json.geo.IGeoJsonService;
import com.raytheon.uf.common.json.geo.SimpleGeoJsonService;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.viz.core.VizApp;
@ -42,7 +43,8 @@ import com.raytheon.viz.ui.cmenu.AbstractRightClickAction;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Feb 9, 2015 3975 njensen Initial creation
* Feb 09, 2015 3975 njensen Initial creation
* Apr 23, 2015 4354 dgilling Export as GeoJSON Feature object.
*
* </pre>
*
@ -75,8 +77,9 @@ public class ExportDamagePathAction extends AbstractRightClickAction {
if (filename != null) {
DamagePathLayer<?> layer = (DamagePathLayer<?>) getSelectedRsc();
try (FileOutputStream fos = new FileOutputStream(filename)) {
GeoJsonUtil json = new GeoJsonUtilSimpleImpl();
json.serialize(layer.getPolygon(), fos);
IGeoJsonService json = new SimpleGeoJsonService();
SimpleFeature feature = layer.buildFeature();
json.serialize(feature, fos);
} catch (Exception e) {
statusHandler.error(
"Error exporting damage path file to "

View file

@ -20,14 +20,20 @@
package com.raytheon.uf.viz.damagepath;
import java.io.FileInputStream;
import java.util.LinkedHashMap;
import java.util.Map;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Shell;
import org.opengis.feature.Property;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.type.Name;
import com.raytheon.uf.common.json.JsonException;
import com.raytheon.uf.common.json.geo.GeoJsonUtil;
import com.raytheon.uf.common.json.geo.GeoJsonUtilSimpleImpl;
import com.raytheon.uf.common.json.geo.GeoJsonMapUtil;
import com.raytheon.uf.common.json.geo.IGeoJsonService;
import com.raytheon.uf.common.json.geo.SimpleGeoJsonService;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.viz.core.VizApp;
@ -38,18 +44,19 @@ import com.vividsolutions.jts.geom.Polygon;
/**
* Action to import a damage path from a GeoJSON file specified by the user.
*
*
* <pre>
*
*
* SOFTWARE HISTORY
*
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Feb 12, 2015 3975 njensen Initial creation
* Mar 31, 2015 3977 nabowle Make sure the polygon is not empty.
*
* Apr 23, 2015 4354 dgilling Support GeoJSON Feature objects.
*
* </pre>
*
*
* @author njensen
* @version 1.0
*/
@ -77,15 +84,28 @@ public class ImportDamagePathAction extends AbstractRightClickAction {
if (filename != null) {
DamagePathLayer<?> layer = (DamagePathLayer<?>) getSelectedRsc();
try (FileInputStream fis = new FileInputStream(filename)) {
GeoJsonUtil json = new GeoJsonUtilSimpleImpl();
Geometry geom = json.deserializeGeom(fis);
if (geom instanceof Polygon
&& geom.getCoordinates().length > 0) {
IGeoJsonService json = new SimpleGeoJsonService();
SimpleFeature feature = json.deserializeFeature(fis);
Geometry geom = (Geometry) feature.getDefaultGeometry();
if ((geom instanceof Polygon)
&& (geom.getCoordinates().length > 0)) {
layer.setPolygon((Polygon) geom);
} else {
throw new JsonException("Damage path file "
+ filename + " must contain a Polygon!");
}
Name defaultGeomAttrib = feature
.getDefaultGeometryProperty().getName();
Map<String, String> featureProps = new LinkedHashMap<>();
featureProps.put(GeoJsonMapUtil.ID_KEY, feature.getID());
for (Property p : feature.getProperties()) {
if (!defaultGeomAttrib.equals(p.getName())) {
featureProps.put(p.getName().toString(), p
.getValue().toString());
}
}
layer.setFeatureProperties(featureProps);
} catch (Exception e) {
statusHandler.error("Error importing damage path from "
+ filename, e);
@ -94,5 +114,4 @@ public class ImportDamagePathAction extends AbstractRightClickAction {
}
});
}
}

View file

@ -0,0 +1,82 @@
/**
* 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.Map;
import org.eclipse.swt.widgets.Shell;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.viz.ui.VizWorkbenchManager;
import com.raytheon.viz.ui.cmenu.AbstractRightClickAction;
import com.raytheon.viz.ui.dialogs.ICloseCallback;
/**
* {@code Action} class to launch the {@code EditGeoJsonPropertiesDlg}.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 23, 2015 #4354 dgilling Initial creation
*
* </pre>
*
* @author dgilling
* @version 1.0
*/
public class OpenGeoJsonPropertiesDlgAction extends AbstractRightClickAction {
public OpenGeoJsonPropertiesDlgAction() {
super("Set GeoJSON Properties...");
}
@Override
public void run() {
VizApp.runSync(new Runnable() {
@Override
public void run() {
Shell shell = VizWorkbenchManager.getInstance()
.getCurrentWindow().getShell();
final DamagePathLayer<?> layer = (DamagePathLayer<?>) getSelectedRsc();
final Map<String, String> geoJsonProps = layer
.getFeatureProperties();
EditGeoJsonPropertiesDlg dlg = new EditGeoJsonPropertiesDlg(
shell, geoJsonProps);
dlg.setCloseCallback(new ICloseCallback() {
@Override
public void dialogClosed(Object returnValue) {
if ((returnValue != null)
&& (!geoJsonProps.equals(returnValue))) {
Map<String, String> updatedProperties = (Map<String, String>) returnValue;
layer.setFeatureProperties(updatedProperties);
}
}
});
dlg.open();
}
});
}
}

View file

@ -185,7 +185,7 @@
id="com.raytheon.uf.viz.aviation.advisory.feature"
version="0.0.0"/>
<includes
<includes
id="com.raytheon.uf.viz.datadelivery.feature"
version="0.0.0"/>
@ -197,6 +197,10 @@
id="com.raytheon.uf.viz.d2d.damagepath.feature"
version="0.0.0"/>
<includes
id="gov.noaa.gsd.viz.hazards.feature"
version="0.0.0"/>
<requires>
<import feature="com.raytheon.uf.viz.application.feature" version="1.0.0.qualifier"/>
</requires>

View file

@ -29,8 +29,8 @@ import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import com.raytheon.uf.common.http.MimeType;
import com.raytheon.uf.common.json.geo.GeoJsonUtil;
import com.raytheon.uf.common.json.geo.GeoJsonUtilSimpleImpl;
import com.raytheon.uf.common.json.geo.IGeoJsonService;
import com.raytheon.uf.common.json.geo.SimpleGeoJsonService;
import com.raytheon.uf.common.json.geo.MixedFeatureCollection;
import com.raytheon.uf.edex.ogc.common.OgcResponse;
import com.raytheon.uf.edex.ogc.common.OgcResponse.TYPE;
@ -56,7 +56,7 @@ public class JsonFeatureFormatter implements SimpleFeatureFormatter {
public static MimeType mimeType = new MimeType("application/json");
protected GeoJsonUtil jsonUtil = new GeoJsonUtilSimpleImpl();
protected IGeoJsonService jsonUtil = new SimpleGeoJsonService();
/*
* (non-Javadoc)