001/**
002 * J3DGeomPoint -- A Java3D node that represents a GeomPoint in a J3D scene graph.
003 * 
004 * Copyright (C) 2009-2023, Joseph A. Huwaldt
005 * All rights reserved.
006 * 
007 * This library is free software; you can redistribute it and/or modify it under the terms
008 * of the GNU Lesser General Public License as published by the Free Software Foundation;
009 * either version 2.1 of the License, or (at your option) any later version.
010 * 
011 * This library is distributed in the hope that it will be useful, but WITHOUT ANY
012 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
013 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public License along with
016 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place -
017 * Suite 330, Boston, MA 02111-1307, USA. Or visit: http://www.gnu.org/licenses/lgpl.html
018 */
019package geomss.j3d;
020
021import geomss.app.GeomSSCanvas3D;
022import geomss.geom.GeomPoint;
023import static java.util.Objects.requireNonNull;
024import javax.measure.unit.SI;
025import org.jogamp.java3d.*;
026import org.jogamp.vecmath.*;
027
028/**
029 * A Java 3D node that represents a GeomPoint in a Java 3D scene graph.
030 *
031 * <p> Modified by: Joseph A. Huwaldt </p>
032 *
033 * @author Joseph A. Huwaldt, Date: April 13, 2009
034 * @version June 4, 2023
035 */
036public class J3DGeomPoint extends J3DGeomGroup<GeomPoint> {
037
038    //  The switch for main or mirrored geometry.
039    private Switch _symmSG;
040
041    /**
042     * Construct a J3DGeomPoint using the specified GeomPoint as a reference.
043     *
044     * @param canvas   The canvas that the geometry is being rendered into.
045     * @param geometry The GeomSS geometry to be turned into a Java3D node.
046     */
047    public J3DGeomPoint(GeomSSCanvas3D canvas, GeomPoint geometry) {
048        super(requireNonNull(canvas), requireNonNull(geometry));
049    }
050
051    /**
052     * Set the display of a mirrored copy of this geometry. This is called from
053     * "setDisplayed()" to turn on and off the display of mirrored geometry without
054     * changing the "mirrored state" of the object. This call does not affect the output
055     * of "isMirrored()".
056     *
057     * @param mirrored Flag indicating if the mirrored geometry should be displayed or
058     *                 not.
059     * @see #setMirrored(boolean)
060     * @see #isMirrored()
061     */
062    @Override
063    protected void internalSetMirrored(boolean mirrored) {
064        if (mirrored)
065            _symmSG.setWhichChild(Switch.CHILD_ALL);
066        else
067            _symmSG.setWhichChild(0);
068    }
069
070    /**
071     * Create a new Java 3D <code>Group</code> that contains the geometry contained in
072     * this object. This method is called from <code>createSceneGraph</code>. Sub-classes
073     * must over-ride this method to provide geometry specific implementations.
074     *
075     * @return New Java 3D Group that contains the geometry in this object.
076     * @see #createSceneGraph
077     */
078    @Override
079    protected Group createGeometry() {
080        J3DRenderingPrefs drawPrefs = getRenderingPrefs();
081
082        //      Create a point array with a single point in it.
083        PointArray pointA = new PointArray(1, PointArray.COORDINATES | PointArray.COLOR_4);
084        GeomPoint thisPoint = this.getGeomElement();
085        GeomPoint point = thisPoint.to(SI.METER);               //      Convert all geometry to meters.
086        int dims = point.getPhyDimension();
087        double x = point.getValue(0);
088        double y = (dims > 1 ? point.getValue(1) : 0);
089        double z = (dims > 2 ? point.getValue(2) : 0);
090        pointA.setCoordinate(0, new Point3d(x, y, z));
091        pointA.setColor(0, drawPrefs.getPointColorJ3D());
092
093        //      Create a 3D shape from the point array
094        Shape3D pointShape = new GeomShape3D(thisPoint, pointA);
095        Appearance pApp = new Appearance();
096        pointShape.setAppearance(pApp);
097        pApp.setPointAttributes(new PointAttributes(drawPrefs.getPointSize(), true));
098
099        //      Add the basic unmirrored geometry to the switch.
100        _symmSG = new Switch();
101        _symmSG.setCapability(Switch.ALLOW_SWITCH_READ);
102        _symmSG.setCapability(Switch.ALLOW_SWITCH_WRITE);
103        _symmSG.addChild(pointShape);
104
105        //      Clone the basic geometry to make the mirrored geometry.
106        Node mirrored = pointShape.cloneTree();
107
108        //      Create a mirror across the XZ plane of symmetry transform.
109        Transform3D symmT = new Transform3D();
110        symmT.setScale(new Vector3d(1, -1, 1));
111        TransformGroup symmTG = new TransformGroup(symmT);
112
113        //      Add the mirrored geometry to the symmetry transform group.
114        symmTG.addChild(mirrored);
115
116        //      Add the mirrored geometry to the switch.
117        _symmSG.addChild(symmTG);
118
119        //      By default, display only the main geometry (not the mirrored).
120        _symmSG.setWhichChild(0);
121
122        return _symmSG;
123    }
124
125    /**
126     * Creates a new instance of the node. This routine is called by
127     * <code>cloneTree</code> to duplicate the current node.
128     *
129     * @param forceDuplicate when set to <code>true</code>, causes the
130     *                       <code>duplicateOnCloneTree</code> flag to be ignored. When
131     *                       <code>false</code>, the value of each node's
132     *                       <code>duplicateOnCloneTree</code> variable determines whether
133     *                       NodeComponent data is duplicated or copied.
134     * @return A new instance of this Java3D node.
135     */
136    @Override
137    public Node cloneNode(boolean forceDuplicate) {
138        J3DGeomPoint node = new J3DGeomPoint(this.getCanvas3D(), this.getGeomElement());
139        node.duplicateNode(this, forceDuplicate);
140        return node;
141    }
142}