D3 Treemap Hierarchy ThreeJS

76 views
Skip to first unread message

Andy Shepherd

unread,
Jun 9, 2020, 10:06:31 AM6/9/20
to d3-js
Hi All,

I'm trying to build something a little funky, a treemap but instead of each value as a Div I'm trying to use a ThreeJS geometry for the nested areas for each value.

I have a multi layer Treemap working in other graphs, and I have other D3 graphs working that output to ThreeJS data.  

But what I'm struggling with is treemap/leaves.  I believe every approach I've tried is fundamentally wrong (rather than just a code mistake):
- .enter().append("geometry") wont work because they are not nodes
- using JS to loop through the treemap to build objects with absolute positions got crazy quick
- building a treemap in Div then looping through each to extract absolute coordinates seems the wrong approach
- and a few more

Does anyone know how to approach this / can point my research in the right direction please

Suggestions very welcomed

Thanks
Andy

Andy Shepherd

unread,
Jun 9, 2020, 11:47:59 AM6/9/20
to d3-js
Another attempt

 square.datum(root).selectAll(".node")
.data(tree.leaves())
  .enter()
.each(function(d){

The problem is that each outputs entire JSON, not the specific DIV, and parsing through to get absolute coords for each becomes same as above

Andy Shepherd

unread,
Jun 9, 2020, 11:50:13 AM6/9/20
to d3-js
Also tried append function (go extract coords for each div)

node = square.datum(root).selectAll(".node")
        .data(tree.leaves())
      .enter()
          .append(function(d){qq(d)})

But functions don't have a "insertbefore" lol 

Andy Shepherd

unread,
Jun 9, 2020, 11:58:00 AM6/9/20
to d3-js
Sorry for spamming

I suppose the crux of it is, is there an easy way to either:

- .enter() data and append non DOM objects
- alternatively a way to parse through a treemap/root and get absolute coords into a flat array that I can parse


Andy Shepherd

unread,
Jun 9, 2020, 12:50:45 PM6/9/20
to d3-js
Spammage is allowed when you have a working answer right?  :)   (code needs cleaning up, but essentially)

data['children'] details the coords
data['data']['children'] details the actual data
Both have matching structures, so using a recursive loop we can go through


The code in D3 section


const root = d3.hierarchy(data, (d) => d.children)
.sum((d) => d.size);
const tree = treemap(root);


flatCords = treeToFlat(tree)


_.each(flatCords, function(coords){
var markerGeometry = new THREE.CubeGeometry(flatScale(coords['width']), 0, flatScale(coords['height']));
var material = new THREE.MeshBasicMaterial( { color: "black"} );
//////
var markerX = new THREE.Mesh(markerGeometry, material);
markerX.position.x = flatScale(coords['x'])
markerX.position.y = 0
markerX.position.z = flatScale(coords['y'])
scene.add(markerX);
})



Then the functions



function treeToFlat(data){

return treeToFlatRecursive(data['data'], data, [])

}

function treeToFlatRecursive(dataNode, childrenNode, returnList){

if(childrenNode.hasOwnProperty("children")){
for ( var i = 0 ; i < childrenNode['children'].length; i++){
var a = dataNode['children'][i]
var b = childrenNode['children'][i]
treeToFlatRecursive(a, b, returnList)

}

}else{
// miniObject
var mO = {}
mO['x'] = childrenNode['x0']
mO['y'] = childrenNode['y0']
mO['width'] = childrenNode['x1'] - childrenNode['x0']
mO['height'] = childrenNode['y1'] - childrenNode['y0']
mO['avg'] = dataNode['avg']
qq(mO)
returnList.push(mO)

}

return returnList

}


 flatCords comes out as something simple that we can use in ThreeJS to map geo to

          [{
                  "x": 1,
                  "y": 1,
                  "width": 488.8009708737864,
                  "height": 468.96039603960395,
                  "avg": 156.57692307692307
              }, {
                  "x": 1,
                  "y": 470.96039603960395,
                  "width": 488.8009708737864,
                  "height": 408.03960396039605,
                  "avg": 135158
              }, {
                  "x": 490.8009708737864,
                  "y": 1,
                  "width": 271.15810177435554,
                  "height": 484.54285714285714,
                  "avg": 4764.6875
              }, {
                  "x": 762.959072648142,
                  "y": 1,
                  "width": 236.04092735185804,
                  "height": 484.54285714285714,
                  "avg": 2129
              }, {
                  "x": 490.8009708737864,
                  "y": 486.54285714285714,
                  "width": 291.5185912001652,
                  "height": 246.7322751322751,
                  "avg": 321.3333333333333
              }, {
                  "x": 490.8009708737864,
                  "y": 734.2751322751323,
                  "width": 291.5185912001652,
                  "height": 144.72486772486775,
                  "avg": 96
              }, {
                  "x": 783.3195620739516,
                  "y": 486.54285714285714,
                  "width": 215.6804379260484,
                  "height": 176.05571428571426,
                  "avg": 0
              }, {
                  "x": 783.3195620739516,
                  "y": 663.5985714285714,
                  "width": 176.28399466676683,
                  "height": 143.26761904761906,
                  "avg": 3879
              }, {
                  "x": 783.3195620739516,
                  "y": 807.8661904761905,
                  "width": 176.28399466676683,
                  "height": 71.13380952380953,
                  "avg": 428
              }, {
                  "x": 960.6035567407184,
                  "y": 663.5985714285714,
                  "width": 38.39644325928157,
                  "height": 215.4014285714286,
                  "avg": 6865990
              }
          ]

Andy
Reply all
Reply to author
Forward
0 new messages