package Savage.Robots.UnmannedUnderwaterVehicles;

import org.web3d.x3d.jsail.Core.*;
import org.web3d.x3d.jsail.fields.*;
import org.web3d.x3d.jsail.Geometry3D.*;
import org.web3d.x3d.jsail.Grouping.*;
import org.web3d.x3d.jsail.Navigation.*;
import org.web3d.x3d.jsail.Networking.*;
import org.web3d.x3d.jsail.Rendering.*;
import org.web3d.x3d.jsail.Scripting.*;
import org.web3d.x3d.jsail.Shape.*;
import org.web3d.x3d.jsail.Text.*;

// Javadoc metadata annotations follow, see below for X3DJSAIL Java source code.
/**
 * <p> Model of the Acoustic Radio Interactive Exploratory Server (ARIES), an operational NPS-designed Unmanned Underwater Vehicle (AUV). Expose position, rotation, sonars, thrusters, fins, etc. as a reusable prototype. </p>
 <p> Related links: Catalog page <a href="../../../../Robots/UnmannedUnderwaterVehicles/AriesPrototypeIndex.html" target="_blank">AriesPrototype</a>,  source <a href="../../../../Robots/UnmannedUnderwaterVehicles/AriesPrototype.java">AriesPrototype.java</a>, <a href="https://www.web3d.org/x3d/content/examples/X3dResources.html" target="_blank">X3D Resources</a>, <a href="https://www.web3d.org/x3d/content/examples/X3dSceneAuthoringHints.html" target="_blank">X3D Scene Authoring Hints</a>, and <a href="https://www.web3d.org/x3d/content/X3dTooltips.html" target="_blank">X3D Tooltips</a>. </p>
	<table style="color:black; border:0px solid; border-spacing:10px 0px;">
        <caption>Scene Meta Information</caption>
		<tr style="background-color:silver; border-color:silver;">
			<td style="text-align:center; padding:10px 0px;"><i>meta tags</i></td>
			<td style="text-align:left;   padding:10px 0px;">&nbsp; Document Metadata </td>
		</tr>

		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> title </i> </td>
			<td> <a href="../../../../Robots/UnmannedUnderwaterVehicles/AriesPrototype.x3d">AriesPrototype.x3d</a> </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> description </i> </td>
			<td> Model of the Acoustic Radio Interactive Exploratory Server (ARIES), an operational NPS-designed Unmanned Underwater Vehicle (AUV). Expose position, rotation, sonars, thrusters, fins, etc. as a reusable prototype. </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> creator </i> </td>
			<td> Don Brutzman NPS, aboard RV Gyre in Gulf of Mexico off Gulfport MS 1999; Jane Wu Rolands and Associates 2001, Duane Davis NPS 2003 </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> created </i> </td>
			<td> 30 July 2000 </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> modified </i> </td>
			<td> 20 October 2019 </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> photo </i> </td>
			<td> AriesHoistCloseup.jpg </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> reference </i> </td>
			<td> <a href="../../../../Robots/UnmannedUnderwaterVehicles/AriesFlyerMarch2001.pdf">AriesFlyerMarch2001.pdf</a> </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> reference </i> </td>
			<td> <a href="../../../../Robots/UnmannedUnderwaterVehicles/organic_mcmONR2002.pdf">organic_mcmONR2002.pdf</a> </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> reference </i> </td>
			<td> AriesSchematic.png </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> reference </i> </td>
			<td> AriesSchematic.ppt </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> identifier </i> </td>
			<td> <a href="https://www.web3d.org/x3d/content/examples/Savage/Robots/UnmannedUnderwaterVehicles/AriesPrototype.x3d" target="_blank">https://www.web3d.org/x3d/content/examples/Savage/Robots/UnmannedUnderwaterVehicles/AriesPrototype.x3d</a> </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> generator </i> </td>
			<td> X3D-Edit 3.2, <a href="https://www.web3d.org/x3d/tools/X3D-Edit" target="_blank">https://www.web3d.org/x3d/tools/X3D-Edit</a> </td>
		</tr>
		<tr>
			<td style="text-align:right; vertical-align: text-top;"> <i> license </i> </td>
			<td> <a href="../../../../Robots/UnmannedUnderwaterVehicles/../../license.html">../../license.html</a> </td>
		</tr>
		<tr style="background-color:silver; border-color:silver;">
			<td style="text-align:center;" colspan="2">  &nbsp; </td>
		</tr>
	</table>

	<p>
		This program uses the
		<a href="https://www.web3d.org/specifications/java/X3DJSAIL.html" target="_blank">X3D Java Scene Access Interface Library (X3DJSAIL)</a>.
		It has been produced using the 
		<a href="https://www.web3d.org/x3d/stylesheets/X3dToJava.xslt" target="_blank">X3dToJava.xslt</a>
		stylesheet
	       (<a href="https://sourceforge.net/p/x3d/code/HEAD/tree/www.web3d.org/x3d/stylesheets/X3dToJava.xslt" target="_blank">version control</a>)
                which is used to create Java source code from an original <code>.x3d</code> model.
	</p>

	* @author Don Brutzman NPS, aboard RV Gyre in Gulf of Mexico off Gulfport MS 1999; Jane Wu Rolands and Associates 2001, Duane Davis NPS 2003
 */

public class AriesPrototype
{
	/** Default constructor to create this object. */
	public AriesPrototype ()
	{
	  initialize();
	}

