001/** 002 * J3DGeomVector -- A Java3D node that represents a GeomVector 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 geomss.geom.GeomVector; 024import static java.util.Objects.requireNonNull; 025import javax.measure.quantity.Dimensionless; 026import javax.measure.unit.SI; 027import org.jogamp.java3d.*; 028import org.jogamp.vecmath.*; 029 030/** 031 * A Java 3D node that represents a <code>GeomVector</code> in a Java 3D scene graph. 032 * 033 * <p> Modified by: Joseph A. Huwaldt </p> 034 * 035 * @author Joseph A. Huwaldt, Date: June 14, 2009 036 * @version June 4, 2023 037 */ 038public class J3DGeomVector extends J3DGeomGroup<GeomVector> { 039 040 // The switch for main or mirrored geometry. 041 private Switch _symmSG; 042 043 /** 044 * Construct a J3DGeomVector using the specified GeomVector as a reference. 045 * 046 * @param canvas The canvas that the geometry is being rendered into. 047 * @param geometry The GeomSS geometry to be turned into a Java3D node. 048 */ 049 public J3DGeomVector(GeomSSCanvas3D canvas, GeomVector geometry) { 050 super(requireNonNull(canvas), requireNonNull(geometry)); 051 } 052 053 /** 054 * Set the display of a mirrored copy of this geometry. This is called from 055 * "setDisplayed()" to turn on and off the display of mirrored geometry without 056 * changing the "mirrored state" of the object. This call does not affect the output 057 * of "isMirrored()". 058 */ 059 @Override 060 protected void internalSetMirrored(boolean mirrored) { 061 if (mirrored) 062 _symmSG.setWhichChild(Switch.CHILD_ALL); 063 else 064 _symmSG.setWhichChild(0); 065 } 066 067 /** 068 * Create a new Java 3D <code>Group</code> that contains the geometry contained in 069 * this object. This method is called from <code>createSceneGraph</code>. Sub-classes 070 * must over-ride this method to provide geometry specific implementations. 071 * 072 * @return New Java 3D Group that contains the geometry in this object. 073 * @see #createSceneGraph 074 */ 075 @Override 076 protected Group createGeometry() { 077 078 // Create a line and a point array. 079 GeomVector thisVector = this.getGeomElement(); 080 int nVerts = 2; 081 LineArray lineA = new LineArray(nVerts, LineArray.COORDINATES | LineArray.COLOR_4); 082 PointArray pointA = new PointArray(1, PointArray.COORDINATES | PointArray.COLOR_4); 083 084 // Set the coordinates of the line. 085 J3DRenderingPrefs drawPrefs = getRenderingPrefs(); 086 Color4f pointColor = drawPrefs.getPointColorJ3D(); 087 Color4f lineColor = drawPrefs.getLineColorJ3D(); 088 089 // Get the origin point. 090 GeomPoint o = thisVector.getOrigin().to(SI.METER); // Convert all geometry to meters. 091 int dims = o.getPhyDimension(); 092 double x = o.getValue(0); 093 double y = (dims > 1 ? o.getValue(1) : 0); 094 double z = (dims > 2 ? o.getValue(2) : 0); 095 Point3d point3d = new Point3d(x, y, z); 096 097 lineA.setCoordinate(0, point3d); // Store start of line segment. 098 lineA.setColor(0, lineColor); 099 pointA.setCoordinate(0, point3d); 100 pointA.setColor(0, pointColor); 101 102 // Create a point representing the other end of the vector. 103 if (!thisVector.getUnit().equals(Dimensionless.UNIT)) 104 thisVector = (GeomVector)thisVector.to(SI.METER); // Convert all geometry to meters. 105 106 x += thisVector.getValue(0); 107 y += (dims > 1 ? thisVector.getValue(1) : 0); 108 z += (dims > 2 ? thisVector.getValue(2) : 0); 109 point3d = new Point3d(x, y, z); 110 111 lineA.setCoordinate(1, point3d); // Store start of line segment. 112 lineA.setColor(1, lineColor); 113 114 // Create a 3D shape from the line array 115 Shape3D lineShape = new GeomShape3D(thisVector, lineA); 116 117 // Define the appearance of the line. 118 Appearance lineAppearance = new Appearance(); 119 LineAttributes lineAttrib = new LineAttributes(); 120 lineAttrib.setLineWidth(drawPrefs.getLineWidth()); 121 lineAppearance.setLineAttributes(lineAttrib); 122 lineShape.setAppearance(lineAppearance); 123 124 // Create a 3D shape from the point array 125 Shape3D pointShape = new GeomShape3D(thisVector, pointA); 126 Appearance appearance = new Appearance(); 127 pointShape.setAppearance(appearance); 128 appearance.setPointAttributes(new PointAttributes(drawPrefs.getPointSize(), true)); 129 130 // Create a group for the main geometry (unmirrored) 131 // that contains each part of the display properties of a GeomVector. 132 Group renderGroup = new Switch(Switch.CHILD_ALL); 133 renderGroup.setCapability(Switch.ALLOW_SWITCH_READ); 134 renderGroup.setCapability(Switch.ALLOW_SWITCH_WRITE); 135 136 // Add the geometry to the display switch. 137 renderGroup.addChild(lineShape); 138 renderGroup.addChild(pointShape); 139 140 // Add the basic unmirrored geometry to the symmetry switch. 141 _symmSG = new Switch(); 142 _symmSG.setCapability(Switch.ALLOW_SWITCH_READ); 143 _symmSG.setCapability(Switch.ALLOW_SWITCH_WRITE); 144 _symmSG.addChild(renderGroup); 145 146 // Clone the basic geometry to make the mirrored geometry. 147 Node mirrored = renderGroup.cloneTree(); 148 149 // Create a mirror across the XZ plane of symmetry transform. 150 Transform3D symmT = new Transform3D(); 151 symmT.setScale(new Vector3d(1, -1, 1)); 152 TransformGroup symmTG = new TransformGroup(symmT); 153 154 // Add the mirrored geometry to the symmetry transform group. 155 symmTG.addChild(mirrored); 156 157 // Add the mirrored geometry to the symmetry switch. 158 _symmSG.addChild(symmTG); 159 160 // By default, display only the main geometry (not the mirrored). 161 _symmSG.setWhichChild(0); 162 163 return _symmSG; 164 } 165 166 /** 167 * Creates a new instance of the node. This routine is called by 168 * <code>cloneTree</code> to duplicate the current node. 169 * 170 * @param forceDuplicate when set to <code>true</code>, causes the 171 * <code>duplicateOnCloneTree</code> flag to be ignored. When 172 * <code>false</code>, the value of each node's 173 * <code>duplicateOnCloneTree</code> variable determines whether 174 * NodeComponent data is duplicated or copied. 175 * @return A new instance of this Java3D node. 176 */ 177 @Override 178 public Node cloneNode(boolean forceDuplicate) { 179 J3DGeomVector node = new J3DGeomVector(this.getCanvas3D(), this.getGeomElement()); 180 node.duplicateNode(this, forceDuplicate); 181 return node; 182 } 183}