From e858388f245dbb2d64e35efc9d5a7546825c0cc3 Mon Sep 17 00:00:00 2001 From: James Rummel Date: Tue, 9 Jan 2018 15:25:24 -0500 Subject: [PATCH 1/3] Switching path to nasa emp3 ellipse. --- .../feature/EMPtoWWFeatureConverter.java | 204 ++++++++++++++++++ .../feature/FeatureRenderableMapping.java | 11 +- .../worldwind/feature/RenderedFeature.java | 20 +- .../mil/emp3/core/utils/MilStdRenderer.java | 18 +- 4 files changed, 247 insertions(+), 6 deletions(-) diff --git a/mapengine/worldwind/apk/src/main/java/mil/emp3/worldwind/feature/EMPtoWWFeatureConverter.java b/mapengine/worldwind/apk/src/main/java/mil/emp3/worldwind/feature/EMPtoWWFeatureConverter.java index 317ea04f..7ef1448f 100644 --- a/mapengine/worldwind/apk/src/main/java/mil/emp3/worldwind/feature/EMPtoWWFeatureConverter.java +++ b/mapengine/worldwind/apk/src/main/java/mil/emp3/worldwind/feature/EMPtoWWFeatureConverter.java @@ -27,6 +27,8 @@ import gov.nasa.worldwind.shape.Placemark; import gov.nasa.worldwind.shape.PlacemarkAttributes; import gov.nasa.worldwind.shape.SurfaceImage; +import mil.emp3.api.Circle; +import mil.emp3.api.Ellipse; import mil.emp3.api.Path; import mil.emp3.api.Polygon; import mil.emp3.api.Text; @@ -304,6 +306,50 @@ public gov.nasa.worldwind.shape.Label createWWLabel(Text feature, boolean isSele return wwLabel; } + + public gov.nasa.worldwind.shape.Ellipse createWWCircle(final Circle circle, final boolean isSelected) { + IGeoStrokeStyle selectedStrokeStyle = null; + gov.nasa.worldwind.shape.ShapeAttributes shapeAttribute = new gov.nasa.worldwind.shape.ShapeAttributes(); + if(isSelected) { + selectedStrokeStyle = getMapInstance().getEmpResources().getSelectedStrokeStyle(getMapInstance()); + } + // TODO - Code Review: Are we supporting altitude, please advise. + final Position center = new Position(circle.getFeatureBoundingBox().centerLatitude(), + circle.getFeatureBoundingBox().centerLongitude(), + 0.0); + + final gov.nasa.worldwind.shape.Ellipse wwEllipse = new gov.nasa.worldwind.shape.Ellipse(center, + circle.getRadius(), + circle.getRadius(), + shapeAttribute); + setWWCircleAttributes(circle, wwEllipse, selectedStrokeStyle); + + wwEllipse.setPickDelegate(circle); + wwEllipse.setPathType(WorldWind.RHUMB_LINE); + return wwEllipse; + } + + public gov.nasa.worldwind.shape.Ellipse createWWEllipse(final Ellipse ellipse, final boolean isSelected) { + IGeoStrokeStyle selectedStrokeStyle = null; + gov.nasa.worldwind.shape.ShapeAttributes shapeAttribute = new gov.nasa.worldwind.shape.ShapeAttributes(); + if(isSelected) { + selectedStrokeStyle = getMapInstance().getEmpResources().getSelectedStrokeStyle(getMapInstance()); + } + // TODO - Code Review: Are we supporting altitude, please advise. + final Position center = new Position(ellipse.getFeatureBoundingBox().centerLatitude(), + ellipse.getFeatureBoundingBox().centerLongitude(), + 0.0); + final gov.nasa.worldwind.shape.Ellipse wwEllipse = new gov.nasa.worldwind.shape.Ellipse(center, + ellipse.getSemiMajor(), + ellipse.getSemiMinor(), + shapeAttribute); + setWWEllipseAttributes(ellipse, wwEllipse, selectedStrokeStyle); + + wwEllipse.setPickDelegate(ellipse); + wwEllipse.setPathType(WorldWind.RHUMB_LINE); + return wwEllipse; + } + /** * This method must be override by the subclass to create a buffer renderable for the feature. * @param buffer The buffer distance in meters. @@ -524,6 +570,164 @@ private void setWWPolygonAttributes(mil.emp3.api.Polygon feature, gov.nasa.world break; } } + // TODO - These set attributes methods are too similar. Collapse and condense into helper methods. + private void setWWEllipseAttributes(mil.emp3.api.Ellipse feature, gov.nasa.worldwind.shape.Ellipse wwEllipse, IGeoStrokeStyle strokeStyle) { + gov.nasa.worldwind.shape.ShapeAttributes shapeAttribute = wwEllipse.getAttributes(); + + if (shapeAttribute == null) { + shapeAttribute = new gov.nasa.worldwind.shape.ShapeAttributes(); + } + + if (feature.getExtrude()) { + shapeAttribute.setDrawVerticals(true); + } else { + shapeAttribute.setDrawVerticals(false); + } + + if ((strokeStyle == null) && (feature.getStrokeStyle() != null)) { + strokeStyle = feature.getStrokeStyle(); + } + + if (strokeStyle != null) { + shapeAttribute.setDrawOutline(true); + shapeAttribute.setOutlineColor(Conversion.convertColor(strokeStyle.getStrokeColor())); + shapeAttribute.setOutlineWidth((float) strokeStyle.getStrokeWidth()); + + if (strokeStyle.getStipplingPattern() != 0) { + ImageSource imageSource = ImageSource.fromLineStipple((int) ((double) strokeStyle.getStipplingFactor() * STIPPLE_FACTOR_DISPLAY_DENSITY_MODIFIER), + strokeStyle.getStipplingPattern()); + shapeAttribute.setOutlineImageSource(imageSource); + } + } else { + shapeAttribute.setDrawOutline(false); + } + + + if (feature.getFillStyle() != null) { + IGeoFillStyle fillStyle = feature.getFillStyle(); + + shapeAttribute.setDrawInterior(true); + + switch (fillStyle.getFillPattern()) { + case crossHatched: + shapeAttribute.setInteriorImageSource(mapInstance.getCrossHatchImage()); + break; + case hatched: + shapeAttribute.setInteriorImageSource(mapInstance.getHatchImage()); + break; + case solid: + // nothing additional to fill + break; + default: + } + shapeAttribute.setInteriorColor(Conversion.convertColor(fillStyle.getFillColor())); + } else { + shapeAttribute.setDrawInterior(false); + } + + Conversion.convertAndSetIGeoAltitudeMode(wwEllipse, feature.getAltitudeMode()); + + if (feature.getAltitudeMode() == IGeoAltitudeMode.AltitudeMode.ABSOLUTE){ + wwEllipse.setFollowTerrain(false); + } else { + wwEllipse.setFollowTerrain(true); + } + wwEllipse.setPickDelegate(feature); + wwEllipse.setAttributes(shapeAttribute); + wwEllipse.setHighlighted(false); + + + switch (feature.getPathType()) { + case GREAT_CIRCLE: + wwEllipse.setPathType(WorldWind.GREAT_CIRCLE); + break; + case LINEAR: + wwEllipse.setPathType(WorldWind.LINEAR); + break; + case RHUMB_LINE: + wwEllipse.setPathType(WorldWind.RHUMB_LINE); + break; + } + } + + private void setWWCircleAttributes(mil.emp3.api.Circle feature, gov.nasa.worldwind.shape.Ellipse wwEllipse, IGeoStrokeStyle strokeStyle) { + gov.nasa.worldwind.shape.ShapeAttributes shapeAttribute = wwEllipse.getAttributes(); + + if (shapeAttribute == null) { + shapeAttribute = new gov.nasa.worldwind.shape.ShapeAttributes(); + } + + if (feature.getExtrude()) { + shapeAttribute.setDrawVerticals(true); + } else { + shapeAttribute.setDrawVerticals(false); + } + + if ((strokeStyle == null) && (feature.getStrokeStyle() != null)) { + strokeStyle = feature.getStrokeStyle(); + } + + if (strokeStyle != null) { + shapeAttribute.setDrawOutline(true); + shapeAttribute.setOutlineColor(Conversion.convertColor(strokeStyle.getStrokeColor())); + shapeAttribute.setOutlineWidth((float) strokeStyle.getStrokeWidth()); + + if (strokeStyle.getStipplingPattern() != 0) { + ImageSource imageSource = ImageSource.fromLineStipple((int) ((double) strokeStyle.getStipplingFactor() * STIPPLE_FACTOR_DISPLAY_DENSITY_MODIFIER), + strokeStyle.getStipplingPattern()); + shapeAttribute.setOutlineImageSource(imageSource); + } + } else { + shapeAttribute.setDrawOutline(false); + } + + + if (feature.getFillStyle() != null) { + IGeoFillStyle fillStyle = feature.getFillStyle(); + + shapeAttribute.setDrawInterior(true); + + switch (fillStyle.getFillPattern()) { + case crossHatched: + shapeAttribute.setInteriorImageSource(mapInstance.getCrossHatchImage()); + break; + case hatched: + shapeAttribute.setInteriorImageSource(mapInstance.getHatchImage()); + break; + case solid: + // nothing additional to fill + break; + default: + } + shapeAttribute.setInteriorColor(Conversion.convertColor(fillStyle.getFillColor())); + } else { + shapeAttribute.setDrawInterior(false); + } + + Conversion.convertAndSetIGeoAltitudeMode(wwEllipse, feature.getAltitudeMode()); + + if (feature.getAltitudeMode() == IGeoAltitudeMode.AltitudeMode.ABSOLUTE){ + wwEllipse.setFollowTerrain(false); + } else { + wwEllipse.setFollowTerrain(true); + } + wwEllipse.setPickDelegate(feature); + wwEllipse.setAttributes(shapeAttribute); + wwEllipse.setHighlighted(false); + + + switch (feature.getPathType()) { + case GREAT_CIRCLE: + wwEllipse.setPathType(WorldWind.GREAT_CIRCLE); + break; + case LINEAR: + wwEllipse.setPathType(WorldWind.LINEAR); + break; + case RHUMB_LINE: + wwEllipse.setPathType(WorldWind.RHUMB_LINE); + break; + } + } /** * Takes path type value of {@link gov.nasa.worldwind.shape.Path} and converts it diff --git a/mapengine/worldwind/apk/src/main/java/mil/emp3/worldwind/feature/FeatureRenderableMapping.java b/mapengine/worldwind/apk/src/main/java/mil/emp3/worldwind/feature/FeatureRenderableMapping.java index 32064af1..78cb0aad 100644 --- a/mapengine/worldwind/apk/src/main/java/mil/emp3/worldwind/feature/FeatureRenderableMapping.java +++ b/mapengine/worldwind/apk/src/main/java/mil/emp3/worldwind/feature/FeatureRenderableMapping.java @@ -5,6 +5,8 @@ import gov.nasa.worldwind.render.RenderContext; import gov.nasa.worldwind.render.Renderable; +import mil.emp3.api.Circle; +import mil.emp3.api.Ellipse; import mil.emp3.api.Path; import mil.emp3.api.Polygon; import mil.emp3.api.Text; @@ -172,7 +174,14 @@ protected void generateRenderables() { if (this.getFeature() instanceof mil.emp3.api.Point) { // Create a WW placemark. tempRenderable = this.createPlacemark((mil.emp3.api.Point) this.getFeature(), isSelected()); - } else if (this.getFeature() instanceof Path) { + } + else if (this.getFeature() instanceof Circle) { + tempRenderable = this.createWWCircle((Circle) this.getFeature(), isSelected()); + } + else if (this.getFeature() instanceof Ellipse) { + tempRenderable = this.createWWEllipse((Ellipse) this.getFeature(), isSelected()); + } + else if (this.getFeature() instanceof Path) { // Create a WW path object. tempRenderable = this.createWWPath((Path) this.getFeature(), isSelected()); } else if (this.getFeature() instanceof Polygon) { diff --git a/mapengine/worldwind/apk/src/main/java/mil/emp3/worldwind/feature/RenderedFeature.java b/mapengine/worldwind/apk/src/main/java/mil/emp3/worldwind/feature/RenderedFeature.java index 6a680f3e..5ef37197 100644 --- a/mapengine/worldwind/apk/src/main/java/mil/emp3/worldwind/feature/RenderedFeature.java +++ b/mapengine/worldwind/apk/src/main/java/mil/emp3/worldwind/feature/RenderedFeature.java @@ -9,6 +9,8 @@ import gov.nasa.worldwind.render.RenderContext; import gov.nasa.worldwind.render.Renderable; +import mil.emp3.api.Circle; +import mil.emp3.api.Ellipse; import mil.emp3.api.Path; import mil.emp3.api.Polygon; import mil.emp3.api.Text; @@ -121,7 +123,23 @@ private void renderFeature(IGeoBounds bounds) { tempRenderable.setPickDelegate(this.getFeature()); this.pathRenderableList.add(tempRenderable); } - } else if (feature instanceof Polygon) { + } + else if (feature instanceof Circle) { + tempRenderable = this.createWWCircle((Circle) feature, false); + if (tempRenderable != null) { + + tempRenderable.setPickDelegate(this.getFeature()); + this.addRenderable(tempRenderable); + } + } + else if (feature instanceof Ellipse) { + tempRenderable = this.createWWEllipse((Ellipse) feature, false); + if (tempRenderable != null) { + tempRenderable.setPickDelegate(this.getFeature()); + this.addRenderable(tempRenderable); + } + } + else if (feature instanceof Polygon) { // Create a WW polygon object. tempRenderable = this.createWWPolygon((Polygon) feature, false); diff --git a/sdk/sdk-core/aar/src/main/java/mil/emp3/core/utils/MilStdRenderer.java b/sdk/sdk-core/aar/src/main/java/mil/emp3/core/utils/MilStdRenderer.java index fa12d2fd..6b7015bd 100644 --- a/sdk/sdk-core/aar/src/main/java/mil/emp3/core/utils/MilStdRenderer.java +++ b/sdk/sdk-core/aar/src/main/java/mil/emp3/core/utils/MilStdRenderer.java @@ -24,6 +24,8 @@ import armyc2.c2sd.renderer.utilities.ModifiersTG; import armyc2.c2sd.renderer.utilities.RendererSettings; import armyc2.c2sd.renderer.utilities.ShapeInfo; +import mil.emp3.api.Circle; +import mil.emp3.api.Ellipse; import mil.emp3.api.MilStdSymbol; import mil.emp3.api.Path; import mil.emp3.api.Polygon; @@ -779,10 +781,18 @@ private void renderBasicShapeParser(List featureList, List> listOfPosList = this.convertListOfPointListsToListOfPositionLists(shapeInfo.getPolylines()); for (List posList : listOfPosList) { - IFeature feature = new Path(posList); - feature.setStrokeStyle(currentStrokeStyle); - feature.setAltitudeMode(renderFeature.getAltitudeMode()); - featureList.add(feature); + if(renderFeature instanceof Circle) { + featureList.add(renderFeature); + } + else if (renderFeature instanceof Ellipse) { + featureList.add(renderFeature); + } + else { + IFeature feature = new Path(posList); + feature.setStrokeStyle(currentStrokeStyle); + feature.setAltitudeMode(renderFeature.getAltitudeMode()); + featureList.add(feature); + } } break; } From c2012464effdedb235a5570e80fd2bddd9a26994 Mon Sep 17 00:00:00 2001 From: James Rummel Date: Wed, 10 Jan 2018 17:24:17 -0500 Subject: [PATCH 2/3] Attempting to smooth out circles. --- .../emp3/worldwind/feature/EMPtoWWFeatureConverter.java | 8 ++++++-- .../java/mil/emp3/worldwind/feature/RenderedFeature.java | 1 - .../src/main/java/mil/emp3/core/utils/MilStdRenderer.java | 1 - 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/mapengine/worldwind/apk/src/main/java/mil/emp3/worldwind/feature/EMPtoWWFeatureConverter.java b/mapengine/worldwind/apk/src/main/java/mil/emp3/worldwind/feature/EMPtoWWFeatureConverter.java index 7ef1448f..71de106a 100644 --- a/mapengine/worldwind/apk/src/main/java/mil/emp3/worldwind/feature/EMPtoWWFeatureConverter.java +++ b/mapengine/worldwind/apk/src/main/java/mil/emp3/worldwind/feature/EMPtoWWFeatureConverter.java @@ -325,7 +325,9 @@ public gov.nasa.worldwind.shape.Ellipse createWWCircle(final Circle circle, fina setWWCircleAttributes(circle, wwEllipse, selectedStrokeStyle); wwEllipse.setPickDelegate(circle); - wwEllipse.setPathType(WorldWind.RHUMB_LINE); + wwEllipse.setPathType(WorldWind.LINEAR); + wwEllipse.setFollowTerrain(false); + wwEllipse.setAltitudeMode(WorldWind.CLAMP_TO_GROUND); return wwEllipse; } @@ -346,7 +348,9 @@ public gov.nasa.worldwind.shape.Ellipse createWWEllipse(final Ellipse ellipse, f setWWEllipseAttributes(ellipse, wwEllipse, selectedStrokeStyle); wwEllipse.setPickDelegate(ellipse); - wwEllipse.setPathType(WorldWind.RHUMB_LINE); + wwEllipse.setPathType(WorldWind.LINEAR); + wwEllipse.setFollowTerrain(false); + wwEllipse.setAltitudeMode(WorldWind.CLAMP_TO_GROUND); return wwEllipse; } diff --git a/mapengine/worldwind/apk/src/main/java/mil/emp3/worldwind/feature/RenderedFeature.java b/mapengine/worldwind/apk/src/main/java/mil/emp3/worldwind/feature/RenderedFeature.java index 5ef37197..9ad6e3b7 100644 --- a/mapengine/worldwind/apk/src/main/java/mil/emp3/worldwind/feature/RenderedFeature.java +++ b/mapengine/worldwind/apk/src/main/java/mil/emp3/worldwind/feature/RenderedFeature.java @@ -127,7 +127,6 @@ private void renderFeature(IGeoBounds bounds) { else if (feature instanceof Circle) { tempRenderable = this.createWWCircle((Circle) feature, false); if (tempRenderable != null) { - tempRenderable.setPickDelegate(this.getFeature()); this.addRenderable(tempRenderable); } diff --git a/sdk/sdk-core/aar/src/main/java/mil/emp3/core/utils/MilStdRenderer.java b/sdk/sdk-core/aar/src/main/java/mil/emp3/core/utils/MilStdRenderer.java index 6b7015bd..ec1bdf1e 100644 --- a/sdk/sdk-core/aar/src/main/java/mil/emp3/core/utils/MilStdRenderer.java +++ b/sdk/sdk-core/aar/src/main/java/mil/emp3/core/utils/MilStdRenderer.java @@ -627,7 +627,6 @@ public List getFeatureRenderableShapes(IMapInstance mapInstance, IFeat String altitudeModeStr = MilStdUtilities.geoAltitudeModeToString(feature.getAltitudeMode()); SparseArray modifiers = new SparseArray<>(); SparseArray attributes; - if (feature instanceof mil.emp3.api.Circle) { mil.emp3.api.Circle circleFeature = (mil.emp3.api.Circle) feature; symbolCode = "PBS_CIRCLE-----"; From 1b2c4fd7ad155c71131b1fe084fdcbc7c910ad73 Mon Sep 17 00:00:00 2001 From: James Rummel Date: Thu, 11 Jan 2018 15:26:29 -0500 Subject: [PATCH 3/3] Suggested interval. --- .../worldwind/feature/EMPtoWWFeatureConverter.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/mapengine/worldwind/apk/src/main/java/mil/emp3/worldwind/feature/EMPtoWWFeatureConverter.java b/mapengine/worldwind/apk/src/main/java/mil/emp3/worldwind/feature/EMPtoWWFeatureConverter.java index 71de106a..0c71da79 100644 --- a/mapengine/worldwind/apk/src/main/java/mil/emp3/worldwind/feature/EMPtoWWFeatureConverter.java +++ b/mapengine/worldwind/apk/src/main/java/mil/emp3/worldwind/feature/EMPtoWWFeatureConverter.java @@ -57,6 +57,8 @@ public class EMPtoWWFeatureConverter { // to apply an additional factor to account for the display density. private static final double STIPPLE_FACTOR_DISPLAY_DENSITY_MODIFIER = DISPLAY_PIXEL_DENSITY / 96.0; + private static final int ELLIPSE_MAXIMUM_INTERVAL = 256; + private final MapInstance mapInstance; public EMPtoWWFeatureConverter(MapInstance instance) { @@ -325,9 +327,9 @@ public gov.nasa.worldwind.shape.Ellipse createWWCircle(final Circle circle, fina setWWCircleAttributes(circle, wwEllipse, selectedStrokeStyle); wwEllipse.setPickDelegate(circle); - wwEllipse.setPathType(WorldWind.LINEAR); - wwEllipse.setFollowTerrain(false); + wwEllipse.setFollowTerrain(true); wwEllipse.setAltitudeMode(WorldWind.CLAMP_TO_GROUND); + wwEllipse.setMaximumIntervals(ELLIPSE_MAXIMUM_INTERVAL); return wwEllipse; } @@ -348,9 +350,10 @@ public gov.nasa.worldwind.shape.Ellipse createWWEllipse(final Ellipse ellipse, f setWWEllipseAttributes(ellipse, wwEllipse, selectedStrokeStyle); wwEllipse.setPickDelegate(ellipse); - wwEllipse.setPathType(WorldWind.LINEAR); - wwEllipse.setFollowTerrain(false); + wwEllipse.setFollowTerrain(true); wwEllipse.setAltitudeMode(WorldWind.CLAMP_TO_GROUND); + wwEllipse.setMaximumIntervals(ELLIPSE_MAXIMUM_INTERVAL); + return wwEllipse; } @@ -639,6 +642,7 @@ private void setWWEllipseAttributes(mil.emp3.api.Ellipse feature, gov.nasa.world wwEllipse.setPickDelegate(feature); wwEllipse.setAttributes(shapeAttribute); wwEllipse.setHighlighted(false); + wwEllipse.setMaximumIntervals(256); switch (feature.getPathType()) { @@ -718,6 +722,7 @@ private void setWWCircleAttributes(mil.emp3.api.Circle feature, gov.nasa.worldwi wwEllipse.setPickDelegate(feature); wwEllipse.setAttributes(shapeAttribute); wwEllipse.setHighlighted(false); + wwEllipse.setMaximumIntervals(256); switch (feature.getPathType()) {