All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.gov.nasa.worldwind.symbology.milstd2525.graphics.lines.AttackRotaryWing Maven / Gradle / Ivy

Go to download

World Wind is a collection of components that interactively display 3D geographic information within Java applications or applets.

There is a newer version: 2.0.0-986
Show newest version
/*
 * Copyright (C) 2012 United States Government as represented by the Administrator of the
 * National Aeronautics and Space Administration.
 * All Rights Reserved.
 */

package gov.nasa.worldwind.symbology.milstd2525.graphics.lines;

import gov.nasa.worldwind.geom.*;
import gov.nasa.worldwind.globes.Globe;
import gov.nasa.worldwind.symbology.milstd2525.graphics.TacGrpSidc;

import java.util.*;

/**
 * Implementation of the Aviation offensive graphic (hierarchy 2.X.2.5.2.1.3, SIDC: G*GPOLAR--****X).
 *
 * @author pabercrombie
 * @version $Id: AttackRotaryWing.java 1171 2013-02-11 21:45:02Z dcollins $
 */
public class AttackRotaryWing extends Aviation
{
    /** Index of the left vertical path in the {@code paths} array. */
    protected final static int LEFT_VERTICAL = 1;
    /** Index of the right vertical path in the {@code paths} array. */
    protected final static int RIGHT_VERTICAL = 2;
    /** Index of the rotor symbol path in the {@code paths} array. */
    protected final static int ROTOR_SYMBOL = 3;

    /**
     * Indicates the graphics supported by this class.
     *
     * @return List of masked SIDC strings that identify graphics that this class supports.
     */
    public static List getSupportedGraphics()
    {
        return Arrays.asList(TacGrpSidc.C2GM_OFF_LNE_AXSADV_ATK);
    }

    /**
     * Create a new graphic.
     *
     * @param sidc Symbol code the identifies the graphic.
     */
    public AttackRotaryWing(String sidc)
    {
        super(sidc, 4);
    }

    @Override
    protected void createLinePositions(List leftPositions, List rightPositions, double halfWidth,
        Globe globe)
    {
        super.createLinePositions(leftPositions, rightPositions, halfWidth, globe);

        // Rotary Wing is based on the Aviation graphic, but adds a symbol for the rotor (an upward pointing arrow),
        // and two vertical lines on either side of the cross over point (X) between points 1 and 2.
        //            |\
        //______      | \
        //     C\    / A \
        //       \  /     \
        // Pt. 2  \/X      \ Pt. 1
        //        /\       /
        //       /  \     /
        // ____B/    \ D /
        //            | /
        //            |/

        Iterator iterator = this.positions.iterator();
        final Position pos1 = iterator.next();
        final Position pos2 = iterator.next();

        final Position posA = rightPositions.get(0);
        final Position posB = rightPositions.get(1);
        final Position posC = leftPositions.get(1);
        final Position posD = leftPositions.get(0);

        final Vec4 p1 = globe.computePointFromLocation(pos1);
        final Vec4 p2 = globe.computePointFromLocation(pos2);

        final Vec4 pA = globe.computePointFromLocation(posA);
        final Vec4 pB = globe.computePointFromLocation(posB);
        final Vec4 pC = globe.computePointFromLocation(posC);
        final Vec4 pD = globe.computePointFromLocation(posD);

        final Vec4 vAB = pB.subtract3(pA);
        final Vec4 vCD = pD.subtract3(pC);

        final Vec4 v21 = p1.subtract3(p2);

        // Find the cross over point, Pt. X
        final Vec4 pMidCA = pA.subtract3(pC).divide3(2).add3(pC); // Find midpoint of segment CA
        final Vec4 pMidBD = pD.subtract3(pB).divide3(2).add3(pB); // Find midpoint of segment BD

        Vec4 pX = pMidBD.subtract3(pMidCA).divide3(2).add3(pMidCA);

        // Make sure that pX falls on one of the lines
        pX = Line.fromSegment(pD, pC).nearestPointTo(pX);

        // Find points required to draw a vertical line on one side of Pt. X
        double offsetDist = vAB.getLength3() / 4;
        Vec4 start = pX.add3(vAB.normalize3().multiply3(offsetDist));
        Vec4 end = pX.add3(vCD.normalize3().multiply3(-offsetDist));

        Position posStart = globe.computePositionFromPoint(start);
        Position posEnd = globe.computePositionFromPoint(end);

        this.paths[LEFT_VERTICAL].setPositions(Arrays.asList(posStart, posEnd));

        // Find points required to draw a vertical line on the other side of Pt. X
        start = pX.add3(vAB.normalize3().multiply3(-offsetDist));
        end = pX.add3(vCD.normalize3().multiply3(offsetDist));

        posStart = globe.computePositionFromPoint(start);
        posEnd = globe.computePositionFromPoint(end);

        this.paths[RIGHT_VERTICAL].setPositions(Arrays.asList(posStart, posEnd));

        // Compute positions for the rotor symbol. Points are named according to this diagram:
        //     H
        //    /|\
        //   / | \
        // I   |  J
        //     |
        // E ----- F
        //     G

        // Compute the width of the symbol base from the width of the entire graphic
        final double halfBaseWidth = halfWidth / 4;

        Vec4 normal = globe.computeSurfaceNormalAtPoint(pX);
        Vec4 perpendicular = v21.cross3(normal).normalize3().multiply3(halfWidth);

        final Vec4 pH = pX.subtract3(perpendicular);
        final Vec4 pG = pX.add3(perpendicular);

        normal = globe.computeSurfaceNormalAtPoint(end);
        perpendicular = start.subtract3(end).cross3(normal).normalize3().multiply3(halfBaseWidth);

        final Vec4 pE = pG.add3(perpendicular);
        final Vec4 pF = pG.subtract3(perpendicular);

        // Find the point on segment HG that is halfBaseWidth away from point H
        Vec4 pMidIJ = pG.subtract3(pH).normalize3().multiply3(halfBaseWidth).add3(pH);

        final Vec4 pI = pMidIJ.add3(perpendicular);
        final Vec4 pJ = pMidIJ.subtract3(perpendicular);

        Position posE = globe.computePositionFromPoint(pE);
        Position posF = globe.computePositionFromPoint(pF);
        Position posG = globe.computePositionFromPoint(pG);
        Position posH = globe.computePositionFromPoint(pH);
        Position posI = globe.computePositionFromPoint(pI);
        Position posJ = globe.computePositionFromPoint(pJ);

        // Draw the symbol as a single path (the path doubles back itself when drawing the base of the symbol, and the
        // arrow head.
        this.paths[ROTOR_SYMBOL].setPositions(Arrays.asList(posE, posF, posG, posH, posI, posH, posJ));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy