001/**
002 * Axis -- Representation of a set of axes around a origin of a coordinate system.
003 *
004 * Copyright (C) 2009-2015, by Joseph A. Huwaldt. All rights reserved.
005 *
006 * This library is free software; you can redistribute it and/or modify it under the terms
007 * of the GNU Lesser General Public License as published by the Free Software Foundation;
008 * either version 2.1 of the License, or (at your option) any later version.
009 *
010 * This library is distributed in the hope that it will be useful, but WITHOUT ANY
011 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
012 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
013 *
014 * You should have received a copy of the GNU Lesser General Public License along with
015 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place -
016 * Suite 330, Boston, MA 02111-1307, USA. Or visit: http://www.gnu.org/licenses/lgpl.html
017 *
018 *
019 * This class is based on "org.j3d.renderer.java3d.geom.Axis" which bore the following
020 * notation: J3D.org Copyright (c) 2000 Java Source This source is licensed under the GNU
021 * LGPL v2.1
022 */
023package geomss.app;
024
025import java.util.ResourceBundle;
026import javax.media.j3d.*;
027import javax.vecmath.AxisAngle4f;
028import javax.vecmath.Color3f;
029import org.j3d.geom.*;
030
031/**
032 * Representation of a set of axes around the coordinates.
033 * <p>
034 * Each axis is color coordinated and the length can be adjusted.
035 * </p>
036 * <p>
037 * X axis: Red<br>
038 * Y axis: Green<br>
039 * Z axis: Blue
040 * </p>
041 *
042 * <p> Modified by: Joseph A.Huwaldt </p>
043 *
044 * @author Jason Taylor, based on the work by Justin Couch
045 * @version October 19, 2015
046 */
047public class Axis extends Group {
048
049    //  The resource bundle for this class.
050    private static final ResourceBundle RB
051            = ResourceBundle.getBundle("geomss.app.AxisResources", java.util.Locale.getDefault());
052
053    /**
054     * The default length of the axis
055     */
056    private static final float DEFAULT_AXIS_LENGTH = 5;
057
058    /**
059     * The scale to apply to the length to get the thickness for the arrows
060     */
061    private static final float DEFAULT_X_SCALE = 0.05f;
062
063    /**
064     * Create a default axis object with each item length 5 from the origin
065     */
066    public Axis() {
067        this(DEFAULT_AXIS_LENGTH, 0);
068    }
069
070    /**
071     * Create an axis object with the given axis length from the origin.
072     *
073     * @param length The length to use. Must be positive
074     */
075    public Axis(float length) {
076        this(length, 0);
077    }
078
079    /**
080     * Create an axis object with the given axis length from the origin. The transparency
081     * of the axis can be controlled through the use of the second parameter.
082     *
083     * @param length       The length to use. Must be positive
084     * @param transparency The amount of transparency in the axis (0=opaque, 1=fully
085     *                     transparent).
086     */
087    public Axis(float length, float transparency) {
088        if (length <= 0)
089            throw new IllegalArgumentException(RB.getString("axisLengthNegative"));
090
091        // Change the thickness in propotion to the length.
092        float X_SIZE = length * DEFAULT_X_SCALE;
093
094        // Create a single item of geometry and then share/rotate as needed
095        //BoxGenerator box_gen = new BoxGenerator(X_SIZE, length, X_SIZE);
096        CylinderGenerator cyl_gen = new CylinderGenerator(length, X_SIZE, 4);
097
098        int format = GeometryArray.COORDINATES | GeometryArray.NORMALS;
099        GeometryData data = new GeometryData();
100        data.geometryType = GeometryData.TRIANGLE_STRIPS;
101        data.geometryComponents = GeometryData.NORMAL_DATA;
102
103        cyl_gen.generate(data);
104
105        CoordinateUtils cu = new CoordinateUtils();
106        cu.translate(data.coordinates,
107                data.vertexCount,
108                0,
109                length / 2,
110                0);
111
112        TriangleStripArray axis_array
113                = new TriangleStripArray(data.vertexCount, format, data.stripCounts);
114
115        axis_array.setCoordinates(0, data.coordinates);
116        axis_array.setNormals(0, data.normals);
117
118        ConeGenerator cone_gen = new ConeGenerator(X_SIZE * 4, X_SIZE * 2, 3);
119        data.geometryType = GeometryData.INDEXED_TRIANGLE_FANS;
120        data.vertexCount = 0;
121        data.coordinates = null;
122        data.normals = null;
123        data.stripCounts = null;
124
125        cone_gen.generate(data);
126
127        cu.translate(data.coordinates,
128                data.vertexCount,
129                0,
130                length + (X_SIZE * 2),
131                0);
132
133        IndexedTriangleStripArray cone_array
134                = new IndexedTriangleStripArray(data.vertexCount,
135                        format,
136                        data.indexesCount,
137                        data.stripCounts);
138
139        cone_array.setCoordinates(0, data.coordinates);
140        cone_array.setNormals(0, data.normals);
141        cone_array.setCoordinateIndices(0, data.indexes);
142        cone_array.setNormalIndices(0, data.indexes);
143
144        Color3f blue = new Color3f(0, 0, 0.8f);
145        Material blue_material = new Material();
146        blue_material.setDiffuseColor(blue);
147        blue_material.setLightingEnable(true);
148
149        Color3f red = new Color3f(0.8f, 0, 0);
150        Material red_material = new Material();
151        red_material.setDiffuseColor(red);
152        red_material.setLightingEnable(true);
153
154        Color3f green = new Color3f(0, 0.8f, 0);
155        Material green_material = new Material();
156        green_material.setDiffuseColor(green);
157        green_material.setLightingEnable(true);
158
159        Appearance x_app = new Appearance();
160        x_app.setMaterial(red_material);
161
162        Appearance y_app = new Appearance();
163        y_app.setMaterial(green_material);
164
165        Appearance z_app = new Appearance();
166        z_app.setMaterial(blue_material);
167
168        if (transparency != 0) {
169            TransparencyAttributes attr
170                    = new TransparencyAttributes(TransparencyAttributes.FASTEST,
171                            transparency);
172
173            x_app.setTransparencyAttributes(attr);
174            y_app.setTransparencyAttributes(attr);
175            z_app.setTransparencyAttributes(attr);
176        }
177
178        Shape3D x_shape = new Shape3D();
179        x_shape.setAppearance(x_app);
180        x_shape.addGeometry(axis_array);
181        x_shape.addGeometry(cone_array);
182
183        Shape3D y_shape = new Shape3D();
184        y_shape.setAppearance(y_app);
185        y_shape.addGeometry(axis_array);
186        y_shape.addGeometry(cone_array);
187
188        Shape3D z_shape = new Shape3D();
189        z_shape.setAppearance(z_app);
190        z_shape.addGeometry(axis_array);
191        z_shape.addGeometry(cone_array);
192
193        // The three axis values are all pointing up along the Y axis. Apply a
194        // transform to X and Z to move them to the correct position.
195        Transform3D tx = new Transform3D();
196        AxisAngle4f angle = new AxisAngle4f();
197
198        // X Axis first
199        angle.set(0, 0, 1, -(float)(Math.PI * 0.5f));
200        tx.setRotation(angle);
201
202        TransformGroup x_tg = new TransformGroup(tx);
203        x_tg.addChild(x_shape);
204
205        angle.set(1, 0, 0, (float)(Math.PI * 0.5f));
206        tx.setRotation(angle);
207
208        TransformGroup z_tg = new TransformGroup(tx);
209        z_tg.addChild(z_shape);
210
211        addChild(x_tg);
212        addChild(y_shape);
213        addChild(z_tg);
214    }
215}