<?xml version='1.0' encoding="UTF-8"?>
<xsl:stylesheet version="1.0"    
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt">

<!-- (c) 2010, Trimble Navigation Limited. All rights reserved.                                -->
<!-- Permission is hereby granted to use, copy, modify, or distribute this style sheet for any -->
<!-- purpose and without fee, provided that the above copyright notice appears in all copies   -->
<!-- and that both the copyright notice and the limited warranty and restricted rights notice  -->
<!-- below appear in all supporting documentation.                                             -->

<!-- TRIMBLE NAVIGATION LIMITED PROVIDES THIS STYLE SHEET "AS IS" AND WITH ALL FAULTS.         -->
<!-- TRIMBLE NAVIGATION LIMITED SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF MERCHANTABILITY -->
<!-- OR FITNESS FOR A PARTICULAR USE. TRIMBLE NAVIGATION LIMITED DOES NOT WARRANT THAT THE     -->
<!-- OPERATION OF THIS STYLE SHEET WILL BE UNINTERRUPTED OR ERROR FREE.                        -->

<xsl:output method="xml" omit-xml-declaration="no" encoding="utf-8"/>

<!-- Set the numeric display details i.e. decimal point, thousands separator etc -->
<xsl:variable name="DecPt" select="string('.')"/>    <!-- Change as appropriate for US/European -->
<xsl:variable name="GroupSep" select="string(',')"/> <!-- Change as appropriate for US/European -->
<!-- Also change decimal-separator & grouping-separator in decimal-format below 
     as appropriate for US/European output -->
<xsl:decimal-format name="Standard" 
                    decimal-separator="."
                    grouping-separator=","
                    infinity="Infinity"
                    minus-sign="-"
                    NaN=""
                    percent="%"
                    per-mille="&#2030;"
                    zero-digit="0" 
                    digit="#" 
                    pattern-separator=";" />

<xsl:variable name="DecPl0" select="string('#0')"/>
<xsl:variable name="DecPl1" select="string(concat('#0', $DecPt, '0'))"/>
<xsl:variable name="DecPl2" select="string(concat('#0', $DecPt, '00'))"/>
<xsl:variable name="DecPl3" select="string(concat('#0', $DecPt, '000'))"/>
<xsl:variable name="DecPl4" select="string(concat('#0', $DecPt, '0000'))"/>
<xsl:variable name="DecPl5" select="string(concat('#0', $DecPt, '00000'))"/>
<xsl:variable name="DecPl6" select="string(concat('#0', $DecPt, '000000'))"/>
<xsl:variable name="DecPl8" select="string(concat('#0', $DecPt, '00000000'))"/>

<xsl:variable name="Pi" select="3.14159265358979323846264"/>
<xsl:variable name="halfPi" select="$Pi div 2.0"/>
<xsl:variable name="DegreesSymbol" select="'.'"/>
<xsl:variable name="MinutesSymbol" select="''"/>
<xsl:variable name="SecondsSymbol" select="''"/>

<xsl:variable name="fileExt" select="'xml'"/>

<xsl:key name="redPtName-search" match="//JOBFile/Reductions/Point" use="Name"/>

<!-- User variable definitions - Appropriate fields are displayed on the       -->
<!-- Survey Controller screen to allow the user to enter specific values       -->
<!-- which can then be used within the style sheet definition to control the   -->
<!-- output data.                                                              -->
<!--                                                                           -->
<!-- All user variables must be identified by a variable element definition    -->
<!-- named starting with 'userField' (case sensitive) followed by one or more  -->
<!-- characters uniquely identifying the user variable definition.             -->
<!--                                                                           -->
<!-- The text within the 'select' field for the user variable description      -->
<!-- references the actual user variable and uses the '|' character to         -->
<!-- separate the definition details into separate fields as follows:          -->
<!-- For all user variables the first field must be the name of the user       -->
<!-- variable itself (this is case sensitive) and the second field is the      -->
<!-- prompt that will appear on the Survey Controller screen.                  -->
<!-- The third field defines the variable type - there are four possible       -->
<!-- variable types: Double, Integer, String and StringMenu.  These variable   -->
<!-- type references are not case sensitive.                                   -->
<!-- The fields that follow the variable type change according to the type of  -->
<!-- variable as follow:                                                       -->
<!-- Double and Integer: Fourth field = optional minimum value                 -->
<!--                     Fifth field = optional maximum value                  -->
<!--   These minimum and maximum values are used by the Survey Controller for  -->
<!--   entry validation.                                                       -->
<!-- String: No further fields are needed or used.                             -->
<!-- StringMenu: Fourth field = number of menu items                           -->
<!--             Remaining fields are the actual menu items - the number of    -->
<!--             items provided must equal the specified number of menu items. -->
<!--                                                                           -->
<!-- The style sheet must also define the variable itself, named according to  -->
<!-- the definition.  The value within the 'select' field will be displayed in -->
<!-- the Survey Controller as the default value for the item.                  -->

<!-- Need to use the select attribute for userField definitions and also include the -->
<!-- contents in single quotes so that the user information can be picked up by the  -->
<!-- Survey Controller and ASCII File Generator.  This means it is not possible to   -->
<!-- have text that includes any apostrophes (single quotes) in it.                  -->


<!-- **************************************************************** -->
<!-- Set global variables from the Environment section of JobXML file -->
<!-- **************************************************************** -->
<xsl:variable name="DistUnit"   select="/JOBFile/Environment/DisplaySettings/DistanceUnits" />
<xsl:variable name="AngleUnit"  select="/JOBFile/Environment/DisplaySettings/AngleUnits" />
<xsl:variable name="CoordOrder" select="/JOBFile/Environment/DisplaySettings/CoordinateOrder" />
<xsl:variable name="TempUnit"   select="/JOBFile/Environment/DisplaySettings/TemperatureUnits" />
<xsl:variable name="PressUnit"  select="/JOBFile/Environment/DisplaySettings/PressureUnits" />

<!-- Setup conversion factor for coordinate and distance values -->
<xsl:variable name="DistConvFactor">
  <xsl:choose>
    <xsl:when test="$DistUnit='Metres'">1.0</xsl:when>
    <xsl:when test="$DistUnit='InternationalFeet'">3.280839895</xsl:when>
    <xsl:when test="$DistUnit='USSurveyFeet'">3.2808333333357</xsl:when>
    <xsl:otherwise>1.0</xsl:otherwise>
  </xsl:choose>
</xsl:variable>

<!-- Setup conversion factor for angular values -->
<xsl:variable name="AngleConvFactor">
  <xsl:choose>
    <xsl:when test="$AngleUnit='DMSDegrees'">1.0</xsl:when>
    <xsl:when test="$AngleUnit='Gons'">1.111111111111</xsl:when>
    <xsl:when test="$AngleUnit='Mils'">1.111111111111</xsl:when>  <!-- Output as gons -->
    <xsl:otherwise>1.0</xsl:otherwise>
  </xsl:choose>
</xsl:variable>

<!-- Setup boolean variable for coordinate order -->
<xsl:variable name="NECoords">
  <xsl:choose>
    <xsl:when test="$CoordOrder='North-East-Elevation'">true</xsl:when>
    <xsl:when test="$CoordOrder='X-Y-Z'">true</xsl:when>
    <xsl:otherwise>false</xsl:otherwise>
  </xsl:choose>
</xsl:variable>

<!-- Setup conversion factor for pressure values -->
<!-- Pressure values in JobXML file are always in millibars (hPa) -->
<xsl:variable name="PressConvFactor">
  <xsl:choose>
    <xsl:when test="$PressUnit='MilliBar'">1.0</xsl:when>
    <xsl:when test="$PressUnit='InchHg'">0.029529921</xsl:when>
    <xsl:when test="$PressUnit='mmHg'">0.75006</xsl:when>
    <xsl:otherwise>1.0</xsl:otherwise>
  </xsl:choose>
