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

sim.portrayal3d.simple.Arrow Maven / Gradle / Ivy

Go to download

MASON is a fast discrete-event multiagent simulation library core in Java, designed to be the foundation for large custom-purpose Java simulations, and also to provide more than enough functionality for many lightweight simulation needs. MASON contains both a model library and an optional suite of visualization tools in 2D and 3D.

The newest version!
/*
  Copyright 2006 by Sean Luke and George Mason University
  Licensed under the Academic Free License version 3.0
  See the file "LICENSE" for more information
*/

package sim.portrayal3d.simple;

import com.sun.j3d.utils.geometry.*;

import java.awt.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import sim.util.*;

import sim.portrayal3d.SimplePortrayal3D;

/**
 * 
 * @author Gabriel Balan
 * 
 * This file was initially taken from http://www.j3d.org/downloads/Arrow.java
 * 
 * and heavily modified
 */
public class Arrow extends TransformGroup
    {
    static final Color DEFAULT_ARROW_COLOR = Color.gray;
    static final Font3D DEFAULT_FONT3D = new Font3D(new Font(null, Font.PLAIN, 1), null);

    Cone arrowHead;
    Cylinder arrowTail;
    public Cylinder getArrowTail() { return arrowTail; }
    public Cone getArrowHead() { return arrowHead; }

    /**
     * Creates a 3D arrow between points startPoint and
     * endPoint if either label is not null, it adds a Text2D object
     * at the appropriate end.
     */
    public Arrow(double arrowTailRadius, Double3D startPoint, Double3D endPoint, String stLabel,
        String endLabel, Appearance appearance)
        {
        Vector3d stPt = new Vector3d(startPoint.x, startPoint.y, startPoint.z);
        Vector3d endPt = new Vector3d(endPoint.x, endPoint.y, endPoint.z);
        Vector3d v = new Vector3d(stPt);
        v.negate();
        v.add(new Vector3d(endPt));
        // v= start -> end

        float arrowLen = (float) v.length();
        float arrowHeadLen = 5.0f * (float)arrowTailRadius;
        float arrowHeadMaxRadius = 3.0f * (float)arrowTailRadius;
        float cylinderLen = arrowLen - arrowHeadLen;
        
        if(cylinderLen<0)
            {
            //this is a short arrow, 
            //I need a different formula
            arrowHeadLen = arrowLen/16;
            cylinderLen = arrowLen - arrowHeadLen;
            }

        // Apperance for the arrow
        Appearance caAppearance = appearance; 
        if(caAppearance==null)
            {
            caAppearance = SimplePortrayal3D.appearanceForColors(DEFAULT_ARROW_COLOR, null, DEFAULT_ARROW_COLOR, DEFAULT_ARROW_COLOR, 1.0f, 1.0f);
            }

        // Rotation Matrix for whole arrow (cylinder + cone)
        Transform3D caTransform = new Transform3D();
        caTransform.setTranslation(stPt);

        Vector3d oy = new Vector3d(0, 1, 0);

        Vector3d axis = new Vector3d();
        axis.cross(oy, v);
        //if v lies ofn Oy, then axis =[0,0,0]. No rotation is needed
        if(axis.length()!=0)
            {
            //TODO I should use rodrigues formula here
            caTransform.setRotation(new AxisAngle4d(axis, Math.asin(axis.length()
                        / v.length())));
            // axis.length() must be v.length() both doubles or floats, otherwise
            // you might get something bigger than 1.
            }
        caTransform.setTranslation(stPt);

        this.setTransform(caTransform);

        this.arrowTail = new Cylinder((float)arrowTailRadius, cylinderLen, caAppearance);
        Transform3D arrowCylinderTransform = new Transform3D();
        arrowCylinderTransform.set(new Vector3f(0, cylinderLen / 2, 0));
        TransformGroup arrowCylinderTransformGroup = new TransformGroup(
            arrowCylinderTransform);
        arrowCylinderTransformGroup.addChild(this.arrowTail);
        addChild(arrowCylinderTransformGroup);

        Transform3D arrowHeadTransform = new Transform3D();
        arrowHeadTransform.set(new Vector3f(0, cylinderLen, 0));
        TransformGroup arrowHeadTransformGroup = new TransformGroup(
            arrowHeadTransform);
        this.arrowHead = new Cone(arrowHeadMaxRadius, arrowHeadLen, 1, caAppearance);
        arrowHeadTransformGroup.addChild(this.arrowHead);
        this.addChild(arrowHeadTransformGroup);

        if (stLabel != null)
            {
            Text3D txt = new Text3D(DEFAULT_FONT3D, stLabel);
            OrientedShape3D os3d = new OrientedShape3D(txt, caAppearance,
                OrientedShape3D.ROTATE_ABOUT_POINT, new Point3f(0, 0, 0));

            Transform3D t = new Transform3D();
            t.setScale(5 * (float)arrowTailRadius);
            t.setTranslation(new Vector3f(0, -.1f, 0));
            TransformGroup stLabelTG = new TransformGroup(t);

            stLabelTG.addChild(os3d);
            this.addChild(stLabelTG);
            }

        if (endLabel != null)
            {
            Text3D txt = new Text3D(DEFAULT_FONT3D, endLabel);
            OrientedShape3D os3d = new OrientedShape3D(txt, caAppearance,
                OrientedShape3D.ROTATE_ABOUT_POINT, new Point3f(0,
                    arrowLen, 0));

            Transform3D t = new Transform3D();
            t.setScale(5 * (float)arrowTailRadius);
            t.setTranslation(new Vector3f(0, arrowLen + .1f, 0));
            TransformGroup endLabelTG = new TransformGroup(t);

            endLabelTG.addChild(os3d);
            this.addChild(endLabelTG);
            }
        }
    }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy