SVGHMI : create hmi_tree.ysl2, rename bbox_intersect.ysl2 into geometry.ysl2 and move more code into. Add per included ysl2 file debug output. svghmi
authorEdouard Tisserant <edouard.tisserant@gmail.com>
Tue, 17 Mar 2020 07:39:50 +0100
branchsvghmi
changeset 2873 022db76c3bff
parent 2872 83adf8859c55
child 2874 b67af0b8dc72
SVGHMI : create hmi_tree.ysl2, rename bbox_intersect.ysl2 into geometry.ysl2 and move more code into. Add per included ysl2 file debug output.
svghmi/Makefile
svghmi/bbox_intersect.ysl2
svghmi/gen_index_xhtml.xslt
svghmi/gen_index_xhtml.ysl2
svghmi/geometry.ysl2
svghmi/hmi_tree.ysl2
--- a/svghmi/Makefile	Mon Mar 16 18:27:49 2020 +0100
+++ b/svghmi/Makefile	Tue Mar 17 07:39:50 2020 +0100
@@ -12,11 +12,12 @@
 yml2path ?= $(abspath ../../yml2)
 
 ysl2files := gen_index_xhtml.ysl2
+ysl2includes := geometry.ysl2 hmi_tree.ysl2
 xsltfiles := $(patsubst %.ysl2, %.xslt, $(ysl2files))
 
 all:$(xsltfiles)
 
-%.xslt: %.ysl2 svghmi.js ../yslt_noindent.yml2
+%.xslt: %.ysl2 $(ysl2includes) svghmi.js ../yslt_noindent.yml2
 	$(yml2path)/yml2c -I $(yml2path):../ $< -o $@.tmp
 	xmlstarlet fo $@.tmp > $@
 	rm $@.tmp
--- a/svghmi/bbox_intersect.ysl2	Mon Mar 16 18:27:49 2020 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-// bbox_intersect.ysl2
-//
-// bounding boxes intersection tests
-
-// Rates 1D intersection of 2 segments A and B
-// described respectively with a0,a1 and b0,b1
-def "func:intersect_1d" {
-    // it is assumed that a1 > a0 and b1 > b0
-    param "a0";
-    param "a1";
-    param "b0";
-    param "b1";
-
-    const "d0", "$a0 >= $b0";
-    const "d1", "$a1 >= $b1";
-    choose {
-        when "not($d0) and $d1"
-            // b contained in a
-            //   a0<b0 b1<a1
-            // a +--------+
-            // b    +--+
-            result "3";
-        when "$d0 and not($d1)"
-            // a contained in b
-            //   b0<a0 a1<b1
-            // a    +--+
-            // b +--------+
-            result "2";
-        when "$d0 and $d1 and $a0 < $b1"
-            // a and b are overlapped 
-            //   b0<a0<b1<a1
-            // a    +-----+
-            // b +-----+
-            result "1";
-        when "not($d0) and not($d1) and $b0 < $a1"
-            // a and b are overlapped
-            //   a0<b0<a1<b1
-            // a +-----+
-            // b    +-----+
-            result "1";
-            // since orientation doesn't matter,
-            // rated same as previous symetrical overlapping
-        otherwise
-            result "0"; /* no intersection*/
-    }
-}
-
-
-// Rates intersection A and B areas described with x,y,w and h 
-// attributes passed as $a and $b parameters.
-// 
-// returns :
-// 0 - no intersection
-//            .-----.
-//    .-----. |    b|
-//    |     | |     |
-//    |     | '-----'
-//    |a    |
-//    '-----'
-//
-// 1 - overlapping
-//        .-----.
-//    .---|--. b|
-//    |   |  |  |
-//    |   '-----'
-//    |a     |
-//    '------'
-//
-// 2 - overlapping
-//        .-----.
-//        |  a  |
-//    .---|-----|---.
-//    |   '-----'   |
-//    | b           |
-//    '-------------'
-//
-// 3 - overlapping
-//        .-----.
-//        |  b  |
-//    .---|-----|---.
-//    |   '-----'   |
-//    | a           |
-//    '-------------'
-//
-// 4 - a contained in b
-//    .-------------.
-//    |   .-----.   |
-//    |   |  a  |   |
-//    |b  '-----'   |
-//    '-------------'
-//
-// 6 - overlapping
-//        .----.
-//        |   b|
-//    .---|----|---.
-//    |a  |    |   |
-//    '---|----|---'
-//        '----'
-//
-// 9 - b contained in a
-//    .-------------.
-//    |   .-----.   |
-//    |   |  b  |   |
-//    |a  '-----'   |
-//    '-------------'
-//
-def "func:intersect" {
-    param "a";
-    param "b";
-
-    const "x_intersect", "func:intersect_1d($a/@x, $a/@x+$a/@w, $b/@x, $b/@x+$b/@w)";
-
-    choose{
-        when "$x_intersect != 0"{
-            const "y_intersect", "func:intersect_1d($a/@y, $a/@y+$a/@h, $b/@y, $b/@y+$b/@h)";
-            result "$x_intersect * $y_intersect";
-        }
-        otherwise result "0";
-    }
-}
--- a/svghmi/gen_index_xhtml.xslt	Mon Mar 16 18:27:49 2020 +0100
+++ b/svghmi/gen_index_xhtml.xslt	Tue Mar 17 07:39:50 2020 +0100
@@ -1,11 +1,8 @@
 <?xml version="1.0"?>
 <xsl:stylesheet xmlns:func="http://exslt.org/functions" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg" xmlns:str="http://exslt.org/strings" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:exsl="http://exslt.org/common" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ns="beremiz" xmlns:cc="http://creativecommons.org/ns#" xmlns:regexp="http://exslt.org/regular-expressions" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dc="http://purl.org/dc/elements/1.1/" extension-element-prefixes="ns func exsl regexp str dyn" version="1.0" exclude-result-prefixes="ns str regexp exsl func dyn">
   <xsl:output method="xml" cdata-section-elements="xhtml:script"/>
