src.gov.nasa.worldwindx.examples.symbology.TacticalGraphics Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of worldwind Show documentation
Show all versions of worldwind Show documentation
World Wind is a collection of components that interactively display 3D geographic information within Java applications or applets.
/*
* Copyright (C) 2012 United States Government as represented by the Administrator of the
* National Aeronautics and Space Administration.
* All Rights Reserved.
*/
package gov.nasa.worldwindx.examples.symbology;
import gov.nasa.worldwind.Configuration;
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.geom.*;
import gov.nasa.worldwind.layers.RenderableLayer;
import gov.nasa.worldwind.render.*;
import gov.nasa.worldwind.symbology.*;
import gov.nasa.worldwind.symbology.milstd2525.MilStd2525GraphicFactory;
import gov.nasa.worldwind.util.*;
import gov.nasa.worldwindx.examples.ApplicationTemplate;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
/**
* Demonstrates how to create and display World Wind tactical graphics. See the Symbology Usage Guide for more
* information on symbology support in World Wind.
*
* See the {@link TacticalSymbols} for a detailed example of using World Wind tactical symbols in an application.
*
* @author pabercrombie
* @version $Id: TacticalGraphics.java 1171 2013-02-11 21:45:02Z dcollins $
*/
public class TacticalGraphics extends ApplicationTemplate
{
public static class AppFrame extends ApplicationTemplate.AppFrame
{
protected RenderableLayer pointLayer;
protected RenderableLayer lineLayer;
protected RenderableLayer areaLayer;
/** Shared attributes for line and area graphics. */
protected TacticalGraphicAttributes sharedAttrs;
/** Shared attributes for point graphics. */
protected TacticalGraphicAttributes sharedPointAttrs;
public AppFrame()
{
super(true, true, false);
this.pointLayer = new RenderableLayer();
this.pointLayer.setName("Tactical Graphics (Points)");
this.lineLayer = new RenderableLayer();
this.lineLayer.setName("Tactical Graphics (Lines)");
this.areaLayer = new RenderableLayer();
this.areaLayer.setName("Tactical Graphics (Areas)");
// Create attributes for line and area graphics. Line and area graphics use the scale attribute to determine
// the size of tactical symbols included in the graphic. Setting the scale to 1/4 prevents the symbol
// overwhelming the rest of the graphic.
this.sharedAttrs = new BasicTacticalGraphicAttributes();
this.sharedAttrs.setScale(0.25);
// Create attributes for point graphics. Point graphics use the scale attribute to determine the size of the
// point graphic icon. Do not share attributes with line and area graphics because point graphics look
// better with a larger scale value.
this.sharedPointAttrs = new BasicTacticalGraphicAttributes();
// Create tactical symbols and graphics and add them to the layer
this.createPointGraphics(this.pointLayer);
this.createLineGraphics(this.lineLayer);
this.createAreaGraphics(this.areaLayer);
insertBeforePlacenames(getWwd(), this.pointLayer);
insertBeforePlacenames(getWwd(), this.lineLayer);
insertBeforePlacenames(getWwd(), this.areaLayer);
this.getLayerPanel().update(this.getWwd());
// Add a BasicDragger so that graphics can be moved by clicking and dragging.
this.getWwd().addSelectListener(new BasicDragger(this.getWwd()));
this.addGraphicControls();
// Size the World Window to provide enough screen space for the graphics, and center the World Window
// on the screen.
Dimension size = new Dimension(1800, 1000);
this.setPreferredSize(size);
this.pack();
WWUtil.alignComponent(null, this, AVKey.CENTER);
}
protected void createPointGraphics(RenderableLayer layer)
{
TacticalGraphicFactory factory = new MilStd2525GraphicFactory();
TacticalGraphic graphic;
/////////////////////////////////////////////
// Nuclear Event (2.X.3.4.2)
/////////////////////////////////////////////
graphic = factory.createPoint("GHMPNZ--------X", Position.fromDegrees(35.2144, -117.8824), null);
graphic.setValue(AVKey.DISPLAY_NAME, "Nuclear Event (2.X.3.4.2)");
graphic.setText("X691");
graphic.setModifier(SymbologyConstants.DATE_TIME_GROUP, "10095900ZJAN92");
graphic.setModifier(SymbologyConstants.QUANTITY, "15");
graphic.setModifier(SymbologyConstants.TYPE, "B83");
layer.addRenderable(graphic);
/////////////////////////////////////////////
// High tower
/////////////////////////////////////////////
graphic = factory.createPoint("GHMPOHTH------X", Position.fromDegrees(35.2544, -117.724), null);
graphic.setValue(AVKey.DISPLAY_NAME, "High Tower");
graphic.setModifier(SymbologyConstants.ALTITUDE_DEPTH, "2562");
layer.addRenderable(graphic);
// Apply shared attributes to all graphics on this layer
this.setAttributes(layer, this.sharedAttrs, this.sharedPointAttrs);
}
protected void createLineGraphics(RenderableLayer layer)
{
TacticalGraphicFactory factory = new MilStd2525GraphicFactory();
TacticalGraphic graphic;
/////////////////////////////////////////////
// Phase line (2.X.2.1.2.4)
/////////////////////////////////////////////
// Create a Friendly Phase Line
List positions = Arrays.asList(
Position.fromDegrees(34.9349, -117.6303),
Position.fromDegrees(34.9843, -117.5885),
Position.fromDegrees(34.9961, -117.4891));
graphic = factory.createGraphic("GFGPGLP----AUSX", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Phase line: friendly (2.X.2.2.2.2)");
graphic.setText("A");
layer.addRenderable(graphic);
// Create a Hostile Phase Line
positions = Arrays.asList(
Position.fromDegrees(34.9190, -117.5919),
Position.fromDegrees(34.9589, -117.5618),
Position.fromDegrees(34.9701, -117.4798));
graphic = factory.createGraphic("GHGPGLP----AUSX", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Phase line: hostile (2.X.2.2.2.2)");
graphic.setText("B");
layer.addRenderable(graphic);
// Create a Hostile, Anticipated, Phase Line
positions = Arrays.asList(
Position.fromDegrees(34.8910, -117.5726),
Position.fromDegrees(34.9367, -117.5354),
Position.fromDegrees(34.9480, -117.4741));
graphic = factory.createGraphic("GHGAGLP----AUSX", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Phase line: hostile, anticipated (2.X.2.2.2.2)");
graphic.setText("C");
layer.addRenderable(graphic);
// Create a line with a custom color and font
positions = Arrays.asList(
Position.fromDegrees(34.8703, -117.5525),
Position.fromDegrees(34.9158, -117.5153),
Position.fromDegrees(34.9238, -117.4600));
graphic = factory.createGraphic("GFGPGLP----AUSX", positions, null);
graphic.setText("D");
graphic.setValue(AVKey.DISPLAY_NAME, "Phase line: custom color and font (2.X.2.2.2.2)");
// Create a custom attributes bundle. Any fields set in this bundle will override the default attributes.
TacticalGraphicAttributes attrs = new BasicTacticalGraphicAttributes();
attrs.setOutlineMaterial(Material.GRAY);
attrs.setTextModifierFont(Font.decode("Arial-12"));
// Apply the attributes to the graphic
graphic.setAttributes(attrs);
layer.addRenderable(graphic);
/////////////////////////////////////////////
// Boundary (2.X.2.1.2.1)
/////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(34.5479, -117.8777),
Position.fromDegrees(34.5137, -118.0092),
Position.fromDegrees(34.5898, -118.0775),
Position.fromDegrees(34.5360, -118.1833));
graphic = factory.createGraphic("GHGPGLB----JUSX", positions, null);
graphic.setModifier(SymbologyConstants.UNIQUE_DESIGNATION, Arrays.asList("40ID", "18ID"));
graphic.setValue(AVKey.DISPLAY_NAME, "Boundary (2.X.2.1.2.1)");
layer.addRenderable(graphic);
/////////////////////////////////////////////
// Main Attack (2.X.2.5.2.1.4.1)
/////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(34.6643, -117.7323), // Pt. 1: Tip of the arrow
Position.fromDegrees(34.6962, -117.7808), // Pt. 2: First path control point
Position.fromDegrees(34.6934, -117.8444),
Position.fromDegrees(34.6602, -117.8570), // Pt. N - 1: Last path control point
Position.fromDegrees(34.6844, -117.7303)); // Pt. N: Width of the arrow head
graphic = factory.createGraphic("GFGPOLAGM-----X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Main Attack (2.X.2.5.2.1.4.1)");
layer.addRenderable(graphic);
/////////////////////////////////////////////
// Attack, rotary wing (2.X.2.5.2.1.3)
/////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(34.7610, -117.4541),
Position.fromDegrees(34.7614, -117.5852),
Position.fromDegrees(34.7287, -117.6363),
Position.fromDegrees(34.6726, -117.6363),
Position.fromDegrees(34.7820, -117.4700));
graphic = factory.createGraphic("GFGPOLAR------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Attack, Rotary Wing (2.X.2.5.2.1.3)");
layer.addRenderable(graphic);
/////////////////////////////////////////////
// Aviation axis of advance (2.X.2.5.2.1.1)
/////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(34.7437, -117.8007),
Position.fromDegrees(34.7535, -117.9256),
Position.fromDegrees(34.8051, -117.9707),
Position.fromDegrees(34.7643, -117.8219));
graphic = factory.createGraphic("GFGPOLAV------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Aviation (2.X.2.5.2.1.1)");
layer.addRenderable(graphic);
/////////////////////////////////////////////
// Supporting attack (2.X.2.5.2.1.4.2)
/////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(34.6980, -117.5541),
Position.fromDegrees(34.6951, -117.4667),
Position.fromDegrees(34.6733, -117.4303),
Position.fromDegrees(34.6217, -117.4056),
Position.fromDegrees(34.6780, -117.53));
graphic = factory.createGraphic("GFGPOLAGS-----X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Supporting Attack (2.X.2.5.2.1.4.2)");
layer.addRenderable(graphic);
/////////////////////////////////////////////
// Airborne (2.X.2.5.2.1.2)
/////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(34.7099, -117.9047),
Position.fromDegrees(34.6725, -117.9590),
Position.fromDegrees(34.6814, -118.0522),
Position.fromDegrees(34.7124, -117.9284));
graphic = factory.createGraphic("GFGPOLAA------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Airborne (2.X.2.5.2.1.2)");
graphic.setModifier(SymbologyConstants.SYMBOL_INDICATOR, "SFGPUCI--------");
layer.addRenderable(graphic);
/////////////////////////////////////////////
// Minimum risk route (2.X.2.2.2.2)
/////////////////////////////////////////////
// Create a Minimum Risk Route graphic
// First create some Air Control Points to place along the route
List controlPoints = new ArrayList();
// Create an Air Control Point
TacticalPoint point = factory.createPoint("GFGPAPP-------X", Position.fromDegrees(34.8802, -117.9773),
null);
point.setText("1");
controlPoints.add(point);
// And another Air Control Point
point = factory.createPoint("GFGPAPP-------X", Position.fromDegrees(35.0947, -117.9578), null);
point.setText("2");
controlPoints.add(point);
// And a Communication Checkpoint
point = factory.createPoint("GFGPAPC-------X", Position.fromDegrees(35.1739, -117.6957), null);
point.setText("3");
controlPoints.add(point);
// Now create the route from the control points
TacticalRoute route = factory.createRoute("GFGPALM-------X", controlPoints, null);
route.setValue(AVKey.DISPLAY_NAME, "Minimum Risk Route (2.X.2.2.2.2)");
route.setText("KNIGHT");
route.setModifier(SymbologyConstants.DISTANCE, 4000.0);
route.setModifier(SymbologyConstants.DATE_TIME_GROUP, Arrays.asList("270600Z", "271845Z"));
route.setModifier(SymbologyConstants.ALTITUDE_DEPTH, Arrays.asList("50 FT AGL", "200 FT AGL"));
// And add the route to the layer. Note that we do not need to add the individual control points
// to the layer because the route will take care of drawing them.
layer.addRenderable(route);
///////////////////////////////////////////////////
// Direction of Main Attack (2.X.2.5.2.2.2.1)
///////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(35.0459, -117.3795),
Position.fromDegrees(35.0459, -117.5633));
graphic = factory.createGraphic("GFGPOLKGM-----X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Direction of Main Attack (2.X.2.5.2.2.2.1)");
layer.addRenderable(graphic);
///////////////////////////////////////////////////
// Final Protective Fire (2.X.4.2.1.2)
///////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(34.8917, -117.8344),
Position.fromDegrees(34.8283, -117.6794));
graphic = factory.createGraphic("GFFPLTF-------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Final Protective Fire (2.X.4.2.1.2)");
graphic.setModifier(SymbologyConstants.UNIQUE_DESIGNATION, Arrays.asList("AG1201", "2-22 INF MORT"));
layer.addRenderable(graphic);
///////////////////////////////////////////////////
// Ambush (2.X.2.6.1.1)
///////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(34.5556, -117.4123),
Position.fromDegrees(34.5210, -117.4786),
Position.fromDegrees(34.5942, -117.4766));
graphic = factory.createGraphic("GFGPSLA-------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Ambush (2.X.2.6.1.1)");
layer.addRenderable(graphic);
///////////////////////////////////////////////////
// Forward Edge of Battle Area (FEBA) (2.X.2.4.2.1)
///////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(35.2805, -117.5978),
Position.fromDegrees(35.2978, -117.3702));
graphic = factory.createGraphic("GFGPDLF-------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Forward Edge of Battle Area (2.X.2.4.2.1)");
layer.addRenderable(graphic);
///////////////////////////////////////////////////
// Line of Contact (.X.2.1.2.3)
///////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(35.2829, -117.5900),
Position.fromDegrees(35.2990, -117.3727));
graphic = factory.createGraphic("GFGPGLC-------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Line of Contact (2.X.2.1.2.3)");
layer.addRenderable(graphic);
///////////////////////////////////////////////////
// Fire Support Coordination Line (2.X.4.2.2.1)
///////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(34.4179, -117.4399),
Position.fromDegrees(34.4486, -117.6857));
graphic = factory.createGraphic("GFFPLCF-------X", positions, null);
graphic.setModifier(SymbologyConstants.UNIQUE_DESIGNATION, Arrays.asList("X CORPS", "ALPHA"));
graphic.setModifier(SymbologyConstants.DATE_TIME_GROUP, Arrays.asList("202100Z", "270800Z SEP"));
graphic.setValue(AVKey.DISPLAY_NAME, "Fire Support Coordination Line (2.X.4.2.2.1)");
layer.addRenderable(graphic);
///////////////////////////////////////////////////
// Principle Direction of Fire (2.X.2.4.2.2)
///////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(34.7502, -118.1980),
Position.fromDegrees(34.8542, -118.2565),
Position.fromDegrees(34.8515, -118.1129));
graphic = factory.createGraphic("GFGPDLP-------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Principle Direction of Fire (2.X.2.4.2.2)");
graphic.setModifier(SymbologyConstants.SYMBOL_INDICATOR, "SFGPEWRH--MTUSG");
layer.addRenderable(graphic);
///////////////////////////////////////////////////
// Search Area/Reconnaissance Area (2.X.2.1.3.9)
///////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(34.9738, -118.2632),
Position.fromDegrees(34.9306, -118.1597),
Position.fromDegrees(35.0092, -118.1717));
graphic = factory.createGraphic("GFGPGAS-------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Search Area/Reconnaissance Area (2.X.2.1.3.9)");
graphic.setModifier(SymbologyConstants.SYMBOL_INDICATOR, "SFGPEWRH--MTUSG");
layer.addRenderable(graphic);
///////////////////////////////////////////////////
// Forward Line of Own Troops (2.X.2.1.2.2)
///////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(35.3401, -117.6356),
Position.fromDegrees(35.3723, -117.5290),
Position.fromDegrees(35.3776, -117.4182));
graphic = factory.createGraphic("GFGPGLF-------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Forward Line of Own Troops (2.X.2.1.2.2)");
layer.addRenderable(graphic);
///////////////////////////////////////////////////
// Direction of Attack, Aviation (2.X.2.5.2.2.1)
///////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(35.1143, -118.0609),
Position.fromDegrees(35.0765, -118.2397));
graphic = factory.createGraphic("GHGPOLKA------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Direction of Attack, Aviation (2.X.2.5.2.2.1)");
layer.addRenderable(graphic);
///////////////////////////////////////////////////
// Infiltration Lane (2.X.2.5.2.4)
///////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(35.2678, -118.0194),
Position.fromDegrees(35.1504, -118.1822),
Position.fromDegrees(35.2402, -118.0716));
graphic = factory.createGraphic("GFGPOLI-------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Infiltration Lane (2.X.2.5.2.4)");
graphic.setText("CHARLIE");
layer.addRenderable(graphic);
///////////////////////////////////////////////////
// Axis of Advance for Feint (2.X.2.3.2)
///////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(34.6377, -118.0770),
Position.fromDegrees(34.6413, -118.1572),
Position.fromDegrees(34.6808, -118.2100),
Position.fromDegrees(34.6547, -118.0988));
graphic = factory.createGraphic("GFGPPA--------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Axis of Advance for Feint (2.X.2.3.2)");
graphic.setText("GREEN");
layer.addRenderable(graphic);
///////////////////////////////////////////////////
// Holding Line (2.X.2.6.1.2)
///////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(35.1184, -118.4377),
Position.fromDegrees(35.0339, -118.4318),
Position.fromDegrees(35.0843, -118.3376));
graphic = factory.createGraphic("GFGPSLH-------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Holding Line (2.X.2.6.1.2)");
graphic.setText("ALPHA");
layer.addRenderable(graphic);
///////////////////////////////////////////////////
// Direction of Attack for Feint (2.X.2.3.3)
///////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(35.0656, -118.0508),
Position.fromDegrees(35.0383, -118.2275));
graphic = factory.createGraphic("GFGPPF--------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Direction of Attack for Feint (2.X.2.3.3)");
graphic.setText("DAVID");
layer.addRenderable(graphic);
// Apply shared attributes to all graphics on this layer
this.setAttributes(layer, this.sharedAttrs, this.sharedPointAttrs);
}
protected void createAreaGraphics(RenderableLayer layer)
{
TacticalGraphicFactory factory = new MilStd2525GraphicFactory();
TacticalGraphic graphic;
/////////////////////////////////////////////
// Assembly area (2.X.2.1.3.2)
/////////////////////////////////////////////
List positions = Arrays.asList(
Position.fromDegrees(34.9130, -117.1897),
Position.fromDegrees(34.9789, -117.1368),
Position.fromDegrees(34.9706, -116.9900),
Position.fromDegrees(34.9188, -116.9906));
graphic = factory.createGraphic("GHGPGAA----AUSX", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Assembly Area (2.X.2.1.3.2)");
graphic.setText("Atlanta");
layer.addRenderable(graphic);
/////////////////////////////////////////////
// Fortified area (2.X.2.1.3.4)
/////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(34.7985, -117.1938),
Position.fromDegrees(34.8358, -117.1282),
Position.fromDegrees(34.8456, -117.0773),
Position.fromDegrees(34.8159, -116.9723),
Position.fromDegrees(34.7836, -117.1010),
Position.fromDegrees(34.7985, -117.1938));
graphic = factory.createGraphic("GHGPGAF----AUSX", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Fortified Area (2.X.2.1.3.4)");
layer.addRenderable(graphic);
/////////////////////////////////////////////
// Airfield zone (2.X.2.1.3.11)
/////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(34.9001, -117.4044),
Position.fromDegrees(34.9910, -117.3297),
Position.fromDegrees(34.9851, -117.2224),
Position.fromDegrees(34.9134, -117.2670));
graphic = factory.createGraphic("GFGPGAZ----AUSX", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Airfield Zone (2.X.2.1.3.11)");
layer.addRenderable(graphic);
/////////////////////////////////////////////
// Restricted Operation Zone (2.X.2.2.3.1)
/////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(35.2331, -117.6217),
Position.fromDegrees(35.2331, -117.3552),
Position.fromDegrees(35.1998, -117.2560),
Position.fromDegrees(35.0851, -117.3604),
Position.fromDegrees(35.0857, -117.6261));
graphic = factory.createGraphic("GFGPAAR----AUSX", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Restricted Operations Zone (2.X.2.2.3.1)");
graphic.setText("(Unit ID)");
graphic.setModifier(SymbologyConstants.DATE_TIME_GROUP, Arrays.asList("180500Z", "180615Z"));
graphic.setModifier(SymbologyConstants.ALTITUDE_DEPTH, Arrays.asList("2000 FT AGL", "3000 FT AGL"));
layer.addRenderable(graphic);
/////////////////////////////////////////////
// Weapons Free Zone (2.X.2.2.3.5)
/////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(34.7849, -117.3661),
Position.fromDegrees(34.6715, -117.3738),
Position.fromDegrees(34.6374, -117.3208),
Position.fromDegrees(34.6549, -117.1448),
Position.fromDegrees(34.7506, -117.1436));
graphic = factory.createGraphic("GFGPAAW----AUSX", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Weapons Free Zone (2.X.2.2.3.5)");
graphic.setText("(Unit ID)");
graphic.setModifier(SymbologyConstants.DATE_TIME_GROUP, Arrays.asList("1000Z", "1300Z"));
layer.addRenderable(graphic);
/////////////////////////////////////////////
// Circular target (2.X.4.3.1.2)
/////////////////////////////////////////////
Position position = (Position.fromDegrees(35.1108, -117.0870));
TacticalCircle circle = factory.createCircle("GHFPATC-------X", position, 5000.0, null);
circle.setValue(AVKey.DISPLAY_NAME, "Circular Target (2.X.4.3.1.2)");
circle.setText("AG9999");
layer.addRenderable(circle);
/////////////////////////////////////////////
// Rectangular target (2.X.4.3.1.1)
/////////////////////////////////////////////
position = (Position.fromDegrees(35.0295, -116.9290));
TacticalQuad quad = factory.createQuad("GHFPATR-------X", Arrays.asList(position), null);
quad.setLength(8000.0);
quad.setWidth(4000.0);
quad.setText("AB0176");
quad.setValue(AVKey.DISPLAY_NAME, "Rectangular Target (2.X.4.3.1.1)");
layer.addRenderable(quad);
/////////////////////////////////////////////
// Position Area for Artillery, Circular target (2.X.4.3.2.6.2)
/////////////////////////////////////////////
position = Position.fromDegrees(35.2106, -117.0092);
circle = factory.createCircle("GFFPACPC------X", position, 5000.0, null);
circle.setValue(AVKey.DISPLAY_NAME, "Position Area for Artillery (2.X.4.3.2.6.2)");
layer.addRenderable(circle);
/////////////////////////////////////////////
// Position Area for Artillery, Rectangular target (2.X.4.3.2.6.1)
/////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(35.2520, -116.8968),
Position.fromDegrees(35.2364, -116.8063));
quad = factory.createQuad("GFFPACPR------X", positions, null);
quad.setWidth(5000.0);
quad.setValue(AVKey.DISPLAY_NAME, "Position Area for Artillery (2.X.4.3.2.6.1)");
layer.addRenderable(quad);
//////////////////////////////////////////////////
// Circular Weapon/Sensor Range Fan (2.X.4.3.4.1)
//////////////////////////////////////////////////
position = (Position.fromDegrees(34.6813, -116.9724));
graphic = factory.createGraphic("GFFPAXC-------X", Arrays.asList(position), null);
graphic.setModifier(SymbologyConstants.DISTANCE, Arrays.asList(1000.0, 6000.0, 11000.0));
graphic.setModifier(SymbologyConstants.ALTITUDE_DEPTH, Arrays.asList("GL", "GL", "GL"));
graphic.setValue(AVKey.DISPLAY_NAME, "Weapon/Sensor Range Fan (2.X.4.3.4.1)");
// Add a symbol at the center of the range fan
graphic.setModifier(SymbologyConstants.SYMBOL_INDICATOR, "SFGPUCFH-------");
layer.addRenderable(graphic);
//////////////////////////////////////////////////
// Sector Weapon/Sensor Range Fan (2.X.4.3.4.2)
//////////////////////////////////////////////////
List azimuths = Arrays.asList(
Angle.fromDegrees(290), Angle.fromDegrees(30), // Range 1, left azimuth, right azimuth
Angle.fromDegrees(290), Angle.fromDegrees(30), // Range 2, left azimuth, right azimuth
Angle.fromDegrees(315), Angle.fromDegrees(30), // Range 3, left azimuth, right azimuth
Angle.fromDegrees(315), Angle.fromDegrees(35));
position = (Position.fromDegrees(34.5798, -116.6591));
graphic = factory.createGraphic("GFFPAXS-------X", Arrays.asList(position), null);
graphic.setModifier(SymbologyConstants.DISTANCE, Arrays.asList(4000.0, 6000.0, 11000.0, 15000.0));
graphic.setModifier(SymbologyConstants.AZIMUTH, azimuths);
graphic.setModifier(SymbologyConstants.ALTITUDE_DEPTH, Arrays.asList("GL", "GL", "GL", "GL"));
graphic.setValue(AVKey.DISPLAY_NAME, "Weapon/Sensor Range Fan (2.X.4.3.4.2)");
// Add a symbol at the center of the range fan.
graphic.setModifier(SymbologyConstants.SYMBOL_INDICATOR, "SFGPUCFTR------");
layer.addRenderable(graphic);
////////////////////////////////////////////////////////////
// Restrictive Fire Area (RFA), Rectangular (2.X.4.3.2.5.2)
////////////////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(34.9672, -116.8974),
Position.fromDegrees(34.9188, -116.8205));
graphic = factory.createGraphic("GFFPACRR------X", positions, null);
graphic.setModifier(SymbologyConstants.DISTANCE, 5000.0);
graphic.setValue(AVKey.DISPLAY_NAME, "Restrictive Fire Area (2.X.4.3.2.5.2)");
graphic.setText("X CORPS");
graphic.setModifier(SymbologyConstants.DATE_TIME_GROUP, Arrays.asList("051030", "051600Z"));
layer.addRenderable(graphic);
/////////////////////////////////////////////////////
// Fire Support Area (FSA), Circular (2.X.4.3.2.1.3)
/////////////////////////////////////////////////////
position = Position.fromDegrees(34.8208, -116.8284);
graphic = factory.createCircle("GFFPACSC------X", position, 5000.0, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Fire Support Area (2.X.4.3.2.1.3)");
graphic.setText("GREEN");
graphic.setModifier(SymbologyConstants.DATE_TIME_GROUP, Arrays.asList("051030", "051600Z"));
layer.addRenderable(graphic);
////////////////////////////////////////////////////////////
// Sensor Zone, Rectangular
////////////////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(35.0592, -117.2903),
Position.fromDegrees(35.0620, -117.1606));
graphic = factory.createGraphic("GFFPACER------X", positions, null);
graphic.setModifier(SymbologyConstants.DISTANCE, 5000.0);
graphic.setValue(AVKey.DISPLAY_NAME, "Sensor Zone");
graphic.setText("Q37");
graphic.setModifier(SymbologyConstants.DATE_TIME_GROUP, Arrays.asList("051030", "051600Z"));
layer.addRenderable(graphic);
////////////////////////////////////////////////////////////
// Call for Fire Zone, Irregular (2.X.4.3.3.2.1)
////////////////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(35.1386, -116.9302),
Position.fromDegrees(35.1030, -116.9302),
Position.fromDegrees(35.0731, -116.9561),
Position.fromDegrees(35.0620, -116.8345),
Position.fromDegrees(35.1422, -116.8193));
graphic = factory.createGraphic("GFFPAZXI------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Call for Fire Zone (2.X.4.3.3.2.1)");
graphic.setText("3BDE 4ID");
graphic.setModifier(SymbologyConstants.DATE_TIME_GROUP, Arrays.asList("051030", "051600Z"));
layer.addRenderable(graphic);
////////////////////////////////////////////////////////////
// Series or Group of Targets (2.X.4.3.1.3)
////////////////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(35.0160, -116.6625),
Position.fromDegrees(35.0601, -116.6773),
Position.fromDegrees(35.0542, -116.7611),
Position.fromDegrees(35.0092, -116.7790));
graphic = factory.createGraphic("GFFPATG-------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Series or Group of Targets (2.X.4.3.1.3)");
graphic.setText("JEFF");
layer.addRenderable(graphic);
////////////////////////////////////////////////////////////
// Airhead (2.X.2.6.2.2)
////////////////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(35.1260, -116.6625),
Position.fromDegrees(35.1701, -116.6773),
Position.fromDegrees(35.1642, -116.7611),
Position.fromDegrees(35.1192, -116.7790));
graphic = factory.createGraphic("GFGPSAA-------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Airhead (2.X.2.6.2.2)");
graphic.setText("DELTA");
layer.addRenderable(graphic);
////////////////////////////////////////////////////////////
// Minimum Safe Distance Zones (2.X.3.4.1)
////////////////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(34.9073, -116.7041), // Center point of graphic
Position.fromDegrees(34.9230, -116.6842), // Radius of ring 1
Position.fromDegrees(34.8723, -116.6841), // Radius of ring 2
Position.fromDegrees(34.8870, -116.7783)); // Radius of ring 3
graphic = factory.createGraphic("GFMPNM--------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Minimum Safe Distance Zones (2.X.3.4.1)");
layer.addRenderable(graphic);
////////////////////////////////////////////////////////////
// Pull-Up Point (2.X.3.4.1)
////////////////////////////////////////////////////////////
position = Position.fromDegrees(35.2132, -117.8042);
circle = factory.createCircle("GFGPAPU-------X", position, 2000.0, null);
circle.setValue(AVKey.DISPLAY_NAME, "Pull-Up Point (2.X.2.2.1.3)");
layer.addRenderable(circle);
///////////////////////////////////////////////////
// Attack by Fire Position (2.X.2.5.3.3)
///////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(34.6297, -117.6718),
Position.fromDegrees(34.5807, -117.5902),
Position.fromDegrees(34.5344, -117.6686));
graphic = factory.createGraphic("GFGPOAF-------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Attack by Fire Position (2.X.2.5.3.3)");
layer.addRenderable(graphic);
///////////////////////////////////////////////////
// Support by Fire Position (2.X.2.5.3.4)
///////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(34.6159, -117.8571),
Position.fromDegrees(34.5775, -117.7887),
Position.fromDegrees(34.6308, -117.8477),
Position.fromDegrees(34.5837, -117.7725));
graphic = factory.createGraphic("GFGPOAS-------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Support by Fire Position (2.X.2.5.3.4)");
layer.addRenderable(graphic);
///////////////////////////////////////////////////
// Biologically Contaminated Area (2.X.3.4.5)
///////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(34.4916, -117.3427),
Position.fromDegrees(34.5770, -117.2273),
Position.fromDegrees(34.5666, -117.0920),
Position.fromDegrees(34.4943, -117.0629),
Position.fromDegrees(34.4570, -117.1613),
Position.fromDegrees(34.4508, -117.3106));
graphic = factory.createGraphic("GFMPNB--------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Biologically Contaminated Area (2.X.3.4.5)");
layer.addRenderable(graphic);
graphic = factory.createPoint("GFMPNEB-------X", Position.fromDegrees(34.5059, -117.2020), null);
graphic.setValue(AVKey.DISPLAY_NAME, "Biological Release Event (2.X.3.4.7.1)");
graphic.setShowLocation(false);
layer.addRenderable(graphic);
// Apply shared attributes to all graphics on this layer
this.setAttributes(layer, this.sharedAttrs, this.sharedPointAttrs);
//////////////////////////////////////////////////////////////
// Battle Position, Prepared but not occupied (2.X.2.4.3.1.1)
//////////////////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(34.9684, -116.4864),
Position.fromDegrees(34.9776, -116.6114),
Position.fromDegrees(35.0271, -116.5614),
Position.fromDegrees(35.0309, -116.4132));
graphic = factory.createGraphic("GHGPDAB----J--X", positions, null);
graphic.setText("Blue");
graphic.setValue(AVKey.DISPLAY_NAME, "Battle Position, Prepared but not Occupied (2.X.2.4.3.1.1)");
layer.addRenderable(graphic);
//////////////////////////////////////////////////////////////
// Encirclement (2.X.2.6.2.3)
//////////////////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(34.8166, -116.5491),
Position.fromDegrees(34.8121, -116.5027),
Position.fromDegrees(34.8182, -116.4528),
Position.fromDegrees(34.8489, -116.4137),
Position.fromDegrees(34.8848, -116.4246),
Position.fromDegrees(34.9050, -116.4664),
Position.fromDegrees(34.9080, -116.5246),
Position.fromDegrees(34.8893, -116.5828),
Position.fromDegrees(34.8495, -116.6091),
Position.fromDegrees(34.8211, -116.5782));
graphic = factory.createGraphic("GHGPSAE-------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Encirclement (2.X.2.6.2.3)");
layer.addRenderable(graphic);
//////////////////////////////////////////////////////////////
// Dose Rate Contour Line (2.X.3.4.9)
//////////////////////////////////////////////////////////////
positions = Arrays.asList(
Position.fromDegrees(34.7710, -116.4909),
Position.fromDegrees(34.7764, -116.4720),
Position.fromDegrees(34.7790, -116.4210),
Position.fromDegrees(34.7509, -116.3918),
Position.fromDegrees(34.7285, -116.3810),
Position.fromDegrees(34.7066, -116.3831),
Position.fromDegrees(34.6787, -116.4378),
Position.fromDegrees(34.6850, -116.4900),
Position.fromDegrees(34.7063, -116.5192),
Position.fromDegrees(34.7330, -116.5170));
graphic = factory.createGraphic("GFMPNL--------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Dose Rate Contour Line (2.X.3.4.9)");
graphic.setText("100 cGY");
layer.addRenderable(graphic);
// Create a second contour line inside the first.
positions = Arrays.asList(
Position.fromDegrees(34.7504, -116.4800),
Position.fromDegrees(34.7552, -116.4637),
Position.fromDegrees(34.7556, -116.4283),
Position.fromDegrees(34.7469, -116.4137),
Position.fromDegrees(34.7259, -116.4129),
Position.fromDegrees(34.7091, -116.4138),
Position.fromDegrees(34.7053, -116.4280),
Position.fromDegrees(34.7073, -116.4634),
Position.fromDegrees(34.7149, -116.4891),
Position.fromDegrees(34.7314, -116.4908));
graphic = factory.createGraphic("GFMPNL--------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Dose Rate Contour Line (2.X.3.4.9)");
graphic.setText("300 cGY");
layer.addRenderable(graphic);
//////////////////////////////////////////////////////////////
// Limited Access Area (2.X.2.1.3.10)
//////////////////////////////////////////////////////////////
// Create the area part of the graphic. This can be any type of area graphic. Here we use a General Area.
positions = Arrays.asList(
Position.fromDegrees(35.1421, -116.5798),
Position.fromDegrees(35.0979, -116.5971),
Position.fromDegrees(35.0934, -116.4595),
Position.fromDegrees(35.1570, -116.4832));
graphic = factory.createGraphic("GFGPGAG-------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "General Area (2.X.2.1.3.1)");
graphic.setText("CHEM");
layer.addRenderable(graphic);
// Now create a pentagon associated with the area. The first position specifies the position of the pentagon,
// and the second position specifies the end point of the line that connects the pentagon to the area.
positions = Arrays.asList(
Position.fromDegrees(35.1612, -116.4304),
Position.fromDegrees(35.1358, -116.4955));
graphic = factory.createGraphic("GFGPGAY-------X", positions, null);
graphic.setValue(AVKey.DISPLAY_NAME, "Limited Access Area (2.X.2.1.3.10)");
graphic.setModifier(SymbologyConstants.SYMBOL_INDICATOR, "SFGPUCI--------");
layer.addRenderable(graphic);
// Apply shared attributes to all graphics on this layer
this.setAttributes(layer, this.sharedAttrs, this.sharedPointAttrs);
}
/**
* Apply attributes to all TacticalGraphics on a layer.
*
* @param layer Layer of graphics to modify.
* @param attrs Attributes to apply to non-point graphics.
* @param pointAttrs Attributes to apply to TacticalPoint graphics graphics.
*/
protected void setAttributes(RenderableLayer layer, TacticalGraphicAttributes attrs,
TacticalGraphicAttributes pointAttrs)
{
for (Renderable renderable : layer.getRenderables())
{
if (renderable instanceof TacticalPoint)
{
// Apply attributes if the graphic does not already have attributes.
TacticalGraphic graphic = (TacticalGraphic) renderable;
if (graphic.getAttributes() == null)
{
graphic.setAttributes(pointAttrs);
}
}
else if (renderable instanceof TacticalGraphic)
{
// Apply attributes if the graphic does not already have attributes.
TacticalGraphic graphic = (TacticalGraphic) renderable;
if (graphic.getAttributes() == null)
{
graphic.setAttributes(attrs);
}
}
}
}
protected void addGraphicControls()
{
javax.swing.Box box = javax.swing.Box.createVerticalBox();
box.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
// Create a slider that controls the opacity of all symbols.
JLabel label = new JLabel("Opacity");
JSlider slider = new JSlider(0, 100, 100);
slider.addChangeListener(new ChangeListener()
{
public void stateChanged(ChangeEvent changeEvent)
{
// Set the opacity for only the normal attributes. This causes symbols to return to 100% opacity
// when highlighted. Changes in these attributes are reflected in all symbols that use them.
JSlider slider = (JSlider) changeEvent.getSource();
double opacity = (double) slider.getValue() / 100d;
sharedAttrs.setInteriorOpacity(opacity);
sharedAttrs.setOutlineOpacity(opacity);
sharedPointAttrs.setInteriorOpacity(opacity);
sharedPointAttrs.setOutlineOpacity(opacity);
getWwd().redraw(); // Cause the World Window to refresh in order to make these changes visible.
}
});
box.add(javax.swing.Box.createVerticalStrut(10));
label.setAlignmentX(JComponent.LEFT_ALIGNMENT);
slider.setAlignmentX(JComponent.LEFT_ALIGNMENT);
box.add(label);
box.add(slider);
// Create a check box that toggles the visibility of text modifiers for all symbols.
JCheckBox cb = new JCheckBox("Text Modifiers", true);
cb.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent actionEvent)
{
boolean tf = ((JCheckBox) actionEvent.getSource()).isSelected();
this.setShowModifiers(pointLayer, tf);
this.setShowModifiers(lineLayer, tf);
this.setShowModifiers(areaLayer, tf);
getWwd().redraw(); // Cause the World Window to refresh in order to make these changes visible.
}
protected void setShowModifiers(RenderableLayer layer, boolean show)
{
for (Renderable r : layer.getRenderables())
{
if (r instanceof TacticalGraphic)
((TacticalGraphic) r).setShowTextModifiers(show);
}
}
});
cb.setAlignmentX(JComponent.LEFT_ALIGNMENT);
box.add(javax.swing.Box.createVerticalStrut(10));
box.add(cb);
// Create a check box that toggles the visibility of graphic modifiers for all symbols.
cb = new JCheckBox("Graphic Modifiers", true);
cb.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent actionEvent)
{
boolean tf = ((JCheckBox) actionEvent.getSource()).isSelected();
this.setShowModifiers(pointLayer, tf);
this.setShowModifiers(lineLayer, tf);
this.setShowModifiers(areaLayer, tf);
getWwd().redraw(); // Cause the World Window to refresh in order to make these changes visible.
}
protected void setShowModifiers(RenderableLayer layer, boolean show)
{
for (Renderable r : layer.getRenderables())
{
if (r instanceof TacticalGraphic)
((TacticalGraphic) r).setShowGraphicModifiers(show);
}
}
});
cb.setAlignmentX(JComponent.LEFT_ALIGNMENT);
box.add(javax.swing.Box.createVerticalStrut(10));
box.add(cb);
// Create a check box that toggles the visibility of text and graphic modifiers for all symbols.
cb = new JCheckBox("Hostile indicator", true);
cb.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent actionEvent)
{
boolean tf = ((JCheckBox) actionEvent.getSource()).isSelected();
this.setShowHostile(pointLayer, tf);
this.setShowHostile(lineLayer, tf);
this.setShowHostile(areaLayer, tf);
getWwd().redraw(); // Cause the World Window to refresh in order to make these changes visible.
}
protected void setShowHostile(RenderableLayer layer, boolean show)
{
for (Renderable r : layer.getRenderables())
{
if (r instanceof TacticalGraphic)
((TacticalGraphic) r).setShowHostileIndicator(show);
}
}
});
cb.setAlignmentX(JComponent.LEFT_ALIGNMENT);
box.add(javax.swing.Box.createVerticalStrut(10));
box.add(cb);
this.getLayerPanel().add(box, BorderLayout.SOUTH);
}
}
public static void main(String[] args)
{
Configuration.setValue(AVKey.INITIAL_LATITUDE, 34.90);
Configuration.setValue(AVKey.INITIAL_LONGITUDE, -117.44);
Configuration.setValue(AVKey.INITIAL_ALTITUDE, 155000);
ApplicationTemplate.start("World Wind Tactical Graphics", AppFrame.class);
}
}