@prefix :        <https://www.web3d.org/x3d/content/examples/Savage/Tools/Animation/BathymetryGeneratorViaExtrusionPrototype.ttl#> .
@prefix owl:     <http://www.w3.org/2002/07/owl#> .
@prefix rdf:     <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:    <http://www.w3.org/2000/01/rdf-schema#> .
@prefix schema:  <http://schema.org/> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix xsd:     <http://www.w3.org/2001/XMLSchema#> .
@prefix x3d:     <https://www.web3d.org/specifications/x3d-4.0.xsd#> .
@prefix x3do:    <https://www.web3d.org/specifications/X3dOntology4.0#> .

:X3D a owl:NamedIndividual, x3do:X3D ;
  x3do:hasHead :head ;
  x3do:hasScene :Scene ;
  x3do:profile 'Immersive' ;
  x3do:version '3.0' ;
  x3do:noNamespaceSchemaLocation 'https://www.web3d.org/specifications/x3d-3.0.xsd' .
:head a owl:NamedIndividual, x3do:head ;
  x3do:hasParent :X3D ;
  x3do:hasMeta :meta_1_1, :meta_1_2, :meta_1_3, :meta_1_4, :meta_1_5, :meta_1_6, :meta_1_7, :meta_1_8, :meta_1_9, :meta_1_10 .
:meta_1_1 a owl:NamedIndividual, x3do:meta ;
  x3do:hasParent :head ;
  x3do:content 'BathymetryGeneratorViaExtrusionPrototype.x3d' ;
  x3do:name 'title' .
:meta_1_2 a owl:NamedIndividual, x3do:meta ;
  x3do:hasParent :head ;
  x3do:content 'This prototype generates bathymetry based on the input data, and uses Extrusion as the output geometry (with some problems as a result).' ;
  x3do:name 'description' .
:meta_1_3 a owl:NamedIndividual, x3do:meta ;
  x3do:hasParent :head ;
  x3do:content 'Jane Wu' ;
  x3do:name 'creator' .
:meta_1_4 a owl:NamedIndividual, x3do:meta ;
  x3do:hasParent :head ;
  x3do:content '8 January 2002' ;
  x3do:name 'created' .
:meta_1_5 a owl:NamedIndividual, x3do:meta ;
  x3do:hasParent :head ;
  x3do:content '28 November 2019' ;
  x3do:name 'modified' .
:meta_1_6 a owl:NamedIndividual, x3do:meta ;
  x3do:hasParent :head ;
  x3do:content 'bathymetry' ;
  x3do:name 'subject' .
:meta_1_7 a owl:NamedIndividual, x3do:meta ;
  x3do:hasParent :head ;
  x3do:content 'https://www.web3d.org/technicalinfo/specifications/vrml97/part1/nodesRef.html#Extrusion' ;
  x3do:name 'reference' .
:meta_1_8 a owl:NamedIndividual, x3do:meta ;
  x3do:hasParent :head ;
  x3do:content 'https://www.web3d.org/x3d/content/examples/Savage/Tools/Animation/BathymetryGeneratorViaExtrusionPrototype.x3d' ;
  x3do:name 'identifier' .
:meta_1_9 a owl:NamedIndividual, x3do:meta ;
  x3do:hasParent :head ;
  x3do:content 'X3D-Edit 3.2, https://www.web3d.org/x3d/tools/X3D-Edit' ;
  x3do:name 'generator' .
:meta_1_10 a owl:NamedIndividual, x3do:meta ;
  x3do:hasParent :head ;
  x3do:content '../../license.html' ;
  x3do:name 'license' .
:meta dcterms:title "BathymetryGeneratorViaExtrusionPrototype.x3d" .
:meta dcterms:description "This prototype generates bathymetry based on the input data, and uses Extrusion as the output geometry (with some problems as a result)." .
:meta dcterms:creator "Jane Wu" .
:meta dcterms:created "8 January 2002" .
:meta dcterms:modified "28 November 2019" .
:meta dcterms:subject "bathymetry" .
:meta dcterms:reference "https://www.web3d.org/technicalinfo/specifications/vrml97/part1/nodesRef.html#Extrusion" .
:meta dcterms:identifier "https://www.web3d.org/x3d/content/examples/Savage/Tools/Animation/BathymetryGeneratorViaExtrusionPrototype.x3d" .
:meta dcterms:generator "X3D-Edit 3.2, https://www.web3d.org/x3d/tools/X3D-Edit" .
:meta dcterms:license "../../license.html" .
:Scene a owl:NamedIndividual, x3do:Scene ;
  x3do:hasParent :X3D ;
  x3do:hasChildren :WorldInfo_2_1, :Viewpoint_2_3, :ProtoInstance_2_4 ;
  x3do:hasProtoDeclare :ProtoDeclare_2_2 .
:WorldInfo_2_1 a owl:NamedIndividual, x3do:WorldInfo ;
  x3do:hasParent :Scene ;
  x3do:title 'BathymetryGeneratorViaExtrusionPrototype.x3d' .
:ProtoDeclare_2_2 a owl:NamedIndividual, x3do:ProtoDeclare ;
  x3do:hasParent :Scene ;
  x3do:hasProtoInterface :ProtoInterface_2_2_1 ;
  x3do:hasProtoBody :ProtoBody_2_2_2 ;
  x3do:name 'BathymetryGenerator' .
:ProtoInterface_2_2_1 a owl:NamedIndividual, x3do:ProtoInterface ;
  x3do:hasParent :ProtoDeclare_2_2 ;
  x3do:hasField :field_2_2_1_1, :field_2_2_1_2, :field_2_2_1_3, :field_2_2_1_4, :field_2_2_1_5, :field_2_2_1_6, :field_2_2_1_7 .
:field_2_2_1_1 a owl:NamedIndividual, x3do:field ;
  x3do:hasParent :ProtoInterface_2_2_1 ;
  x3do:accessType 'initializeOnly' ;
  x3do:name 'positionArray' ;
  x3do:type 'MFVec3f' ;
  x3do:value ( 0 0 0 10 -4 0 25 -6 0 30 -8 5 38 -15 5 45 -18 5 55 -22 5 60 -25 15 60 -27 22 55 -30 35 48 -35 35 35 -35 35 25 -45 35 20 -55 35 15 -70 35 3 -70 35 -5 -72 40 -5 -75 50 0 -80 55 15 -75 55 30 -70 55 35 -60 55 40 -50 55 50 -34 55 65 -23 70 ) .
:field_2_2_1_2 a owl:NamedIndividual, x3do:field ;
  x3do:hasParent :ProtoInterface_2_2_1 ;
  x3do:accessType 'initializeOnly' ;
  x3do:appinfo 'for future development' ;
  x3do:name 'timeArray' ;
  x3do:type 'MFTime' ;
  x3do:value '1 3 6 8 10 12 14 15 17 18 23 28 35 37 39 43 45 47 48 53 58 60 61 65 70' .
:field_2_2_1_3 a owl:NamedIndividual, x3do:field ;
  x3do:hasParent :ProtoInterface_2_2_1 ;
  x3do:accessType 'initializeOnly' ;
  x3do:name 'colorSchemeDepthRangeArray' ;
  x3do:type 'MFVec2f' ;
  x3do:value ( 0 -10 -10 -20 -20 -30 -30 -40 -40 -50 -50 -60 -60 -70 -70 -999999 ) .
:field_2_2_1_4 a owl:NamedIndividual, x3do:field ;
  x3do:hasParent :ProtoInterface_2_2_1 ;
  x3do:accessType 'initializeOnly' ;
  x3do:name 'colorSchemeColorArray' ;
  x3do:type 'MFColor' ;
  x3do:value ( 1 1 0.2 0.6 1 1 0 1 1 0.2 0.6 0.2 1 0 1 0.56 0 0.32 0.2 0.3 0.7 0 0 1 ) .
:field_2_2_1_5 a owl:NamedIndividual, x3do:field ;
  x3do:hasParent :ProtoInterface_2_2_1 ;
  x3do:accessType 'initializeOnly' ;
  x3do:name 'beamWidth' ;
  x3do:type 'SFFloat' ;
  x3do:value 2 .
:field_2_2_1_6 a owl:NamedIndividual, x3do:field ;
  x3do:hasParent :ProtoInterface_2_2_1 ;
  x3do:accessType 'initializeOnly' ;
  x3do:name 'surfaceTransparency' ;
  x3do:type 'SFFloat' ;
  x3do:value 0.25 .
