2013-02-01 111 views
0

我想做一個xslt,可以通過四元數轉換位置(vector3)到一個新的位置。我做了以下設置,但是我正在檢索NaN的值接近於0的非常小的值。如何使用從四元數到右向量計算的值進一步計算?科學浮點數的計算結果,不能用它來計算

<xsl:template name="object_markingtape_position"> 
    <xsl:param name="sign"/> <!-- left or right (-1 or 1) --> 
    <xsl:param name="quaternion"/> <!-- quaternion in x,y,z,w --> 
    <xsl:variable name="rightvec"> 
    <xsl:call-template name="QuatToRight"> 
     <xsl:with-param name="x" select="$quaternion/ns:x"/> 
     <xsl:with-param name="y" select="$quaternion/ns:y"/> 
     <xsl:with-param name="z" select="$quaternion/ns:z"/> 
     <xsl:with-param name="w" select="$quaternion/ns:w"/> 
    </xsl:call-template> 
    </xsl:variable> 

    Right vector y: <xsl:value-of select="number($rightvec/y)"/> <!-- results in a value with 1.5435434E-04 --> 
    <xsl:element name="position" namespace="{$ns}"> 
    <xsl:element name="x" namespace="{$ns}"> 
     <xsl:value-of select="$sign * 1.5 * $rightvec/x + ns:position/ns:x"/> 
    </xsl:element> 
    <xsl:element name="y" namespace="{$ns}"> <!-- results into NaN --> 
     <xsl:value-of select="$sign * 1.5 * $rightvec/y + ns:position/ns:y"/> 
    </xsl:element> 
    <xsl:element name="z" namespace="{$ns}"> 
     <xsl:value-of select="$sign * 1.5 * $rightvec/z + ns:position/ns:z"/> 
    </xsl:element> 
    </xsl:element> 
</xsl:template> 

<!-- Functionality for calculating the vectors from a quaternion --> 
<!-- From http://nic-gamedev.blogspot.nl/2011/11/quaternion-math-getting-local-axis.html --> 
<xsl:template name="QuatToRight"> 
    <xsl:param name="x"/> 
    <xsl:param name="y"/> 
    <xsl:param name="z"/> 
    <xsl:param name="w"/> 
    <xsl:element name="vec3"> 
    <xsl:element name="x"> 
     <xsl:value-of select="1 - 2 * ($x * $y - $w * $z)"/> 
    </xsl:element> 
    <xsl:element name="y"> 
     <xsl:value-of select="2 * ($x * $y + $w * $z)"/> 
    </xsl:element> 
    <xsl:element name="z"> 
     <xsl:value-of select="2 * ($x * $z - $w * $y)"/> 
    </xsl:element> 
    </xsl:element> 
</xsl:template> 

可以進來XML值的示例如下:

<Item> 
    <position> 
    <x>-106.6172</x> 
    <y>0.780673563</y> 
    <z>-13.0446815</z> 
    </position> 
    <rotation> <!-- this is where the quaternion param is filled with --> 
    <x>0.0810996</x> 
    <y>0.354339659</y> 
    <z>-0.207844481</z> 
    <w>-0.908111751</w> 
    </rotation> 
</Item> 
+0

你能發表一個輸入XML的例子嗎? – MiMo

+0

您正在使用哪種處理器?你最好的選擇可能是使用擴展功能。 –

+0

@MiMo我已經添加了部分xml示例。所有參數和變量都被正確填充,但我只是遇到了將8237489234E-04帶回實際工作的問題。 – Marnix

回答

0

我解決了這個與一些數據丟失,但它是迄今爲止最乾淨的解決方案。我用format-number()

<xsl:template name="QuatToRight"> 
    <xsl:param name="x"/> 
    <xsl:param name="y"/> 
    <xsl:param name="z"/> 
    <xsl:param name="w"/> 
    <xsl:element name="vec3"> 
    <xsl:element name="x"> 
     <xsl:value-of select="format-number(1 - 2 * ($x * $y - $w * $z),'0.000000')"/> 
    </xsl:element> 
    <xsl:element name="y"> 
     <xsl:value-of select="format-number(2 * ($x * $y + $w * $z),'0.000000')"/> 
    </xsl:element> 
    <xsl:element name="z"> 
     <xsl:value-of select="format-number(2 * ($x * $z - $w * $y),'0.000000')"/> 
    </xsl:element> 
    </xsl:element> 
</xsl:template> 
0

