Dear all.
I have nearly completed a mini project to display slope (geotechnical engineering) information in the form of an SVG cross section (as well as many other elements).
I am desperately close to the finish line but have a problem which could be altered in one or two ways I think, however I cannot figure it out (not experienced enough). I apologise if the code shown here isn't great...but it works other than this!
The XML data relevant to this part will be held as:
Code:
<geo:case caseID="ID1">
<geo:slope>
<geo:groundLayers>
<diggs:layers diggs:id="1">
<diggs:layer>
<geo:location>
<gml:Point gml:id="1">
<gml:pos>316865 504940</gml:pos>
</gml:Point>
<geo:Height>749</geo:Height>
<diggs:top>200</diggs:top>
</geo:location>
</diggs:layer>
<diggs:layer>
<geo:location>
<gml:Point gml:id="level2Point1">
<gml:pos>316570 505159</gml:pos>
</gml:Point>
<geo:Height>450</geo:Height>
<diggs:top>150</diggs:top>
</geo:location>
</diggs:layer>
</diggs:layer>
</diggs:layers>
<diggs:layers diggs:id="2">
...
...
<diggs:layers> then appears any number of times (with new diggs:id) and again will contain any number of <diggs:layer> elements. Essentially what this is storing is information regarding a coordinate (Easting and Northing), an altitude (above/below sea level) and <diggs:top> holds the depth in metres to a soil ground layer. Each diggs:layers id represents a new ground (sub-strata) level (found by a borehole). Each <diggs:layer> within <diggs:layers> will essentially be plotting a point on a path for the cross section.
Here is a function I have at the bottom:
Code:
<!-- Ground Layer Function -->
<xsl:function name="geo:point3" as="xs:integer+">
<xsl:param name="location3" as="element(diggs:layer)"/>
<xsl:variable name="point3" as="xs:string" select="$location3/geo:location/gml:Point/gml:pos"/>
<xsl:sequence select="xs:integer(substring-before($point3, ' '))"/>
<xsl:sequence select="xs:integer(substring-after($point3, ' '))"/>
</xsl:function>
This splits up the coordinate tuple so that each individual coordinate can be held as Easting or Northing so that things can be calculated to show the image.
Here are the variables required for this part (and utilises the function above):
Code:
<!-- Ground layer variables -->
<xsl:variable name="groundLayers" as="element(groundLayer)+">
<xsl:for-each select="geo:slope/geo:groundLayers/diggs:layers/diggs:layer">
<!--<xsl:sort select="parent::geo:location/parent::diggs:layer/parent::diggs:layers/@diggs:id" order="descending"/>-->
<xsl:variable name="groundLayer" as="xs:integer+" select="geo:point3(.)"/>
<xsl:variable name="coordinateX1" as="xs:integer" select="$groundLayer[1]"/>
<xsl:variable name="coordinateY1" as="xs:integer" select="$groundLayer[2]"/>
<xsl:variable name="c2" as="xs:decimal" select="$groundLayer[2] - (($m2)*$groundLayer[1])"/>
<xsl:variable name="cdiff" as="xs:decimal" select="$c1 - $c2"/>
<xsl:variable name="xi" as="xs:decimal" select="$cdiff div $mdiff"/>
<xsl:variable name="yi" as="xs:decimal" select="($m2*$xi)+$c2"/>
<xsl:variable name="xdiff" as="xs:decimal" select="$toe[1] - $xi"/>
<xsl:variable name="ydiff" as="xs:decimal" select="$toe[2] - $yi"/>
<xsl:variable name="distanceGL" as="xs:decimal"
select="xs:integer(round(math:sqrt($ydiff * $ydiff + $xdiff * $xdiff)))"/>
<xsl:variable name="heightGL" as="xs:integer" select="geo:location/geo:Height"/>
<xsl:variable name="altitudeGL" as="xs:integer">
<xsl:choose>
<xsl:when test="$altitude[1] < 0">
<xsl:value-of select="$altitude[1]+$heightGL"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$heightGL - $altitude[1]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="layerTopDepth" as="xs:integer" select="geo:location/diggs:top"/>
<xsl:variable name="layerId" select="@id" />
<groundLayer xmlns="">
<distanceGL>
<xsl:value-of select="$distanceGL"/>
</distanceGL>
<altitudeGL>
<xsl:value-of select="$altitudeGL"/>
</altitudeGL>
<heightGL>
<xsl:value-of select="$heightGL"/>
</heightGL>
<coordinateX1>
<xsl:value-of select="$coordinateX1"/>
</coordinateX1>
<coordinateY1>
<xsl:value-of select="$coordinateY1"/>
</coordinateY1>
<layerTopDepth>
<xsl:value-of select="$layerTopDepth"/>
</layerTopDepth>
<layerId>
<xsl:value-of select="$layerId" />
</layerId>
</groundLayer>
</xsl:for-each>
</xsl:variable>
There is a lot calculated there I know..sorry! It is all needed though.
So the important part here is the <xsl:for-each select="geo:slope/geo:groundLayers/diggs:layers/diggs:layer">. This means that it is looping within <diggs:layer> and performing the function shown earlier to help calculate the variables.
Ok so my problem: I need to now split all of the data from this in to each <diggs:layers>, per each diggs:id. In my test example I have two layers (so diggs:id's of 1 and 2). Once these are split up I need them to be sorted in a descending order by id.
I tried doing the above by using a for-each loop (over the <diggs:layers>) when it came to stating the SVG path. If I do then I receive an error because I need <xsl:for-each select="$groundLayers"> in order to access my variable information.
My alternative idea was to change the variable's <for-each> loop to looping over <diggs:layers> as this would be ideal! The problem is that there are multiple coordinate tuples found in each sub structure of that level and so the function I showed earlier fails because it is looking for 2 points. (I need to cater for unlimited.)
If anyone has any questions that need answering in order to help me then please do! It's hard to explain this work I'm sorry.
Oh, the calculations etc are all correct and I can plot each point as an svg circle held in that xml structure shown at the top. This means that the data is accessed and calculated ok, it's just a matter of separating them up so that these calculations still work, but the 'answer' coordinates are grouped as per the diggs:layers diggs:id they came from.
Thank you for reading this far!
James
edit:
here's my code for the path at the moment:
Code:
<xsl:for-each select="$groundLayers[1]">
<path stroke="blue" stroke-width="2" fill="none">
<xsl:attribute name="d">
<xsl:text>M</xsl:text>
<xsl:value-of select="$distance - distanceGL"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$height - altitudeGL + layerTopDepth"/>
<xsl:text> L </xsl:text>
<xsl:for-each select="$groundLayers">
<xsl:sort select="xs:double(distanceGL)" order="descending"/>
<xsl:value-of
select="concat($distance - distanceGL, ' ', $height - altitudeGL + layerTopDepth)"/>
<xsl:if test="position() != last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:attribute>
</path>
I used the predicate [1] in the for-each loop so as to just show 1 output path (as in my full xml files I have 2 <diggs:layers> and 4 <diggs:layer> elements within each...giving 8 loops from the variables and therefore 8 paths). This one output path gives the following:
Code:
<path stroke="blue" stroke-width="2" fill="none"
d="M0 200 L 0 200, 0 0, 363 449, 363 299, 574 599, 574 499, 901 599, 901 549"/>
This is almost correct as I've explained before. Basically because the two <diggs:layers> are not grouped separately and therefore drawn in to two different paths, they have performed one iteration and sorted by my current sorting factor (which needs to remain on top of the proposed grouping). After 'L' (in the path) every second coordinate needs to be removed and put in to a new path. So my desired output would be (make comparison):
Code:
<path stroke="blue" stroke-width="2" fill="none"
d="M0 200 L 0 200, 363 449, 574 599, 901 599"/>
<path stroke="blue" stroke-width="2" fill="none"
d="M0 0 L 0 0, 363 299, 574 499, 901 549"/>
Here is an image of my stripped down code (to just focus on this problem) plotting each point as a circle (which therefore is to test that all the correct points have been calculated, which they have, however they need to be sorted and grouped in order to draw the paths correctly and separately). To show each point I removed the predicate [1] from the for-each.
http://i3.photobucket.com/albums/y90...icture1-24.png
And here is the image path shown with the code shown on this page (using predicate). Now that the top line of points and the bottom line of points should be drawn with 2 separate paths...not joined together.
http://i3.photobucket.com/albums/y90...icture2-12.png