edouard@2873: // geometry.ysl2
edouard@2872: //
edouard@2873: // Geometry (bounding box intersection) definitions
edouard@2873: 
edouard@2873: // This retrieves geometry obtained through "inkscape -S"
edouard@2873: // already parsed by python and presented as a list of
edouard@2873: // <bbox x="0" y="0" w="42" h="42">
Edouard@3199: const "all_geometry", "ns:GetSVGGeometry()";
Edouard@3199: const "defs", "//svg:defs/descendant-or-self::svg:*";
Edouard@3199: const "geometry", "$all_geometry[not(@Id = $defs/@id)]";
edouard@2873: 
edouard@2873: // Debug data
edouard@2940: emit "debug:geometry" {
edouard@2875:     | ID, x, y, w, h
Edouard@2879:     foreach "$geometry"
edouard@2873:         |  «@Id» «@x» «@y» «@w» «@h»
edouard@2873: }
Edouard@2779: 
edouard@2872: // Rates 1D intersection of 2 segments A and B
edouard@2872: // described respectively with a0,a1 and b0,b1
edouard@2872: def "func:intersect_1d" {
edouard@2872:     // it is assumed that a1 > a0 and b1 > b0
edouard@2872:     param "a0";
edouard@2872:     param "a1";
edouard@2872:     param "b0";
edouard@2872:     param "b1";
Edouard@2792: 
edouard@2872:     const "d0", "$a0 >= $b0";
edouard@2872:     const "d1", "$a1 >= $b1";
edouard@2872:     choose {
edouard@2872:         when "not($d0) and $d1"
edouard@2872:             // b contained in a
edouard@2872:             //   a0<b0 b1<a1
edouard@2872:             // a +--------+
edouard@2872:             // b    +--+
edouard@2872:             result "3";
edouard@2872:         when "$d0 and not($d1)"
edouard@2872:             // a contained in b
edouard@2872:             //   b0<a0 a1<b1
edouard@2872:             // a    +--+
edouard@2872:             // b +--------+
edouard@2872:             result "2";
edouard@2872:         when "$d0 and $d1 and $a0 < $b1"
edouard@2872:             // a and b are overlapped 
edouard@2872:             //   b0<a0<b1<a1
edouard@2872:             // a    +-----+
edouard@2872:             // b +-----+
edouard@2872:             result "1";
edouard@2872:         when "not($d0) and not($d1) and $b0 < $a1"
edouard@2872:             // a and b are overlapped
edouard@2872:             //   a0<b0<a1<b1
edouard@2872:             // a +-----+
edouard@2872:             // b    +-----+
edouard@2872:             result "1";
edouard@2872:             // since orientation doesn't matter,
edouard@2872:             // rated same as previous symetrical overlapping
edouard@2872:         otherwise
edouard@2872:             result "0"; /* no intersection*/
Edouard@2795:     }
edouard@2872: }
Edouard@2790: 
Edouard@2843: 
edouard@2872: // Rates intersection A and B areas described with x,y,w and h 
edouard@2872: // attributes passed as $a and $b parameters.
edouard@2872: // 
edouard@2872: // returns :
edouard@2872: // 0 - no intersection
edouard@2872: //            .-----.
edouard@2872: //    .-----. |    b|
edouard@2872: //    |     | |     |
edouard@2872: //    |     | '-----'
edouard@2872: //    |a    |
edouard@2872: //    '-----'
edouard@2872: //
edouard@2872: // 1 - overlapping
edouard@2872: //        .-----.
edouard@2872: //    .---|--. b|
edouard@2872: //    |   |  |  |
edouard@2872: //    |   '-----'
edouard@2872: //    |a     |
edouard@2872: //    '------'
edouard@2872: //
edouard@2872: // 2 - overlapping
edouard@2872: //        .-----.
edouard@2872: //        |  a  |
edouard@2872: //    .---|-----|---.
edouard@2872: //    |   '-----'   |
edouard@2872: //    | b           |
edouard@2872: //    '-------------'
edouard@2872: //
edouard@2872: // 3 - overlapping
edouard@2872: //        .-----.
edouard@2872: //        |  b  |
edouard@2872: //    .---|-----|---.
edouard@2872: //    |   '-----'   |
edouard@2872: //    | a           |
edouard@2872: //    '-------------'
edouard@2872: //
edouard@2872: // 4 - a contained in b
edouard@2872: //    .-------------.
edouard@2872: //    |   .-----.   |
edouard@2872: //    |   |  a  |   |
edouard@2872: //    |b  '-----'   |
edouard@2872: //    '-------------'
edouard@2872: //
edouard@2872: // 6 - overlapping
edouard@2872: //        .----.
edouard@2872: //        |   b|
edouard@2872: //    .---|----|---.
edouard@2872: //    |a  |    |   |
edouard@2872: //    '---|----|---'
edouard@2872: //        '----'
edouard@2872: //
edouard@2872: // 9 - b contained in a
edouard@2872: //    .-------------.
edouard@2872: //    |   .-----.   |
edouard@2872: //    |   |  b  |   |
edouard@2872: //    |a  '-----'   |
edouard@2872: //    '-------------'
edouard@2872: //
edouard@2872: def "func:intersect" {
edouard@2872:     param "a";
edouard@2872:     param "b";
edouard@2872: 
edouard@2872:     const "x_intersect", "func:intersect_1d($a/@x, $a/@x+$a/@w, $b/@x, $b/@x+$b/@w)";
edouard@2872: 
edouard@2872:     choose{
edouard@2872:         when "$x_intersect != 0"{
edouard@2872:             const "y_intersect", "func:intersect_1d($a/@y, $a/@y+$a/@h, $b/@y, $b/@y+$b/@h)";
edouard@2872:             result "$x_intersect * $y_intersect";
Edouard@2844:         }
edouard@2872:         otherwise result "0";
Edouard@2808:     }
Edouard@2753: }
edouard@2873: 
edouard@3165: const "groups", "/svg:svg | //svg:g";
edouard@3165: 
edouard@2873: // return overlapping geometry for a given element
edouard@2873: // all intersercting element are returned
edouard@2873: // except groups, that must be contained to be counted in
edouard@2873: def "func:overlapping_geometry" {
edouard@2873:     param "elt";
edouard@2873:     const "g", "$geometry[@Id = $elt/@id]"; 
edouard@2873:     const "candidates", "$geometry[@Id != $elt/@id]";
edouard@2873:     result """$candidates[(@Id = $groups/@id and (func:intersect($g, .) = 9)) or 
edouard@2873:                           (not(@Id = $groups/@id) and (func:intersect($g, .) > 0 ))]""";
edouard@2873: }