</xsl:variable>


<xsl:variable name="SCVersion">
  <xsl:choose>
    <xsl:when test="/JOBFile/@productVersion">
      <xsl:value-of select="/JOBFile/@productVersion"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="/JOBFile/@version div 100"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:variable>


<!-- **************************************************************** -->
<!-- ************************** Main Loop *************************** -->
<!-- **************************************************************** -->
<xsl:template match="/" >
  <xsl:call-template name="NewLine"/>
  <xsl:text disable-output-escaping="yes">&lt;LandXML xmlns="http://www.landxml.org/schema/LandXML-1.0" </xsl:text>
  <xsl:call-template name="NewLine"/>
  <xsl:text>         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" </xsl:text>
  <xsl:call-template name="NewLine"/>
  <xsl:text>         xsi:schemaLocation="http://www.landxml.org/schema/LandXML-1.0 </xsl:text>
  <xsl:text>http://www.landxml.org/schema/LandXML-1.0.xsd"</xsl:text>
  <xsl:call-template name="NewLine"/>
  <xsl:text>         version="1.0"</xsl:text>
  <xsl:text> date="</xsl:text>
  <xsl:value-of select="substring-before(/JOBFile/@TimeStamp, 'T')"/>
  <xsl:text>"</xsl:text>
  <xsl:text> time="</xsl:text>
  <xsl:value-of select="substring-after(/JOBFile/@TimeStamp, 'T')"/>
  <xsl:text>"</xsl:text>
  <xsl:text> readOnly="false"</xsl:text>
  <xsl:text disable-output-escaping="yes"> language="English"&gt;</xsl:text>
  <xsl:call-template name="NewLine"/>

  <xsl:call-template name="Indent"><xsl:with-param name="level" select="1"/></xsl:call-template>
  <xsl:element name="Project">
    <xsl:attribute name="name"><xsl:value-of select="/JOBFile/@jobName"/></xsl:attribute>
  </xsl:element>
  <xsl:call-template name="NewLine"/>



  <xsl:call-template name="outputUnitsElement"/>
  <xsl:call-template name="outputApplicationElement"/>
  <xsl:call-template name="outputCoordinateSystemElement"/>

  <!-- Select the Reductions node to process - output all the points -->
  <xsl:apply-templates select="JOBFile/Reductions" />  <!-- Creates the CgPoints Elements -->

  <!-- If there are any line or arc elements in the FieldBook element output them as PlanFeatures -->
  <xsl:if test="(count(/JOBFile/FieldBook/LineRecord) != 0) or (count(/JOBFile/FieldBook/ArcRecord) != 0)">
    <xsl:apply-templates select="JOBFile/FieldBook" />
  </xsl:if>

  <xsl:text disable-output-escaping="yes">&lt;/LandXML&gt;</xsl:text>  <!-- End of root LandXML element -->
</xsl:template>


<!-- **************************************************************** -->
<!-- ********************* Units Element Output ********************* -->
<!-- **************************************************************** -->
<xsl:template name="outputUnitsElement">

  <xsl:call-template name="Indent"><xsl:with-param name="level" select="1"/></xsl:call-template>
  <xsl:element name="Units">
    <xsl:call-template name="NewLine"/>
    <xsl:choose>
      <xsl:when test="JOBFile/Environment/DisplaySettings/DistanceUnits = 'Metres'">
        <xsl:call-template name="Indent"><xsl:with-param name="level" select="2"/></xsl:call-template>
        <xsl:element name="Metric">
          <xsl:attribute name="areaUnit">squareMeter</xsl:attribute>
          <xsl:attribute name="linearUnit">meter</xsl:attribute>
          <xsl:attribute name="volumeUnit">liter</xsl:attribute>
          <xsl:attribute name="temperatureUnit">celsius</xsl:attribute>
          <xsl:attribute name="pressureUnit">milliBars</xsl:attribute>
          <xsl:attribute name="angularUnit">
            <xsl:choose>
              <xsl:when test="JOBFile/Environment/AngleUnits = 'DMSDegrees'">decimal dd.mm.ss</xsl:when>
              <xsl:when test="JOBFile/Environment/AngleUnits = 'DecimalDegrees'">decimal degrees</xsl:when>
              <xsl:when test="JOBFile/Environment/AngleUnits = 'Gons'">grads</xsl:when>
              <xsl:when test="JOBFile/Environment/AngleUnits = 'Mils'">grads</xsl:when>
              <xsl:otherwise>decimal dd.mm.ss</xsl:otherwise>
            </xsl:choose>
          </xsl:attribute>
          <xsl:attribute name="directionUnit">
            <xsl:choose>
              <xsl:when test="JOBFile/Environment/AngleUnits = 'DMSDegrees'">decimal dd.mm.ss</xsl:when>
              <xsl:when test="JOBFile/Environment/AngleUnits = 'DecimalDegrees'">decimal degrees</xsl:when>
              <xsl:when test="JOBFile/Environment/AngleUnits = 'Gons'">grads</xsl:when>
              <xsl:when test="JOBFile/Environment/AngleUnits = 'Mils'">grads</xsl:when>
              <xsl:otherwise>decimal dd.mm.ss</xsl:otherwise>
            </xsl:choose>
          </xsl:attribute>
        </xsl:element>
      </xsl:when>
      <xsl:otherwise>
        <xsl:call-template name="Indent"><xsl:with-param name="level" select="2"/></xsl:call-template>
        <xsl:element name="Imperial">
          <xsl:attribute name="areaUnit">acre</xsl:attribute>
          <xsl:attribute name="linearUnit">
            <xsl:choose>
              <xsl:when test="JOBFile/Environment/DistanceUnits = 'USSurveyFeet'">USSurveyFoot</xsl:when>
              <xsl:otherwise>foot</xsl:otherwise>
            </xsl:choose>
          </xsl:attribute>
          <xsl:attribute name="volumeUnit">liter</xsl:attribute>
          <xsl:attribute name="temperatureUnit">fahrenheit</xsl:attribute>
          <xsl:attribute name="pressureUnit">inHG</xsl:attribute>
          <xsl:attribute name="angularUnit">
            <xsl:choose>
              <xsl:when test="JOBFile/Environment/AngleUnits = 'DMSDegrees'">decimal dd.mm.ss</xsl:when>
              <xsl:when test="JOBFile/Environment/AngleUnits = 'DecimalDegrees'">decimal degrees</xsl:when>
              <xsl:when test="JOBFile/Environment/AngleUnits = 'Gons'">grads</xsl:when>
              <xsl:when test="JOBFile/Environment/AngleUnits = 'Mils'">grads</xsl:when>
              <xsl:otherwise>decimal dd.mm.ss</xsl:otherwise>
            </xsl:choose>
          </xsl:attribute>
          <xsl:attribute name="directionUnit">
            <xsl:choose>
              <xsl:when test="JOBFile/Environment/AngleUnits = 'DMSDegrees'">decimal dd.mm.ss</xsl:when>
              <xsl:when test="JOBFile/Environment/AngleUnits = 'DecimalDegrees'">decimal degrees</xsl:when>
              <xsl:when test="JOBFile/Environment/AngleUnits = 'Gons'">grads</xsl:when>
              <xsl:when test="JOBFile/Environment/AngleUnits = 'Mils'">grads</xsl:when>
              <xsl:otherwise>decimal dd.mm.ss</xsl:otherwise>
            </xsl:choose>
          </xsl:attribute>
        </xsl:element>
      </xsl:otherwise>
    </xsl:choose>
    <xsl:call-template name="NewLine"/>
    <xsl:call-template name="Indent"><xsl:with-param name="level" select="1"/></xsl:call-template>
  </xsl:element>
  <xsl:call-template name="NewLine"/>
