<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.3//EN" "https://www.web3d.org/specifications/x3d-3.3.dtd">
<X3D profile='Immersive' version='3.3' xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation='https://www.web3d.org/specifications/x3d-3.3.xsd'>
  <head>
    <meta content='SideScanSonarPrototype.x3d' name='title'/>
    <meta content='Produce wireframe or transparent sidescan sonar beams.' name='description'/>
    <meta content='Don Brutzman' name='creator'/>
    <meta content='15 March 2001' name='created'/>
    <meta content='20 October 2019' name='modified'/>
    <meta content='https://www.web3d.org/x3d/content/examples/Savage/CommunicationsAndSensors/Sonar/SideScanSonarPrototype.x3d' name='identifier'/>
    <meta content='X3D-Edit 3.3, https://www.web3d.org/x3d/tools/X3D-Edit' name='generator'/>
    <meta content='../../license.html' name='license'/>
  </head>
  <Scene>
    <NavigationInfo DEF='LockedDownInterface2D' type='"NONE"'/>
    <Background skyColor='0 0.3 0.5'/>
    <WorldInfo info='"Produce wireframe or transparent beam cones."' title='BeamCone Prototyupe'/>
    <Viewpoint description='SideScanSonar Prototype' position='0 0 15'/>
    <ProtoDeclare appinfo='Produce wireframe or semi-transparent sonar sidescan beams' name='SideScanSonar'>
      <ProtoInterface>
        <field accessType='inputOnly' appinfo='vertical distance above bottom in meters along y axis' name='altitude' type='SFFloat'/>
        <field accessType='initializeOnly' appinfo='default vertical distance above bottom in meters along y axis' name='defaultAltitude' type='SFFloat' value='3'/>
        <field accessType='initializeOnly' appinfo='maximum effective altitude of sidescan sonar above bottom' name='maxAltitude' type='SFFloat' value='3'/>
        <field accessType='initializeOnly' appinfo='distance in meters from nadir to rightmost/leftmost edge when operating at defaultAltitude above the bottom' name='defaultCrossTrackHalfRange' type='SFFloat' value='30'/>
        <field accessType='initializeOnly' appinfo='longitudinal width of a single return' name='defaultTrackWidthMeters' type='SFFloat' value='0.30'/>
        <field accessType='initializeOnly' appinfo='width (or diameter) of vehicle carrying port/starboard sidescan sonar transducers' name='vehicleWidthMeters' type='SFFloat' value='0.178'/>
        <field accessType='inputOnly' appinfo='(communications) whether transmitted signal is in contact with receiver or (sensor) is a target return detected?' name='contact' type='SFBool'/>
        <field accessType='initializeOnly' appinfo='draw lines for tracking shape?' name='wireframe' type='SFBool' value='true'/>
        <field accessType='initializeOnly' appinfo='draw solid tracking shape?' name='solid' type='SFBool' value='true'/>
        <field accessType='initializeOnly' appinfo='rendering color when contact=true' name='contactColor' type='SFColor' value='.8 .1 .1'/>
        <field accessType='initializeOnly' appinfo='rendering color when contact=false' name='noContactColor' type='SFColor' value='.3 .5 .5'/>
        <field accessType='inputOutput' appinfo='1 = fully transparent wireframe only' name='transparency' type='SFFloat' value='0'/>
      </ProtoInterface>
      <ProtoBody>
        <!-- BEAM_CONTROL beam scaling is controlled by range/beamHeightDegrees/beamWidthDegrees/direction inputs -->
        <Transform DEF='BEAM_CONTROL'>
          <Switch DEF='WIREFRAME_SWITCH' whichChoice='1'>
            <!-- TODO refactor index values starting from -1, remove WorldInfo -->
            <WorldInfo info='"initial choice is null node (WorldInfo), meaning no wireframe beam"'/>
            <Shape>
              <Appearance>
                <Material DEF='WireMaterial' diffuseColor='.1 .1 .1' emissiveColor='.1 .1 .1'>
                  <IS>
                    <connect nodeField='transparency' protoField='transparency'/>
                  </IS>
                </Material>
              </Appearance>
              <IndexedLineSet DEF='ILS' coordIndex='1 2 3 1 -1 5 3 4 5 -1 6 8 7 6 -1 10 9 8 10 -1 6 7 2 1 6 -1 10 5 4 9 10 -1'>
                <Coordinate DEF='BeamPatternCoordinatePoints' point='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0'/>
              </IndexedLineSet>
            </Shape>
          </Switch>
          <Switch DEF='SOLID_SWITCH' whichChoice='0'>
            <!-- TODO refactor index values starting from -1, remove WorldInfo -->
            <WorldInfo info='"initial choice is null node (WorldInfo), meaning no solid beam"'/>
            <Shape>
              <Appearance>
                <Material DEF='FaceMaterial' diffuseColor='.1 .1 .1'>
                  <IS>
                    <connect nodeField='transparency' protoField='transparency'/>
                  </IS>
                </Material>
              </Appearance>
              <IndexedFaceSet DEF='IFS' coordIndex='1 2 3 1 -1 5 3 4 5 -1 6 8 7 6 -1 10 9 8 10 -1 6 7 2 1 6 -1 10 5 4 9 10 -1' solid='false'>
                <Coordinate USE='BeamPatternCoordinatePoints'/>
              </IndexedFaceSet>
            </Shape>
          </Switch>
        </Transform>
        <!-- Non-renderable animation controls -->
        <Script DEF='BEAM_CALCULATE'>
          <field accessType='inputOnly' name='altitude' type='SFFloat'/>
          <field accessType='initializeOnly' name='defaultAltitude' type='SFFloat'/>
          <field accessType='initializeOnly' name='maxAltitude' type='SFFloat'/>
          <field accessType='initializeOnly' name='defaultCrossTrackHalfRange' type='SFFloat'/>
          <field accessType='initializeOnly' name='defaultTrackWidthMeters' type='SFFloat'/>
          <field accessType='initializeOnly' name='vehicleWidthMeters' type='SFFloat'/>
          <field accessType='outputOnly' name='beamScale' type='SFVec3f'/>
          <field accessType='outputOnly' name='coordinatePoints' type='MFVec3f'/>
          <field accessType='initializeOnly' appinfo='internal flag to turn on Script tracing' name='traceEnabled' type='SFBool' value='false'/>
          <IS>
            <connect nodeField='altitude' protoField='altitude'/>
            <connect nodeField='defaultAltitude' protoField='defaultAltitude'/>
            <connect nodeField='maxAltitude' protoField='maxAltitude'/>
            <connect nodeField='defaultCrossTrackHalfRange' protoField='defaultCrossTrackHalfRange'/>
            <connect nodeField='defaultTrackWidthMeters' protoField='defaultTrackWidthMeters'/>
            <connect nodeField='vehicleWidthMeters' protoField='vehicleWidthMeters'/>
          </IS>
          <![CDATA[
ecmascript:

function tracePrint (value)
{
	if (traceEnabled) Browser.println ('[SideScanSonar BEAM_CALCULATE] ' + value);
}

function initialize () {
 beamScale = new SFVec3f (1, 1, 1);
 dt2 = defaultTrackWidthMeters/2;

 origin = new SFVec3f (0, 0, 0);
 a  = new SFVec3f (-dt2,  0,               -vehicleWidthMeters/2);
 b  = new SFVec3f (-dt2, -defaultAltitude, -defaultCrossTrackHalfRange);
 c  = new SFVec3f (-dt2, -defaultAltitude,  0);
 d  = new SFVec3f (-dt2, -defaultAltitude,  defaultCrossTrackHalfRange);
 e  = new SFVec3f (-dt2,  0,                vehicleWidthMeters/2);
 aa = new SFVec3f ( dt2,  0,               -vehicleWidthMeters/2);
 bb = new SFVec3f ( dt2, -defaultAltitude, -defaultCrossTrackHalfRange);
 cc = new SFVec3f ( dt2, -defaultAltitude,  0);
 dd = new SFVec3f ( dt2, -defaultAltitude,  defaultCrossTrackHalfRange);
 ee = new SFVec3f ( dt2,  0,                vehicleWidthMeters/2);

 coordinatePoints = new MFVec3f (origin, a, b, c, d, e, aa, bb, cc, dd, ee);

 tracePrint ('coordinatePoints =' + coordinatePoints);
}
function altitude (newAltitude, timeStamp) {
 if (newAltitude <= 0)
 {
   beamHeightFactor= 0.001;
   beamScale = new SFVec3f (1, beamHeightFactor, beamHeightFactor);
 }
 else if (newAltitude < maxAltitude)
 {
   beamHeightFactor= newAltitude / defaultAltitude;
   beamScale = new SFVec3f (1, beamHeightFactor, beamHeightFactor);
 }
 else
 {
   beamHeightFactor= maxAltitude / defaultAltitude;
   beamScale = new SFVec3f (1, beamHeightFactor, beamHeightFactor);
 }
 tracePrint ('newAltitude      =' + newAltitude);
 tracePrint ('beamHeightFactor =' + beamHeightFactor);
 tracePrint ('beamScale        =' + beamScale);
}
]]>
        </Script>
        <Script DEF='DETECTION' directOutput='true'>
          <field accessType='inputOnly' name='contact' type='SFBool'/>
          <field accessType='initializeOnly' name='wireframe' type='SFBool'/>
          <field accessType='initializeOnly' name='solid' type='SFBool'/>
          <field accessType='initializeOnly' name='contactColor' type='SFColor'/>
          <field accessType='initializeOnly' name='noContactColor' type='SFColor'/>
          <field accessType='outputOnly' name='beamColor' type='SFColor'/>
          <field accessType='outputOnly' name='wireframeChoice' type='SFInt32'/>
          <field accessType='outputOnly' name='solidChoice' type='SFInt32'/>
          <field accessType='initializeOnly' name='MaterialNodeHolder' type='SFNode'>
            <Material USE='FaceMaterial'/>
          </field>
          <field accessType='initializeOnly' appinfo='internal flag to turn on Script tracing' name='traceEnabled' type='SFBool' value='false'/>
          <IS>
            <connect nodeField='contact' protoField='contact'/>
            <connect nodeField='wireframe' protoField='wireframe'/>
            <connect nodeField='solid' protoField='solid'/>
            <connect nodeField='contactColor' protoField='contactColor'/>
            <connect nodeField='noContactColor' protoField='noContactColor'/>
          </IS>
          <![CDATA[
ecmascript:

function tracePrint (value)
{
	if (traceEnabled) Browser.println ('[SideScanSonar DETECTION] ' + value);
}

function initialize ()
{
	beamColor = noContactColor;
	if (wireframe == true) wireframeChoice = 1;
	if (solid     == true) solidChoice     = 1;

	// Debug  statements
	tracePrint ('  wireframe       =' + wireframe);
	tracePrint ('  solid           =' + solid);
	tracePrint ('  contactColor    =' + contactColor);
	tracePrint ('  noContactColor  =' + noContactColor);
	tracePrint ('  beamColor       =' + beamColor);
	tracePrint ('  wireframeChoice =' + wireframeChoice);
	tracePrint ('  solidChoice     =' + solidChoice);
	tracePrint ('  transparency    =' + MaterialNodeHolder.transparency);
}
function contact (newDetect, timeStamp)
{
	tracePrint ('  newDetect       =' + newDetect);
	if (newDetect) beamColor = contactColor;
	else           beamColor = noContactColor;
}
]]>
        </Script>
        <ROUTE fromField='beamScale' fromNode='BEAM_CALCULATE' toField='scale' toNode='BEAM_CONTROL'/>
        <ROUTE fromField='coordinatePoints' fromNode='BEAM_CALCULATE' toField='point' toNode='BeamPatternCoordinatePoints'/>
        <ROUTE fromField='beamColor' fromNode='DETECTION' toField='emissiveColor' toNode='WireMaterial'/>
        <ROUTE fromField='beamColor' fromNode='DETECTION' toField='emissiveColor' toNode='FaceMaterial'/>
        <ROUTE fromField='wireframeChoice' fromNode='DETECTION' toField='whichChoice' toNode='WIREFRAME_SWITCH'/>
        <ROUTE fromField='solidChoice' fromNode='DETECTION' toField='whichChoice' toNode='SOLID_SWITCH'/>
      </ProtoBody>
    </ProtoDeclare>
    <!-- Viewable geometry for this scene is anchored text that links to an example showing ExternProtoDeclare usage of BeamCone -->
    <Anchor description='SideScanSonar Example' parameter='"target=_blank"' url='"SideScanSonarExample.x3d" "https://www.web3d.org/x3d/content/examples/Savage/CommunicationsAndSensors/Sonar/SideScanSonarExample.x3d" "SideScanSonarExample.wrl" "https://www.web3d.org/x3d/content/examples/Savage/CommunicationsAndSensors/Sonar/SideScanSonarExample.wrl"'>
      <Shape>
        <Appearance>
          <Material diffuseColor='0 1 1' emissiveColor='0 1 1'/>
        </Appearance>
        <Text string='"SideScanSonarPrototype" "is a Prototype definition file." "" "To see an example scene" "click this text and view" "SideScanSonarExample."'>
          <FontStyle justify='"MIDDLE" "MIDDLE"'/>
        </Text>
      </Shape>
      <Shape>
        <!-- transparent Box as text-selection assist -->
        <Box size='10.5 6 .001'/>
        <Appearance>
          <Material transparency='1'/>
        </Appearance>
      </Shape>
    </Anchor>
  </Scene>
</X3D>