Match trees by branch paths - find corresponding item indices by branch

I’m working on a script that creates doors in a wall, but I need to get rid of the line segments in the wall that are of equal length as the doors.


The tree structure is matching, so the tree branch for the wall lines corresponds to the branch for the door lengths. However, since Grasshopper does not match by branch path, but on an item by item basis, how could I find the lines to cull?

Cull lines.gh (16.6 KB)

Since there are multiple items to be matched for some branches ({8} in this example set), that solution doesn’t work:

exactly, because the matching would be like:

Member index works well in these cases, together with Cull Index:


Cull lines_Re.gh (12.9 KB)

1 Like

Yeah, that’s what I thought, but the results were empty. So the number conversion was where the issue was at… Thanks!

yep, stuff being output by a Data Parameter is not a Number GH type, while output coming from a Length output is Number GH type, so they won’t match by default

many times I also found myself getting number inputs from external sources, and despite passing both through a Number Parameter before the Member Index, also a trim to 2 or 3 decimals was necessary :+1:

Yeah, the decimals (and rounding) can be a pain.

not a big fan of juggling datatrees.
for my eyes a simple script does offer more readability:

Cull lines_02_tp.gh (15.5 KB)

private void RunScript(List<double> lTest, List<double> lRef, ref object isHit)
    {
        double tolerance = 0.001;
        List<bool> returnHits = new List<bool>(lRef.Count);
        foreach (double d in lTest)
        {
            bool found = lRef.Any(item => Math.Abs(item - d) <= tolerance);
            returnHits.Add(found);
        }
        isHit = returnHits;
    }

EDIT:
and a proper approach for comparing doubles would be to use a expression with some threshold / tolerance, retrieve a true / false and then cull with a pattern.
I left the expression part in above definition, but I was not motivated to get the datatrees in the right structure to perform the logic…

1 Like

I’m very much a Python beginner, I would take this chance to mimic something like your nice and slender C# with some basic Python:


Cull_lines_Py.gh (15.2 KB)

# x, y inputs both floats with List access

def same_length(a, b, tol):
    if abs(a-b) <= tol:
        return True
    return False

a = []

for test_len in x:
    res = True
    for bad_len in y:
        if same_length(test_len, bad_len, 0.001):
            res = False
            break
    a.append(res)
1 Like

how about:

def same_length(a, b, tol):
    return abs(a-b) <= tol:

?


and just curious - how to implement the same logic without scripting, with pure vanilla gh-components ? (get the same true,false, … tree ?)

1 Like

that is a bit painful :slight_smile: my best guess is, given tree_A and tree_B:

graft tree_A in such a way each branch carries just one single item

in tree_B, duplicate branches times the amount of respective elements in ungrafted tree_A

then Mass Addition to OR everything together and get one single boolean per branch, then Trim Tree et voilà :slight_smile:

visually:

Cull lines_Re_Re.gh (22.3 KB)

:rage:
ok - somehow you proofed my fear…

I think it would be super strong feature, if a cluster could have the same input / access as a script component. I wrote this as a wish, but did not get any answers:

Propagate Ancestors component from TreeSloth would be my main choice here. Then again, doing it natively teaches you valuable lessons about DataTrees - like how to painfully crush your toes over and over again by hitting them against DataTrees.

I would always solve stuff like this with a script … but anyhow it seamed a nice challenge…
…here is my vanilla gh solution to find a cull pattern.
instead of multiply data I use cross reference (holistic) to get the combinations for the equality-test.

flattening the final pattern and unflatten with the original tree as guide seems more readable for me…

compare_lists_with_lists_01.gh (16.6 KB)

1 Like