</xsl:template>


<!-- **************************************************************** -->
<!-- ****************** Application Element Output ****************** -->
<!-- **************************************************************** -->
<xsl:template name="outputApplicationElement">
  <!-- Always output in metric units so hardwire this -->
  <xsl:call-template name="Indent"><xsl:with-param name="level" select="1"/></xsl:call-template>
  <xsl:element name="Application">
    <xsl:attribute name="name">
      <xsl:value-of select="/JOBFile/@product"/>
    </xsl:attribute>
    <xsl:attribute name="desc">Generalised LandXML output</xsl:attribute>
      <xsl:attribute name="manufacturer">Trimble</xsl:attribute>
      <xsl:attribute name="version">
        <xsl:value-of select="/JOBFile/@productVersion"/>
      </xsl:attribute>
      <xsl:attribute name="manufacturerURL">http://www.trimble.com</xsl:attribute>
    </xsl:element>
    <xsl:call-template name="NewLine"/>
</xsl:template>


<!-- **************************************************************** -->
<!-- **************** CoordinateSystem Element Output *************** -->
<!-- **************************************************************** -->
<xsl:template name="outputCoordinateSystemElement">

</xsl:template>


<!-- **************************************************************** -->
<!-- *********** Output Points from the Reductions Element ********** -->
<!-- **************************************************************** -->
<xsl:template match="Reductions">

  <xsl:call-template name="Indent"><xsl:with-param name="level" select="1"/></xsl:call-template>
  <xsl:element name="CgPoints">
    <xsl:call-template name="NewLine"/>
    <xsl:for-each select="Point[(string(number(Grid/North)) != 'NaN') and (string(number(Grid/East)) != 'NaN')]">
      <xsl:variable name="ptName" select="Name"/>
      <xsl:call-template name="Indent"><xsl:with-param name="level" select="2"/></xsl:call-template>
      <xsl:element name="CgPoint">
        <xsl:attribute name="name">
          <xsl:value-of select="Name"/>
        </xsl:attribute>
        
        <xsl:attribute name="code">
          <xsl:value-of select="Code"/>
        </xsl:attribute>

        <xsl:if test="Description1 or Description2">
          <xsl:attribute name="desc">
            <xsl:if test="Description1">
              <xsl:value-of select="Description1/@Name"/>
              <xsl:text>: </xsl:text>
              <xsl:value-of select="Description1"/>
            </xsl:if>
            <xsl:if test="Description1 and Description2">
              <xsl:value-of select="' '"/>
            </xsl:if>
            <xsl:if test="Description2">
              <xsl:value-of select="Description2/@Name"/>
              <xsl:text>: </xsl:text>
              <xsl:value-of select="Description2"/>
            </xsl:if>
          </xsl:attribute>
        </xsl:if>

        <!-- Now output the time stamp of the referenced FieldBook element -->
        <xsl:attribute name="timeStamp">
          <xsl:variable name="recID" select="ID"/>
          <xsl:value-of select="/JOBFile/FieldBook/PointRecord[@ID = $recID]/@TimeStamp"/>
        </xsl:attribute>
        
        <!-- Output the north, east and possibly elevation values -->
        <xsl:value-of select="format-number(Grid/North * $DistConvFactor, $DecPl3, 'Standard')"/>
        <xsl:value-of select="' '"/>
        <xsl:value-of select="format-number(Grid/East * $DistConvFactor, $DecPl3, 'Standard')"/>
        <xsl:if test="string(number(Grid/Elevation)) != 'NaN'">
          <xsl:value-of select="' '"/>
          <xsl:value-of select="format-number(Grid/Elevation * $DistConvFactor, $DecPl3, 'Standard')"/>
        </xsl:if>
      </xsl:element>
      <xsl:call-template name="NewLine"/>

      <xsl:if test="Features">
        <!-- If the point has a Features element then write out a Feature element to the LandXML file -->
        <!-- for each Feature in the JobXML with a Property element for each Attribute                -->
        <xsl:for-each select="Features/Feature">
          <xsl:call-template name="Indent"><xsl:with-param name="level" select="2"/></xsl:call-template>
          <xsl:element name="Feature">
            <xsl:attribute name="code">
              <xsl:value-of select="@Name"/>
            </xsl:attribute>
            <xsl:attribute name="source">  <!-- Reference the Feature element back to the point it is associated with using the source attribute -->
              <xsl:value-of select="$ptName"/>
            </xsl:attribute>
            <xsl:for-each select="Attribute">
              <xsl:call-template name="NewLine"/>
              <xsl:call-template name="Indent"><xsl:with-param name="level" select="3"/></xsl:call-template>
              <xsl:element name="Property">
                <xsl:attribute name="label">
                  <xsl:value-of select="Name"/>
                </xsl:attribute>
                <xsl:attribute name="value">
                  <xsl:value-of select="Value"/>
                </xsl:attribute>
              </xsl:element>
            </xsl:for-each>
            <xsl:call-template name="NewLine"/>
            <xsl:call-template name="Indent"><xsl:with-param name="level" select="2"/></xsl:call-template>
          </xsl:element>
          <xsl:call-template name="NewLine"/>
        </xsl:for-each>
      </xsl:if>

    </xsl:for-each>   <!-- Point -->

    <xsl:call-template name="Indent"><xsl:with-param name="level" select="1"/></xsl:call-template>
  </xsl:element>  <!-- CgPoints -->
  <xsl:call-template name="NewLine"/>

</xsl:template>


<!-- **************************************************************** -->
<!-- ******* Output lines and arcs from the FieldBook Element ******* -->
<!-- **************************************************************** -->
<xsl:template match="FieldBook">

  <xsl:call-template name="Indent"><xsl:with-param name="level" select="1"/></xsl:call-template>
  <xsl:element name="PlanFeatures">
    <xsl:for-each select="*[(name(.) = 'LineRecord') or (name(.) = 'ArcRecord')]">
      <xsl:if test="Deleted = 'false'">
        <xsl:call-template name="NewLine"/>
        <xsl:call-template name="Indent"><xsl:with-param name="level" select="2"/></xsl:call-template>
        <xsl:element name="PlanFeature">
          <xsl:call-template name="NewLine"/>
          <xsl:call-template name="Indent"><xsl:with-param name="level" select="3"/></xsl:call-template>
          <xsl:element name="CoordGeom">
            <xsl:choose>
              <xsl:when test="name(.) = 'LineRecord'">  <!-- We are dealing with a LineRecord -->
                <xsl:call-template name="OutputLineElement"/>
              </xsl:when>

              <xsl:otherwise>
                <xsl:call-template name="OutputArcElement"/>
              </xsl:otherwise>
            </xsl:choose>
            <xsl:call-template name="NewLine"/>
            <xsl:call-template name="Indent"><xsl:with-param name="level" select="3"/></xsl:call-template>
          </xsl:element>  <!-- CoordGeom element -->
          <xsl:call-template name="NewLine"/>
          <xsl:call-template name="Indent"><xsl:with-param name="level" select="2"/></xsl:call-template>
        </xsl:element>  <!-- PlanFeature element -->
      </xsl:if>
    </xsl:for-each>
    <xsl:call-template name="NewLine"/>
    <xsl:call-template name="Indent"><xsl:with-param name="level" select="1"/></xsl:call-template>
  </xsl:element>
  <xsl:call-template name="NewLine"/>
</xsl:template>