:field_2_2_1_7 a owl:NamedIndividual, x3do:field ;
  x3do:hasParent :ProtoInterface_2_2_1 ;
  x3do:accessType 'initializeOnly' ;
  x3do:name 'traceEnabled' ;
  x3do:type 'SFBool' ;
  x3do:value false .
:ProtoBody_2_2_2 a owl:NamedIndividual, x3do:ProtoBody ;
  x3do:hasParent :ProtoDeclare_2_2 ;
  x3do:hasChildren :Group_2_2_2_1 .
:Group_2_2_2_1 a owl:NamedIndividual, x3do:Group ;
  x3do:hasParent :ProtoBody_2_2_2 ;
  x3do:hasChildren :Bathymetry, :BathymetryScript, :Shape_2_2_2_1_4 ;
  x3do:hasROUTE :ROUTE_2_2_2_1_3 .
:Bathymetry a owl:NamedIndividual, x3do:Transform ;
  x3do:hasParent :Group_2_2_2_1 ;
  x3do:DEF 'Bathymetry' .
:BathymetryScript a owl:NamedIndividual, x3do:Script ;
  x3do:hasParent :Group_2_2_2_1 ;
  x3do:hasField :field_2_2_2_1_2_1, :field_2_2_2_1_2_2, :field_2_2_2_1_2_3, :field_2_2_2_1_2_4, :field_2_2_2_1_2_5, :field_2_2_2_1_2_6, :field_2_2_2_1_2_7, :field_2_2_2_1_2_8, :field_2_2_2_1_2_9, :field_2_2_2_1_2_10, :field_2_2_2_1_2_11, :field_2_2_2_1_2_12, :field_2_2_2_1_2_13, :field_2_2_2_1_2_14, :field_2_2_2_1_2_15, :field_2_2_2_1_2_16 ;
  x3do:hasIS :IS_2_2_2_1_2_17 ;
  x3do:DEF 'BathymetryScript' ;
  x3do:directOutput true ;
  x3do:sourceCode """
ecmascript:

function initialize()
{
	bathyNodeIndex = 0;

	spineIndex = 0;
	position = positionArray[0];
	spine[spineIndex] = new SFVec3f(position.x, 0, position.z);
	scale[spineIndex] = new SFVec2f(1, Math.abs(position.y));
	spineIndex++;

	previousPosition = new SFVec3f(position.x, position.y, position.z);
	//Determine the initial depth range
	for (j = 0; j < colorSchemeDepthRangeArray.length; j++)
	{
		if (position.y >= colorSchemeDepthRangeArray[j].y)
			break;
	}
	currentDepthRangeIndex = j;

	for (i = 1; i < positionArray.length; i++)
	{			
		if (previousPosition.y == colorSchemeDepthRangeArray[currentDepthRangeIndex].y &&
		    positionArray[i].y != colorSchemeDepthRangeArray[currentDepthRangeIndex].y)
			terminateExtrusionSegmentWithCurrentPosition(currentDepthRangeIndex);

		//Update new position
		position = positionArray[i];

		//Determine the correct depth range
		if (position.y <= previousPosition.y)
		{
			for (j = currentDepthRangeIndex; j < colorSchemeDepthRangeArray.length; j++)
			{
				if (position.y >= colorSchemeDepthRangeArray[j].y)
					break;

				if (previousPosition.y != colorSchemeDepthRangeArray[currentDepthRangeIndex].y)
					terminateExtrusionSegmentWithDepthRangeBoundary(currentDepthRangeIndex);
			}
			currentDepthRangeIndex = j;
		}
		else
		{
			for (j = currentDepthRangeIndex; j > -1; j--)
			{
				if (position.y < colorSchemeDepthRangeArray[j-1].y)
					break;

				if (position.y > colorSchemeDepthRangeArray[j-1].y)
					terminateExtrusionSegmentWithDepthRangeBoundary(j-1);
			}
			currentDepthRangeIndex = j;
		}

		spine[spineIndex] = new SFVec3f(position.x, 0, position.z);
		scale[spineIndex] = new SFVec2f(1, Math.abs(position.y));
		spineIndex++;

		previousPosition = new SFVec3f(position.x, position.y, position.z);
	}
	terminateExtrusionSegmentWithCurrentPosition(currentDepthRangeIndex);
}

function terminateExtrusionSegmentWithDepthRangeBoundary(index)
{
	depthRange = colorSchemeDepthRangeArray[index];

	findCoordinate(previousPosition.x, position.x, previousPosition.y, position.y, depthRange.y);
	xPrime = coordinate;
	findCoordinate(previousPosition.z, position.z, previousPosition.y, position.y, depthRange.y);
	zPrime = coordinate;
	spine[spineIndex] = new SFVec3f(xPrime, 0, zPrime);
	scale[spineIndex] = new SFVec2f(1, Math.abs(depthRange.y));

	if (scale[scale.length-2].y > scale[scale.length-1].y)
		color = colorSchemeColorArray[index+1];
	else
		color = colorSchemeColorArray[index];

	createExtrusionShape(spine, scale, color);

	//Reset values to start the next extrustion segment
	spineIndex = 0;
	resetSpine();
	resetScale();

	//Update the current segment end as the start of the next segment
	spine[spineIndex] = new SFVec3f(xPrime, 0, zPrime);
	scale[spineIndex] = new SFVec2f(1, Math.abs(depthRange.y));
	spineIndex++;	
}

function terminateExtrusionSegmentWithCurrentPosition(index)
{
	if (scale[scale.length-1].y != Math.abs(colorSchemeDepthRangeArray[index].y))
		index--;

	if (scale[scale.length-2].y > scale[scale.length-1].y)
		color = colorSchemeColorArray[index+1];
	else
		color = colorSchemeColorArray[index];

	createExtrusionShape(spine, scale, color);

	//Reset values to start the next extrustion segment
	spineIndex = 0;
	resetSpine();
	resetScale();

	//Update the current segment end as the start of the next segment
	spine[spineIndex] = new SFVec3f(position.x, 0, position.z);
	scale[spineIndex] = new SFVec2f(1, Math.abs(position.y));
	spineIndex++;

	//Update the previousPosition
	previousPosition = new SFVec3f(position.x, position.y, position.z);
}

function findCoordinate(x1, x2, y1, y2, yPrime)
{
	coordinate = ((x1 - x2) / (y1 - y2)) * yPrime + ((x2*y1 - x1*y2) / (y1 - y2));
}

function createExtrusionShape(spine, scale, color)
{
	determineOrientation(spine);
	tracePrint('An extrusion is created whose spine is: ' + spine);
	tracePrint('and scale is: ' + scale);
	tracePrint('orientation is: ' + orientation);
	tracePrint('color is: ' + color);
	alwaysPrint('number of spine points is: ' + spine.length);
	alwaysPrint('orientation is: ' + orientation);

	//Build the VRML string
	extrusionSyntax  = 'Shape {\n';
	extrusionSyntax += '   appearance Appearance {' + '\n';
	extrusionSyntax += '      material Material {' + '\n';
	extrusionSyntax += '         diffuseColor ' + color + '\n';
	extrusionSyntax += '         transparency ' + transparency + '\n';
	extrusionSyntax += '      }' + '\n';
	extrusionSyntax += '   }' + '\n';
	extrusionSyntax += '   geometry Extrusion {' + '\n';
	extrusionSyntax += '      crossSection [' + (beamWidth/(-2)) + ', 1, ' + (beamWidth/2) + ', 1, ' + (beamWidth/(-2)) + ', 1]' + '\n';
	extrusionSyntax += '      scale ' + scale + '\n';
	extrusionSyntax += '      spine ' + spine + '\n';
	extrusionSyntax += '      orientation ' + orientation + '\n';
	extrusionSyntax += '      creaseAngle 1.57' + '\n';
	extrusionSyntax += '   }' + '\n';
	extrusionSyntax += '}';

	//Create Extrusion shape
	tracePrint (extrusionSyntax);
	bathySegment = new SFNode(extrusionSyntax);

	bathyNodes[bathyNodeIndex] = bathySegment;
	bathyNodeIndex++;
}

function determineOrientation(spine)
{
   previousZAxis = null;
   orientation = new MFRotation();
   //Special cases
   if (spine.length == 2)
   {
      if (spine[0].z == spine[1].z)
      {
         if (spine[0].x <= spine[1].x) //positive x direction
            orientation[0] = orientation[1] = new SFRotation(0, 1, 0, 1.57);
         else //negative x direction
            orientation[0] = orientation[1] = new SFRotation(0, 1, 0, -1.57);
      }
      else
      {
         if (spine[0].x == spine[1].x) //parallet to the z axis
            orientation[0] = orientation[1] = new SFRotation(0, 1, 0, 0);
         else
         {
            angleRadian = Math.atan((spine[0].x- spine[1].x) / (spine[0].z - spine[1].z));
//          angleRadian = Math.atan2((spine[0].x- spine[1].x), (spine[0].z - spine[1].z));
            
            orientation[0] = orientation[1] = new SFRotation(0, 1, 0, angleRadian);
         }
      }
      return;
   }

   for (n = 0; n < spine.length; n++)
   {
      //If spine is not closed, the Z axis used for the first spine point is the same as the Z axis for spine[1].
      //The Z axis used for the last spine point is the same as the Z axis for spine[spine.length - 2].   
      if (n == 0)
         si = 1;
      else if (n == (spine.length - 1))
         si = spine.length - 2;
      else
         si = n;

      zAxis = (spine[si+1].subtract(spine[si])).cross((spine[si-1].subtract(spine[si])));

      while (zAxis.x == 0 && zAxis.y == 0 && zAxis.z == 0)
      {
         if (previousZAxis == null)
         {
            ++si;
            if (si == (spine.length - 1)) //The entire spine is collinear
            {
               zAxis = new SFVec3f(1, 0, 0);
               break;
            }

            zAxis = (spine[si+1].subtract(spine[si])).cross((spine[si-1].subtract(spine[si])));
         }
         else
            zAxis = new SFVec3f(previousZAxis.x, previousZAxis.y, previousZAxis.z);
      }

      adjustedZAxis = zAxis;
      if (n == 0)
         previousZAxis = zAxis;
      else
      {
         dotProduct = zAxis.dot(previousZAxis);
         if (dotProduct < 0)
            adjustedZAxis = new SFVec3f(zAxis.multiply(-1).x, zAxis.multiply(-1).y, zAxis.multiply(-1).z);

         previousZAxis = adjustedZAxis;
      }
      
      zAxisNormalized = adjustedZAxis.normalize();
      theta = Math.acos(zAxisNormalized.dot(new SFVec3f(0, -1, 0)));
      if (spine[1].x < spine[0].x)
         orientation[n] = new SFRotation(0, -1, 0, theta);
      else
         orientation[n] = new SFRotation(0, 1, 0, theta);
   }
if (theta == 0)
   Browser.println ('rotation angle = ' + theta);
else if (theta > 1.57 && theta < 3.14)
   Browser.println ('rotation angle = ' + theta);
else if (theta > 3.14)
   Browser.println ('rotation angle = ' + theta);
}

function resetSpine()
{
	spine = new MFVec3f();
}

function resetScale()
{
	scale = new MFVec2f();
}

function tracePrint(string)
{
	if (traceEnabled)
		Browser.println ('[BathymetryGenerator] ' + string);
}

function alwaysPrint(string)
{
	Browser.println ('[BathymetryGenerator] ' + string);
}
""" .
:field_2_2_2_1_2_1 a owl:NamedIndividual, x3do:field ;
  x3do:hasParent :BathymetryScript ;
  x3do:accessType 'initializeOnly' ;
  x3do:name 'positionArray' ;
  x3do:type 'MFVec3f' .
