1010import gov .nasa .worldwind .geom .*;
1111import gov .nasa .worldwind .globes .Globe ;
1212import gov .nasa .worldwind .render .*;
13- import gov .nasa .worldwind .symbology .SymbologyConstants ;
13+ import gov .nasa .worldwind .symbology .* ;
1414import gov .nasa .worldwind .util .Logging ;
1515
1616import java .awt .geom .*;
@@ -65,6 +65,8 @@ public class MilStd2525Util
6565 protected static final Size DIAMOND_SIZE = Size .fromFraction (0.90625 , 0.90625 );
6666 protected static final Offset DIAMOND_C2_HQ_OFFSET = Offset .fromFraction (0.0 , -0.05172 );
6767
68+ protected static final Vec4 SCREEN_NORMAL = new Vec4 (0.0 , 0.0 , 1.0 , 1.0 );
69+
6870 public static class SymbolInfo
6971 {
7072 public Offset iconOffset ;
@@ -312,10 +314,11 @@ else if ((bd != null && bd.equalsIgnoreCase(SymbologyConstants.BATTLE_DIMENSION_
312314 * @param heading Direction of movement, as a bearing clockwise from North.
313315 * @param length Length of the indicator line, in pixels.
314316 *
317+ * @param directionOnly A value indicating whether is direction only, or speed leader line.
315318 * @return List of screen points that describe the speed leader line.
316319 */
317320 public static List <? extends Point2D > computeCenterHeadingIndicatorPoints (DrawContext dc , Vec4 symbolPoint ,
318- Angle heading , double length )
321+ Angle heading , double length , Boolean directionOnly )
319322 {
320323 if (dc == null )
321324 {
@@ -338,9 +341,17 @@ public static List<? extends Point2D> computeCenterHeadingIndicatorPoints(DrawCo
338341 Vec4 pt1 = view .project (symbolPoint );
339342 Vec4 pt2 = view .project (symbolPoint .add3 (dir ));
340343
341- return Arrays .asList (
342- new Point2D .Double (0 , 0 ),
343- new Point2D .Double (pt2 .x - pt1 .x , pt2 .y - pt1 .y ));
344+ Vec4 base = new Vec4 (0 , 0 );
345+ Vec4 tip = new Vec4 (pt2 .x - pt1 .x , pt2 .y - pt1 .y );
346+
347+ ArrayList <Point2D > points = new ArrayList <Point2D >();
348+ points .add (new Point2D .Double (base .x , base .y ));
349+ points .add (new Point2D .Double (tip .x , tip .y ));
350+
351+ if (directionOnly )
352+ computeArrowHeadPoints (base , tip , points );
353+
354+ return points ;
344355 }
345356
346357 /**
@@ -352,11 +363,11 @@ public static List<? extends Point2D> computeCenterHeadingIndicatorPoints(DrawCo
352363 * @param heading Direction of movement, as a bearing clockwise from North.
353364 * @param length Length of the indicator line, in pixels.
354365 * @param frameHeight Height of the symbol's bounding rectangle, in pixels.
355- *
366+ * @param directionOnly A value indicating whether is direction only, or speed leader line.
356367 * @return List of screen points that describe the speed leader line.
357368 */
358369 public static List <? extends Point2D > computeGroundHeadingIndicatorPoints (DrawContext dc , Vec4 symbolPoint ,
359- Angle heading , double length , double frameHeight )
370+ Angle heading , double length , double frameHeight , Boolean directionOnly )
360371 {
361372 if (dc == null )
362373 {
@@ -379,10 +390,18 @@ public static List<? extends Point2D> computeGroundHeadingIndicatorPoints(DrawCo
379390 Vec4 pt1 = view .project (symbolPoint );
380391 Vec4 pt2 = view .project (symbolPoint .add3 (dir ));
381392
382- return Arrays .asList (
383- new Point2D .Double (0 , 0 ),
384- new Point2D .Double (0 , -frameHeight / 2d ),
385- new Point2D .Double (pt2 .x - pt1 .x , -frameHeight / 2d + (pt2 .y - pt1 .y )));
393+ Vec4 tip = new Vec4 (pt2 .x - pt1 .x , -frameHeight / 2d + (pt2 .y - pt1 .y ));
394+ Vec4 base = new Vec4 (0 , -frameHeight / 2d );
395+
396+ List <Point2D > points = new ArrayList <Point2D >();
397+ points .add (new Point2D .Double (0 , 0 ));
398+ points .add (new Point2D .Double (base .x , base .y ));
399+ points .add (new Point2D .Double (tip .x , tip .y ));
400+
401+ if (directionOnly )
402+ computeArrowHeadPoints (base , tip , points );
403+
404+ return points ;
386405 }
387406
388407 /**
@@ -412,6 +431,38 @@ protected static Vec4 computeDirectionOfMovement(DrawContext dc, Vec4 symbolPoin
412431 return dir .transformBy3 (surfaceOrientation ).normalize3 ().multiply3 (length * pixelSize );
413432 }
414433
434+ /**
435+ * Computes the arrow head points for a direction of movement indicator.
436+ *
437+ * @param base The base point of the direction of movement vector.
438+ * @param tip The end point of the direction of movement vector.
439+ * @param points The list of points to add the arrow line points.
440+ */
441+ private static void computeArrowHeadPoints (Vec4 base , Vec4 tip , List <Point2D > points ){
442+
443+ // Vector that is parallel to the direction between the tip to the base of the arrow
444+ Vec4 parallel = base .subtract3 (tip );
445+
446+ // Compute perpendicular component
447+ Vec4 perpendicular = SCREEN_NORMAL .cross3 (parallel );
448+
449+ double finalArrowLength = 14 ;
450+ double arrowHalfWidth = finalArrowLength * Angle .fromDegrees (30.0 ).tanHalfAngle ();
451+
452+ perpendicular = perpendicular .normalize3 ().multiply3 (arrowHalfWidth );
453+ parallel = parallel .normalize3 ().multiply3 (finalArrowLength );
454+
455+ // Compute geometry of direction arrow
456+ Vec4 vertex1 = tip .add3 (parallel ).add3 (perpendicular );
457+ Vec4 vertex2 = tip .add3 (parallel ).subtract3 (perpendicular );
458+
459+ // Add the extra points to the list of points to draw the arrow head at the end of
460+ // the direction of movement indicator.
461+ points .add (new Point2D .Double (vertex1 .x , vertex1 .y ));
462+ points .add (new Point2D .Double (vertex2 .x , vertex2 .y ));
463+ points .add (new Point2D .Double (tip .x , tip .y ));
464+ }
465+
415466 /**
416467 * Determines a default color to apply to a symbol. MIL-STD-2525C section 5.5.1.1 (pg. 37) states that obstacles
417468 * should be displayed in green, friendly entities in black or blue, and hostile entities in red. This method return
0 commit comments