<!-- **************************************************************** -->
<!-- ******************* Output a Line element ********************** -->
<!-- **************************************************************** -->
<xsl:template name="OutputLineElement">

  <xsl:call-template name="NewLine"/>
  <xsl:call-template name="Indent"><xsl:with-param name="level" select="4"/></xsl:call-template>
  <xsl:element name="Line">  <!-- Create a Line element -->
    <xsl:attribute name="name">
      <xsl:value-of select="Name"/>
    </xsl:attribute>
    <xsl:call-template name="NewLine"/>
    <xsl:call-template name="Indent"><xsl:with-param name="level" select="5"/></xsl:call-template>

    <xsl:variable name="startPtName" select="StartPoint"/>
    <xsl:variable name="startN" select="/JOBFile/Reductions/Point[Name = $startPtName]/Grid/North"/>
    <xsl:variable name="startE" select="/JOBFile/Reductions/Point[Name = $startPtName]/Grid/East"/>
    <xsl:variable name="startEle" select="/JOBFile/Reductions/Point[Name = $startPtName]/Grid/Elevation"/>

    <xsl:element name="Start">  <!-- Output the line start coordinates -->
      <xsl:value-of select="format-number($startN *$DistConvFactor, $DecPl3, 'Standard')"/>
      <xsl:value-of select="' '"/>
      <xsl:value-of select="format-number($startE *$DistConvFactor, $DecPl3, 'Standard')"/>
      <xsl:if test="string(number($startEle)) != 'NaN'">
        <xsl:value-of select="' '"/>
        <xsl:value-of select="format-number($startEle *$DistConvFactor, $DecPl3, 'Standard')"/>
      </xsl:if>
    </xsl:element>  <!-- Start element -->

    <xsl:call-template name="NewLine"/>
    <xsl:call-template name="Indent"><xsl:with-param name="level" select="5"/></xsl:call-template>
    <xsl:element name="End">  <!-- Output the line end coordinates -->
      <xsl:choose>
        <xsl:when test="Method = 'TwoPoints'">
          <xsl:variable name="ptName" select="EndPoint"/>
          <xsl:for-each select="/JOBFile/Reductions/Point[Name = $ptName]">
            <xsl:value-of select="format-number(Grid/North *$DistConvFactor, $DecPl3, 'Standard')"/>
            <xsl:value-of select="' '"/>
            <xsl:value-of select="format-number(Grid/East * $DistConvFactor, $DecPl3, 'Standard')"/>
            <xsl:if test="string(number(Grid/Elevation)) != 'NaN'">
              <xsl:value-of select="' '"/>
              <xsl:value-of select="format-number(Grid/Elevation * $DistConvFactor, $DecPl3, 'Standard')"/>
            </xsl:if>
          </xsl:for-each>
        </xsl:when>

        <xsl:when test="Method = 'BearingAndDistance'">
          <xsl:variable name="endPt">
            <xsl:call-template name="FollowAzimuth">  <!-- Compute the end coords of the line -->
              <xsl:with-param name="azimuth" select="Azimuth"/>
              <xsl:with-param name="distance" select="Length"/>
              <xsl:with-param name="startN" select="$startN"/>
              <xsl:with-param name="startE" select="$startE"/>
              <xsl:with-param name="startElev" select="$startEle"/>
              <xsl:with-param name="grade" select="Grade"/>
            </xsl:call-template>
          </xsl:variable>
          
          <xsl:value-of select="format-number(msxsl:node-set($endPt)/north * $DistConvFactor, $DecPl3, 'Standard')"/>
          <xsl:value-of select="' '"/>
          <xsl:value-of select="format-number(msxsl:node-set($endPt)/east * $DistConvFactor, $DecPl3, 'Standard')"/>
          <xsl:if test="string(number(msxsl:node-set($endPt)/elevation)) != 'NaN'">
            <xsl:value-of select="' '"/>
            <xsl:value-of select="format-number(msxsl:node-set($endPt)/elevation * $DistConvFactor, $DecPl3, 'Standard')"/>
          </xsl:if>
        </xsl:when>
      </xsl:choose>
    </xsl:element>  <!-- End element -->

    <xsl:call-template name="NewLine"/>
    <xsl:call-template name="Indent"><xsl:with-param name="level" select="4"/></xsl:call-template>
  </xsl:element>  <!-- Line element -->
</xsl:template>


<!-- **************************************************************** -->
<!-- ******************* Output an Arc element ********************** -->
<!-- **************************************************************** -->
<xsl:template name="OutputArcElement">
  <!-- Need to determine the start, end and centre points plus the direction for curve as a minimum -->
  <!-- Get the start point coordinates -->
  <xsl:variable name="startPt">
    <xsl:choose>
      <xsl:when test="(Method = 'IntersectionPointAndTangents')">
        <!-- Need to compute the start point for the arc -->
        <xsl:call-template name="ComputeArcStartPointCoords"/>
      </xsl:when>
      <xsl:otherwise>  <!-- Already have the start point name - get coords from Reductions section -->
        <xsl:call-template name="GetCoordsForPoint">
          <xsl:with-param name="ptName" select="StartPoint"/>
        </xsl:call-template>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <!-- Get the end point coordinates -->
  <xsl:variable name="endPt">
    <xsl:choose>
      <xsl:when test="(Method = 'TwoPointsAndRadius') or (Method = 'TwoPointsAndCenterPoint') or (Method = 'ThreePoints')">
        <xsl:call-template name="GetCoordsForPoint">
          <xsl:with-param name="ptName" select="EndPoint"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:call-template name="ComputeArcEndPointCoords"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <!-- Get the arc direction -->
  <xsl:variable name="arcDirn">
    <xsl:choose>
      <xsl:when test="Method = 'ThreePoints'">
        <xsl:call-template name="GetArcDirection">
          <xsl:with-param name="startPt" select="$startPt"/>
          <xsl:with-param name="endPt" select="$endPt"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="Direction"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <!-- Get the arc radius -->
  <xsl:variable name="radius">
    <xsl:choose>
      <xsl:when test="Radius">
        <xsl:value-of select="Radius"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:call-template name="ComputeArcRadius">
          <xsl:with-param name="startPt" select="$startPt"/>
          <xsl:with-param name="endPt" select="$endPt"/>
        </xsl:call-template>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
  
  <!-- Get the centre point coordinates -->
  <xsl:variable name="centrePt">
    <xsl:choose>
      <xsl:when test="Method = 'TwoPointsAndCenterPoint'">
        <xsl:call-template name="GetCoordsForPoint">
          <xsl:with-param name="ptName" select="CenterPoint"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:call-template name="ComputeArcCentrePointCoords">
          <xsl:with-param name="startPt" select="$startPt"/>
          <xsl:with-param name="endPt" select="$endPt"/>
          <xsl:with-param name="arcDirn" select="$arcDirn"/>
          <xsl:with-param name="radius" select="$radius"/>
        </xsl:call-template>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <!-- Now output the actual element -->
  <xsl:call-template name="NewLine"/>
  <xsl:call-template name="Indent"><xsl:with-param name="level" select="4"/></xsl:call-template>
  <xsl:element name="Curve">  <!-- Create a Curve (arc) element -->
    <xsl:attribute name="name">
      <xsl:value-of select="Name"/>
    </xsl:attribute>
    <xsl:attribute name="rot">
      <xsl:choose>
        <xsl:when test="$arcDirn = 'Right'">cw</xsl:when>
        <xsl:otherwise>ccw</xsl:otherwise>
      </xsl:choose>
    </xsl:attribute>
    <xsl:attribute name="radius">
      <xsl:value-of select="format-number($radius * $DistConvFactor, $DecPl3, 'Standard')"/>
    </xsl:attribute>
    <xsl:attribute name="crvType">arc</xsl:attribute>
    <xsl:attribute name="staStart">
      <xsl:value-of select="format-number(StartStation * $DistConvFactor, $DecPl3, 'Standard')"/>
    </xsl:attribute>
    <xsl:call-template name="NewLine"/>
    <xsl:call-template name="Indent"><xsl:with-param name="level" select="5"/></xsl:call-template>

    <xsl:element name="Start">  <!-- Output the arc start coordinates -->
      <xsl:value-of select="format-number(msxsl:node-set($startPt)/north * $DistConvFactor, $DecPl3, 'Standard')"/>
      <xsl:value-of select="' '"/>
      <xsl:value-of select="format-number(msxsl:node-set($startPt)/east * $DistConvFactor, $DecPl3, 'Standard')"/>
      <xsl:if test="string(number(msxsl:node-set($startPt)/elevation)) != 'NaN'">
        <xsl:value-of select="' '"/>
        <xsl:value-of select="format-number(msxsl:node-set($startPt)/elevation * $DistConvFactor, $DecPl3, 'Standard')"/>
      </xsl:if>
    </xsl:element>  <!-- Start element -->

    <xsl:call-template name="NewLine"/>
    <xsl:call-template name="Indent"><xsl:with-param name="level" select="5"/></xsl:call-template>

    <xsl:element name="Center">  <!-- Output the arc centre coordinates -->
      <xsl:value-of select="format-number(msxsl:node-set($centrePt)/north * $DistConvFactor, $DecPl3, 'Standard')"/>
      <xsl:value-of select="' '"/>
      <xsl:value-of select="format-number(msxsl:node-set($centrePt)/east * $DistConvFactor, $DecPl3, 'Standard')"/>
      <xsl:if test="string(number(msxsl:node-set($centrePt)/elevation)) != 'NaN'">
        <xsl:value-of select="' '"/>
        <xsl:value-of select="format-number(msxsl:node-set($centrePt)/elevation * $DistConvFactor, $DecPl3, 'Standard')"/>
      </xsl:if>
    </xsl:element>  <!-- Center element -->

    <xsl:call-template name="NewLine"/>
    <xsl:call-template name="Indent"><xsl:with-param name="level" select="5"/></xsl:call-template>

    <xsl:element name="End">  <!-- Output the arc end coordinates -->
      <xsl:value-of select="format-number(msxsl:node-set($endPt)/north * $DistConvFactor, $DecPl3, 'Standard')"/>
      <xsl:value-of select="' '"/>
      <xsl:value-of select="format-number(msxsl:node-set($endPt)/east * $DistConvFactor, $DecPl3, 'Standard')"/>
      <xsl:if test="string(number(msxsl:node-set($endPt)/elevation)) != 'NaN'">
        <xsl:value-of select="' '"/>
        <xsl:value-of select="format-number(msxsl:node-set($endPt)/elevation * $DistConvFactor, $DecPl3, 'Standard')"/>
      </xsl:if>
    </xsl:element>  <!-- End element -->

    <xsl:call-template name="NewLine"/>
    <xsl:call-template name="Indent"><xsl:with-param name="level" select="4"/></xsl:call-template>
  </xsl:element>  <!-- Curve element -->