:field_2_2_2_1_2_2 a owl:NamedIndividual, x3do:field ;
  x3do:hasParent :BathymetryScript ;
  x3do:accessType 'initializeOnly' ;
  x3do:name 'timeArray' ;
  x3do:type 'MFTime' .
:field_2_2_2_1_2_3 a owl:NamedIndividual, x3do:field ;
  x3do:hasParent :BathymetryScript ;
  x3do:accessType 'initializeOnly' ;
  x3do:name 'colorSchemeDepthRangeArray' ;
  x3do:type 'MFVec2f' .
:field_2_2_2_1_2_4 a owl:NamedIndividual, x3do:field ;
  x3do:hasParent :BathymetryScript ;
  x3do:accessType 'initializeOnly' ;
  x3do:name 'colorSchemeColorArray' ;
  x3do:type 'MFColor' .
:field_2_2_2_1_2_5 a owl:NamedIndividual, x3do:field ;
  x3do:hasParent :BathymetryScript ;
  x3do:accessType 'initializeOnly' ;
  x3do:name 'beamWidth' ;
  x3do:type 'SFFloat' .
:field_2_2_2_1_2_6 a owl:NamedIndividual, x3do:field ;
  x3do:hasParent :BathymetryScript ;
  x3do:accessType 'initializeOnly' ;
  x3do:name 'transparency' ;
  x3do:type 'SFFloat' .
