Skip to content

Commit

Permalink
Implemented the following MIL-STD-2525C graphics:
Browse files Browse the repository at this point in the history
- Fire Support Area, Rectangular (2.X.4.3.2.1.2)
- Sensor Zone, Rectangular
- Dead Space Area, Rectangular
- Zone of Responsibility, Rectangular
- Target Build-up Area, Rectangular
- Target Value Area, Rectangular
- Artillery Target Intelligence Zone, Rectangular (2.X.4.3.3.1.2)
- Call For Fire Zone, Rectangular (2.X.4.3.3.2.2)
- Censor Zone, Rectangular (2.X.4.3.3.4.2)
- Critical Friendly Zone, Rectangular (2.X.4.3.3.6.2)
  • Loading branch information
pabercrombie committed Dec 20, 2011
1 parent cf73ac3 commit 2c1b54a
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 40 deletions.
Expand Up @@ -106,8 +106,18 @@ protected void populateClassMap()
DirectionOfAttack.FUNCTION_ID_SUPPORTING);

this.mapClass(RectangularFireSupportArea.class,
RectangularFireSupportArea.FUNCTION_ID_FSA,
RectangularFireSupportArea.FUNCTION_ID_FFA,
RectangularFireSupportArea.FUNCTION_ID_RFA);
RectangularFireSupportArea.FUNCTION_ID_RFA,
RectangularFireSupportArea.FUNCTION_ID_SENSOR_ZONE,
RectangularFireSupportArea.FUNCTION_ID_DEAD_SPACE_AREA,
RectangularFireSupportArea.FUNCTION_ID_ZONE_OF_RESPONSIBILITY,
RectangularFireSupportArea.FUNCTION_ID_TARGET_BUILDUP,
RectangularFireSupportArea.FUNCTION_ID_TARGET_VALUE,
RectangularFireSupportArea.FUNCTION_ID_ATI,
RectangularFireSupportArea.FUNCTION_ID_CFF,
RectangularFireSupportArea.FUNCTION_ID_CENSOR_ZONE,
RectangularFireSupportArea.FUNCTION_ID_CF);