</xsl:template>


<!-- **************************************************************** -->
<!-- *********** Get Reductions section coords for point ************ -->
<!-- **************************************************************** -->
<xsl:template name="GetCoordsForPoint">
  <xsl:param name="ptName"/>
  
  <xsl:for-each select="key('redPtName-search', $ptName)">
    <xsl:element name="north">
      <xsl:value-of select="Grid/North"/>
    </xsl:element>
    
    <xsl:element name="east">
      <xsl:value-of select="Grid/East"/>
    </xsl:element>

    <xsl:element name="elevation">
      <xsl:value-of select="Grid/Elevation"/>
    </xsl:element>
  </xsl:for-each>
</xsl:template>


<!-- **************************************************************** -->
<!-- ***** Compute arc start/end point for Int point defined arc **** -->
<!-- **************************************************************** -->
<xsl:template name="ComputeIntPointDefinedArcStartEndPointCoords">
  <xsl:param name="start" select="'true'"/>
  
  <xsl:variable name="rawDeflAngle">
    <xsl:choose>
      <xsl:when test="Direction = 'Right'">
        <xsl:value-of select="EndAzimuth - StartAzimuth"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="StartAzimuth - EndAzimuth"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:variable name="deflAngle">
    <xsl:choose>
      <xsl:when test="$rawDeflAngle &lt; 0.0">
        <xsl:value-of select="$rawDeflAngle + 360.0"/>
      </xsl:when>
      <xsl:when test="$rawDeflAngle &gt; 180.0">
        <xsl:value-of select="360.0 - $rawDeflAngle"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$rawDeflAngle"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:variable name="tanHalfDeflAngle">
    <xsl:call-template name="Tan">
      <xsl:with-param name="theAngle" select="$deflAngle div 2.0 * $Pi div 180.0"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="tanLength" select="Radius * $tanHalfDeflAngle"/>

  <xsl:variable name="intPt">
    <xsl:call-template name="GetCoordsForPoint">
      <xsl:with-param name="ptName" select="IntersectionPoint"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:call-template name="FollowAzimuth">
    <xsl:with-param name="azimuth">
      <xsl:choose>
        <xsl:when test="$start = 'true'">
          <xsl:value-of select="StartAzimuth + 180.0"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="EndAzimuth"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:with-param>
    <xsl:with-param name="distance" select="$tanLength"/>
    <xsl:with-param name="startN" select="msxsl:node-set($intPt)/north"/>
    <xsl:with-param name="startE" select="msxsl:node-set($intPt)/east"/>
  </xsl:call-template>
</xsl:template>


<!-- **************************************************************** -->
<!-- ************ Compute the start point coords for arc ************ -->
<!-- **************************************************************** -->
<xsl:template name="ComputeArcStartPointCoords">
  <!-- Only required for the IntersectionPointAndTangents method -->
  <xsl:call-template name="ComputeIntPointDefinedArcStartEndPointCoords"/>
</xsl:template>


<!-- **************************************************************** -->
<!-- ************* Compute the end point coords for arc ************* -->
<!-- **************************************************************** -->
<xsl:template name="ComputeArcEndPointCoords">
  <xsl:choose>
    <xsl:when test="Method = 'IntersectionPointAndTangents'">
      <xsl:call-template name="ComputeIntPointDefinedArcStartEndPointCoords">
        <xsl:with-param name="start" select="'false'"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>  <!-- ArcLengthAndRadius or DeltaAngleAndRadius methods -->
      <xsl:variable name="deflAngle">
        <xsl:choose>
          <xsl:when test="Method = 'ArcLengthAndRadius'">
            <xsl:value-of select="Length div Radius * 180.0 div $Pi"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="DeltaAngle"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:variable>
      
      <xsl:variable name="startToEndAz">
        <xsl:choose>
          <xsl:when test="Direction = 'Right'">
            <xsl:value-of select="StartAzimuth + $deflAngle div 2.0"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="StartAzimuth - $deflAngle div 2.0"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:variable>
      
      <xsl:variable name="sinHalfDeflAngle">
        <xsl:call-template name="Sine">
          <xsl:with-param name="theAngle" select="$deflAngle div 2.0 * $Pi div 180.0"/>
        </xsl:call-template>
      </xsl:variable>
      
      <xsl:variable name="chordDist" select="Radius * $sinHalfDeflAngle * 2.0"/>
      
      <xsl:variable name="startPt">
        <xsl:call-template name="GetCoordsForPoint">
          <xsl:with-param name="ptName" select="StartPoint"/>
        </xsl:call-template>
      </xsl:variable>

      <xsl:call-template name="FollowAzimuth">
        <xsl:with-param name="azimuth" select="$startToEndAz"/>
        <xsl:with-param name="distance" select="$chordDist"/>
        <xsl:with-param name="startN" select="msxsl:node-set($startPt)/north"/>
        <xsl:with-param name="startE" select="msxsl:node-set($startPt)/east"/>
      </xsl:call-template>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>


