svghmi/geometry.ysl2
author Edouard Tisserant <edouard.tisserant@gmail.com>
Mon, 23 Mar 2020 21:44:28 +0100
branchsvghmi
changeset 2894 4cf9ad35e6d0
parent 2879 58e6a91dc37f
child 2904 92d115d8828d
permissions -rw-r--r--
SVGHMI: Easier way to match HMI tree elements to paths. ForEach widget now looks for paths and indexes of all items, and enforce path to be consistent with ForEach items sub widgets
// 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" {
    | ID, x, y, w, h
    foreach "$geometry"
        |  «@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 ))]""";
}