The target we will achieve:
Neural network
[Click here to see more demonstrations including Digital Twins, GIS, VR, BIM, etc.]
Initialization
The initialization work includes the preparation of colors, 3d scene, layout, 3d model, control pane, etc.
var init = function() {
// prepare 3d scene and datamodel
var dm = new ht.DataModel(),
g3d = window.g3d = new ht.graph3d.Graph3dView(dm);
g3d.getBrightness = function() { return null; };
g3d.isMovable = function(node) { return node.s('shape3d') !== 'custom'; };
g3d.addToDOM();
// create node and edges
var edgeList = initDataModel(dm),
// init the control pane and elastic layout
forceLayout = new ht.layout.Force3dLayout(g3d);
// the core code
forceLayout.onRelaxed = function() {
edgeList.forEach(updatePipeline);
};
forceLayout.start();
initFormPane(g3d);
};
Create Nodes and Edges
After the environment is ready, let's create the nodes (balls) and edges. This step is quite simple, when nodes are created, we just need to put the source node and target node into their Edge.
There're two ways to set the source and target endpoint for one Edge:
- Specify the source and target node when creating Edge, i.e. new ht.Edge(node1, node2);
- Use edgeInstance.setSource() and edgeInstance.setTarget() after the Edge has been created
Meanwhile, we'll create one 3d pipeline to connect the source node and target node. Each pipeline will be saved in its corresponding edges.
var createNode = function(dm) {
var node = new ht.Node();
node.s({
'shape3d': 'sphere',
'shape3d.color': randomColor()
});
node.s3(40, 40, 40);
dm.add(node);
return node;
};
var createEdge = function(dm, node1, node2) {
// create one self-defined 3d pipeline
// this pipeline will be used between source node and target node
var node = new ht.Node();
node.s({
'shape3d': 'custom', // self-defined 3d model
'shape3d.color': '#ECE0D4',
'layoutable': false
});
dm.add(node);
// can specify the source node and target node when create the Edge.
var edge = new ht.Edge(node1, node2);
edge.a('pipeline', node); // use one attribute of edge to save the pipline
edge.s('edge.color', 'rgba(0, 0, 0, 0)');
dm.add(edge);
return edge;
};
Update pipelines
The core code of this project is to overload the "onRelaxed" function of ht.layout.Force3dLayout.
The ht.layout.Force3dLayout class provides 3D force layouts, and constructors can input both DataModel and Graph3dView parameters. By default, only the unselected datas are laid out, and if the constructor parameter is Graph3dView, then the isMovable and isVisible functions of the view component will affect whether the data can be laid out, and the style layoutable attribute on the data can also be set to false to prevent datas from participating in the layout.
In this project, the updatePipeline function is created to update each pipeline:
forceLayout.onRelaxed = function() {
edgeList.forEach(updatePipeline);
};
Now the main work is how to update the pipeline corresponding to their edges. Since we have saved the pipeline into each edge attribute, and the source and target node can be get from each edge by edge.getSourceAgent() and edge.getTargetAgent(), we can then use their position to recalculate the shape of the pipeline.
var updatePipeline = function(edge) {
// get the pipeline from edge attribute
var pipeline = edge.a('pipeline');
pipeline.s3(1, 1, 1);
pipeline.p3(0, 0, 0);
// get the source node and target node
var node1 = edge.getSourceAgent(),
node2 = edge.getTargetAgent();
// update the pipeline based on the position of source and target node
pipeline.s('mat', createMatrix(node1.p3(), node2.p3(), 20));
};
var createMatrix = function(p1, p2, width) {
var vec = [p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2]],
dist = ht.Default.getDistance(p1, p2);
return ht.Default.createMatrix({
s3: [width, dist, width], // size
r3: [Math.PI/2 - Math.asin(vec[1]/dist), Math.atan2(vec[0], vec[2]), 0], // rotation
rotationMode: 'xyz',
t3: [(p1[0]+p2[0])/2, (p1[1]+p2[1])/2, (p1[2]+p2[2])/2]
});
};
At this time, the main work has been done. Let's take a look at the neural network:
Neural network
To get the source code, just open the link and press F12.
Top comments (0)