This repository has been archived on 2024-05-19. You can view files and clone it, but cannot push or open issues or pull requests.
l-systems/traceur.xsl

202 lines
8.7 KiB
XML
Raw Normal View History

2024-05-06 14:27:40 +02:00
<xsl:transform version="2.0"
2024-05-03 01:59:58 +02:00
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs math">
<xsl:output method="xml" indent="yes" />
2024-05-03 01:59:58 +02:00
<!-- Déclaration des variables initiales -->
2024-05-06 14:24:53 +02:00
<xsl:variable name="initial-x" select="0" as="xs:double" />
<xsl:variable
2024-05-03 01:59:58 +02:00
name="initial-y" select="0" as="xs:double" />
2024-05-06 14:24:53 +02:00
<xsl:variable name="initial-angle" select="0"
2024-05-03 01:59:58 +02:00
as="xs:double" />
2024-05-06 14:24:53 +02:00
<xsl:template match="/tortue">
2024-05-03 01:59:58 +02:00
<xsl:processing-instruction name="xml-model">href="traceur.xsd"</xsl:processing-instruction>
2024-05-06 14:24:53 +02:00
<traceur>
<!-- Appel du template pour traiter les commandes
avec les valeurs initiales des paramètres -->
2024-05-03 01:59:58 +02:00
<xsl:call-template name="process-commands">
2024-05-06 14:24:53 +02:00
<xsl:with-param name="commands"
select="*" />
<xsl:with-param name="x"
2024-05-03 01:59:58 +02:00
select="$initial-x" />
2024-05-06 14:24:53 +02:00
<xsl:with-param name="y"
select="$initial-y" />
<xsl:with-param
2024-05-03 01:59:58 +02:00
name="angle" select="$initial-angle" />
2024-05-06 14:24:53 +02:00
<xsl:with-param name="states"
select="()" />
2024-05-03 01:59:58 +02:00
</xsl:call-template>
</traceur>
</xsl:template>
2024-05-03 01:59:58 +02:00
<!-- Template récursif pour traiter les commandes individuelles -->
2024-05-06 14:24:53 +02:00
<xsl:template
2024-05-03 01:59:58 +02:00
name="process-commands">
2024-05-06 14:24:53 +02:00
<xsl:param
name="commands" />
<xsl:param
name="x" />
<xsl:param
name="y" />
<xsl:param
2024-05-03 01:59:58 +02:00
name="angle" />
2024-05-06 14:24:53 +02:00
<xsl:param
2024-05-03 01:59:58 +02:00
name="states" />
2024-05-03 01:59:58 +02:00
<!-- Si il reste des commandes à traiter -->
2024-05-06 14:24:53 +02:00
<xsl:if test="$commands">
2024-05-03 01:59:58 +02:00
<!-- Sélection de la première commande à traiter -->
2024-05-06 14:24:53 +02:00
<xsl:variable name="current-command"
select="$commands[1]" />
<xsl:choose>
2024-05-03 01:59:58 +02:00
<!-- Si la commande est une ligne -->
<xsl:when test="local-name($current-command) = 'line'">
<!-- Calcul de la distance à parcourir et conversion de l'angle en radians -->
2024-05-06 14:24:53 +02:00
<xsl:variable name="distance"
2024-05-03 01:59:58 +02:00
select="number($current-command)" />
2024-05-06 14:24:53 +02:00
<xsl:variable name="radians"
2024-05-03 01:59:58 +02:00
select="$angle * math:pi() div 180" />
2024-05-06 14:24:53 +02:00
<xsl:variable name="new-x"
2024-05-03 01:59:58 +02:00
select="$x + $distance * math:cos($radians)" />
2024-05-06 14:24:53 +02:00
<xsl:variable name="new-y"
2024-05-03 01:59:58 +02:00
select="$y + $distance * math:sin($radians)" />
2024-05-06 14:24:53 +02:00
2024-05-03 01:59:58 +02:00
<!-- Création de l'élément LINETO avec les nouvelles coordonnées calculées -->
2024-05-06 14:24:53 +02:00
<LINETO
2024-05-03 01:59:58 +02:00
x="{format-number($new-x, '#.######')}"
y="{format-number($new-y, '#.######')}" />
2024-05-06 14:24:53 +02:00
2024-05-03 01:59:58 +02:00
<!-- Rappel récursif du template avec la mise à jour des coordonnées et des
commandes restantes -->
2024-05-06 14:24:53 +02:00
<xsl:call-template
2024-05-03 01:59:58 +02:00
name="process-commands">
2024-05-06 14:24:53 +02:00
<xsl:with-param
name="commands" select="$commands[position() > 1]" />
<xsl:with-param
2024-05-03 01:59:58 +02:00
name="x" select="$new-x" />
2024-05-06 14:24:53 +02:00
<xsl:with-param
name="y" select="$new-y" />
<xsl:with-param
2024-05-03 01:59:58 +02:00
name="angle" select="$angle" />
2024-05-06 14:24:53 +02:00
<xsl:with-param
name="states" select="$states" />
2024-05-03 01:59:58 +02:00
</xsl:call-template>
</xsl:when>
2024-05-06 14:24:53 +02:00
2024-05-03 01:59:58 +02:00
<!-- Si la commande est un turn -->
<xsl:when test="local-name($current-command) = 'turn'">
<!-- Calcul du nouvel angle avec modulo 360 pour rester dans un cercle complet -->
2024-05-06 14:24:53 +02:00
<xsl:variable name="new-angle"
select="($angle + number($current-command)) mod 360" />
2024-05-03 01:59:58 +02:00
<!-- Rappel récursif du template sans changer de position mais en mettant à jour
l'angle -->
2024-05-06 14:24:53 +02:00
<xsl:call-template
2024-05-03 01:59:58 +02:00
name="process-commands">
2024-05-06 14:24:53 +02:00
<xsl:with-param
name="commands" select="$commands[position() > 1]" />
<xsl:with-param
2024-05-03 01:59:58 +02:00
name="x" select="$x" />
2024-05-06 14:24:53 +02:00
<xsl:with-param
name="y" select="$y" />
<xsl:with-param
2024-05-03 01:59:58 +02:00
name="angle" select="$new-angle" />
2024-05-06 14:24:53 +02:00
<xsl:with-param name="states"
2024-05-03 01:59:58 +02:00
select="$states" />
</xsl:call-template>
</xsl:when>
2024-05-06 14:24:53 +02:00
2024-05-03 01:59:58 +02:00
<!-- Si la commande est un MOVE -->
<xsl:when test="local-name($current-command) = 'move'">
<!-- Calcul de la distance à parcourir et conversion de l'angle en radians -->
2024-05-06 14:24:53 +02:00
<xsl:variable name="distance"
2024-05-03 01:59:58 +02:00
select="number($current-command)" />
2024-05-06 14:24:53 +02:00
<xsl:variable name="radians"
2024-05-03 01:59:58 +02:00
select="$angle * math:pi() div 180" />
2024-05-06 14:24:53 +02:00
<xsl:variable name="new-x"
2024-05-03 01:59:58 +02:00
select="$x + $distance * math:cos($radians)" />
2024-05-06 14:24:53 +02:00
<xsl:variable name="new-y"
2024-05-03 01:59:58 +02:00
select="$y + $distance * math:sin($radians)" />
2024-05-06 14:24:53 +02:00
2024-05-03 01:59:58 +02:00
<!-- Création de l'élément MOVETO avec les nouvelles coordonnées calculées -->
2024-05-06 14:24:53 +02:00
<MOVETO
2024-05-03 01:59:58 +02:00
x="{format-number($new-x, '#.######')}"
y="{format-number($new-y, '#.######')}" />
2024-05-06 14:24:53 +02:00
2024-05-03 01:59:58 +02:00
<!-- Rappel récursif du template avec la mise à jour des coordonnées et des
commandes restantes -->
2024-05-06 14:24:53 +02:00
<xsl:call-template
2024-05-03 01:59:58 +02:00
name="process-commands">
2024-05-06 14:24:53 +02:00
<xsl:with-param
name="commands" select="$commands[position() > 1]" />
<xsl:with-param
2024-05-03 01:59:58 +02:00
name="x" select="$new-x" />
2024-05-06 14:24:53 +02:00
<xsl:with-param
name="y" select="$new-y" />
<xsl:with-param
2024-05-03 01:59:58 +02:00
name="angle" select="$angle" />
2024-05-06 14:24:53 +02:00
<xsl:with-param name="states"
select="$states" />
2024-05-03 01:59:58 +02:00
</xsl:call-template>
</xsl:when>
2024-05-06 14:24:53 +02:00
2024-05-03 01:59:58 +02:00
<!-- Si la commande est un store -->
<xsl:when test="local-name($current-command) = 'store'">
<!-- On enregistre le nouvelle état-->
2024-05-06 14:24:53 +02:00
<xsl:variable name="new-state">
2024-05-03 01:59:58 +02:00
<state x="{$x}" y="{$y}" angle="{$angle}" />
</xsl:variable>
<!-- On l'ajoute au précédent -->
2024-05-06 14:24:53 +02:00
<xsl:variable
2024-05-03 01:59:58 +02:00
name="new-states" select="($states, $new-state)" />
2024-05-06 14:24:53 +02:00
<xsl:call-template
2024-05-03 01:59:58 +02:00
name="process-commands">
2024-05-06 14:24:53 +02:00
<xsl:with-param
name="commands" select="$commands[position() > 1]" />
<xsl:with-param
2024-05-03 01:59:58 +02:00
name="x" select="$x" />
2024-05-06 14:24:53 +02:00
<xsl:with-param
name="y" select="$y" />
<xsl:with-param
2024-05-03 01:59:58 +02:00
name="angle" select="$angle" />
2024-05-06 14:24:53 +02:00
<xsl:with-param name="states"
2024-05-03 01:59:58 +02:00
select="$new-states" />
</xsl:call-template>
</xsl:when>
2024-05-06 14:24:53 +02:00
2024-05-03 01:59:58 +02:00
<!-- Si la commande est un restore et que au moins 1 état est enregistré : -->
2024-05-06 14:24:53 +02:00
<xsl:when test="local-name($current-command) = 'restore' and count($states) >= 1">
<!-- On séléctionne notre state (Revoir pourquoi ceci marche) -->
2024-05-06 14:24:53 +02:00
<xsl:variable
2024-05-03 01:59:58 +02:00
name="state" select="$states/state[1]" />
2024-05-06 14:24:53 +02:00
<xsl:variable
2024-05-03 01:59:58 +02:00
name="remaining-states"
select="subsequence($states/state, 1, count($states/state) - 1)" />
<!-- Création de l'élément MOVETO avec les nouvelles coordonnées restaurées -->
<MOVETO
x="{format-number($states/state[last()]/@x, '#.######')}"
y="{format-number($states/state[last()]/@y, '#.######')}" />
<xsl:call-template
2024-05-03 01:59:58 +02:00
name="process-commands">
2024-05-06 14:24:53 +02:00
<xsl:with-param
name="commands" select="$commands[position() > 1]" />
<xsl:with-param
2024-05-03 01:59:58 +02:00
name="x" select="($state/@x)[last()]" />
2024-05-06 14:24:53 +02:00
<xsl:with-param name="y"
2024-05-03 01:59:58 +02:00
select="($state/@y)[last()]" />
2024-05-06 14:24:53 +02:00
<xsl:with-param name="angle"
2024-05-03 01:59:58 +02:00
select="($state/@angle)[last()]" />
2024-05-06 14:24:53 +02:00
<xsl:with-param name="states"
2024-05-03 01:59:58 +02:00
select="$remaining-states" />
</xsl:call-template>
</xsl:when>
</xsl:choose>
</xsl:if>
</xsl:template>
</xsl:transform>