	/** Create and initialize the X3D model for this object. */
	public final void initialize()
	{
            try { // catch-all
  x3dModel = new X3D().setProfile(X3D.PROFILE_IMMERSIVE).setVersion(X3D.VERSION_3_0)
  .setHead(new head()
    .addMeta(new meta().setName(meta.NAME_TITLE      ).setContent("AriesPrototype.x3d"))
    .addMeta(new meta().setName(meta.NAME_DESCRIPTION).setContent("Model of the Acoustic Radio Interactive Exploratory Server (ARIES), an operational NPS-designed Unmanned Underwater Vehicle (AUV). Expose position, rotation, sonars, thrusters, fins, etc. as a reusable prototype."))
    .addMeta(new meta().setName(meta.NAME_CREATOR    ).setContent("Don Brutzman NPS, aboard RV Gyre in Gulf of Mexico off Gulfport MS 1999; Jane Wu Rolands and Associates 2001, Duane Davis NPS 2003"))
    .addMeta(new meta().setName(meta.NAME_CREATED    ).setContent("30 July 2000"))
    .addMeta(new meta().setName(meta.NAME_MODIFIED   ).setContent("20 October 2019"))
    .addMeta(new meta().setName(meta.NAME_PHOTO      ).setContent("AriesHoistCloseup.jpg"))
    .addMeta(new meta().setName(meta.NAME_REFERENCE  ).setContent("AriesFlyerMarch2001.pdf"))
    .addMeta(new meta().setName(meta.NAME_REFERENCE  ).setContent("organic_mcmONR2002.pdf"))
    .addMeta(new meta().setName(meta.NAME_REFERENCE  ).setContent("AriesSchematic.png"))
    .addMeta(new meta().setName(meta.NAME_REFERENCE  ).setContent("AriesSchematic.ppt"))
    .addMeta(new meta().setName(meta.NAME_IDENTIFIER ).setContent("https://www.web3d.org/x3d/content/examples/Savage/Robots/UnmannedUnderwaterVehicles/AriesPrototype.x3d"))
    .addMeta(new meta().setName(meta.NAME_GENERATOR  ).setContent("X3D-Edit 3.2, https://www.web3d.org/x3d/tools/X3D-Edit"))
    .addMeta(new meta().setName(meta.NAME_LICENSE    ).setContent("../../license.html")))
  .setScene(new Scene()
    .addComments(" Produce wireframe or transparent beam cones. ")
    .addChild(new WorldInfo().setTitle("AriesPrototype.x3d"))
    .addChild(new ExternProtoDeclare("BeamCone").setName("BeamCone").setAppinfo("Produce wireframe or transparent beam cones. Typical uses include propeller/thruster water flow or line-of-sight sonar/radar/light beams. Negative range values invert base and apex at same relative location. Default: beam with apex at (0 0 0) and base of radius 1 in x-z plane at (1 0 0).").setUrl(new String[] {"../../CommunicationsAndSensors/Beam/BeamConePrototype.x3d#BeamCone","https://www.web3d.org/x3d/content/examples/Savage/CommunicationsAndSensors/Beam/BeamConePrototype.x3d#BeamCone","../../CommunicationsAndSensors/Beam/BeamConePrototype.wrl#BeamCone","https://www.web3d.org/x3d/content/examples/Savage/CommunicationsAndSensors/Beam/BeamConePrototype.wrl#BeamCone"})
      .addField(new field().setName("name").setType(field.TYPE_SFSTRING).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setAppinfo("BeamCone name aids tracing"))
      .addField(new field().setName("contact").setType(field.TYPE_SFBOOL).setAccessType(field.ACCESSTYPE_INPUTONLY).setAppinfo("(communications) is transmitted signal in contact with receiver or (sensor) is a target return detected?"))
      .addField(new field().setName("range").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY).setAppinfo("distance in meters along x axis"))
      .addField(new field().setName("defaultRange").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setAppinfo("distance in meters used until eventIn range sent"))
      .addField(new field().setName("wireframe").setType(field.TYPE_SFBOOL).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setAppinfo("whether wireframe beam is drawn"))
      .addField(new field().setName("solid").setType(field.TYPE_SFBOOL).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setAppinfo("whether solid beam is drawn"))
      .addField(new field().setName("beamHeightDegrees").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setAppinfo("degrees across vertical y axis"))
      .addField(new field().setName("beamWidthDegrees").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setAppinfo("degrees across horizontal z axis"))
      .addField(new field().setName("contactColor").setType(field.TYPE_SFCOLOR).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setAppinfo("rendering color when contact=true"))
      .addField(new field().setName("noContactColor").setType(field.TYPE_SFCOLOR).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setAppinfo("rendering color when contact=false"))
      .addField(new field().setName("transparency").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTOUTPUT).setAppinfo("1 = fully transparent wireframe only"))
      .addField(new field().setName("traceEnabled").setType(field.TYPE_SFBOOL).setAccessType(field.ACCESSTYPE_INITIALIZEONLY).setAppinfo("flag to turn on Script tracing")))
    .addChild(new ProtoDeclare("Aries").setName("Aries").setAppinfo("Acoustic Radio Interactive Exploratory Server (ARIES) is an operational NPS-designed Unmanned Underwater Vehicle (AUV)")
      .setProtoInterface(new ProtoInterface()
        .addField(new field().setName("hullName").setType(field.TYPE_SFSTRING).setAccessType(field.ACCESSTYPE_INPUTOUTPUT).setValue("Aries").setAppinfo("can be overridden at instantiation time only"))
        .addField(new field().setName("hullColor").setType(field.TYPE_SFCOLOR).setAccessType(field.ACCESSTYPE_INPUTOUTPUT).setValue(new SFColor(.9,.9,.9)).setAppinfo("hull color for this UUV instance"))
        .addField(new field().setName("planeColor").setType(field.TYPE_SFCOLOR).setAccessType(field.ACCESSTYPE_INPUTOUTPUT).setValue(new SFColor(.1,.1,.8)).setAppinfo("plane color for this UUV instance"))
        .addField(new field().setName("translation").setType(field.TYPE_SFVEC3F).setAccessType(field.ACCESSTYPE_INPUTOUTPUT).setValue(new SFVec3f(0.0,0.0,0.0)))
        .addField(new field().setName("rotation").setType(field.TYPE_SFROTATION).setAccessType(field.ACCESSTYPE_INPUTOUTPUT).setValue(new SFRotation(0.0,0.0,1.0,0.0)))
        .addField(new field().setName("set_portRpm").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
        .addField(new field().setName("set_stbdRpm").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
        .addField(new field().setName("set_forwardRudders").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
        .addField(new field().setName("set_afterRudders").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
        .addField(new field().setName("set_forwardPlanes").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
        .addField(new field().setName("set_afterPlanes").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
        .addField(new field().setName("set_forwardVerticalThruster").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
        .addField(new field().setName("set_afterVerticalThruster").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
        .addField(new field().setName("set_forwardLateralThruster").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
        .addField(new field().setName("set_afterLateralThruster").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
        .addField(new field().setName("set_ST725Range").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY).setAppinfo("meters along sonar axis"))
        .addField(new field().setName("set_ST725Bearing").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY).setAppinfo("degrees about vertical axis"))
        .addField(new field().setName("set_ST725Intensity").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY).setAppinfo("signal-to-noise ratio decibels"))
        .addField(new field().setName("set_ST1000Range").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY).setAppinfo("meters along sonar axis"))
        .addField(new field().setName("set_ST1000Bearing").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY).setAppinfo("degrees about vertical axis"))
        .addField(new field().setName("set_ST1000Intensity").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY).setAppinfo("signal-to-noise ratio decibels")))
      .setProtoBody(new ProtoBody()
        .addChild(new Transform("AriesTransform")
          .setIS(new IS()
            .addConnect(new connect().setNodeField("translation").setProtoField("translation"))
            .addConnect(new connect().setNodeField("rotation").setProtoField("rotation")))
          .addChild(new Transform("ST725").setTranslation(.9,-0.12,-0.03)
            .addChild(new ProtoInstance("BeamCone", "ST725BeamCone").setContainerField("children")
              .addFieldValue(new fieldValue().setName("name").setValue("ST725BeamCone"))
              .addFieldValue(new fieldValue().setName("defaultRange").setValue(1))
              .addFieldValue(new fieldValue().setName("beamHeightDegrees").setValue(24))
              .addFieldValue(new fieldValue().setName("beamWidthDegrees").setValue(1))
              .addFieldValue(new fieldValue().setName("solid").setValue(true))
              .addFieldValue(new fieldValue().setName("wireframe").setValue(false))
              .addFieldValue(new fieldValue().setName("contactColor").setValue(new SFColor(1.0,0.0,0.0)))
              .addFieldValue(new fieldValue().setName("noContactColor").setValue(new SFColor(.3,.05,.05)))
              .addFieldValue(new fieldValue().setName("transparency").setValue(.2))
              .addFieldValue(new fieldValue().setName("traceEnabled").setValue(false))))
          .addChild(new Transform("ST1000").setTranslation(.7,.12,.05)
            .addChild(new ProtoInstance("BeamCone", "ST1000BeamCone").setContainerField("children")
              .addFieldValue(new fieldValue().setName("name").setValue("ST1000BeamCone"))
              .addFieldValue(new fieldValue().setName("defaultRange").setValue(1))
              .addFieldValue(new fieldValue().setName("beamHeightDegrees").setValue(1))
              .addFieldValue(new fieldValue().setName("beamWidthDegrees").setValue(1))
              .addFieldValue(new fieldValue().setName("solid").setValue(true))
              .addFieldValue(new fieldValue().setName("wireframe").setValue(false))
              .addFieldValue(new fieldValue().setName("contactColor").setValue(new SFColor(1.0,.8,0.0)))
              .addFieldValue(new fieldValue().setName("noContactColor").setValue(new SFColor(.4,.3,.05)))
              .addFieldValue(new fieldValue().setName("transparency").setValue(.2))
              .addFieldValue(new fieldValue().setName("traceEnabled").setValue(false))))
          .addChild(new Script("SONAR_STEERING_AND_DETECTS").setSourceCode("""
ecmascript:

function degreeToRadian( value )
{
   return value * Math.PI / 180;
}

function set_ST725Range (value, timeStamp)
{
   if ((value > 0) && (value < 30.0))
   {
      ST725Contact = true;
      ST725Range_changed = value;
   }
   else
   {
      ST725Contact = false;
      if ( value < 0 )
         ST725Range_changed = 0.0;
      else
         ST725Range_changed = 30.0;
   }
}
function set_ST725Bearing (value, timeStamp)
{
   ST725Rotation = new SFRotation(0, 1, 0, degreeToRadian(value));
}
function set_ST725Intensity (value, timeStamp)
{
   ST725Intensity = new SFFloat(value);
}

function set_ST1000Range (value, timeStamp)
{
   if ((value > 0) && (value < 30.0))
   {
      ST1000Contact = true;
      ST1000Range_changed = value;
   }
   else
   {
      ST1000Contact = false;
      if ( value < 0 )
         ST1000Range_changed = 0.0;
      else
         ST1000Range_changed = 30.0;
   }
}
function set_ST1000Bearing (value, timeStamp)
{
   ST1000Rotation = new SFRotation(0, 1, 0, degreeToRadian(value));
}
function set_ST1000Intensity (value, timeStamp)
{
   ST1000Intensity = new SFFloat(value);
}
""")
            .addField(new field().setName("set_ST725Range").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
            .addField(new field().setName("set_ST725Bearing").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
            .addField(new field().setName("set_ST725Intensity").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
            .addField(new field().setName("set_ST1000Range").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
            .addField(new field().setName("set_ST1000Bearing").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
            .addField(new field().setName("set_ST1000Intensity").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
            .addField(new field().setName("ST725Rotation").setType(field.TYPE_SFROTATION).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
            .addField(new field().setName("ST1000Rotation").setType(field.TYPE_SFROTATION).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
            .addField(new field().setName("ST725Contact").setType(field.TYPE_SFBOOL).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
            .addField(new field().setName("ST1000Contact").setType(field.TYPE_SFBOOL).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
            .addField(new field().setName("ST725Range_changed").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
            .addField(new field().setName("ST1000Range_changed").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
            .addField(new field().setName("ST725Intensity").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
            .addField(new field().setName("ST1000Intensity").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
            .setIS(new IS()
              .addConnect(new connect().setNodeField("set_ST725Range").setProtoField("set_ST725Range"))
              .addConnect(new connect().setNodeField("set_ST725Bearing").setProtoField("set_ST725Bearing"))
              .addConnect(new connect().setNodeField("set_ST725Intensity").setProtoField("set_ST725Intensity"))
              .addConnect(new connect().setNodeField("set_ST1000Range").setProtoField("set_ST1000Range"))
              .addConnect(new connect().setNodeField("set_ST1000Bearing").setProtoField("set_ST1000Bearing"))
              .addConnect(new connect().setNodeField("set_ST1000Intensity").setProtoField("set_ST1000Intensity"))))
          .addChild(new Group()
            .addChild(new ROUTE().setFromNode("SONAR_STEERING_AND_DETECTS").setFromField("ST725Rotation").setToNode("ST725").setToField("rotation"))
            .addChild(new ROUTE().setFromNode("SONAR_STEERING_AND_DETECTS").setFromField("ST1000Rotation").setToNode("ST1000").setToField("rotation"))
            .addChild(new ROUTE().setFromNode("SONAR_STEERING_AND_DETECTS").setFromField("ST725Contact").setToNode("ST725BeamCone").setToField("contact"))
            .addChild(new ROUTE().setFromNode("SONAR_STEERING_AND_DETECTS").setFromField("ST1000Contact").setToNode("ST1000BeamCone").setToField("contact"))
            .addChild(new ROUTE().setFromNode("SONAR_STEERING_AND_DETECTS").setFromField("ST725Range_changed").setToNode("ST725BeamCone").setToField("range"))
            .addChild(new ROUTE().setFromNode("SONAR_STEERING_AND_DETECTS").setFromField("ST1000Range_changed").setToNode("ST1000BeamCone").setToField("range"))
            .addChild(new ROUTE().setFromNode("SONAR_STEERING_AND_DETECTS").setFromField("ST725Intensity").setToNode("ST725BeamCone").setToField("transparency"))
            .addChild(new ROUTE().setFromNode("SONAR_STEERING_AND_DETECTS").setFromField("ST1000Intensity").setToNode("ST1000BeamCone").setToField("transparency")))
          .addChild(new LOD().setRange(new double[] {400.0})
            .addComments(" ### hack job! need to update actual numbers instead of scaling ")
            .addChild(new Transform("PRIMARY_AUV_GEOMETRY").setScale(1.0,1.3,1.0)
              .addComments(" positive rotation about y-axis rotates rudders to port ")
              .addChild(new Transform("FORWARD_RUDDERS").setTranslation(.6223,0.0,0.0)
                .addChild(new Transform().setTranslation(0.0,.13335,0.0)
                  .addChild(new Shape("PLANE_SHAPE")
                    .setAppearance(new Appearance()
                      .setMaterial(new Material("PlaneMaterial")
                        .setIS(new IS()
                          .addConnect(new connect().setNodeField("diffuseColor").setProtoField("planeColor")))))
                    .addComments(" creaseAngle for sharp edges ")
                    .setGeometry(new IndexedFaceSet().setCreaseAngle(3.14159).setCoordIndex(new int[] {0,3,2,1,-1,4,5,6,7,-1,0,1,5,4,-1,1,2,6,5,-1,2,3,7,6,-1,0,3,7,4,-1})
                      .addComments(" indices for point values range [0..7] ")
                      .setCoord(new Coordinate().setPoint(new MFVec3f(new double[] {.0635,0.0,-0.0127,.0381,.1778,-0.0127,-0.0381,.1778,-0.0127,-0.0889,0.0,-0.0127,.0635,0.0,.0127,.0381,.1778,.0127,-0.0381,.1778,.0127,-0.0889,0.0,.0127}))))))
                .addChild(new Transform().setRotation(1.0,0.0,0.0,3.14159267).setTranslation(0.0,-0.13335,0.0)
                  .addChild(new Shape().setUSE("PLANE_SHAPE"))))
              .addComments(" positive rotation about y-axis rotates rudder to port ")
              .addChild(new Transform("AFTER_RUDDERS").setTranslation(-0.7747,0.0,0.0)
                .addChild(new Transform().setTranslation(0.0,.13335,0.0)
                  .addChild(new Shape().setUSE("PLANE_SHAPE")))
                .addChild(new Transform().setRotation(1.0,0.0,0.0,3.14159267).setTranslation(0.0,-0.13335,0.0)
                  .addChild(new Shape().setUSE("PLANE_SHAPE"))))
              .addChild(new Transform("FORWARD_PLANES").setTranslation(.6223,0.0,0.0)
                .addChild(new Transform().setRotation(1.0,0.0,0.0,1.57079).setTranslation(0.0,0.0,.20955)
                  .addChild(new Shape().setUSE("PLANE_SHAPE")))
                .addChild(new Transform().setRotation(1.0,0.0,0.0,-1.57079).setTranslation(0.0,0.0,-0.20955)
                  .addChild(new Shape().setUSE("PLANE_SHAPE"))))
              .addChild(new Transform("AFTER_PLANES").setTranslation(-0.7747,0.0,0.0)
                .addChild(new Transform().setRotation(1.0,0.0,0.0,1.57079).setTranslation(0.0,0.0,.20955)
                  .addChild(new Shape().setUSE("PLANE_SHAPE")))
                .addChild(new Transform().setRotation(1.0,0.0,0.0,-1.57079).setTranslation(0.0,0.0,-0.20955)
                  .addChild(new Shape().setUSE("PLANE_SHAPE"))))
              .addChild(new Script("PLANE_SURFACES").setSourceCode("""
ecmascript:

function set_forwardRudders (value, timeStamp) {
   forwardRuddersRotation = new SFRotation(0, 1, 0, value);
}

function set_afterRudders (value, timeStamp) {
   afterRuddersRotation = new SFRotation(0, 1, 0, value);
}

function set_forwardPlanes (value, timeStamp) {
   forwardPlanesRotation = new SFRotation(0, 0, 1, value);
}

function set_afterPlanes (value, timeStamp) {
   afterPlanesRotation = new SFRotation(0, 0, 1, value);
}
""")
                .addField(new field().setName("set_forwardRudders").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
                .addField(new field().setName("set_afterRudders").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
                .addField(new field().setName("set_forwardPlanes").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
                .addField(new field().setName("set_afterPlanes").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
                .addField(new field().setName("forwardRuddersRotation").setType(field.TYPE_SFROTATION).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
                .addField(new field().setName("afterRuddersRotation").setType(field.TYPE_SFROTATION).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
                .addField(new field().setName("forwardPlanesRotation").setType(field.TYPE_SFROTATION).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
                .addField(new field().setName("afterPlanesRotation").setType(field.TYPE_SFROTATION).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
                .setIS(new IS()
                  .addConnect(new connect().setNodeField("set_forwardRudders").setProtoField("set_forwardRudders"))
                  .addConnect(new connect().setNodeField("set_afterRudders").setProtoField("set_afterRudders"))
                  .addConnect(new connect().setNodeField("set_forwardPlanes").setProtoField("set_forwardPlanes"))
                  .addConnect(new connect().setNodeField("set_afterPlanes").setProtoField("set_afterPlanes"))))
              .addChild(new Group()
                .addChild(new ROUTE().setFromNode("PLANE_SURFACES").setFromField("forwardRuddersRotation").setToNode("FORWARD_RUDDERS").setToField("rotation"))
                .addChild(new ROUTE().setFromNode("PLANE_SURFACES").setFromField("afterRuddersRotation").setToNode("AFTER_RUDDERS").setToField("rotation"))
                .addChild(new ROUTE().setFromNode("PLANE_SURFACES").setFromField("forwardPlanesRotation").setToNode("FORWARD_PLANES").setToField("rotation"))
                .addChild(new ROUTE().setFromNode("PLANE_SURFACES").setFromField("afterPlanesRotation").setToNode("AFTER_PLANES").setToField("rotation")))
              .addChild(new Transform("FORWARD_VERTICAL_THRUSTER").setTranslation(.3302,0.0,0.0)
                .addChild(new Shape("VERTICAL_THRUSTER_SHAPE")
                  .setAppearance(new Appearance("THRUSTER_APPEARANCE")
                    .setMaterial(new Material().setDiffuseColor(.2,.2,.2)))
                  .setGeometry(new Cylinder().setHeight(.29).setRadius(.0635).setSide(false)))
                .addChild(new Transform("FORWARD_VERTICAL_BEAMCONE").setRotation(0.0,0.0,1.0,1.57079).setTranslation(0.0,.145,0.0)
                  .addChild(new ProtoInstance("BeamCone", "ForwardVerticalBeamCone").setContainerField("children")
                    .addFieldValue(new fieldValue().setName("name").setValue("ForwardVerticalBeamCone"))
                    .addComments(" range -1.0..0..1.0m <==> -24V..0..24V ")
                    .addFieldValue(new fieldValue().setName("defaultRange").setValue(1))
                    .addFieldValue(new fieldValue().setName("beamHeightDegrees").setValue(8))
                    .addFieldValue(new fieldValue().setName("beamWidthDegrees").setValue(8))
                    .addFieldValue(new fieldValue().setName("solid").setValue(false))
                    .addFieldValue(new fieldValue().setName("wireframe").setValue(true))
                    .addFieldValue(new fieldValue().setName("noContactColor").setValue(new SFColor(0.0,.8,.4)))
                    .addFieldValue(new fieldValue().setName("transparency").setValue(0))
                    .addFieldValue(new fieldValue().setName("traceEnabled").setValue(false)))))
              .addChild(new Transform("AFTER_VERTICAL_THRUSTER").setTranslation(-0.4953,0.0,0.0)
                .addChild(new Shape().setUSE("VERTICAL_THRUSTER_SHAPE"))
                .addChild(new Transform("AFTER_VERTICAL_BEAMCONE").setRotation(0.0,0.0,1.0,1.57079).setTranslation(0.0,.145,0.0)
                  .addChild(new ProtoInstance("BeamCone", "AfterVerticalBeamCone").setContainerField("children")
                    .addFieldValue(new fieldValue().setName("name").setValue("AfterVerticalBeamCone"))
                    .addComments(" range -1.0..0..1.0m <==> -24V..0..24V ")
                    .addFieldValue(new fieldValue().setName("defaultRange").setValue(1))
                    .addFieldValue(new fieldValue().setName("beamHeightDegrees").setValue(8))
                    .addFieldValue(new fieldValue().setName("beamWidthDegrees").setValue(8))
                    .addFieldValue(new fieldValue().setName("solid").setValue(false))
                    .addFieldValue(new fieldValue().setName("wireframe").setValue(true))
                    .addFieldValue(new fieldValue().setName("noContactColor").setValue(new SFColor(0.0,.8,.4)))
                    .addFieldValue(new fieldValue().setName("transparency").setValue(0))
                    .addFieldValue(new fieldValue().setName("traceEnabled").setValue(false)))))
              .addChild(new Transform("FORWARD_LATERAL_THRUSTER").setRotation(1.0,0.0,0.0,1.57079).setTranslation(.4699,0.0,0.0)
                .addChild(new Shape("LATERAL_THRUSTER_SHAPE")
                  .setAppearance(new Appearance().setUSE("THRUSTER_APPEARANCE"))
                  .setGeometry(new Cylinder().setHeight(.44).setRadius(.0635).setSide(false)))
                .addChild(new Transform("FORWARD_LATERAL_BEAMCONE").setRotation(0.0,0.0,1.0,1.57079).setTranslation(0.0,.145,0.0)
                  .addChild(new ProtoInstance("BeamCone", "ForwardLateralBeamCone").setContainerField("children")
                    .addFieldValue(new fieldValue().setName("name").setValue("ForwardLateralBeamCone"))
                    .addComments(" range -1.0..0..1.0m <==> -24V..0..24V ")
                    .addFieldValue(new fieldValue().setName("defaultRange").setValue(1))
                    .addFieldValue(new fieldValue().setName("beamHeightDegrees").setValue(8))
                    .addFieldValue(new fieldValue().setName("beamWidthDegrees").setValue(8))
                    .addFieldValue(new fieldValue().setName("solid").setValue(false))
                    .addFieldValue(new fieldValue().setName("wireframe").setValue(true))
                    .addFieldValue(new fieldValue().setName("noContactColor").setValue(new SFColor(0.0,.8,.4)))
                    .addFieldValue(new fieldValue().setName("transparency").setValue(0))
                    .addFieldValue(new fieldValue().setName("traceEnabled").setValue(false)))))
              .addChild(new Transform("AFTER_LATERAL_THRUSTER").setRotation(1.0,0.0,0.0,1.57079).setTranslation(-0.6223,0.0,0.0)
                .addChild(new Shape().setUSE("LATERAL_THRUSTER_SHAPE"))
                .addChild(new Transform("AFTER_LATERAL_BEAMCONE").setRotation(0.0,0.0,1.0,1.57079).setTranslation(0.0,.145,0.0)
                  .addChild(new ProtoInstance("BeamCone", "AfterLateralBeamCone").setContainerField("children")
                    .addFieldValue(new fieldValue().setName("name").setValue("AfterLateralBeamCone"))
                    .addComments(" range -1.0..0..1.0m <==> -24V..0..24V ")
                    .addFieldValue(new fieldValue().setName("defaultRange").setValue(1))
                    .addFieldValue(new fieldValue().setName("beamHeightDegrees").setValue(8))
                    .addFieldValue(new fieldValue().setName("beamWidthDegrees").setValue(8))
                    .addFieldValue(new fieldValue().setName("solid").setValue(false))
                    .addFieldValue(new fieldValue().setName("wireframe").setValue(true))
                    .addFieldValue(new fieldValue().setName("noContactColor").setValue(new SFColor(0.0,.8,.4)))
                    .addFieldValue(new fieldValue().setName("transparency").setValue(0))
                    .addFieldValue(new fieldValue().setName("traceEnabled").setValue(false)))))
              .addChild(new Script("THRUSTER_CONES").setSourceCode("""
ecmascript:

function set_forwardVerticalThruster (value, timeStamp) {
   if (value >= 0)
      forwardVerticalThrusterBeamTranslation = new SFVec3f(0, .145, 0);
   else
      forwardVerticalThrusterBeamTranslation = new SFVec3f(0, -0.145 + value, 0);

   forwardVerticalThrusterBeamRange = value;
}

function set_afterVerticalThruster (value, timeStamp) {
   if (value >= 0)
      afterVerticalThrusterBeamTranslation = new SFVec3f(0, .145, 0);
   else
      afterVerticalThrusterBeamTranslation = new SFVec3f(0, -0.145 + value, 0);

   afterVerticalThrusterBeamRange = value;
}

function set_forwardLateralThruster (value, timeStamp) {
   if (value >= 0)
      forwardLateralThrusterBeamTranslation = new SFVec3f(0, .21, 0);
   else
      forwardLateralThrusterBeamTranslation = new SFVec3f(0, -0.21 + value, 0);

   forwardLateralThrusterBeamRange = value;
}

function set_afterLateralThruster (value, timeStamp) {
   if (value >= 0)
      afterLateralThrusterBeamTranslation = new SFVec3f(0, .21, 0);
   else
      afterLateralThrusterBeamTranslation = new SFVec3f(0, -0.21 + value, 0);

   afterLateralThrusterBeamRange = value;
}
""")
                .addField(new field().setName("set_forwardVerticalThruster").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
                .addField(new field().setName("set_afterVerticalThruster").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
                .addField(new field().setName("set_forwardLateralThruster").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
                .addField(new field().setName("set_afterLateralThruster").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_INPUTONLY))
                .addField(new field().setName("forwardVerticalThrusterBeamTranslation").setType(field.TYPE_SFVEC3F).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
                .addField(new field().setName("forwardVerticalThrusterBeamRange").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
                .addField(new field().setName("afterVerticalThrusterBeamTranslation").setType(field.TYPE_SFVEC3F).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
                .addField(new field().setName("afterVerticalThrusterBeamRange").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
                .addField(new field().setName("forwardLateralThrusterBeamTranslation").setType(field.TYPE_SFVEC3F).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
                .addField(new field().setName("forwardLateralThrusterBeamRange").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
                .addField(new field().setName("afterLateralThrusterBeamTranslation").setType(field.TYPE_SFVEC3F).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
                .addField(new field().setName("afterLateralThrusterBeamRange").setType(field.TYPE_SFFLOAT).setAccessType(field.ACCESSTYPE_OUTPUTONLY))
                .setIS(new IS()
                  .addConnect(new connect().setNodeField("set_forwardVerticalThruster").setProtoField("set_forwardVerticalThruster"))
                  .addConnect(new connect().setNodeField("set_afterVerticalThruster").setProtoField("set_afterVerticalThruster"))
                  .addConnect(new connect().setNodeField("set_forwardLateralThruster").setProtoField("set_forwardLateralThruster"))
                  .addConnect(new connect().setNodeField("set_afterLateralThruster").setProtoField("set_afterLateralThruster"))))
              .addChild(new Group()
                .addChild(new ROUTE().setFromNode("THRUSTER_CONES").setFromField("forwardVerticalThrusterBeamTranslation").setToNode("FORWARD_VERTICAL_BEAMCONE").setToField("translation"))
                .addChild(new ROUTE().setFromNode("THRUSTER_CONES").setFromField("forwardVerticalThrusterBeamRange").setToNode("ForwardVerticalBeamCone").setToField("range"))
                .addChild(new ROUTE().setFromNode("THRUSTER_CONES").setFromField("afterVerticalThrusterBeamTranslation").setToNode("AFTER_VERTICAL_BEAMCONE").setToField("translation"))
                .addChild(new ROUTE().setFromNode("THRUSTER_CONES").setFromField("afterVerticalThrusterBeamRange").setToNode("AfterVerticalBeamCone").setToField("range"))
                .addChild(new ROUTE().setFromNode("THRUSTER_CONES").setFromField("forwardLateralThrusterBeamTranslation").setToNode("FORWARD_LATERAL_BEAMCONE").setToField("translation"))
                .addChild(new ROUTE().setFromNode("THRUSTER_CONES").setFromField("forwardLateralThrusterBeamRange").setToNode("ForwardLateralBeamCone").setToField("range"))
                .addChild(new ROUTE().setFromNode("THRUSTER_CONES").setFromField("afterLateralThrusterBeamTranslation").setToNode("AFTER_LATERAL_BEAMCONE").setToField("translation"))
                .addChild(new ROUTE().setFromNode("THRUSTER_CONES").setFromField("afterLateralThrusterBeamRange").setToNode("AfterLateralBeamCone").setToField("range")))
              .addChild(new Shape("HULL")
                .setAppearance(new Appearance("HULL_APPEARANCE")
                  .setMaterial(new Material("HullMaterial")
                    .setIS(new IS()
                      .addConnect(new connect().setNodeField("diffuseColor").setProtoField("hullColor")))))
                .setGeometry(new IndexedFaceSet().setCreaseAngle(2.2).setCoordIndex(getIndexedFaceSet_9_242_coordIndex())
                  .addComments(" Bow Cowling [0..24], Stern Cowling [25..30], Rudder Post [31..38] ")
                  .setCoord(new Coordinate().setPoint(new MFVec3f(new double[] {.6985,.13335,-0.20955,.6985,.13335,.20955,.6985,-0.13335,.20955,.6985,-0.13335,-0.20955,1.05,.085,0.0,1.05,0.0,.1143,1.05,-0.085,0.0,1.05,0.0,-0.1143,1.05,.04572,-0.098985,1.05,.079188,-0.05715,1.05,.079188,.05715,1.05,.04572,.098985,1.05,-0.04572,.098985,1.05,-0.079188,.05715,1.05,-0.079188,-0.05715,1.05,-0.04572,-0.098985,1.1,.04064,.02032,1.1,.02032,.06096,1.1,-0.02032,.06096,1.1,-0.04064,.02032,1.1,-0.04064,-0.02032,1.1,-0.02032,-0.06096,1.1,.02032,-0.06096,1.1,.04064,-0.02032,1.11,0.0,0.0,-0.6985,.13335,.20955,-0.6985,.13335,-0.20955,-0.6985,-0.13335,-0.20955,-0.6985,-0.13335,.20955,-1.1303,0.0,.20955,-1.1303,0.0,-0.20955,-0.6985,.13335,.0635,-0.8509,.13335,.0635,-0.8509,.13335,-0.0635,-0.6985,.13335,-0.0635,-0.6985,-0.13335,.0635,-0.8509,-0.13335,.0635,-0.8509,-0.13335,-0.0635,-0.6985,-0.13335,-0.0635})))))
              .addComments(" original translation -1.1557 0 .09525 ")
              .addChild(new Transform("STARTBOARD_SCREW_BEAMCONE_AND_SHAFT").setTranslation(-1.3,0.0,.3)
                .addChild(new Transform("STARTBOARD_THRUSTER_BODY").setRotation(0.0,0.0,1.0,1.57).setTranslation(.15,0.0,0.0)
                  .addChild(new Shape()
                    .setAppearance(new Appearance("THRUSTER_BODY_APPEARANCE")
                      .setMaterial(new Material().setDiffuseColor(.9,.9,.9)))
                    .setGeometry(new Cylinder().setHeight(.16).setRadius(.08)))
                  .addChild(new Shape()
                    .setAppearance(new Appearance("THRUSTER_INNERBODY_APPEARANCE")
                      .setMaterial(new Material().setDiffuseColor(.2,.2,.2)))
                    .setGeometry(new Cylinder().setHeight(.22).setRadius(.06))))
                .addChild(new Transform("STARBOARD_THRUSTER_BRACKET").setRotation(0.0,0.0,1.0,1.57).setTranslation(.2,0.0,-0.05)
                  .addChild(new Shape()
                    .setAppearance(new Appearance()
                      .setMaterial(new Material().setDiffuseColor(.9,.9,.9)))
                    .setGeometry(new Box().setSize(.02,.05,.2))))
                .addChild(new Transform("STARBOARD_SCREW_BEAMCONE").setRotation(0.0,1.0,0.0,3.14)
                  .addChild(new ProtoInstance("BeamCone", "StarboardScrewBeamCone").setContainerField("children")
                    .addFieldValue(new fieldValue().setName("name").setValue("StarboardScrewBeamCone"))
                    .addComments(" range values -1..0..1m <==> -700..0..700 RPM ")
                    .addFieldValue(new fieldValue().setName("defaultRange").setValue(1))
                    .addFieldValue(new fieldValue().setName("beamHeightDegrees").setValue(8))
                    .addFieldValue(new fieldValue().setName("beamWidthDegrees").setValue(8))
                    .addFieldValue(new fieldValue().setName("solid").setValue(false))
                    .addFieldValue(new fieldValue().setName("wireframe").setValue(true))
                    .addFieldValue(new fieldValue().setName("noContactColor").setValue(new SFColor(0.0,.8,.4)))
                    .addFieldValue(new fieldValue().setName("transparency").setValue(0))
                    .addFieldValue(new fieldValue().setName("traceEnabled").setValue(false))
                    .setIS(new IS()
                      .addConnect(new connect().setNodeField("range").setProtoField("set_stbdRpm")))))
                .addChild(new Group("SHAFT")
                  .addChild(new Transform().setRotation(0.0,0.0,1.0,1.57079).setTranslation(.0281,0.0,0.0)
                    .addChild(new Shape("SCREW_SHAFT")
                      .setAppearance(new Appearance("SCREW_APPEARANCE")
                        .setMaterial(new Material().setDiffuseColor(.226,.197,0.0)))
                      .setGeometry(new Cylinder().setBottom(false).setHeight(.0762).setRadius(.008).setTop(false))))
                  .addChild(new Transform().setRotation(0.0,0.0,1.0,1.57079).setTranslation(-0.015,0.0,0.0)
                    .addChild(new Shape("SHAFT_END_CAP")
                      .setAppearance(new Appearance().setUSE("SCREW_APPEARANCE"))
                      .setGeometry(new Cone().setBottom(false).setBottomRadius(.008).setHeight(.01))))))
              .addComments(" original translation -1.1557 0 .09525 ")
              .addChild(new Transform("STARBOARD_SCREW").setTranslation(-1.3,0.0,.3)
                .addChild(new Transform("STARBOARD_BLADE")
                  .addChild(new Transform().setRotation(0.0,1.0,0.0,-0.39)
                    .addChild(new Shape()
                      .setAppearance(new Appearance().setUSE("SCREW_APPEARANCE"))
                      .setGeometry(new IndexedFaceSet().setCoordIndex(new int[] {0,1,2,3,4,5,6,7,-1,0,7,6,5,4,3,2,1,-1})
                        .setCoord(new Coordinate("BLADE_COORDINATES").setPoint(new MFVec3f(new double[] {0.0,0.0,-0.00508,0.0,.02540,-0.02032,0.0,.04572,-0.01524,0.0,.05080,-0.00508,0.0,.05080,.00508,0.0,.04572,.01524,0.0,.02540,.02032,0.0,0.0,.00508})))))))
                .addChild(new Transform().setRotation(1.0,0.0,0.0,1.57079)
                  .addChild(new Transform().setUSE("STARBOARD_BLADE")))
                .addChild(new Transform().setRotation(1.0,0.0,0.0,3.14159267)
                  .addChild(new Transform().setUSE("STARBOARD_BLADE")))
                .addChild(new Transform().setRotation(1.0,0.0,0.0,-1.57079)
                  .addChild(new Transform().setUSE("STARBOARD_BLADE"))))
              .addComments(" original translation -1.1557 0 -0.09525 ")
              .addChild(new Transform("PORT_SCREW_BEAMCONE_AND_SHAFT").setTranslation(-1.3,0.0,-0.3)
                .addChild(new Transform("PORT_THRUSTER_BODY").setRotation(0.0,0.0,1.0,1.57).setTranslation(.15,0.0,0.0)
                  .addChild(new Shape()
                    .setAppearance(new Appearance().setUSE("THRUSTER_BODY_APPEARANCE"))
                    .setGeometry(new Cylinder().setHeight(.16).setRadius(.08)))
                  .addChild(new Shape()
                    .setAppearance(new Appearance().setUSE("THRUSTER_INNERBODY_APPEARANCE"))
                    .setGeometry(new Cylinder().setHeight(.22).setRadius(.05))))
                .addChild(new Transform("PORT_THRUSTER_BRACKET").setRotation(0.0,0.0,1.0,1.57).setTranslation(.2,0.0,.05)
                  .addChild(new Shape()
                    .setAppearance(new Appearance()
                      .setMaterial(new Material().setDiffuseColor(.9,.9,.9)))
                    .setGeometry(new Box().setSize(.02,.05,.2))))
                .addChild(new Transform("PORT_SCREW_BEAMCONE").setRotation(0.0,1.0,0.0,3.14)
                  .addChild(new ProtoInstance("BeamCone", "PortScrewBeamCone").setContainerField("children")
                    .addFieldValue(new fieldValue().setName("name").setValue("PortScrewBeamCone"))
                    .addComments(" range values -1..0..1 m <==> -700..0..700 RPM ")
                    .addFieldValue(new fieldValue().setName("defaultRange").setValue(1))
                    .addFieldValue(new fieldValue().setName("beamHeightDegrees").setValue(8))
                    .addFieldValue(new fieldValue().setName("beamWidthDegrees").setValue(8))
                    .addFieldValue(new fieldValue().setName("solid").setValue(false))
                    .addFieldValue(new fieldValue().setName("wireframe").setValue(true))
                    .addComments(" Greenish blue for sea water flow ")
                    .addFieldValue(new fieldValue().setName("noContactColor").setValue(new SFColor(0.0,.8,.4)))
                    .addFieldValue(new fieldValue().setName("transparency").setValue(0))
                    .addFieldValue(new fieldValue().setName("traceEnabled").setValue(false))
                    .setIS(new IS()
                      .addConnect(new connect().setNodeField("range").setProtoField("set_portRpm")))))
                .addChild(new Group().setUSE("SHAFT")))
              .addComments(" original translation -1.1557 0 -0.09525 ")
              .addChild(new Transform("PORT_SCREW").setTranslation(-1.3,0.0,-0.3)
                .addChild(new Group("PORT_BLADE")
                  .addChild(new Transform().setRotation(0.0,1.0,0.0,.39)
                    .addChild(new Shape()
                      .setAppearance(new Appearance().setUSE("SCREW_APPEARANCE"))
                      .setGeometry(new IndexedFaceSet().setCoordIndex(new int[] {0,1,2,3,4,5,6,7,-1,0,7,6,5,4,3,2,1,-1})
                        .addComments(" This blade has reversed pitch ")
                        .setCoord(new Coordinate().setUSE("BLADE_COORDINATES"))))))
                .addChild(new Transform().setRotation(1.0,0.0,0.0,1.57079)
                  .addChild(new Group().setUSE("PORT_BLADE")))
                .addChild(new Transform().setRotation(1.0,0.0,0.0,3.14159267)
                  .addChild(new Group().setUSE("PORT_BLADE")))
                .addChild(new Transform().setRotation(1.0,0.0,0.0,-1.57079)
                  .addChild(new Group().setUSE("PORT_BLADE")))))
            .addChild(new Shape()
              .addComments(" Medium-resolution LOD level ")
              .setAppearance(new Appearance().setUSE("HULL_APPEARANCE"))
              .addComments(" size is full length, height, width ")
              .setGeometry(new Box().setSize(2.2,.26,.42))))
          .addChild(new Group()
            .addChild(new Viewpoint("HULLNAME_VIEWPOINT").setDescription("Aries Prototype").setPosition(0.0,0.0,4.0)
              .setIS(new IS()
                .addConnect(new connect().setNodeField("description").setProtoField("hullName"))))
            .addChild(new Viewpoint().setDescription("Port Bow").setOrientation(0.0,1.0,0.0,2.356).setPosition(8.0,0.0,-8.0))
            .addChild(new Viewpoint().setDescription("Bow").setOrientation(0.0,1.0,0.0,1.572).setPosition(10.0,0.0,0.0))
            .addChild(new Viewpoint().setDescription("Starboard Bow").setOrientation(0.0,1.0,0.0,0.785).setPosition(8.0,0.0,8.0))
            .addChild(new Viewpoint().setDescription("Port Beam").setOrientation(0.0,1.0,0.0,3.14159267).setPosition(0.0,0.0,-10.0))
            .addChild(new Viewpoint().setDescription("Port Astern").setOrientation(0.0,1.0,0.0,3.926).setPosition(-8.0,0.0,-8.0))
            .addChild(new Viewpoint().setDescription("Astern").setOrientation(0.0,1.0,0.0,-1.4).setPosition(-10.0,0.0,0.0))
            .addChild(new Viewpoint().setDescription("Starboard Astern").setOrientation(0.0,1.0,0.0,-0.783).setPosition(-10.0,0.0,10.0))
            .addChild(new Viewpoint().setDescription("Looking down from 25m above Aries").setOrientation(1.0,0.0,0.0,-1.57).setPosition(0.0,25.0,0.0))))))
    .addChild(new Viewpoint().setDescription("Aries AUV"))
    .addChild(new Group()
      .addChild(new ProtoInstance("Aries").setContainerField("children")
        .addFieldValue(new fieldValue().setName("translation").setValue(new SFVec3f(0.0,0.4,0.0)))))
    .addComments(" Viewable geometry is anchored text that links to an example that showing the usage of AriesPrototype ")
    .addChild(new Anchor().setDescription("AriesExample").setParameter(new String[] {"target=_blank"}).setUrl(new String[] {"AriesExample.x3d","https://www.web3d.org/x3d/content/examples/Savage/Robots/UnmannedUnderwaterVehicles/AriesExample.x3d","AriesExample.wrl","https://www.web3d.org/x3d/content/examples/Savage/Robots/UnmannedUnderwaterVehicles/AriesExample.wrl"})
      .addChild(new Shape()
        .setAppearance(new Appearance()
          .setMaterial(new Material().setDiffuseColor(0.0,1.0,1.0).setEmissiveColor(0.0,1.0,1.0)))
        .setGeometry(new Text().setString(new String[] {"AriesPrototype","is a prototype definition file","","click on text to view","AriesExample"})
          .setFontStyle(new FontStyle().setJustify(FontStyle.JUSTIFY_MIDDLE_MIDDLE))))));
            }
            catch (Exception ex)
            {       
                System.err.println ("*** Further hints on X3DJSAIL errors and exceptions at");
                System.err.println ("*** https://www.web3d.org/specifications/java/X3DJSAIL.html");
                throw (ex);
            }
	}
	// end of initialize() method

		/** Define subarrays using type int[] */
		private int[] getIndexedFaceSet_9_242_coordIndex_1()
		{
			int[] value = {0,26,34,33,32,31,25,1,-1,1,25,31,32,33,34,26,0,-1,1,25,29,28,2,-1,2,28,29,25,1,-1,2,28,35,36,37,38,27,3,-1,3,27,38,37,36,35,28,2,-1,3,27,30,26,0,-1,0,26,30,27,3,-1,0,4,1,-1,0,1,4,-1,1,5,2,-1,1,2,5,-1,2,6,3,-1,2,3,6,-1,3,7,0,-1,3,0,7,-1,7,0,8,-1,7,8,0,-1,8,0,9,-1,8,9,0,-1,9,0,4,-1,9,4,0,-1,4,1,10,-1,4,10,1,-1,10,1,11,-1,10,11,1,-1,11,1,5,-1,11,5,1,-1,5,2,12,-1,5,12,2,-1,12,2,13,-1,12,13,2,-1,13,2,6,-1,13,6,2,-1,6,3,14,-1,6,14,3,-1,14,3,15,-1,14,15,3,-1,15,3,7,-1,15,7,3,-1,4,10,16,-1,10,4,16,-1,10,11,16,-1,11,10,16,-1,11,5,17,-1,5,11,17,-1,5,12,18,-1,12,5,18,-1,12,13,19,-1,13,12,19,-1,13,6,19,-1,6,13,19,-1,6,14,20,-1,14,6,20,-1,14,15,20,-1,15,14,20,-1,15,7,21,-1,7,15,21,-1,7,8,22,-1,8,7,22,-1,8,9,23,-1,9,8,23,-1,9,4,23,-1,4,9,23,-1,4,16,23,-1,16,4,23,-1,11,17,16,-1,17,11,16,-1,5,18,17,-1,18,5,17,-1,12,19,18,-1,19,12,18,-1,6,20,19,-1,20,6,19,-1,20,15,21,-1,15,20,21,-1,21,7,22,-1,7,21,22,-1,22,8,23,-1,8,22,23,-1,23,16,24,-1,16,23,24,-1,16,17,24,-1,17,16,24,-1,17,18,24,-1,18,17,24,-1,18,19,24,-1,19,18,24,-1,19,20,24,-1,20,19,24,-1,20,21,24,-1,21,20,24,-1,21,22,24,-1,22,21,24,-1,22,23,24,-1,23,22,24,-1,25,26,30,29,-1,29,30,26,25,-1,27,28,29,30,-1,30,29,28,27,-1,31,32,36,35,-1,35,36,32,31,-1,32,33,37,36,-1,36,37,33,32,-1,34,38,37,33,-1,33,37,38,34,-1};
			return value;
		}

		/** Large attribute array: IndexedFaceSet coordIndex field, scene-graph level=9, element #242, 462 total numbers.
		 * Reassemble split array as single method to improve readability and runnability.
		 * Provide large array values via separate methods, hoping to avoid 'code too large' Java compilation errors. 
		 * Individual Java methods (including aggregated initializations) are limited to 64KB.
		 * @see https://stackoverflow.com/questions/2407912/code-too-large-compilation-error-in-java
		 * @see https://stackoverflow.com/questions/11437905/java-too-many-constants-jvm-error
		 */
		private MFInt32 getIndexedFaceSet_9_242_coordIndex()
		{
			MFInt32 IndexedFaceSet_9_242_coordIndex = new MFInt32()/*2.finalize*/
				.append(new MFInt32(getIndexedFaceSet_9_242_coordIndex_1()));
			return IndexedFaceSet_9_242_coordIndex;
		}

	/** The initialized model object, created within initialize() method. */
	private X3D x3dModel;

	/** 
	 * Provide a 
	 * <a href="https://dzone.com/articles/java-copy-shallow-vs-deep-in-which-you-will-swim" target="_blank">shallow copy</a>
	 * of the X3D model.
	 * @see <a href="https://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/Core/X3D.html">X3D</a>
	 * @return AriesPrototype model
	 */
	public X3D getX3dModel()
	{	  
		return x3dModel;
	}
	   
    /** 
     * Default main() method provided for test purposes, uses CommandLine to set global ConfigurationProperties for this object.
     * @param args array of input parameters, provided as arguments
     * @see <a href="https://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/Core/X3D.html#handleArguments-java.lang.String:A-">X3D.handleArguments(args)</a>
     * @see <a href="https://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/Core/X3D.html#validationReport--">X3D.validationReport()</a>
     * @see <a href="https://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/CommandLine.html">CommandLine</a>
     * @see <a href="https://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/CommandLine.html#USAGE">CommandLine.USAGE</a>
     * @see <a href="https://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/ConfigurationProperties.html">ConfigurationProperties</a>
     */
    public static void main(String args[])
    {
        System.out.println("Build this X3D model, showing validation diagnostics...");
        X3D thisExampleX3dModel = new AriesPrototype().getX3dModel();
//      System.out.println("X3D model construction complete.");
	
        // next handle command line arguments
        boolean hasArguments = (args != null) && (args.length > 0);
        boolean validate = true; // default
        boolean argumentsLoadNewModel = false;
        String  fileName = new String();

        if (args != null)
        {
                for (String arg : args)
                {
                        if (arg.toLowerCase().startsWith("-v") || arg.toLowerCase().contains("validate"))
                        {
                                validate = true; // making sure
                        }
                        if (arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_X3D) ||
                                arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_CLASSICVRML) ||
                                arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_X3DB) ||
                                arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_VRML97) ||
                                arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_EXI) ||
                                arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_GZIP) ||
                                arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_ZIP) ||
                                arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_HTML) ||
                                arg.toLowerCase().endsWith(X3D.FILE_EXTENSION_XHTML))
                        {
                                argumentsLoadNewModel = true;
                                fileName = arg;
                        }
                }
        }
        if      (argumentsLoadNewModel)
                System.out.println("WARNING: \"Savage.Robots.UnmannedUnderwaterVehicles.AriesPrototype\" model invocation is attempting to load file \"" + fileName + "\" instead of simply validating itself... file loading ignored.");
        else if (hasArguments) // if no arguments provided, this method produces usage warning
                thisExampleX3dModel.handleArguments(args);
	
        if (validate)
        {
            //  System.out.println("--- TODO fix duplicated outputs ---"); // omit when duplicated outputs problem is solved/refactored
		String validationResults = thisExampleX3dModel.validationReport();
            //  System.out.println("-----------------------------------"); // omit when duplicated outputs problem is solved/refactored
                System.out.print("Savage.Robots.UnmannedUnderwaterVehicles.AriesPrototype self-validation test confirmation: ");
                if (!validationResults.equals("success"))
                    System.out.println();
                System.out.println(validationResults.trim());

                // experimental: test X3DJSAIL output files
                // Robots/UnmannedUnderwaterVehicles/AriesPrototype_JavaExport.* file validation is checked when building X3D Example Archives
                String filenameX3D  = "Robots/UnmannedUnderwaterVehicles/AriesPrototype_JavaExport.x3d"; 
                String filenameX3DV = "Robots/UnmannedUnderwaterVehicles/AriesPrototype_JavaExport.x3dv"; 
                String filenameJSON = "Robots/UnmannedUnderwaterVehicles/AriesPrototype_JavaExport.json";
                thisExampleX3dModel.toFileX3D        (filenameX3D);
                thisExampleX3dModel.toFileClassicVRML(filenameX3DV);
// TODO         thisExampleX3dModel.toFileJSON       (filenameJSON);
        }
    }
}
