// 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 "all_geometry", "ns:GetSVGGeometry()";
const "defs", "//svg:defs/descendant-or-self::svg:*";
const "geometry", "$all_geometry[not(@Id = $defs/@id)]";
// Debug data
emit "debug:geometry" {
| ID, x, y, w, h
foreach "$geometry"
| «@Id» «@x» «@y» «@w» «@h»
}
// 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";
}
}
const "groups", "/svg:svg | //svg:g";
// 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 "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 ))]""";
}
def "func:offset" {
param "elt1";
param "elt2";
const "g1", "$geometry[@Id = $elt1/@id]";
const "g2", "$geometry[@Id = $elt2/@id]";
const "result" vector {
attrib "x" value "$g2/@x - $g1/@x";
attrib "y" value "$g2/@y - $g1/@y";
}
result "exsl:node-set($result)";
}