:field_2_2_2_1_2_7 a owl:NamedIndividual, x3do:field ;
  x3do:hasParent :BathymetryScript ;
  x3do:accessType 'initializeOnly' ;
  x3do:name 'spine' ;
  x3do:type 'MFVec3f' ;
  x3do:value ( 0 0 0 0 1 0 ) .
:field_2_2_2_1_2_8 a owl:NamedIndividual, x3do:field ;
  x3do:hasParent :BathymetryScript ;
  x3do:accessType 'initializeOnly' ;
  x3do:name 'scale' ;
  x3do:type 'MFVec2f' ;
  x3do:value ( 1 1 ) .
:field_2_2_2_1_2_9 a owl:NamedIndividual, x3do:field ;
  x3do:hasParent :BathymetryScript ;
  x3do:accessType 'initializeOnly' ;
  x3do:name 'orientation' ;
  x3do:type 'MFRotation' ;
  x3do:value ( 0 0 1 0 ) .
:field_2_2_2_1_2_10 a owl:NamedIndividual, x3do:field ;
  x3do:hasParent :BathymetryScript ;
  x3do:accessType 'initializeOnly' ;
  x3do:name 'bathyColor' ;
  x3do:type 'SFColor' ;
  x3do:value ( 1 1 1 ) .
:field_2_2_2_1_2_11 a owl:NamedIndividual, x3do:field ;
  x3do:hasParent :BathymetryScript ;
  x3do:accessType 'outputOnly' ;
  x3do:name 'bathyNodes' ;
  x3do:type 'MFNode' .