-  <xsl:variable name="geometry" select="ns:GetSVGGeometry()"/>
-  <xsl:variable name="hmitree" select="ns:GetHMITree()"/>
   <xsl:variable name="svg_root_id" select="/svg:svg/@id"/>
   <xsl:variable name="hmi_elements" select="//svg:*[starts-with(@inkscape:label, 'HMI:')]"/>
-  <xsl:variable name="hmi_geometry" select="$geometry[@Id = $hmi_elements/@id]"/>
   <xsl:variable name="hmi_pages" select="$hmi_elements[func:parselabel(@inkscape:label)/widget/@type = 'Page']"/>
   <xsl:variable name="default_page">
     <xsl:choose>
@@ -54,6 +51,25 @@
       </xsl:otherwise>
     </xsl:choose>
   </func:function>
+  <xsl:variable name="geometry" select="ns:GetSVGGeometry()"/>
+  <xsl:template name="debug_geometry">
+    <xsl:text>GEOMETRY : ID, x, y, w, h
+</xsl:text>
+    <xsl:for-each select="$geometry[@Id = $hmi_elements/@id]">
+      <xsl:text> </xsl:text>
+      <xsl:value-of select="@Id"/>
+      <xsl:text> </xsl:text>
+      <xsl:value-of select="@x"/>
+      <xsl:text> </xsl:text>
+      <xsl:value-of select="@y"/>
+      <xsl:text> </xsl:text>
+      <xsl:value-of select="@w"/>
+      <xsl:text> </xsl:text>
+      <xsl:value-of select="@h"/>
+      <xsl:text>
+</xsl:text>
+    </xsl:for-each>
+  </xsl:template>
   <func:function name="func:intersect_1d">
     <xsl:param name="a0"/>
     <xsl:param name="a1"/>
@@ -98,7 +114,7 @@
     <xsl:variable name="groups" select="/svg:svg | //svg:g"/>
     <xsl:variable name="g" select="$geometry[@Id = $elt/@id]"/>
     <xsl:variable name="candidates" select="$geometry[@Id != $elt/@id]"/>
-    <func:result select="$candidates[(@Id = $groups/@id and (func:intersect($g, .) = 9)) or &#10;                              (not(@Id = $groups/@id) and (func:intersect($g, .) &gt; 0 ))]"/>
+    <func:result select="$candidates[(@Id = $groups/@id and (func:intersect($g, .) = 9)) or &#10;                          (not(@Id = $groups/@id) and (func:intersect($g, .) &gt; 0 ))]"/>
   </func:function>
   <func:function name="func:all_related_elements">
     <xsl:param name="page"/>
@@ -140,6 +156,7 @@
   </func:function>
   <xsl:variable name="_detachable_elements" select="func:detachable_elements($hmi_pages)"/>
   <xsl:variable name="detachable_elements" select="$_detachable_elements[not(ancestor::*/@id = $_detachable_elements/@id)]"/>
+  <xsl:variable name="hmitree" select="ns:GetHMITree()"/>
   <xsl:variable name="_indexed_hmitree">
     <xsl:apply-templates mode="index" select="$hmitree"/>
   </xsl:variable>
@@ -319,7 +336,13 @@
       <xsl:text>Made with SVGHMI. https://beremiz.org</xsl:text>
     </xsl:comment>
     <xsl:comment>
-      <xsl:apply-templates mode="testgeo" select="$hmi_geometry"/>
+      <xsl:text>
+</xsl:text>
+      <xsl:text>debug_geometry:
+</xsl:text>
+      <xsl:call-template name="debug_geometry"/>
+      <xsl:text>
+</xsl:text>
     </xsl:comment>
     <xsl:comment>
       <xsl:apply-templates mode="testtree" select="$hmitree"/>
@@ -1445,20 +1468,6 @@
     <xsl:text>//})();
 </xsl:text>
   </xsl:template>
-  <xsl:template mode="testgeo" match="bbox">
-    <xsl:text>ID: </xsl:text>
-    <xsl:value-of select="@Id"/>
-    <xsl:text> x: </xsl:text>
-    <xsl:value-of select="@x"/>
-    <xsl:text> y: </xsl:text>
-    <xsl:value-of select="@y"/>
-    <xsl:text> w: </xsl:text>
-    <xsl:value-of select="@w"/>
-    <xsl:text> h: </xsl:text>
-    <xsl:value-of select="@h"/>
-    <xsl:text>
-</xsl:text>
-  </xsl:template>
   <xsl:template mode="testtree" match="*">
     <xsl:param name="indent" select="''"/>
     <xsl:value-of select="$indent"/>
--- a/svghmi/gen_index_xhtml.ysl2	Mon Mar 16 18:27:49 2020 +0100
+++ b/svghmi/gen_index_xhtml.ysl2	Tue Mar 17 07:39:50 2020 +0100
@@ -17,6 +17,8 @@
 in xsl decl svgtmpl(match, xmlns="http://www.w3.org/2000/svg") alias template;
 in xsl decl svgfunc(name, xmlns="http://www.w3.org/2000/svg") alias template;
 
+!debug_output_calls = []
+
 istylesheet
             /* From Inkscape */
             xmlns:dc="http://purl.org/dc/elements/1.1/"
@@ -33,16 +35,9 @@
             extension-element-prefixes="ns func exsl regexp str dyn"
             exclude-result-prefixes="ns str regexp exsl func dyn" {
 
-    /* This retrieves geometry obtained through "inkscape -S"
-     * already parsed by python and presented as a list of
-     * <bbox x="0" y="0" w="42" h="42">
-     */
-    const "geometry", "ns:GetSVGGeometry()";
-    const "hmitree", "ns:GetHMITree()";
 
     const "svg_root_id", "/svg:svg/@id";
     const "hmi_elements", "//svg:*[starts-with(@inkscape:label, 'HMI:')]";
-    const "hmi_geometry", "$geometry[@Id = $hmi_elements/@id]";
 
     const "hmi_pages", "$hmi_elements[func:parselabel(@inkscape:label)/widget/@type = 'Page']";
 
@@ -85,19 +80,8 @@
         }
     }
 
-    include bbox_intersect.ysl2
-
-    // return overlapping geometry for a given element
-    // all intersercting element are returned
-    // except groups, that must be contained to be counted in
-    def "func:overlapping_geometry" {
-        param "elt";
-        const "groups", "/svg:svg | //svg:g";
-        const "g", "$geometry[@Id = $elt/@id]"; 
-        const "candidates", "$geometry[@Id != $elt/@id]";
-        result """$candidates[(@Id = $groups/@id and (func:intersect($g, .) = 9)) or 
-                              (not(@Id = $groups/@id) and (func:intersect($g, .) > 0 ))]""";
-    }
+    include geometry.ysl2
+
 
     def "func:all_related_elements" {
         param "page";
@@ -155,47 +139,7 @@
     const "detachable_elements", "$_detachable_elements[not(ancestor::*/@id = $_detachable_elements/@id)]";
 
 
-    //////////////// HMI Tree Index
-
-    const "_indexed_hmitree" apply "$hmitree", mode="index";
-    const "indexed_hmitree", "exsl:node-set($_indexed_hmitree)";
-
-    template "*", mode="index" {
-        param "index", "0";
-        param "parentpath", "''";
-        const "content" {
-            const "path"
-                choose {
-                    when "local-name() = 'HMI_ROOT'" > «$parentpath»
-                    otherwise > «$parentpath»/«@name»
-                }
-            choose {
-                when "not(local-name() = $categories/noindex)" {
-                    xsl:copy {
-                        attrib "index" > «$index»
-                        attrib "hmipath" > «$path»
-                        foreach "@*" xsl:copy;
-                    }
-                    apply "*[1]", mode="index"{
-                         with "index", "$index + 1";
-                         with "parentpath" > «$path»
-                    }
-                }
-                otherwise {
-                    apply "*[1]", mode="index"{
-                        with "index", "$index";
-                        with "parentpath" > «$path»
-                    }
-                }
-            }
-        }
-
-        copy "$content";
-        apply "following-sibling::*[1]", mode="index" {
-            with "index", "$index + count(exsl:node-set($content)/*)";
-            with "parentpath" > «$parentpath»
-        }
-    }
+    include hmi_tree.ysl2
 
 
     def "func:is_descendant_path" {
@@ -316,13 +260,14 @@
     const "result_svg" apply "/", mode="inline_svg";
     const "result_svg_ns", "exsl:node-set($result_svg)";
 
-    /* copy root node and add geometry as comment for a test */
     template "/" {
         comment > Made with SVGHMI. https://beremiz.org
-        /* DEBUG DATA */
-        comment {
-            apply "$hmi_geometry", mode="testgeo";
-        }
+
+        // use python to call all debug output from included definitions
+        // '&bug' is a workaround for old pyPEG that choke on empty python results
+        !"&bug "+"\n".join(["comment {|\n| %s:\n call \"%s\";\n| \n}"%(n,n) for n in debug_output_calls])!
+
+        // TODO
         comment {
             apply "$hmitree", mode="testtree";
         }
@@ -570,10 +515,6 @@
 
 
     /**/
-    template "bbox", mode="testgeo"{
-        | ID: «@Id» x: «@x» y: «@y» w: «@w» h: «@h»
-    }
-
     template "*", mode="testtree"{
         param "indent", "''";
         > «$indent» «local-name()» 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/svghmi/geometry.ysl2	Tue Mar 17 07:39:50 2020 +0100
@@ -0,0 +1,145 @@
+// geometry.ysl2
+//
+// Geometry (bounding box intersection) definitions
+
+// This retrieves geometry obtained through "inkscape -S"
+// already parsed by python and presented as a list of
+// <bbox x="0" y="0" w="42" h="42">
+const "geometry", "ns:GetSVGGeometry()";
+
+// Debug data
+function "debug_geometry" {
+    | GEOMETRY : ID, x, y, w, h
+    foreach "$geometry[@Id = $hmi_elements/@id]"
+        |  «@Id» «@x» «@y» «@w» «@h»
+}
+!debug_output_calls.append("debug_geometry")
+
+// Rates 1D intersection of 2 segments A and B
+// described respectively with a0,a1 and b0,b1
+def "func:intersect_1d" {
+    // it is assumed that a1 > a0 and b1 > b0
+    param "a0";
+    param "a1";
+    param "b0";
+    param "b1";
+
+    const "d0", "$a0 >= $b0";
+    const "d1", "$a1 >= $b1";
+    choose {
+        when "not($d0) and $d1"
+            // b contained in a
+            //   a0<b0 b1<a1
+            // a +--------+
+            // b    +--+
+            result "3";
+        when "$d0 and not($d1)"
+            // a contained in b
+            //   b0<a0 a1<b1
+            // a    +--+
+            // b +--------+
+            result "2";
+        when "$d0 and $d1 and $a0 < $b1"
+            // a and b are overlapped 
+            //   b0<a0<b1<a1
+            // a    +-----+
+            // b +-----+
+            result "1";
+        when "not($d0) and not($d1) and $b0 < $a1"
+            // a and b are overlapped
+            //   a0<b0<a1<b1
+            // a +-----+
+            // b    +-----+
+            result "1";
+            // since orientation doesn't matter,
+            // rated same as previous symetrical overlapping
+        otherwise
+            result "0"; /* no intersection*/
+    }
+}
+
+
+// Rates intersection A and B areas described with x,y,w and h 
+// attributes passed as $a and $b parameters.
+// 
+// returns :
+// 0 - no intersection
+//            .-----.
+//    .-----. |    b|
+//    |     | |     |
+//    |     | '-----'
+//    |a    |
+//    '-----'
+//
+// 1 - overlapping
+//        .-----.
+//    .---|--. b|
+//    |   |  |  |
+//    |   '-----'
+//    |a     |
+//    '------'
+//
+// 2 - overlapping
+//        .-----.
+//        |  a  |
+//    .---|-----|---.
+//    |   '-----'   |
+//    | b           |
+//    '-------------'
+//
+// 3 - overlapping
+//        .-----.
+//        |  b  |
+//    .---|-----|---.
+//    |   '-----'   |
+//    | a           |
+//    '-------------'
+//
+// 4 - a contained in b
+//    .-------------.
+//    |   .-----.   |
+//    |   |  a  |   |
+//    |b  '-----'   |
+//    '-------------'
+//
+// 6 - overlapping
+//        .----.
+//        |   b|
+//    .---|----|---.
+//    |a  |    |   |
+//    '---|----|---'
+//        '----'
+//
+// 9 - b contained in a
+//    .-------------.
+//    |   .-----.   |
+//    |   |  b  |   |
+//    |a  '-----'   |
+//    '-------------'
+//
+def "func:intersect" {
+    param "a";
+    param "b";
+
+    const "x_intersect", "func:intersect_1d($a/@x, $a/@x+$a/@w, $b/@x, $b/@x+$b/@w)";
+
+    choose{
+        when "$x_intersect != 0"{
+            const "y_intersect", "func:intersect_1d($a/@y, $a/@y+$a/@h, $b/@y, $b/@y+$b/@h)";
+            result "$x_intersect * $y_intersect";
+        }
+        otherwise result "0";
+    }
+}
+
+// return overlapping geometry for a given element
+// all intersercting element are returned
+// except groups, that must be contained to be counted in
+def "func:overlapping_geometry" {
+    param "elt";
+    const "groups", "/svg:svg | //svg:g";
+    const "g", "$geometry[@Id = $elt/@id]"; 
+    const "candidates", "$geometry[@Id != $elt/@id]";
+    result """$candidates[(@Id = $groups/@id and (func:intersect($g, .) = 9)) or 
+                          (not(@Id = $groups/@id) and (func:intersect($g, .) > 0 ))]""";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/svghmi/hmi_tree.ysl2	Tue Mar 17 07:39:50 2020 +0100
@@ -0,0 +1,47 @@
+// hmi_tree.ysl2
+
+
+// HMI Tree computed from VARIABLES.CSV in svghmi.py
+const "hmitree", "ns:GetHMITree()";
+
+
+// HMI Tree Index
+const "_indexed_hmitree" apply "$hmitree", mode="index";
+const "indexed_hmitree", "exsl:node-set($_indexed_hmitree)";
+
+template "*", mode="index" {
+    param "index", "0";
+    param "parentpath", "''";
+    const "content" {
+        const "path"
+            choose {
+                when "local-name() = 'HMI_ROOT'" > «$parentpath»
+                otherwise > «$parentpath»/«@name»
+            }
+        choose {
+            when "not(local-name() = $categories/noindex)" {
+                xsl:copy {
+                    attrib "index" > «$index»
+                    attrib "hmipath" > «$path»
+                    foreach "@*" xsl:copy;
+                }
+                apply "*[1]", mode="index"{
+                     with "index", "$index + 1";
+                     with "parentpath" > «$path»
+                }
+            }
+            otherwise {
+                apply "*[1]", mode="index"{
+                    with "index", "$index";
+                    with "parentpath" > «$path»
+                }
+            }
+        }
+    }
+
+    copy "$content";
+    apply "following-sibling::*[1]", mode="index" {
+        with "index", "$index + count(exsl:node-set($content)/*)";
+        with "parentpath" > «$parentpath»
+    }
+}