<!-- **************************************************************** -->
<!-- ************ Compute the centre point coords for arc ************ -->
<!-- **************************************************************** -->
<xsl:template name="ComputeArcCentrePointCoords">
  <xsl:param name="startPt"/>
  <xsl:param name="endPt"/>
  <xsl:param name="arcDirn"/>
  <xsl:param name="radius"/>

  <xsl:choose>
    <xsl:when test="(Method = 'ArcLengthAndRadius') or (Method = 'DeltaAngleAndRadius') or (Method = 'IntersectionPointAndTangents')">
      <xsl:variable name="azToCentre">
        <xsl:choose>
          <xsl:when test="Direction = 'Right'">
            <xsl:value-of select="StartAzimuth + 90.0"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="StartAzimuth - 90.0"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:variable>
      
      <xsl:call-template name="FollowAzimuth">
        <xsl:with-param name="azimuth" select="$azToCentre"/>
        <xsl:with-param name="distance" select="Radius"/>
        <xsl:with-param name="startN" select="msxsl:node-set($startPt)/north"/>
        <xsl:with-param name="startE" select="msxsl:node-set($startPt)/east"/>
      </xsl:call-template>
    </xsl:when>
    
    <xsl:otherwise>  <!-- TwoPointsAndRadius and ThreePoints methods -->
      <xsl:variable name="chordMidPtN" select="(msxsl:node-set($startPt)/north + msxsl:node-set($endPt)/north) div 2.0"/>
      <xsl:variable name="chordMidPtE" select="(msxsl:node-set($startPt)/east + msxsl:node-set($endPt)/east) div 2.0"/>
      
      <xsl:variable name="chordLen">
        <xsl:call-template name="InverseDistance">
          <xsl:with-param name="deltaN" select="msxsl:node-set($startPt)/north - msxsl:node-set($endPt)/north"/>
          <xsl:with-param name="deltaE" select="msxsl:node-set($startPt)/east - msxsl:node-set($endPt)/east"/>
        </xsl:call-template>
      </xsl:variable>
      
      <xsl:variable name="chordAz">
        <xsl:call-template name="InverseAzimuth">
          <xsl:with-param name="deltaN" select="msxsl:node-set($endPt)/north - msxsl:node-set($startPt)/north"/>
          <xsl:with-param name="deltaE" select="msxsl:node-set($endPt)/east - msxsl:node-set($startPt)/east"/>
        </xsl:call-template>
      </xsl:variable>
      
      <xsl:variable name="azToCentre">
        <xsl:choose>
          <xsl:when test="$arcDirn = 'Right'">
            <xsl:value-of select="$chordAz + 90.0"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="$chordAz - 90.0"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:variable>

      <xsl:variable name="distToCentre">
        <xsl:call-template name="Sqrt">
          <xsl:with-param name="num" select="$radius * $radius - ($chordLen div 2.0) * ($chordLen div 2.0)"/>
        </xsl:call-template>
      </xsl:variable>

      <xsl:call-template name="FollowAzimuth">
        <xsl:with-param name="azimuth" select="$azToCentre"/>
        <xsl:with-param name="distance" select="$distToCentre"/>
        <xsl:with-param name="startN" select="$chordMidPtN"/>
        <xsl:with-param name="startE" select="$chordMidPtE"/>
      </xsl:call-template>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>


<!-- **************************************************************** -->
<!-- ******************* Compute the arc radius ********************* -->
<!-- **************************************************************** -->
<xsl:template name="ComputeArcRadius">
  <xsl:param name="startPt"/>
  <xsl:param name="endPt"/>

  <!-- The arc radius will not be present as an element for the TwoPointsAndCenterPoint and ThreePoints methods -->
  <xsl:choose>
    <xsl:when test="Method = 'ThreePoints'">
      <xsl:call-template name="ComputeRadiusFromThreePts">
        <xsl:with-param name="startPt" select="$startPt"/>
        <xsl:with-param name="endPt" select="$endPt"/>
      </xsl:call-template>
    </xsl:when>

    <xsl:when test="Method = 'TwoPointsAndCenterPoint'">
      <xsl:variable name="centrePt">
        <xsl:call-template name="GetCoordsForPoint">
          <xsl:with-param name="ptName" select="CenterPoint"/>
        </xsl:call-template>
      </xsl:variable>
      
      <xsl:call-template name="InverseDistance">
        <xsl:with-param name="deltaN" select="msxsl:node-set($startPt)/north - msxsl:node-set($centrePt)/north"/>
        <xsl:with-param name="deltaE" select="msxsl:node-set($startPt)/east - msxsl:node-set($centrePt)/east"/>
      </xsl:call-template>
    </xsl:when>
  </xsl:choose>
</xsl:template>


<!-- **************************************************************** -->
<!-- ************** Compute the radius for 3 point arc ************** -->
<!-- **************************************************************** -->
<xsl:template name="ComputeRadiusFromThreePts">
  <xsl:param name="startPt"/>
  <xsl:param name="endPt"/>

  <xsl:variable name="otherPt">
    <xsl:call-template name="GetCoordsForPoint">
      <xsl:with-param name="ptName" select="OtherPointOnArc"/>
    </xsl:call-template>
  </xsl:variable>

  <!-- The radius of the circle with the three points on its circumference is the -->
  <!-- circumradius of the triangle formed by the three points i.e. the radius of -->
  <!-- the circle within which the triangle is inscribed.                         -->
  <xsl:variable name="a">
    <xsl:call-template name="InverseDistance">
      <xsl:with-param name="deltaN" select="msxsl:node-set($startPt)/north - msxsl:node-set($otherPt)/north"/>
      <xsl:with-param name="deltaE" select="msxsl:node-set($startPt)/east - msxsl:node-set($otherPt)/east"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="b">
    <xsl:call-template name="InverseDistance">
      <xsl:with-param name="deltaN" select="msxsl:node-set($endPt)/north - msxsl:node-set($otherPt)/north"/>
      <xsl:with-param name="deltaE" select="msxsl:node-set($endPt)/east - msxsl:node-set($otherPt)/east"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="c">
    <xsl:call-template name="InverseDistance">
      <xsl:with-param name="deltaN" select="msxsl:node-set($startPt)/north - msxsl:node-set($endPt)/north"/>
      <xsl:with-param name="deltaE" select="msxsl:node-set($startPt)/east - msxsl:node-set($endPt)/east"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="s" select="0.5 * ($a + $b + $c)"/>

  <xsl:variable name="K">
    <xsl:call-template name="Sqrt">
      <xsl:with-param name="num" select="$s * ($s - $a) * ($s - $b) * ($s - $c)"/>
    </xsl:call-template>
  </xsl:variable>
  
  <!-- Now return the radius -->
  <xsl:value-of select="($a * $b * $c) div (4.0 * $K)"/>
</xsl:template>


<!-- **************************************************************** -->
<!-- *********** Determine arc direction (for 3 point arc) ********** -->
<!-- **************************************************************** -->
<xsl:template name="GetArcDirection">
  <xsl:param name="startPt"/>
  <xsl:param name="endPt"/>

  <xsl:variable name="otherPt">
    <xsl:call-template name="GetCoordsForPoint">
      <xsl:with-param name="ptName" select="OtherPointOnArc"/>
    </xsl:call-template>
  </xsl:variable>
  
  <!-- Determine if the arc is going left or right - return 'Left' or 'Right' -->
  <xsl:variable name="test" select="(msxsl:node-set($endPt)/north - msxsl:node-set($startPt)/north) * (msxsl:node-set($otherPt)/east - msxsl:node-set($startPt)/east) -
                                    (msxsl:node-set($endPt)/east - msxsl:node-set($startPt)/east) * (msxsl:node-set($otherPt)/north - msxsl:node-set($startPt)/north)"/>
  <xsl:choose>
    <xsl:when test="$test &lt; 0">Right</xsl:when>
    <xsl:otherwise>Left</xsl:otherwise>
  </xsl:choose>

