<?xml version="1.0" encoding="UTF-8" ?>

<!--
    Document   : x3d2pml.xsl
    Created on : 22 October 2004, 11:00
    Author     : emmanuel promayon
    Description:
        Convert a simple X3D file ("nterchange" profile) to PML
        
        v 0.1, 22 Oct 2004
        - Supports only IndexedFacetSet
        - only works for one instance of <Shape>
        - only works for triangle and quand facets
        
/*****************************************************************************
 * $CAMITK_LICENCE_BEGIN$
 *
 * CamiTK - Computer Assisted Medical Intervention ToolKit
 * (c) 2001-2025 Univ. Grenoble Alpes, CNRS, Grenoble INP - UGA, TIMC, 38000 Grenoble, France
 *
 * Visit http://camitk.imag.fr for more information
 *
 * This file is part of CamiTK.
 *
 * CamiTK is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * CamiTK is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with CamiTK.  If not, see <http://www.gnu.org/licenses/>.
 *
 * $CAMITK_LICENCE_END$
 ****************************************************************************/
        
-->

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:x3d='http://www.web3d.org/specifications/x3d-3.0.xsd'
                xmlns:str="http://exslt.org/strings"
                id="xsl2pml 0.1">
<!--                xmlns:date="http://exslt.org/dates-and-times"
                xmlns:common="http://exslt.org/common">//-->

    <xsl:output method="xml" indent="yes" encoding="UTF-8"/>
    
    <!-- top level -->
    <xsl:template match="/X3D">
    
        <xsl:element name="physicalModel">
        
            <xsl:attribute name="name">converted from X3D</xsl:attribute>
            
            <!-- only convert the first Shape -->
            <xsl:apply-templates select="//Shape[1]"/>
            
        </xsl:element>
        
    </xsl:template>
    
    <!-- Shape level -->
    <xsl:template match="Shape">
    
            <!-- get color and transparencies -->
            <xsl:variable name="rgb">
                <xsl:choose>
                    <xsl:when test="count(Appearance/Material/@diffuseColor) > 0">
                            <xsl:value-of select="Appearance/Material/@diffuseColor"/>
                    </xsl:when>
                    <xsl:otherwise>0.5 0.5 0.5</xsl:otherwise>
                </xsl:choose>
            </xsl:variable>
            <xsl:variable name="alpha">
                <xsl:choose>
                    <!-- transparency is the inverse of alpha chanel -->
                    <xsl:when test="count(Appearance/Material/@transparency) > 0">
                        <xsl:value-of select="1.0 - Appearance/Material/@transparency"/>
                    </xsl:when>
                    <xsl:otherwise>1.0</xsl:otherwise>
                </xsl:choose>
            </xsl:variable>
            
            
            <!-- create atom list from the Coordinate @point -->
            <xsl:apply-templates select="IndexedFaceSet/Coordinate"/>
        
            <!-- create the list of facets, i.e cells -->
            <exclusiveComponents>
                <multiComponent name="Exclusive components">
                    <!-- call the templates with specified colors -->
                    <xsl:apply-templates select="IndexedFaceSet">
                        <xsl:with-param name="rgb" select="$rgb"/>
                        <xsl:with-param name="alpha" select="$alpha"/>
                    </xsl:apply-templates>
                </multiComponent>
            </exclusiveComponents>
    </xsl:template>
    
    <!-- Coordinate level -->
    <xsl:template match="Coordinate">
        <atoms>
            <structuralComponent name="element list">
            
            <!-- split the point attribute value to coordinates triplets -->
            <xsl:for-each select="str:split(@point, ', ')">
            
                <!-- here the value of . is "   xi  yi zi" (with any number of space separating the values) -->
                
                <!-- xCoord is the first token when separating using space, yCoord the second and zCoord the last one -->
                <xsl:variable name="xCoord" select="str:split(.,' ')[1]"/>
                <xsl:variable name="yCoord" select="str:split(.,' ')[2]"/>
                <xsl:variable name="zCoord" select="str:split(.,' ')[3]"/>
                
                <!-- for each triplet output a new atom and its position -->
                <atom>
                <xsl:element name="atomProperties">
                    <xsl:attribute name="index">
                        <xsl:copy-of select="position()-1"/> <!-- index starts at 0 -->
                    </xsl:attribute>
                    <xsl:attribute name="x">
                        <xsl:copy-of select="$xCoord"/>
                    </xsl:attribute>
                    <xsl:attribute name="y">
                        <xsl:copy-of select="$yCoord"/>
                    </xsl:attribute>
                    <xsl:attribute name="z">
                        <xsl:copy-of select="$zCoord"/>
                    </xsl:attribute>
                </xsl:element>
                </atom>
                
            </xsl:for-each> 
              
            </structuralComponent>
        </atoms>

    </xsl:template>

    <xsl:template match="IndexedFaceSet">
        <xsl:param name="rgb"/>
        <xsl:param name="alpha"/>
        
        <structuralComponent name="IndexedFaceSet" mode="WIREFRAME_AND_SURFACE">
        
            <xsl:element name="color">
                <xsl:attribute name="r">
                    <xsl:value-of select="$rgb"/>
                </xsl:attribute>
                <xsl:attribute name="a">
                    <xsl:value-of select="$alpha"/>
                </xsl:attribute>
            </xsl:element>
            
            <!-- split the coordIndex to get each facet index -->
            <xsl:for-each select="str:split(@coordIndex, '-1')">
                <!-- a facet is a pml cell 
                     Here the value of . is "  v1  v2 ... vn"
                  -->
                <!-- compute nr of vertices -->
                <xsl:variable name="nbOfVertices" select="count(str:split(.,' '))"/>
                
                <!-- do not create any cell if the list of vertices is empty! -->
                <xsl:if test="$nbOfVertices > 0">
                    <cell>
                        <xsl:element name="cellProperties">
                            <xsl:attribute name="type">
                                
                                <xsl:choose>
                                    <xsl:when test="$nbOfVertices = 3">TRIANGLE</xsl:when>
                                    <xsl:when test="$nbOfVertices = 4">QUAD</xsl:when>
                                    <xsl:otherwise>POLY_VERTEX</xsl:otherwise>
                                </xsl:choose>
                            </xsl:attribute>
                        </xsl:element>
                        
                        <!-- the atom index -->
                        <xsl:for-each select="str:split(.,' ')">
                            <!-- here . is the index of the atom -->
                            <xsl:element name="atomRef">
                                <xsl:attribute name="index">
                                    <xsl:value-of select="."/>
                                </xsl:attribute>
                            </xsl:element>
                        </xsl:for-each>
                        
                    </cell>
                </xsl:if>
            </xsl:for-each>
            
        </structuralComponent>

    </xsl:template>
    
</xsl:stylesheet>
