A genogram or pedigree chart is an extended family tree diagram that displays information about each person or each relationship.
Note that the term "marriage" here does not refer to a legal or cultural kind of relationship, but simply one representing the female and male genetic sources for any children.
There are functions that convert an attribute value into a brush color or Shape geometry, to be added to the Node representing the person.
A custom LayeredDigraphLayout does the layout, assuming there is a central person whose mother and father each have their own ancestors. In this case we focus on "Bill", but any of the children of "Alice" and "Aaron" would work. The overridden add function allows husband/wife pairs to be represented by a single LayeredDigraphVertex.
For a simpler family tree, see the family tree sample or Japanese family tree sample.
The node data representing the people, processed by the setupDiagram
function is below.
The properties are:
[ { key: 0, n: "Aaron", s: "M", m: -10, f: -11, ux: 1, a: ["C", "F", "K"] }, { key: 1, n: "Alice", s: "F", m: -12, f: -13, a: ["B", "H", "K"] }, { key: 2, n: "Bob", s: "M", m: 1, f: 0, ux: 3, a: ["C", "H", "L"] }, { key: 3, n: "Barbara", s: "F", a: ["C"] }, { key: 4, n: "Bill", s: "M", m: 1, f: 0, ux: 5, a: ["E", "H"] }, { key: 5, n: "Brooke", s: "F", a: ["B", "H", "L"] }, { key: 6, n: "Claire", s: "F", m: 1, f: 0, a: ["C"] }, { key: 7, n: "Carol", s: "F", m: 1, f: 0, a: ["C", "I"] }, { key: 8, n: "Chloe", s: "F", m: 1, f: 0, vir: 9, a: ["E"] }, { key: 9, n: "Chris", s: "M", a: ["B", "H"] }, { key: 10, n: "Ellie", s: "F", m: 3, f: 2, a: ["E", "G"] }, { key: 11, n: "Dan", s: "M", m: 3, f: 2, a: ["B", "J"] }, { key: 12, n: "Elizabeth", s: "F", vir: 13, a: ["J"] }, { key: 13, n: "David", s: "M", m: 5, f: 4, a: ["B", "H"] }, { key: 14, n: "Emma", s: "F", m: 5, f: 4, a: ["E", "G"] }, { key: 15, n: "Evan", s: "M", m: 8, f: 9, a: ["F", "H"] }, { key: 16, n: "Ethan", s: "M", m: 8, f: 9, a: ["D", "K"] }, { key: 17, n: "Eve", s: "F", vir: 16, a: ["B", "F", "L"] }, { key: 18, n: "Emily", s: "F", m: 8, f: 9 }, { key: 19, n: "Fred", s: "M", m: 17, f: 16, a: ["B"] }, { key: 20, n: "Faith", s: "F", m: 17, f: 16, a: ["L"] }, { key: 21, n: "Felicia", s: "F", m: 12, f: 13, a: ["H"] }, { key: 22, n: "Frank", s: "M", m: 12, f: 13, a: ["B", "H"] }, // "Aaron"'s ancestors { key: -10, n: "Paternal Grandfather", s: "M", m: -33, f: -32, ux: -11, a: ["A", "S"] }, { key: -11, n: "Paternal Grandmother", s: "F", a: ["E", "S"] }, { key: -32, n: "Paternal Great", s: "M", ux: -33, a: ["F", "H", "S"] }, { key: -33, n: "Paternal Great", s: "F", a: ["S"] }, { key: -40, n: "Great Uncle", s: "M", m: -33, f: -32, a: ["F", "H", "S"] }, { key: -41, n: "Great Aunt", s: "F", m: -33, f: -32, a: ["B", "I", "S"] }, { key: -20, n: "Uncle", s: "M", m: -11, f: -10, a: ["A", "S"] }, // "Alice"'s ancestors { key: -12, n: "Maternal Grandfather", s: "M", ux: -13, a: ["D", "L", "S"] }, { key: -13, n: "Maternal Grandmother", s: "F", m: -31, f: -30, a: ["H", "S"] }, { key: -21, n: "Aunt", s: "F", m: -13, f: -12, a: ["C", "I"] }, { key: -22, n: "Uncle", s: "M", ux: -21 }, { key: -23, n: "Cousin", s: "M", m: -21, f: -22 }, { key: -30, n: "Maternal Great", s: "M", ux: -31, a: ["D", "J", "S"] }, { key: -31, n: "Maternal Great", s: "F", m: -50, f: -51, a: ["B", "H", "L", "S"] }, { key: -42, n: "Great Uncle", s: "M", m: -30, f: -31, a: ["C", "J", "S"] }, { key: -43, n: "Great Aunt", s: "F", m: -30, f: -31, a: ["E", "G", "S"] }, { key: -50, n: "Maternal Great Great", s: "F", vir: -51, a: ["D", "I", "S"] }, { key: -51, n: "Maternal Great Great", s: "M", a: ["B", "H", "S"] } ]
It is sometimes useful to display a variable number of elements in a node by data binding to a JavaScript Array. In GoJS, this is simply achieved by binding (or setting) Panel.itemArray. The Panel will create an element in the panel for each value in the Array. More information can be found in the GoJS Intro.
GoJS provides its own collection classes: List, Set, and Map. You can iterate over a collection by using an Iterator. More information can be found in the GoJS Intro.
This predefined layout is used for placing Nodes of a general directed graph in layers (rows or columns). This is more general than TreeLayout, as it does not require that the graph be tree-structured. More information can be found in the GoJS Intro.
GoJS allows for the creation of custom layouts to meet specific needs.
There are also many layouts that are extensions -- not predefined in the go.js
or go-debug.js
library,
but available as source code in one of the three extension directories, with some documentation and corresponding samples.
More information can be found in the GoJS Intro.
The GoJS Geometry class controls the "shape" of a Shape, whereas the Shape.fill and Shape.stroke and other shape properties control the colors and appearance of the shape. For common shape figures, there are predefined geometries that can be used by setting Shape.figure. However one can also define custom geometries.
One can construct any Geometry by allocating and initializing a Geometry of at least one PathFigure holding some PathSegments. But you may find that using the string representation of a Geometry is easier to write and save in a database. Use the static method Geometry.parse or the Shape.geometryString property to transform a geometry path string into a Geometry object.
More information can be found in the GoJS Intro.