</xsl:template>


<!-- **************************************************************** -->
<!-- ***************** Output a new line character ****************** -->
<!-- **************************************************************** -->
<xsl:template name="NewLine">
  <xsl:value-of select="'&#10;'"/>
</xsl:template>


<!-- **************************************************************** -->
<!-- ******************** Indent to given level ********************* -->
<!-- **************************************************************** -->
<xsl:template name="Indent">
  <xsl:param name="level" select="1"/>

  <xsl:variable name="nbrSpaces" select="$level * 2"/>

  <xsl:value-of select="substring('                                       ', 1, $nbrSpaces)"/>
</xsl:template>


<!-- **************************************************************** -->
<!-- ********* Follow Azimuth to Compute New Point Coords *********** -->
<!-- **************************************************************** -->
<xsl:template name="FollowAzimuth">
  <xsl:param name="azimuth"/>  <!-- in degrees -->
  <xsl:param name="distance"/>
  <xsl:param name="startN"/>
  <xsl:param name="startE"/>
  <xsl:param name="startElev" select="''"/>
  <xsl:param name="endElev" select="''"/>
  <xsl:param name="elevInterpLength" select="''"/>
  <xsl:param name="grade"/>

  <xsl:variable name="sineVal">
    <xsl:call-template name="Sine">
      <xsl:with-param name="theAngle" select="$azimuth * $Pi div 180.0"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="cosineVal">
    <xsl:call-template name="Cosine">
      <xsl:with-param name="theAngle" select="$azimuth * $Pi div 180.0"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="newElev">
    <xsl:choose>
      <xsl:when test="(string(number($startElev)) != 'NaN') and (string(number($endElev)) != 'NaN')">
        <xsl:value-of select="($startElev + $endElev) div 2.0"/> <!-- Return average elevation -->
      </xsl:when>
      <xsl:when test="(string(number($startElev)) != 'NaN') and (string(number($grade)) != 'NaN') and
                      (string(number($elevInterpLength)) != 'NaN')">
        <xsl:value-of select="$startElev + $elevInterpLength * $grade"/> <!-- Apply the grade over the interpolation length to the startElev -->
      </xsl:when>
      <xsl:otherwise><xsl:value-of select="$startElev"/></xsl:otherwise> <!-- Return startElev elevation -->
    </xsl:choose>
  </xsl:variable>

  <!-- Return the coords as a node-set variable -->
  <xsl:element name="north">
    <xsl:value-of select="$startN + $cosineVal * $distance"/>
  </xsl:element>
  <xsl:element name="east">
    <xsl:value-of select="$startE + $sineVal * $distance"/>
  </xsl:element>
  <xsl:element name="elevation">
    <xsl:value-of select="$newElev"/>
  </xsl:element>
</xsl:template>


<!-- **************************************************************** -->
<!-- ****************** Compute Inverse Distance ******************** -->
<!-- **************************************************************** -->
<xsl:template name="InverseDistance">
  <xsl:param name="deltaN"/>
  <xsl:param name="deltaE"/>

  <!-- Compute the inverse distance from the deltas -->
  <xsl:call-template name="Sqrt">
    <xsl:with-param name="num" select="$deltaN * $deltaN + $deltaE * $deltaE"/>
  </xsl:call-template>
</xsl:template>


<!-- **************************************************************** -->
<!-- ******************* Compute Inverse Azimuth ******************** -->
<!-- **************************************************************** -->
<xsl:template name="InverseAzimuth">
  <xsl:param name="deltaN"/>
  <xsl:param name="deltaE"/>

  <!-- Compute the inverse azimuth from the deltas -->
  <xsl:variable name="absDeltaN" select="concat(substring('-',2 - ($deltaN &lt; 0)), '1') * $deltaN"/>
  <xsl:variable name="absDeltaE" select="concat(substring('-',2 - ($deltaE &lt; 0)), '1') * $deltaE"/>

  <xsl:variable name="flag">
    <xsl:choose>
      <xsl:when test="$absDeltaE &gt; $absDeltaN">
        <xsl:value-of select="1"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="0"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:variable name="adjDeltaN">
    <xsl:choose>
      <xsl:when test="$flag">
        <xsl:value-of select="$absDeltaE"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$absDeltaN"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:variable name="adjDeltaE">
    <xsl:choose>
      <xsl:when test="$flag">
        <xsl:value-of select="$absDeltaN"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$absDeltaE"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <!-- Compute the raw angle value -->
  <xsl:variable name="angle">
    <xsl:choose>
      <xsl:when test="$adjDeltaN &lt; 0.000001">
        <xsl:value-of select="0"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:variable name="arcTanAngle">
          <xsl:call-template name="ArcTanSeries">
            <xsl:with-param name="tanVal" select="$adjDeltaE div $adjDeltaN"/>
          </xsl:call-template>
        </xsl:variable>
        <xsl:choose>
          <xsl:when test="$flag">
            <xsl:value-of select="$halfPi - $arcTanAngle"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="$arcTanAngle"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <!-- Assemble the raw angle value into an azimuth -->
  <xsl:variable name="azimuth">
    <xsl:choose>
      <xsl:when test="$deltaE &lt; 0">
        <xsl:choose>
          <xsl:when test="$deltaN &lt; 0">
            <xsl:value-of select="$Pi + $angle"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="$Pi * 2 - $angle"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:when>
      <xsl:otherwise>
        <xsl:choose>
          <xsl:when test="$deltaN &lt; 0">
            <xsl:value-of select="$Pi - $angle"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="$angle"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <!-- Return the azimuth value in decimal degrees -->
  <xsl:value-of select="$azimuth * 180 div $Pi"/>
</xsl:template>


<!-- **************************************************************** -->
<!-- *************** Return the square root of a value ************** -->
<!-- **************************************************************** -->
<xsl:template name="Sqrt">
  <xsl:param name="num" select="0"/>       <!-- The number you want to find the square root of -->
  <xsl:param name="try" select="1"/>       <!-- The current 'try'.  This is used internally. -->
  <xsl:param name="iter" select="1"/>      <!-- The current iteration, checked against maxiter to limit loop count - used internally -->
  <xsl:param name="maxiter" select="40"/>  <!-- Set this up to insure against infinite loops - used internally -->

  <!-- This template uses Sir Isaac Newton's method of finding roots -->

  <xsl:choose>
    <xsl:when test="$try * $try = $num or $iter &gt; $maxiter">
      <xsl:value-of select="$try"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:call-template name="Sqrt">
        <xsl:with-param name="num" select="$num"/>
        <xsl:with-param name="try" select="$try - (($try * $try - $num) div (2 * $try))"/>
        <xsl:with-param name="iter" select="$iter + 1"/>
        <xsl:with-param name="maxiter" select="$maxiter"/>
      </xsl:call-template>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>


<!-- **************************************************************** -->
<!-- ******* Return radians angle less than Specificed Maximum ****** -->
<!-- **************************************************************** -->
<xsl:template name="AngleValueLessThanMax">
  <xsl:param name="inAngle"/>
  <xsl:param name="maxVal"/>
  <xsl:param name="incVal"/>

  <xsl:choose>
    <xsl:when test="$inAngle &gt; $maxVal">
      <xsl:variable name="newAngle">
        <xsl:value-of select="$inAngle - $incVal"/>
      </xsl:variable>
      <xsl:call-template name="AngleValueLessThanMax">
        <xsl:with-param name="inAngle" select="$newAngle"/>
      </xsl:call-template>
    </xsl:when>

    <xsl:otherwise>
      <xsl:value-of select="$inAngle"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>


