Skip to content

Commit 57b265b

Browse files
authored
Merge pull request #81 from WorldWindEarth/Add-Block-and-Penetrate-symbol
Fix computation of arrow angles for "Penetrate". Move "Block" drawin…
2 parents 3388e26 + 4afe979 commit 57b265b

File tree

3 files changed

+332
-1
lines changed

3 files changed

+332
-1
lines changed

src/gov/nasa/worldwind/symbology/milstd2525/MilStd2525GraphicFactory.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ protected void populateClassMap()
101101
this.mapClass(DirectionOfAttackForFeint.class, DirectionOfAttackForFeint.getSupportedGraphics());
102102
this.mapClass(HoldingLine.class, HoldingLine.getSupportedGraphics());
103103
this.mapClass(LimitedAccessArea.class, LimitedAccessArea.getSupportedGraphics());
104+
this.mapClass(TasksBLetterShape.class, TasksBLetterShape.getSupportedGraphics());
104105

105106
// Mobility/survivability
106107

Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
/*
2+
* Copyright 2006-2009, 2017, 2020 United States Government, as represented by the
3+
* Administrator of the National Aeronautics and Space Administration.
4+
* All rights reserved.
5+
*
6+
* The NASA World Wind Java (WWJ) platform is licensed under the Apache License,
7+
* Version 2.0 (the "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software distributed
12+
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
13+
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
14+
* specific language governing permissions and limitations under the License.
15+
*
16+
* NASA World Wind Java (WWJ) also contains the following 3rd party Open Source
17+
* software:
18+
*
19+
* Jackson Parser – Licensed under Apache 2.0
20+
* GDAL – Licensed under MIT
21+
* JOGL – Licensed under Berkeley Software Distribution (BSD)
22+
* Gluegen – Licensed under Berkeley Software Distribution (BSD)
23+
*
24+
* A complete listing of 3rd Party software notices and licenses included in
25+
* NASA World Wind Java (WWJ) can be found in the WorldWindJava-v2.2 3rd-party
26+
* notices and licenses PDF found in code directory.
27+
*/
28+
29+
package gov.nasa.worldwind.symbology.milstd2525.graphics.areas;
30+
31+
import gov.nasa.worldwind.WorldWind;
32+
import gov.nasa.worldwind.avlist.AVKey;
33+
import gov.nasa.worldwind.geom.*;
34+
import gov.nasa.worldwind.render.*;
35+
import gov.nasa.worldwind.symbology.TacticalGraphicLabel;
36+
import gov.nasa.worldwind.symbology.milstd2525.AbstractMilStd2525TacticalGraphic;
37+
import gov.nasa.worldwind.symbology.milstd2525.graphics.TacGrpSidc;
38+
import gov.nasa.worldwind.util.Logging;
39+
40+
import java.util.*;
41+
42+
/**
43+
* Implementation of block graphics. This class implements the following graphics:
44+
* <p>
45+
* <ul> <li>Block (2.X.1.1)</li> <li>Penetrate (2.X.1.17)</li> </ul>
46+
*
47+
* @author maciejziolkowski
48+
* @version $Id: TaskBLetterShape.java 1 2017-10-04 17:45:02Z maciejziolkowski $
49+
*/
50+
public class TasksBLetterShape extends AbstractMilStd2525TacticalGraphic
51+
{
52+
53+
public TasksBLetterShape(String sidc)
54+
{
55+
super(sidc);
56+
}
57+
58+
/**
59+
* Indicates the graphics supported by this class.
60+
*
61+
* @return SIDC string that identify graphics that this class supports.
62+
*/
63+
public static List<String> getSupportedGraphics()
64+
{
65+
return Arrays.asList(TacGrpSidc.TSK_BLK,
66+
TacGrpSidc.TSK_PNE);
67+
}
68+
69+
/**
70+
* Create the label on the graphic.
71+
*/
72+
@Override
73+
protected void createLabels()
74+
{
75+
String code = this.maskedSymbolCode;
76+
if (TacGrpSidc.TSK_PNE.equals(code))
77+
{
78+
addLabel("P");
79+
}
80+
else
81+
{
82+
addLabel("B");
83+
}
84+
}
85+
86+
/**
87+
* Determine the appropriate position for the graphic's labels.
88+
*
89+
* @param dc Current draw context.
90+
*/
91+
@Override
92+
protected void determineLabelPositions(DrawContext dc)
93+
{
94+
Iterator<? extends Position> iterator = this.paths.get(1).getPositions().iterator();
95+
96+
// Find the first and last positions on the path
97+
Position first = iterator.next();
98+
Position second = first;
99+
while (iterator.hasNext())
100+
{
101+
second = iterator.next();
102+
}
103+
104+
TacticalGraphicLabel startLabel = this.labels.get(0);
105+
106+
// Position the labels at the ends of the path
107+
LatLon ll = LatLon.interpolate(0.5, first, second);
108+
startLabel.setPosition(new Position(ll, 0));
109+
startLabel.setOrientationPosition(second);
110+
startLabel.setTextAlign(AVKey.LEFT);
111+
}
112+
113+
/**
114+
* Center point beatween point1 and point2
115+
*/
116+
private LatLon center;
117+
/**
118+
* Distance between Arrow position and point1
119+
*/
120+
private Angle length;
121+
private double lengthDouble;
122+
/**
123+
* Distance between center and point3
124+
*/
125+
private Angle distance;
126+
private double distanceDouble;
127+
/**
128+
* Angle
129+
*/
130+
private Angle ang;
131+
private Angle ang0;
132+
private double angDouble;
133+
134+
/**
135+
* First control point.
136+
*/
137+
protected Position point1;
138+
/**
139+
* Second control point.
140+
*/
141+
protected Position point2;
142+
/**
143+
* Third control point.
144+
*/
145+
protected Position point3;
146+
147+
/**
148+
* Path used to render the line.
149+
*/
150+
protected ArrayList<Path> paths;
151+
152+
/**
153+
* {@inheritDoc}
154+
*
155+
* @param positions Control points that orient the graphic. Must provide at least three points.
156+
*/
157+
public void setPositions(Iterable<? extends Position> positions)
158+
{
159+
if (positions == null)
160+
{
161+
String message = Logging.getMessage("nullValue.PositionsListIsNull");
162+
Logging.logger().severe(message);
163+
throw new IllegalArgumentException(message);
164+
}
165+
166+
try
167+
{
168+
Iterator<? extends Position> iterator = positions.iterator();
169+
this.point1 = iterator.next();
170+
this.point2 = iterator.next();
171+
this.point3 = iterator.next();
172+
}
173+
catch (NoSuchElementException e)
174+
{
175+
String message = Logging.getMessage("generic.InsufficientPositions");
176+
Logging.logger().severe(message);
177+
throw new IllegalArgumentException(message);
178+
}
179+
180+
this.paths = null; // Need to recompute path for the new control points
181+
}
182+
183+
/**
184+
* {@inheritDoc}
185+
*/
186+
public Iterable<? extends Position> getPositions()
187+
{
188+
return Arrays.asList(this.point1, this.point2, this.point3);
189+
}
190+
191+
/**
192+
* {@inheritDoc}
193+
*/
194+
public Position getReferencePosition()
195+
{
196+
return this.point1;
197+
}
198+
199+
/**
200+
* {@inheritDoc}
201+
*/
202+
protected void doRenderGraphic(DrawContext dc)
203+
{
204+
for (Path path : this.paths)
205+
{
206+
path.render(dc);
207+
}
208+
}
209+
210+
/**
211+
* Compute positions and create the paths required to draw graphic.
212+
*
213+
* @param dc Current draw context.
214+
*/
215+
@Override
216+
protected void computeGeometry(DrawContext dc)
217+
{
218+
if (this.paths == null)
219+
{
220+
this.paths = new ArrayList<Path>();
221+
222+
// Create paths for the block
223+
String code = this.maskedSymbolCode;
224+
center = LatLon.getCenter(Arrays.asList(point1, point2));
225+
226+
// Position of the center point
227+
Position centerPosition = new Position(center, 0);
228+
229+
if (TacGrpSidc.TSK_BLK.equals(code))
230+
{
231+
// Create the paths from point1 to point2
232+
this.paths.add(createPath(Arrays.asList(this.point1, this.point2)));
233+
// Create the paths from centerPosition to point3
234+
this.paths.add(createPath(Arrays.asList(centerPosition, this.point3)));
235+
}
236+
else
237+
{
238+
// Size the arrow
239+
LatLon lengthArrow = LatLon.interpolate(0.125, center, point1);
240+
// Position the arrow
241+
Position lengthArrowPosition = new Position(lengthArrow, 0);
242+
length = LatLon.greatCircleDistance(lengthArrowPosition, this.point1);
243+
lengthDouble = length.getRadians();
244+
distance = LatLon.greatCircleDistance(center, this.point3);
245+
distanceDouble = distance.getRadians();
246+
247+
// This is the condition which changing in length arrow proportional to the graphic
248+
if (lengthDouble * 1.3 > distanceDouble)
249+
{
250+
length = length.divide(4);
251+
}
252+
253+
// Angle up and down line of the arrow
254+
// Angle between point3 and center
255+
ang = LatLon.greatCircleAzimuth(center, point3);
256+
Angle arrowTop = ang.add(Angle.fromDegrees(35));
257+
Angle arrowBot = ang.add(Angle.fromDegrees(-35));
258+
// position up and down line of arrow
259+
Position positionLineUpOfArrow = new Position(
260+
LatLon.greatCircleEndPosition(centerPosition, arrowTop, length), 0);
261+
Position positionLineDownOfArrow = new Position(
262+
LatLon.greatCircleEndPosition(centerPosition, arrowBot, length), 0);
263+
// Create the paths from point1 to point2
264+
this.paths.add(createPath(Arrays.asList(this.point1, this.point2)));
265+
// Create the paths from centerPosition to point3
266+
this.paths.add(createPath(Arrays.asList(centerPosition, this.point3)));
267+
// Create the arrow
268+
this.paths.add(
269+
createPath(Arrays.asList(positionLineDownOfArrow, centerPosition, positionLineUpOfArrow)));
270+
}
271+
}
272+
super.computeGeometry(dc);
273+
}
274+
275+
/**
276+
* {@inheritDoc}
277+
*/
278+
protected void applyDelegateOwner(Object owner)
279+
{
280+
if (this.paths == null)
281+
{
282+
return;
283+
}
284+
285+
for (Path path : this.paths)
286+
{
287+
path.setDelegateOwner(owner);
288+
}
289+
}
290+
291+
/**
292+
* Create and configure the Path used to render this graphic.
293+
*
294+
* @param positions Positions that define the path.
295+
*
296+
* @return New path configured with defaults appropriate for this type of graphic.
297+
*/
298+
protected Path createPath(List<Position> positions)
299+
{
300+
Path path = new Path(positions);
301+
path.setFollowTerrain(true);
302+
path.setPathType(AVKey.GREAT_CIRCLE);
303+
path.setAltitudeMode(WorldWind.CLAMP_TO_GROUND);
304+
path.setDelegateOwner(this.getActiveDelegateOwner());
305+
path.setAttributes(this.getActiveShapeAttributes());
306+
return path;
307+
}
308+
}

