Is there any way to find lowest common ancestor in Genogram?

Hello,

If I select two nodes from the Gojs Genogram family tree diagram , then is there any way to find the lowest common ancestor between that nodes ?

Sure. First, let’s find all of the ancestors for a node (a.k.a. person).

    function showAncestors() {
      var node = myDiagram.selection.first();
      if (node === null) return;
      var coll = new go.Set();
      addAncestors(node, coll);
      coll.remove(node);  // don't include node itself
      myDiagram.selectCollection(coll);
    }

    function addAncestors(node, coll) {
      if (!node) return;
      coll.add(node);
      var parentmarriagenode = null;
      node.findNodesInto().each(function(n) {
        if (n.isLinkLabel) parentmarriagenode = n;
      });
      if (!parentmarriagenode) return;
      var marriagelink = parentmarriagenode.labeledLink;
      if (!marriagelink) return;
      addAncestors(marriagelink.fromNode, coll);
      addAncestors(marriagelink.toNode, coll);
    }

This might be called by an HTML button click event:

<button onclick="showAncestors()">Show Ancestors</button>

So if the user selects a node, clicking the button will deselect that node and select all of that node’s ancestor nodes. There might be none, of course.

Now let’s use the functionality of addAncestors to find the most recent common ancestors. That typically means both the mother and the father.

    function showMostRecentCommonAncestors() {
      var node1 = null;
      var node2 = null;
      var it = myDiagram.selection.iterator;
      while (it.next()) {
        var n = it.value;
        if (n instanceof go.Node) {
          if (!node1) {
            node1 = n;
          } else if (!node2) {
            node2 = n;
            break;
          }
        }
      }
      var node1ancestors = new go.Set();
      addAncestors(node1, node1ancestors);
      var node2ancestors = new go.Set();
      addAncestors(node2, node2ancestors);
      var recents = new go.Set();
      addRecentCommonAncestors(node1ancestors, node2ancestors, recents);
      myDiagram.selectCollection(recents);
    }

    function addRecentCommonAncestors(node1ancestors, node2ancestors, recents) {
      var it1 = node1ancestors.iterator;
      while (it1.next()) {
        var n = it1.value;
        if (node2ancestors.contains(n)) {
          recents.add(n);
          recents.add(findSpouse(n));
          break;
        }
      }
      var it2 = node2ancestors.iterator;
      while (it2.next()) {
        var n = it2.value;
        if (node1ancestors.contains(n)) {
          recents.add(n);
          recents.add(findSpouse(n));
          break;
        }
      }
    }

    function findSpouse(n) {
      var it = n.findLinksConnected().iterator;
      while (it.next()) {
        var l = it.value;
        if (l.category === "Marriage") {
          return l.getOtherNode(n);
        }
      }
      return null;
    }

Note that if the user selects a node and an ancestor of that node, this will select that ancestor and its spouse.

I haven’t tested this on a graph where cousins marry each other, but I think it will work. Please tell me if you try it.

It works for me! Thanks a lot!