<!-- **************************************************************** -->
<!-- ************* Return radians angle greater than Zero *********** -->
<!-- **************************************************************** -->
<xsl:template name="AngleValueGreaterThanMin">
  <xsl:param name="inAngle"/>
  <xsl:param name="minVal"/>
  <xsl:param name="incVal"/>

  <xsl:choose>
    <xsl:when test="$inAngle &lt; $minVal">
      <xsl:variable name="newAngle">
        <xsl:value-of select="$inAngle + $incVal"/>
      </xsl:variable>
      <xsl:call-template name="AngleValueGreaterThanMin">
        <xsl:with-param name="inAngle" select="$newAngle"/>
      </xsl:call-template>
    </xsl:when>

    <xsl:otherwise>
      <xsl:value-of select="$inAngle"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>


<!-- **************************************************************** -->
<!-- ********* Return radians angle between Specified Limits ******** -->
<!-- **************************************************************** -->
<xsl:template name="RadianAngleBetweenLimits">
  <xsl:param name="anAngle"/>
  <xsl:param name="minVal" select="0.0"/>
  <xsl:param name="maxVal" select="$Pi * 2.0"/>
  <xsl:param name="incVal" select="$Pi * 2.0"/>

  <xsl:variable name="angle1">
    <xsl:call-template name="AngleValueLessThanMax">
      <xsl:with-param name="inAngle" select="$anAngle"/>
      <xsl:with-param name="maxVal" select="$maxVal"/>
      <xsl:with-param name="incVal" select="$incVal"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="angle2">
    <xsl:call-template name="AngleValueGreaterThanMin">
      <xsl:with-param name="inAngle" select="$angle1"/>
      <xsl:with-param name="minVal" select="$minVal"/>
      <xsl:with-param name="incVal" select="$incVal"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:value-of select="$angle2"/>
</xsl:template>


<!-- **************************************************************** -->
<!-- ************ Return the sine of an angle in radians ************ -->
<!-- **************************************************************** -->
<xsl:template name="Sine">
  <xsl:param name="theAngle"/>
  <xsl:variable name="normalisedAngle">
    <xsl:call-template name="RadianAngleBetweenLimits">
      <xsl:with-param name="anAngle" select="$theAngle"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="theSine">
    <xsl:call-template name="sineIter">
      <xsl:with-param name="pX2" select="$normalisedAngle * $normalisedAngle"/>
      <xsl:with-param name="pRslt" select="$normalisedAngle"/>
      <xsl:with-param name="pElem" select="$normalisedAngle"/>
      <xsl:with-param name="pN" select="1"/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:value-of select="number($theSine)"/>
</xsl:template>

<xsl:template name="sineIter">
  <xsl:param name="pX2"/>
  <xsl:param name="pRslt"/>
  <xsl:param name="pElem"/>
  <xsl:param name="pN"/>
  <xsl:param name="pEps" select="0.00000001"/>
  <xsl:variable name="vnextN" select="$pN+2"/>
  <xsl:variable name="vnewElem"  select="-$pElem*$pX2 div ($vnextN*($vnextN - 1))"/>
  <xsl:variable name="vnewResult" select="$pRslt + $vnewElem"/>
  <xsl:variable name="vdiffResult" select="$vnewResult - $pRslt"/>
  <xsl:choose>
    <xsl:when test="$vdiffResult > $pEps or $vdiffResult &lt; -$pEps">
      <xsl:call-template name="sineIter">
        <xsl:with-param name="pX2" select="$pX2"/>
        <xsl:with-param name="pRslt" select="$vnewResult"/>
        <xsl:with-param name="pElem" select="$vnewElem"/>
        <xsl:with-param name="pN" select="$vnextN"/>
        <xsl:with-param name="pEps" select="$pEps"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$vnewResult"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>


<!-- **************************************************************** -->
<!-- *********** Return the Cosine of an angle in radians *********** -->
<!-- **************************************************************** -->
<xsl:template name="Cosine">
  <xsl:param name="theAngle"/>

  <!-- Use the sine function after subtracting the angle from halfPi -->
  <xsl:call-template name="Sine">
    <xsl:with-param name="theAngle" select="$halfPi - $theAngle"/>
  </xsl:call-template>
</xsl:template>


<!-- **************************************************************** -->
<!-- *********** Return the Tangent of an angle in radians ********** -->
<!-- **************************************************************** -->
<xsl:template name="Tan">
  <xsl:param name="theAngle"/>
  <xsl:param name="prec" select="0.00000001"/>
  <xsl:param name="abortIfInvalid" select="1"/>

  <xsl:variable name="xDivHalfPi" select="floor($theAngle div $halfPi)"/>
  <xsl:variable name="xHalfPiDiff" select="$theAngle - $halfPi * $xDivHalfPi"/>

  <xsl:choose>  <!-- Check for a solution -->
    <xsl:when test="(-$prec &lt; $xHalfPiDiff) and
                    ($xHalfPiDiff &lt; $prec) and
                    ($xDivHalfPi mod 2 = 1)">
      <xsl:choose>
        <xsl:when test="$abortIfInvalid">
          <xsl:message terminate="yes">
            <xsl:value-of select="concat('Function error: tan() not defined for TheAngle =', $theAngle)"/>
          </xsl:message>
        </xsl:when>

        <xsl:otherwise>Infinity</xsl:otherwise>
      </xsl:choose>
    </xsl:when>

    <!-- Compute the sine and cosine of the angle to get the tangent value -->
    <xsl:otherwise>
      <xsl:variable name="vSin">
        <xsl:call-template name="Sine">
          <xsl:with-param name="theAngle" select="$theAngle"/>
        </xsl:call-template>
      </xsl:variable>

      <xsl:variable name="vCos">
        <xsl:call-template name="Cosine">
          <xsl:with-param name="theAngle" select="$theAngle"/>
        </xsl:call-template>
      </xsl:variable>

      <xsl:value-of select="$vSin div $vCos"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>


<!-- **************************************************************** -->
<!-- ******* Return the arcTan value using a series expansion ******* -->
<!-- **************************************************************** -->
<xsl:template name="ArcTanSeries">
  <xsl:param name="tanVal"/>

  <!-- If the absolute value of tanVal is greater than 1 the work with the -->
  <!-- reciprocal value and return the resultant angle subtracted from Pi. -->
  <xsl:variable name="absTanVal" select="concat(substring('-',2 - ($tanVal &lt; 0)), '1') * $tanVal"/>
  <xsl:variable name="tanVal2">
    <xsl:choose>
      <xsl:when test="$absTanVal &gt; 1.0">
        <xsl:value-of select="1.0 div $tanVal"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$tanVal"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:variable name="valSq" select="$tanVal2 * $tanVal2"/>

  <xsl:variable name="angVal">
    <xsl:value-of select="$tanVal2 div (1 + ($valSq
                                   div (3 + (4 * $valSq
                                   div (5 + (9 * $valSq
                                   div (7 + (16 * $valSq
                                   div (9 + (25 * $valSq
                                   div (11 + (36 * $valSq
                                   div (13 + (49 * $valSq
                                   div (15 + (64 * $valSq
                                   div (17 + (81 * $valSq
                                   div (19 + (100 * $valSq
                                   div (21 + (121 * $valSq
                                   div (23 + (144 * $valSq
                                   div (25 + (169 * $valSq
                                   div (27 + (196 * $valSq
                                   div (29 + (225 * $valSq))))))))))))))))))))))))))))))"/>
  </xsl:variable>

  <xsl:choose>
    <xsl:when test="$absTanVal &gt; 1.0">
      <xsl:choose>
        <xsl:when test="$tanVal &lt; 0">
          <xsl:value-of select="-$halfPi - $angVal"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="$halfPi - $angVal"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$angVal"/>
    </xsl:otherwise>
  </xsl:choose>

</xsl:template>


</xsl:stylesheet>