src/gov/nasa/worldwindx/examples/symbology/TacticalGraphics.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,11 +501,33 @@ protected void createAreaGraphics(RenderableLayer layer)
501501
TacticalGraphicFactory factory = new MilStd2525GraphicFactory();
502502
TacticalGraphic graphic;
503503

504+
/////////////////////////////////////////////
505+
// Block (2.X.1.1)
506+
/////////////////////////////////////////////
507+
List<Position> positions = Arrays.asList(
508+
Position.fromDegrees(35.0019, -117.6803),
509+
Position.fromDegrees(35.0513, -117.6803),
510+
Position.fromDegrees(35.0266, -117.5391));
511+
graphic = factory.createGraphic("GFTPB---------X", positions, null);
512+
graphic.setValue(AVKey.DISPLAY_NAME, "Block: (2.X.1.1)");
513+
layer.addRenderable(graphic);
514+
515+
/////////////////////////////////////////////
516+
// Penetrate (2.X.1.17)
517+
/////////////////////////////////////////////
518+
positions = Arrays.asList(
519+
Position.fromDegrees(35.1084, -117.6514),
520+
Position.fromDegrees(35.0600, -117.6514),
521+
Position.fromDegrees(35.0822, -117.7514));
522+
graphic = factory.createGraphic("GFTPP---------X", positions, null);
523+
graphic.setValue(AVKey.DISPLAY_NAME, "Penetrate: (2.X.1.17)");
524+
layer.addRenderable(graphic);
525+
504526
/////////////////////////////////////////////
505527
// Assembly area (2.X.2.1.3.2)
506528
/////////////////////////////////////////////
507529

508-
List<Position> positions = Arrays.asList(
530+
positions = Arrays.asList(
509531
Position.fromDegrees(34.9130, -117.1897),
510532
Position.fromDegrees(34.9789, -117.1368),
511533
Position.fromDegrees(34.9706, -116.9900),

0 commit comments

Comments
 (0)