Skip to content
Snippets Groups Projects
Commit 7c4252c3 authored by Reinhold's avatar Reinhold
Browse files

v1.19: sex encoding and node pinning functionality

parent 42d14a1e
No related branches found
No related tags found
No related merge requests found
################################################################################
# This .gitignore file was automatically created by Microsoft(R) Visual Studio.
################################################################################
/.vs/VSWorkspaceState.json
......@@ -7,8 +7,8 @@ Copyright 2020 Reinhold Preiner, Johanna Schmidt, Gabriel Mistelbauer
### Changelog
* version 1.19:   Encoding person sex in family graph nodes (boxes & circles) and node pinning functionality.
* version 1.18:   Graph Save and Load functionality merged from [extra3](https://github.com/extra3)
* version 1.17:   Node info tooltip functionality merged from [extra3](https://github.com/extra3)
### Run the Demo
......@@ -47,9 +47,12 @@ Left: MA.json, right: MA.ged
The behaviour and appearance of the graph is controlled by the menu on the left, which is structured into different parameter groups
that can be expanded and collapsed by clicking onto the panel title.
Initially the D3 force layout can be interactively modified by picking and pulling individual nodes
Initially the D3 force layout can be interactively modified by picking and pulling individual nodes with the mouse
and by using the "Force Layout" controls in the menu. Use to "Graph Appearance" menu to adjust its visual settings.
When picking and pulling graph nodes, they will be pinned to the location they have beend dragged to.
A single click onto pinned nodes will release them from their fixed position and allow them to freely move again.
Use the 'F' key or the menu switch to freeze the current force layout and compute the underlying TAM.
Use the 'F' key again to unfreeze and re-energize the layout simulation. While freezed, individual nodes can still
be repositioned by picking and pulling with the mouse. One the TAM is visible, its visual appearance can be adjusted
......
......
......@@ -144,9 +144,17 @@ class TAMRenderer
var nodeMap = new Map();
Object.values(json.nodes).forEach(node =>
{
console.log(node);
node.r = PARAM_NODE_RADIUS;
if (node.value == 0)
node.value = 0.001
if (node.fixed) { // restore fixed state
node.fx = node.x;
node.fy = node.y;
}
nodeMap.set(node.id, node);
this.NODES.push(node);
......@@ -838,11 +846,23 @@ class TAMRenderer
saveData()
{
let nodePositions = [];
this.NODES.forEach(node => {
nodePositions.push({
"id": node.id,
"name": node.name,
"value": node.value,
"x": node.x,
"y": node.y,
"fixed": node.fx != null
});
});
let content = [JSON.stringify(
{
"metadata": getMetadata(),
"parameters": getParameters(),
"nodes": this.NODES,
"nodes": nodePositions,
"links": this.LINKS
},
removeInternalValuesFromJSON, 2)];
......
......
......@@ -44,6 +44,7 @@ class TFMRenderer extends TAMRenderer
// set person data
p.type = "PERSON";
p.r = PARAM_NODE_RADIUS;
p.cr = p.sex == FEMALE ? PARAM_NODE_RADIUS : 0;
p.value = p.bdate ? p.bdate.getFullYear() : null;
// set node positions (if available)
......@@ -52,6 +53,10 @@ class TFMRenderer extends TAMRenderer
p.x = nodePositions[p.id].x;
p.y = nodePositions[p.id].y;
p.vis = { 'x': p.x, 'y': p.y };
if (nodePositions[p.id].fixed) { // restore fixed state
p.fx = p.x;
p.fy = p.y;
}
}
else
p.vis = {'x': 0, 'y': 0};
......@@ -76,6 +81,10 @@ class TFMRenderer extends TAMRenderer
f.x = nodePositions[key].x;
f.y = nodePositions[key].y;
f.vis = { 'x': f.x, 'y': f.y };
if (nodePositions[key].fixed) { // restore fixed state
f.fx = f.x;
f.fy = f.y;
}
}
else
f.vis = {'x': 0, 'y': 0};
......@@ -152,6 +161,7 @@ class TFMRenderer extends TAMRenderer
this.SVG_FAMILY_CIRCLES = this.GRAPH_LAYER.selectAll(".family")
.data(this.FNODES).enter()
.append("circle")
.attr("class", "family")
.style("fill", "fnodeColor")
.style("stroke", PARAM_FAMILY_NODE_BORDER_COLOR)
.style("stroke-width", PARAM_FAMILY_NODE_BORDER_WIDTH)
......@@ -169,11 +179,15 @@ class TFMRenderer extends TAMRenderer
this.SVG_NODE_CIRCLES = this.GRAPH_LAYER.selectAll(".person")
.data(this.PNODES).enter()
.append("circle")
.append("rect")
.attr("class", "person")
.style("fill", function(node) { return typeof(node.value) == "number" ? renderer.SVG_COLORMAP(node.value) : "red"; })
.style("stroke", "#222")
.attr("stroke-width", (PARAM_NODE_RADIUS / 4) + "px")
.attr("r", function(node) { return node.r; })
.attr("width", function (f) { return 2 * f.r })
.attr("height", function (f) { return 2 * f.r })
.attr("rx", function (f) { return f.cr })
.attr("ry", function (f) { return f.cr });
if (PARAM_SHOW_NAMES)
this.showNames();
......@@ -181,7 +195,7 @@ class TFMRenderer extends TAMRenderer
console.log("SVG Elements Initialized.")
// Setup interactions
this.SVG_DRAGABLE_ELEMENTS = this.GRAPH_LAYER.selectAll("circle");
this.SVG_DRAGABLE_ELEMENTS = this.GRAPH_LAYER.selectAll(".family,.person");
initInteractions();
console.log("Interactions Initialized.")
}
......@@ -269,7 +283,7 @@ class TFMRenderer extends TAMRenderer
// move family and persons circles to defined position (d.x,d.y)
this.SVG_NODE_CIRCLES.attr("cx", function(p) { return p.vis.x; }).attr("cy", function(p) { return p.vis.y; });
this.SVG_NODE_CIRCLES.attr("x", function (p) { return p.vis.x - p.r; }).attr("y", function (p) { return p.vis.y - p.r; });
this.SVG_FAMILY_CIRCLES.attr("cx", function(f) { return f.vis.x; }).attr("cy", function(f) { return f.vis.y; }).attr("r", function(f) { return f.r; });
......@@ -492,8 +506,8 @@ class TFMRenderer extends TAMRenderer
{
// store person/family node positions with their id
let nodePositions = {};
this.PNODES.forEach(p => { nodePositions[p.id] = {"x": p.x, "y": p.y}; });
this.FNODES.forEach(f => { nodePositions[f.id] = {"x": f.x, "y": f.y}; });
this.PNODES.forEach(p => { nodePositions[p.id] = {"x": p.x, "y": p.y, "fixed": p.fx != null}; });
this.FNODES.forEach(f => { nodePositions[f.id] = {"x": f.x, "y": f.y, "fixed": f.fx != null}; });
let content = [JSON.stringify(
{
......
......
......@@ -31,7 +31,7 @@
<div id="menubar">
<div class="title">
Topographic Attribute Maps
<span id="version" class="version">1.18</span>
<span id="version" class="version">1.19</span>
</div>
<fieldset>
<legend><label>Load File</label></legend>
......
......
......@@ -105,6 +105,14 @@ function setTAMInteractions()
.on("drag", dragNode)
.on("end", dragEndNode)
);
renderer.SVG_DRAGABLE_ELEMENTS
.on("click", onMouseClick)
}
//---------------------------------------------------------------------------
function onMouseClick(d)
{
d.fx = d.fy = null;
}
//---------------------------------------------------------------------------
function mouseoverContour(c)
......@@ -170,8 +178,7 @@ function dragEndNode(d)
if (!d3.event.active && !PARAM_ENERGIZE)
renderer.FORCE_SIMULATION.velocityDecay(PARAM_FRICTION).alpha(0); // reset friction
d.fx = null;
d.fy = null;
//d.fx = d.fy = null;
if (PARAM_SHOW_TOOLTIPS)
d3.select("#tooltip").style("opacity", 1.0);
......
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment