# HG changeset patch # User Edouard Tisserant <edouard.tisserant@gmail.com> # Date 1584427190 -3600 # Node ID 022db76c3bffd6b83e9c372ba7d0bc91b5d01327 # Parent 83adf8859c55d7c000e3ba4c0c3ffbec3748ed02 SVGHMI : create hmi_tree.ysl2, rename bbox_intersect.ysl2 into geometry.ysl2 and move more code into. Add per included ysl2 file debug output. diff -r 83adf8859c55 -r 022db76c3bff svghmi/Makefile --- 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 diff -r 83adf8859c55 -r 022db76c3bff svghmi/bbox_intersect.ysl2 --- 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"; - } -} diff -r 83adf8859c55 -r 022db76c3bff svghmi/gen_index_xhtml.xslt --- 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 (not(@Id = $groups/@id) and (func:intersect($g, .) > 0 ))]"/> + <func:result select="$candidates[(@Id = $groups/@id and (func:intersect($g, .) = 9)) or (not(@Id = $groups/@id) and (func:intersect($g, .) > 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"/> diff -r 83adf8859c55 -r 022db76c3bff svghmi/gen_index_xhtml.ysl2 --- 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()» diff -r 83adf8859c55 -r 022db76c3bff svghmi/geometry.ysl2 --- /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 ))]"""; +} diff -r 83adf8859c55 -r 022db76c3bff svghmi/hmi_tree.ysl2 --- /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» + } +}