this.mapClass(CircularFireSupportArea.class,
CircularFireSupportArea.FUNCTION_ID_TARGET,
Expand Down
Expand Up @@ -17,19 +17,12 @@

/**
* Implementation of circular Fire Support graphics. This class implements the following graphics:
*
* <ul>
* <li>Circular Target (2.X.4.3.1.2)</li>
* <li>Fire Support Area, Circular (2.X.4.3.2.1.3)</li>
* <li>Free Fire Area (FFA), Circular (2.X.4.3.2.3.3)</li>
* <li>Restrictive Fire Area (RFA), Circular (2.X.4.3.2.5.3)</li>
* <li>Airspace Coordination Area (ACA), Circular (2.X.4.3.2.2.3)</li>
* <li>Sensor Zone, Circular</li>
* <li>Dead Space Area, Circular</li>
* <li>Zone of Responsibility, Circular</li>
* <li>Target Build-up Area, Circular</li>
* <li>Target Value Area, Circular</li>
* </ul>
* <p/>
* <ul> <li>Circular Target (2.X.4.3.1.2)</li> <li>Fire Support Area, Circular (2.X.4.3.2.1.3)</li> <li>Free Fire Area
* (FFA), Circular (2.X.4.3.2.3.3)</li> <li>Restrictive Fire Area (RFA), Circular (2.X.4.3.2.5.3)</li> <li>Airspace
* Coordination Area (ACA), Circular (2.X.4.3.2.2.3)</li> <li>Sensor Zone, Circular</li> <li>Dead Space Area,
* Circular</li> <li>Zone of Responsibility, Circular</li> <li>Target Build-up Area, Circular</li> <li>Target Value
* Area, Circular</li> </ul>
*
* @author pabercrombie
* @version $Id$
Expand Down Expand Up @@ -63,11 +56,31 @@ public class CircularFireSupportArea extends MilStd2525TacticalGraphic implement
protected SurfaceCircle circle;
protected Object delegateOwner;

/** Create a new circular area. */
public CircularFireSupportArea()
{
this.circle = this.createShape();
}

/**
* Indicates the function IDs of circular Fire Support area graphics that display a date/time range as a separate
* label at the left side of the circle. Whether or not a graphic supports this is determined by the graphic's
* template in MIL-STD-2525C.
*
* @return A Set containing the function IDs of graphics that support a date/time label separate from the graphic's
* main label.
*/
public static Set<String> getGraphicsWithTimeLabel()
{
return new HashSet<String>(Arrays.asList(
FUNCTION_ID_FSA,
FUNCTION_ID_SENSOR_ZONE,
FUNCTION_ID_DEAD_SPACE_AREA,
FUNCTION_ID_ZONE_OF_RESPONSIBILITY,
FUNCTION_ID_TARGET_BUILDUP,
FUNCTION_ID_TARGET_VALUE));
}

/** {@inheritDoc} */
public String getCategory()
{
Expand Down
Expand Up @@ -40,17 +40,17 @@ public String[] createText(MilStd2525TacticalGraphic graphic)
if (CircularFireSupportArea.FUNCTION_ID_TARGET.equals(functionId))
{
// Circular Target just uses the Unique Designation as a label.
result = new String[] { graphic.getText() };
result = new String[] {graphic.getText()};
}
else if (IrregularFireSupportArea.FUNCTION_ID_BOMB.equals(functionId))
{
// Bomb graphic just says "BOMB"
result = new String[] { "BOMB" };
result = new String[] {"BOMB"};
}
else if (IrregularFireSupportArea.FUNCTION_ID_TERMINALLY_GUIDED_MUNITIONS_FOOTPRINT.equals(functionId))
{
// Terminally guided munitions footprint says "TGMF", and does not support modifiers.
result = new String[] { "TGMF" };
result = new String[] {"TGMF"};
}
else
{
Expand All @@ -70,24 +70,20 @@ else if (IrregularFireSupportArea.FUNCTION_ID_TERMINALLY_GUIDED_MUNITIONS_FOOTPR
if (useSeparateTimeLabel)
{
String timeText = this.createTimeRangeText(graphic);
result = new String[] { mainText, timeText };
result = new String[] {mainText, timeText};
}
else
{
result = new String[] { mainText };
result = new String[] {mainText};
}
}
return result;
}

protected boolean isShowSeparateTimeLabel(String functionId)
{
return CircularFireSupportArea.FUNCTION_ID_FSA.equals(functionId)
|| CircularFireSupportArea.FUNCTION_ID_SENSOR_ZONE.equals(functionId)
|| CircularFireSupportArea.FUNCTION_ID_DEAD_SPACE_AREA.equals(functionId)
|| CircularFireSupportArea.FUNCTION_ID_ZONE_OF_RESPONSIBILITY.equals(functionId)
|| CircularFireSupportArea.FUNCTION_ID_TARGET_BUILDUP.equals(functionId)
|| CircularFireSupportArea.FUNCTION_ID_TARGET_VALUE.equals(functionId);
return CircularFireSupportArea.getGraphicsWithTimeLabel().contains(functionId)
|| RectangularFireSupportArea.getGraphicsWithTimeLabel().contains(functionId);
}

protected boolean isAirspaceCoordinationArea(String functionId)
Expand Down Expand Up @@ -159,30 +155,57 @@ else if (RectangularFireSupportArea.FUNCTION_ID_RFA.equals(functionId)
{
return "RFA";
}
else if (CircularFireSupportArea.FUNCTION_ID_FSA.equals(functionId))
else if (RectangularFireSupportArea.FUNCTION_ID_FSA.equals(functionId)
|| CircularFireSupportArea.FUNCTION_ID_FSA.equals(functionId))
{
return "FSA";
}
else if (CircularFireSupportArea.FUNCTION_ID_SENSOR_ZONE.equals(functionId))
else if (RectangularFireSupportArea.FUNCTION_ID_SENSOR_ZONE.equals(functionId)
|| CircularFireSupportArea.FUNCTION_ID_SENSOR_ZONE.equals(functionId)
|| IrregularFireSupportArea.FUNCTION_ID_SENSOR_ZONE.equals(functionId))
{
return "SENSOR\nZONE";
}
else if (CircularFireSupportArea.FUNCTION_ID_DEAD_SPACE_AREA.equals(functionId))
else if (RectangularFireSupportArea.FUNCTION_ID_DEAD_SPACE_AREA.equals(functionId)
|| CircularFireSupportArea.FUNCTION_ID_DEAD_SPACE_AREA.equals(functionId)
|| IrregularFireSupportArea.FUNCTION_ID_DEAD_SPACE_AREA.equals(functionId))
{
return "DA";
}
else if (CircularFireSupportArea.FUNCTION_ID_ZONE_OF_RESPONSIBILITY.equals(functionId))
else if (RectangularFireSupportArea.FUNCTION_ID_ZONE_OF_RESPONSIBILITY.equals(functionId)
|| CircularFireSupportArea.FUNCTION_ID_ZONE_OF_RESPONSIBILITY.equals(functionId)
|| IrregularFireSupportArea.FUNCTION_ID_ZONE_OF_RESPONSIBILITY.equals(functionId))
{
return "ZOR";
}
else if (CircularFireSupportArea.FUNCTION_ID_TARGET_BUILDUP.equals(functionId))
else if (RectangularFireSupportArea.FUNCTION_ID_TARGET_BUILDUP.equals(functionId)
|| CircularFireSupportArea.FUNCTION_ID_TARGET_BUILDUP.equals(functionId)
|| IrregularFireSupportArea.FUNCTION_ID_TARGET_BUILDUP.equals(functionId))
{
return "TBA";
}
else if (CircularFireSupportArea.FUNCTION_ID_TARGET_VALUE.equals(functionId))
else if (RectangularFireSupportArea.FUNCTION_ID_TARGET_VALUE.equals(functionId)
|| CircularFireSupportArea.FUNCTION_ID_TARGET_VALUE.equals(functionId)
|| IrregularFireSupportArea.FUNCTION_ID_TARGET_VALUE.equals(functionId))
{
return "TVAR";
}
else if (RectangularFireSupportArea.FUNCTION_ID_ATI.equals(functionId))
{
return "ATI ZONE";
}
else if (RectangularFireSupportArea.FUNCTION_ID_CFF.equals(functionId))
{
return "CFF ZONE";
}
else if (RectangularFireSupportArea.FUNCTION_ID_CENSOR_ZONE.equals(functionId))
{
return "CENSOR ZONE";
}
else if (RectangularFireSupportArea.FUNCTION_ID_CF.equals(functionId))
{
return "CF ZONE";
}

return "";
}
Expand Down Expand Up @@ -238,5 +261,4 @@ protected String createAirspaceCoordinationText(MilStd2525TacticalGraphic graphi

return sb.toString();
}

}
Expand Up @@ -40,6 +40,16 @@ public class IrregularFireSupportArea extends BasicArea
public final static String FUNCTION_ID_ACA = "ACAI--";
/** Function ID of the Terminally Guided Munitions Footprint graphic. */
public final static String FUNCTION_ID_TERMINALLY_GUIDED_MUNITIONS_FOOTPRINT = "ACT---";
/** Function ID for the Sensor Zone graphic. */
public final static String FUNCTION_ID_SENSOR_ZONE = "ACEI--";
/** Function ID for the Dead Space Area graphic. */
public final static String FUNCTION_ID_DEAD_SPACE_AREA = "ACDI--";
/** Function ID for the Zone of Responsibility graphic. */
public final static String FUNCTION_ID_ZONE_OF_RESPONSIBILITY = "ACZI--";
/** Function ID for the Target Build-up Area graphic. */
public final static String FUNCTION_ID_TARGET_BUILDUP = "ACBI--";
/** Function ID for the Target Value Area graphic. */
public final static String FUNCTION_ID_TARGET_VALUE = "ACVI--";

/** Center text block on label position when the text is left aligned. */
protected final static Offset LEFT_ALIGN_OFFSET = new Offset(-0.5d, -0.5d, AVKey.FRACTION, AVKey.FRACTION);
Expand Down
Expand Up @@ -17,24 +17,45 @@

/**
* Implementation of rectangular Fire Support graphics. This class implements the following graphics:
*
* <ul>
* <li>Free Fire Area (FFA), Rectangular (2.X.4.3.2.3.2)</li>
* <li>Restrictive Fire Area (RFA), Rectangular (2.X.4.3.2.5.2)</li>
* <li>Airspace Coordination Area (ACA), Rectangular (2.X.4.3.2.2.2)</li>
* </ul>
* <p/>
* <ul> <li>Free Fire Area (FFA), Rectangular (2.X.4.3.2.3.2)</li> <li>Restrictive Fire Area (RFA), Rectangular
* (2.X.4.3.2.5.2)</li> <li>Airspace Coordination Area (ACA), Rectangular (2.X.4.3.2.2.2)</li> <li>Sensor Zone,
* Rectangular</li> <li>Dead Space Area, Rectangular</li> <li>Zone of Responsibility, Rectangular</li> <li>Target
* Build-up Area</li> <li>Target Value Area, Rectangular</li> <li>Artillery Target Intelligence Zone, Rectangular
* (2.X.4.3.3.1.2)</li> <li>Call For Fire Zone, Rectangular (2.X.4.3.3.2.2)</li> <li>Censor Zone, Rectangular
* (2.X.4.3.3.4.2)</li> <li>Critical Friendly Zone, Rectangular (2.X.4.3.3.6.2)</li> </ul>
*
* @author pabercrombie
* @version $Id$
*/
public class RectangularFireSupportArea extends MilStd2525TacticalGraphic implements TacticalQuad, PreRenderable
{
/** Function ID for the Fire Support Area graphic (2.X.4.3.2.1.2). */
public final static String FUNCTION_ID_FSA = "ACSR--";
/** Function ID for the Free Fire Area graphic (2.X.4.3.2.3.2). */
public final static String FUNCTION_ID_FFA = "ACFR--";
/** Function ID for the Restrictive Fire Area graphic (2.X.4.3.2.5.2). */
public final static String FUNCTION_ID_RFA = "ACRR--";
/** Function ID for the Airspace Coordination Area graphic (2.X.4.3.2.2.2). */
public final static String FUNCTION_ID_ACA = "ACAR--";
/** Function ID for the Sensor Zone graphic. */
public final static String FUNCTION_ID_SENSOR_ZONE = "ACER--";
/** Function ID for the Dead Space Area graphic. */
public final static String FUNCTION_ID_DEAD_SPACE_AREA = "ACDR--";
/** Function ID for the Zone of Responsibility graphic. */
public final static String FUNCTION_ID_ZONE_OF_RESPONSIBILITY = "ACZR--";
/** Function ID for the Target Build-up Area graphic. */
public final static String FUNCTION_ID_TARGET_BUILDUP = "ACBR--";
/** Function ID for the Target Value Area graphic. */
public final static String FUNCTION_ID_TARGET_VALUE = "ACVR--";
/** Function ID for the Artillery Target Intelligence Zone graphic (2.X.4.3.3.1.2). */
public final static String FUNCTION_ID_ATI = "AZIR--";
/** Function ID for the Call For Fire Zone graphic (2.X.4.3.3.2.2). */
public final static String FUNCTION_ID_CFF = "AZXR--";
/** Function ID for the Censor Zone graphic (2.X.4.3.3.4.2). */
public final static String FUNCTION_ID_CENSOR_ZONE = "AZCR--";
/** Function ID for the Critical Friendly Zone graphic (2.X.4.3.3.6.2). */
public final static String FUNCTION_ID_CF = "AZFR--";

/** Center text block on label position when the text is left aligned. */
protected final static Offset LEFT_ALIGN_OFFSET = new Offset(-0.5d, -0.5d, AVKey.FRACTION, AVKey.FRACTION);
Expand All @@ -50,6 +71,29 @@ public RectangularFireSupportArea()
this.quad = this.createShape();
}

/**
* Indicates the function IDs of rectangular Fire Support area graphics that display a date/time range as a separate
* label at the left side of the rectangle. Whether or not a graphic supports this is determined by the graphic's
* template in MIL-STD-2525C.
*
* @return A Set containing the function IDs of graphics that support a date/time label separate from the graphic's
* main label.
*/
public static Set<String> getGraphicsWithTimeLabel()
{
return new HashSet<String>(Arrays.asList(
FUNCTION_ID_FSA,
FUNCTION_ID_SENSOR_ZONE,
FUNCTION_ID_DEAD_SPACE_AREA,
FUNCTION_ID_ZONE_OF_RESPONSIBILITY,
FUNCTION_ID_TARGET_BUILDUP,
FUNCTION_ID_TARGET_VALUE,
FUNCTION_ID_ATI,
FUNCTION_ID_CFF,
FUNCTION_ID_CENSOR_ZONE,
FUNCTION_ID_CF));
}

/** {@inheritDoc} */
public String getCategory()
{
Expand Down Expand Up @@ -225,18 +269,48 @@ public void doRenderGraphic(DrawContext dc)
protected void createLabels()
{
FireSupportTextBuilder textBuilder = new FireSupportTextBuilder();
String text = textBuilder.createText(this)[0];
String[] allText = textBuilder.createText(this);

String text = allText[0];
if (!WWUtil.isEmpty(text))
{
Label mainLabel = this.addLabel(text);
mainLabel.setTextAlign(this.getMainLabelTextAlign());
}

if (allText.length > 1)
{
Label timeLabel = this.addLabel(allText[1]);
timeLabel.setTextAlign(AVKey.RIGHT);

// Align the upper right corner of the time label with the upper right corner of the quad.
timeLabel.setOffset(new Offset(0d, 0d, AVKey.FRACTION, AVKey.FRACTION));
}
}

@Override
protected void determineLabelPositions(DrawContext dc)
{
this.labels.get(0).setPosition(new Position(this.quad.getCenter(), 0));
Position center = new Position(this.quad.getCenter(), 0);
this.labels.get(0).setPosition(center);

if (this.labels.size() > 1)
{
double hw = this.quad.getWidth() / 2.0;
double hh = this.quad.getHeight() / 2.0;
double globeRadius = dc.getGlobe().getRadiusAt(center.getLatitude(), center.getLongitude());
double distance = Math.sqrt(hw * hw + hh * hh);
double pathLength = distance / globeRadius;

// Find the upper left corner (looking the quad such that Point 1 is on the left and Point 2 is on the right,
// and the line between the two is horizontal, as the quad is pictured in the MIL-STD-2525C spec, pg. 652).
double cornerAngle = Math.atan2(-hh, hw);
double azimuth = (Math.PI / 2.0) - (cornerAngle - this.quad.getHeading().radians);

LatLon corner = LatLon.greatCircleEndPosition(center, azimuth, pathLength);

this.labels.get(1).setPosition(new Position(corner, 0));
}
}

/**
Expand Down
Expand Up @@ -358,6 +358,20 @@ protected void createAreaGraphics(RenderableLayer layer)
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, 0),
Position.fromDegrees(35.0620, -117.1606, 0));
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);
}
}

Expand Down

0 comments on commit 2c1b54a

Please sign in to comment.