如果你不能找到一個更好的解決方案,您可能需要訴諸使用擴展功能。

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:quat="urn:myExtension" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="quat msxsl" version="1.0"> 
<xsl:param name="x"/> 
<xsl:param name="y"/> 
<xsl:param name="z"/> 
<xsl:param name="w"/> 

<xsl:template match="*"> 
    <xsl:value-of select="quat:calcQuat($x, $y, $z, $w)"/> 
</xsl:template> 

<msxsl:script implements-prefix="quat" language="c#"> 
    <![CDATA[  
    public string calcQuat(double x, double y, double z, double w) 
    {   
     double result = 1 - 2 * (x * y - w * z) 
     return Double.ToString(result) 
    }  

    ]]> 
</msxsl:script> 

+0

當我嘗試這樣做時,出現'XsltException:樣式表腳本編譯錯誤'。什麼是urn:myExtension?你能否給我提供一個如何工作的參考? – Marnix

0

有三個問題,我可以看到:

  • 變量rightvec包含XML片段,但隨後作爲一個節點集 - 這需要一個轉換工作通常(但取決於XSLT處理器)

  • 命名模板object_markingtape_position引用元素ns:position在當前上下文中,所以它的結果取決於它被稱爲的位置 - 更好地將位置作爲參數傳遞;

  • 命名的模板QuatToRight生成一個包含具有值的子元素的vec3元素,但其結果將用作好像沒有中間元素的vec3

使用.NET XSLT處理器,這XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" 
> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template name="object_markingtape_position"> 
    <xsl:param name="sign"/> <!-- left or right (-1 or 1) --> 
    <xsl:param name="quaternion"/> <!-- quaternion in x,y,z,w --> 
    <xsl:param name="position"/> <!-- position in x,y,z --> 
    <xsl:variable name="rightvecFragment"> 
     <xsl:call-template name="QuatToRight"> 
     <xsl:with-param name="x" select="$quaternion/x"/> 
     <xsl:with-param name="y" select="$quaternion/y"/> 
     <xsl:with-param name="z" select="$quaternion/z"/> 
     <xsl:with-param name="w" select="$quaternion/w"/> 
     </xsl:call-template> 
    </xsl:variable> 
    <xsl:variable name="rightvec" select="msxsl:node-set($rightvecFragment)"/> 

    <xsl:element name="position"> 
     <xsl:element name="x"> 
     <xsl:value-of select="$sign * 1.5 * $rightvec/x + $position/x"/> 
     </xsl:element> 
     <xsl:element name="y"> 
     <!-- results into NaN --> 
     <xsl:value-of select="$sign * 1.5 * $rightvec/y + $position/y"/> 
     </xsl:element> 
     <xsl:element name="z"> 
     <xsl:value-of select="$sign * 1.5 * $rightvec/z + $position/z"/> 
     </xsl:element> 
    </xsl:element> 
    </xsl:template> 

    <!-- Functionality for calculating the vectors from a quaternion --> 
    <!-- From http://nic-gamedev.blogspot.nl/2011/11/quaternion-math-getting-local-axis.html --> 
    <xsl:template name="QuatToRight"> 
    <xsl:param name="x"/> 
    <xsl:param name="y"/> 
    <xsl:param name="z"/> 
    <xsl:param name="w"/> 
    <xsl:element name="x"> 
     <xsl:value-of select="1 - 2 * ($x * $y - $w * $z)"/> 
    </xsl:element> 
    <xsl:element name="y"> 
     <xsl:value-of select="2 * ($x * $y + $w * $z)"/> 
    </xsl:element> 
    <xsl:element name="z"> 
     <xsl:value-of select="2 * ($x * $z - $w * $y)"/> 
    </xsl:element> 
    </xsl:template> 

    <xsl:template match="/*"> 
    <xsl:call-template name="object_markingtape_position"> 
     <xsl:with-param name="sign" select="1"/> 
     <xsl:with-param name="position" select="position"/> 
     <xsl:with-param name="quaternion" select="rotation"/> 
    </xsl:call-template> 
    </xsl:template> 

</xsl:stylesheet> 

施加到例如輸入產生:

<position> 
    <x>-104.63717236709732</x> 
    <y>1.4331220235568977</y> 
    <z>-12.129909788264223</z> 
</position> 
+0

我改變了你所說的一切,但我仍然收到下面的輸出:' -111.6288408761534 NaN的 -15.460565039376352' – Marnix

+0

我不知道還有什麼suggets。我得到的結果是正確的嗎? – MiMo

+0

是的,但它可能是我使用Mono而不是.NET。它應該是一樣的,但這不會是我與Mono有關的首要問題之一。 – Marnix