DEV Community

Cover image for How to simulate the neural network with JavaScript (attached source code)
Hightopo
Hightopo

Posted on • Updated on

How to simulate the neural network with JavaScript (attached source code)

The target we will achieve:
Neural network

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);
        };
Enter fullscreen mode Exit fullscreen mode

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:

  1. Specify the source and target node when creating Edge, i.e. new ht.Edge(node1, node2);
  2. 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;
        };
Enter fullscreen mode Exit fullscreen mode

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);
            };
Enter fullscreen mode Exit fullscreen mode

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]
            });
        };
Enter fullscreen mode Exit fullscreen mode

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.

Find more cool demos here

Top comments (0)