:field_2_2_2_1_2_12 a owl:NamedIndividual, x3do:field ;
  x3do:hasParent :BathymetryScript ;
  x3do:accessType 'initializeOnly' ;
  x3do:name 'traceEnabled' ;
  x3do:type 'SFBool' .
:field_2_2_2_1_2_13 a owl:NamedIndividual, x3do:field ;
  x3do:hasParent :BathymetryScript ;
  x3do:accessType 'initializeOnly' ;
  x3do:name 'coordinate' ;
  x3do:type 'SFVec3f' ;
  x3do:value ( 0 0 0 ) .
:field_2_2_2_1_2_14 a owl:NamedIndividual, x3do:field ;
  x3do:hasParent :BathymetryScript ;
  x3do:accessType 'initializeOnly' ;
  x3do:name 'previousPosition' ;
  x3do:type 'SFVec3f' ;
  x3do:value ( 0 0 0 ) .
:field_2_2_2_1_2_15 a owl:NamedIndividual, x3do:field ;
  x3do:hasParent :BathymetryScript ;
  x3do:accessType 'initializeOnly' ;
  x3do:name 'position' ;
  x3do:type 'SFVec3f' ;
  x3do:value ( 0 0 0 ) .
:field_2_2_2_1_2_16 a owl:NamedIndividual, x3do:field ;
  x3do:hasParent :BathymetryScript ;
  x3do:accessType 'initializeOnly' ;
  x3do:name 'bathyNodeIndex' ;
  x3do:type 'SFInt32' ;
  x3do:value 0 .
:IS_2_2_2_1_2_17 a owl:NamedIndividual, x3do:IS ;
  x3do:hasParent :BathymetryScript ;
  x3do:hasConnect :connect_2_2_2_1_2_17_1, :connect_2_2_2_1_2_17_2, :connect_2_2_2_1_2_17_3, :connect_2_2_2_1_2_17_4, :connect_2_2_2_1_2_17_5, :connect_2_2_2_1_2_17_6, :connect_2_2_2_1_2_17_7 .
:connect_2_2_2_1_2_17_1 a owl:NamedIndividual, x3do:connect ;
  x3do:hasParent :IS_2_2_2_1_2_17 ;
  x3do:nodeField 'positionArray' ;
  x3do:protoField 'positionArray' .
:connect_2_2_2_1_2_17_2 a owl:NamedIndividual, x3do:connect ;
  x3do:hasParent :IS_2_2_2_1_2_17 ;
  x3do:nodeField 'timeArray' ;
  x3do:protoField 'timeArray' .
:connect_2_2_2_1_2_17_3 a owl:NamedIndividual, x3do:connect ;
  x3do:hasParent :IS_2_2_2_1_2_17 ;
  x3do:nodeField 'colorSchemeDepthRangeArray' ;
  x3do:protoField 'colorSchemeDepthRangeArray' .
:connect_2_2_2_1_2_17_4 a owl:NamedIndividual, x3do:connect ;
  x3do:hasParent :IS_2_2_2_1_2_17 ;
  x3do:nodeField 'colorSchemeColorArray' ;
  x3do:protoField 'colorSchemeColorArray' .
:connect_2_2_2_1_2_17_5 a owl:NamedIndividual, x3do:connect ;
  x3do:hasParent :IS_2_2_2_1_2_17 ;
  x3do:nodeField 'beamWidth' ;
  x3do:protoField 'beamWidth' .
:connect_2_2_2_1_2_17_6 a owl:NamedIndividual, x3do:connect ;
  x3do:hasParent :IS_2_2_2_1_2_17 ;
  x3do:nodeField 'transparency' ;
  x3do:protoField 'surfaceTransparency' .
:connect_2_2_2_1_2_17_7 a owl:NamedIndividual, x3do:connect ;
  x3do:hasParent :IS_2_2_2_1_2_17 ;
  x3do:nodeField 'traceEnabled' ;
  x3do:protoField 'traceEnabled' .
:ROUTE_2_2_2_1_3 a owl:NamedIndividual, x3do:ROUTE ;
  x3do:hasParent :Group_2_2_2_1 ;
  x3do:fromField 'bathyNodes' ;
  x3do:fromNode 'BathymetryScript' ;
  x3do:toField 'addChildren' ;
  x3do:toNode 'Bathymetry' .
:Shape_2_2_2_1_4 a owl:NamedIndividual, x3do:Shape ;
  x3do:hasParent :Group_2_2_2_1 ;
  x3do:hasGeometry :Extrusion_2_2_2_1_4_1 .
:Extrusion_2_2_2_1_4_1 a owl:NamedIndividual, x3do:Extrusion ;
  x3do:hasParent :Shape_2_2_2_1_4 .
:Viewpoint_2_3 a owl:NamedIndividual, x3do:Viewpoint ;
  x3do:hasParent :Scene ;
  x3do:description 'MainView' ;
  x3do:position ( 0 -50 200 ) .
:ProtoInstance_2_4 a owl:NamedIndividual, x3do:ProtoInstance ;
  x3do:hasParent :Scene ;
  x3do:hasFieldValue :fieldValue_2_4_1, :fieldValue_2_4_2, :fieldValue_2_4_3 ;
  x3do:name 'BathymetryGenerator' .
:fieldValue_2_4_1 a owl:NamedIndividual, x3do:fieldValue ;
  x3do:hasParent :ProtoInstance_2_4 ;
  x3do:name 'positionArray' ;
  x3do:value ( 0 0 0 10 -4 0 25 -6 0 30 -8 5 38 -15 5 45 -18 5 55 -22 5 60 -25 15 60 -27 22 55 -30 35 48 -35 35 35 -35 35 25 -45 35 20 -55 35 15 -70 35 3 -70 35 -5 -72 40 -5 -75 50 0 -80 55 15 -75 55 30 -70 55 35 -60 55 40 -50 55 50 -34 55 65 -23 70 ) .
:fieldValue_2_4_2 a owl:NamedIndividual, x3do:fieldValue ;
  x3do:hasParent :ProtoInstance_2_4 ;
  x3do:name 'surfaceTransparency' ;
  x3do:value 0.25 .
:fieldValue_2_4_3 a owl:NamedIndividual, x3do:fieldValue ;
  x3do:hasParent :ProtoInstance_2_4 ;
  x3do:name 'traceEnabled' ;
  x3do:value true .
