Intelligent Transportation Development New Planning under New Capital Construction: Intelligent Tunnel Monitoring Visualization System

Posted by geo3d on Wed, 10 Jun 2020 18:45:20 +0200

Preface

With the development of the contemporary economy, the transportation environment is getting more and more tense, together with the transportation needs in mountainous areas, the development of tunnel traffic construction is in the ascendant.Tunnel traffic planning is becoming more and more complete, but there are some inadequacies in monitoring, management and maintenance of tunnels.The rise of industrial 4.0 has gradually entered a new era of intellectualization. Along with the emerging power of industrial Internet, industrial control visualization system has emerged as the times require. It can not only play a daily monitoring, management and maintenance, but also take emergency plans as soon as an accident or danger is discovered. It can also collect and feedback real-time data, operate devices remotely and predict their good performance.In order to achieve a more three-dimensional and comprehensive operation of industrial control system.

HT for Web has not only independently developed a powerful 2D and 3D rendering engine based on HTML5, but also provided rich display effects for visualization.Between 2D and 3D configurations, Hightopo's HT for Web products have a rich selection of configurations. This paper will describe how to build a tunnel monitoring visualization system solution using HT rich 2/3D configurations.

It is necessary to monitor the traffic jam in the tunnel, the scene of the accident in the tunnel, display the current location of the accident in the tunnel and give a hint at the tunnel entrance.The main contents of this tunnel monitoring visualization system include lighting, fan, Lane indicator, traffic signal light, information board, fire control, fire alarm, driving cross-hole, wind direction meter, microwave vehicle inspection, control of tunnel emergency exit and accident simulation, etc.

Interface introduction and effect preview

Preview link: http://www.hightopo.com/demo/tunnel2/index.html

Each device in the picture above can be double-clicked, and the camera The location will move from the current position to the front of the double-clicked device; the display board at the tunnel entrance will be rotated automatically, and when an accident occurs, the content of the display board will change from "Speed limit 80, please drive the lamp" to "Overdrive two cars chasing after each other, please slow down". The sign above the escape channel in the middle of the two tunnels is clickable, Click to switch to blue-green activation, twoThe next door to the escape channel opens, then clicks the indicator to turn grey and the door closes; there is also an accident scene simulation, double-clicking one of the transformers on both sides, there will be an "accident scene icon" in the tunnel, clicking this icon, pop-up box showing the accident, and so on.

code implementation

1. Scene building

The whole tunnel is drawn on a 3D scene. First, let's see how to build a 3D scene:

// Data Container
dm = new ht.DataModel();
// 3d Scene
g3d = new ht.graph3d.Graph3dView(dm);
// Add scene to body
g3d.addToDOM();

The addToDOM function in the code above is an encapsulation of a function that adds components to the body, defined as follows:

addToDOM = function(){
    var self = this,
         // Get the underlying div of the component
         view = self.getView(),
         style = view.style;
    // Add component bottom div to body
    document.body.appendChild(view);
    // ht sets position of all components to absolute by default
    style.left = '0';
    style.right = '0';
    style.top = '0';
    style.bottom = '0';
    // Window size change event, call refresh function
    window.addEventListener('resize', function () { self.iv(); }, false);
}

2. JSON Deserialization

The whole scene is exported from a file named Tunnel 1.json, and I just need to convert the contents of the JSON file into what I need with code:

// The xhrLoad function is a function that loads files asynchronously
ht.Default.xhrLoad('./scenes/Tunnel 1.json', function(text) {
    // Turn the text in the json file into the json format we need
    var json = ht.Default.parse(text);
    // Deserialize the Data container, parse the Data object used to generate it and add it to the Data container This is equivalent to generating it in a json fileHt.NodeNodes are deserialized into Data containers so that there is this node in the Data container
    dm.deserialize(json);
});

Since the xhrLoad function is an asynchronous loading function, if the dm data container is directly invoked to its nodes before deserialization is complete, the data will not be available, so generally I write some logic code inside this function or set a timeout stagger for the logic code.

First, since the data is stored in the dm data container (viaDm.add(node) added), so we want to get the data not only by id, tag, and so on, but also by traversing the data container to get multiple elements.Because of the complexity of this scenario and the many facets of the model, I was able to batch Batch batch elements due to the device configuration.

Batch is a unique mechanism in the HT implementation. The principle of batch performance improvement is that when primitives are drawn independently of each other, performance is poor, and when a batch of primitives is aggregated into one large model for one-time drawing, WebGL refresh performance is greatly improved, with the following code executed

dm.each(function(data) {
    // Batch Phone
    if (data.s('front.image') === 'assets/sos Telephone.png'){
        data.s('batch', 'sosBatch');
    }
    // Escape Channel Batch (Transparency also affects performance)
    else if (data.s('all.color') === 'rgba(222,222,222,0.18)') {
        data.s('batch', 'emergencyBatch');
    }
    else if (data.s('shape3d') === 'models/Tunnel/Camera.json' || data.s('shape3d') === 'models/Tunnel/Horizontal Hole.json' || data.s('shape3d') === 'models/Tunnel/Rolling shutter door.json') {
        // Individual cameras are dyed without batch
        if(!data.s('shape3d.blend'))
            // Base lot do nothing
            data.s('batch', 'basicBatch');
    }
    else if (data.s('shape3d') === 'models/Large transformer/Transformer.json') {    
        data.s('batch', 'tileBatch');
        data.setToolTip('Click Roam and double-click the icon at the location of the accident');
    }
    else if (data.getDisplayName() === 'ground') {
        // Setting tunnel "ground" is not optional
        data.s('3d.selectable', false);
    }
    else if (data.s('shape3d') === 'models/Tunnel/Exhaust.json') {
        // Exhaust fan model is complex, so do batch
        data.s('batch', 'fanBatch');
    }
    else if (data.getDisplayName() === 'arrow') {
        // Arrow landmarks on both sides of the tunnel
        if (data.getTag() === 'arrowLeft') data.s('shape3d.image', 'displays/abc.png');
        else data.s('shape3d.image', 'displays/abc2.png');
        data.s({
            'shape3d': 'billboard',
            // Cache, the cost of setting cache is to set invalidateShape3dCachedImage
            'shape3d.image.cache': true,
            // Set this value so that the jagged image is less visible (if the picture type is json, set shape3d).Dynamic.transparent)
            'shape3d.transparent': true 
        });
        g3d.invalidateShape3dCachedImage(data);
    }
    // Intelligence board at tunnel entrance
    else if (data.getTag() === 'board' || data.getTag() === 'board1') {
        // Business property that controls the location of text [x,y,width,height]
        data.a('textRect', [0, 2, 244, 46]); 
        // Business properties, setting text content
        data.a('limitText', 'Speed limit 80, please drive light');
        var min = -245;
        var name = 'board' + data.getId();
        window[name] = setInterval(function() {
            // Set the text in the Intelligence Panel to scroll left and blink three times when all text is displayed
            circleFunc(data, window[name], min);
        }, 100);
    }

    //Dynamically set the color of the dashboard above the escape channel
    var infos = ['Pedestrian crosshole 1', 'Pedestrian crosshole 2', 'Pedestrian crosshole 3', 'Pedestrian crosshole 4', 'Driving cross hole 1', 'Driving Cross Hole 2', 'Driving Cross Hole 3'];
    infos.forEach(function(info) {
        if(data.getDisplayName() === info) {
            data.a('emergencyColor', 'rgb(138, 138, 138)');
        }
    });

    infos = ['Lane Indicator', 'Lane Indicator 1', 'Lane Indicator 2', 'Lane Indicator 3'];
    infos.forEach(function(info) {
        if (data.getDisplayName() === info) {
            // Converting hexahedrons to billboard type elements for performance reasons
            createBillboard(data, 'assets/Lane Signal-too.png', 'assets/Lane Signal-too.png', info);
        }
    });
});

There is a tooltip text prompt set above. To display this text prompt in 3d, you need to set the g3d.enableToolTip() function, which is turned off by default 3D component.

3. Logical Code

Intelligence scrollbar

I will directly follow the method mentioned in the code above, starting with the circleFunc intelligence board text circulation function, in which we use the business attribute limitText to set the text attributes in the intelligence board and textRect to set the text movement position attributes in the intelligence board:

// Set the text in the Intelligence Panel to scroll left and blink three times when all text is displayed
function circleFunc(data, timer, min) {
    // Get the contents of the current business property limitText
    var text = data.a('limitText');
    // Set the coordinates and size of the business property textRect text box
    data.a('textRect', [data.a('textRect')[0]-5, 2, 244, 46]); 
    if (parseInt(data.a('textRect')) <= parseInt(min)) {
        data.a('textRect', [255, 2, 244, 46]);
    }
    else if (data.a('textRect')[0] === 0) {
        clearInterval(timer);
        var index = 0;
        // Multiple timers are set because more than one data can enter this function. If multiple data sets the same timer at the same time, then only the last node will be animated.There are many other pitfalls to be noted
        var testName = 'testTimer' + data.getId();
        window[testName] = setInterval(function() {
            index++;
            // If the text content in the intelligence board is empty
            if(data.a('limitText') === '') {
                setTimeout(function() {
                    // Set to the incoming text value
                    data.a('limitText', text);
                }, 100);
            }
            else {
                setTimeout(function() {
                    // If the text content in the intelligence board is not empty, set it to empty
                    data.a('limitText', ''); 
                }, 100);
            }
            // Repeat three times 
            if(index === 11) { 
                clearInterval(window[testName]);
                data.a('limitText', text);
            }
        }, 100);

        setTimeout(function() {
            timer = setInterval(function() {
                // callback
                circleFunc(data, timer, min);
            }, 100);
        }, 1500);
    }
}

Since WebGL has a lot of browser requirements, in order to adapt as many browsers as possible, we will use all the "road indicators"Ht.NodeReplacing all hexahedrons of type with nodes of type billboard improves performance a lot.

http://www.hightopo.com

The simple way to set billboard is to get the current hexahedron nodes and set them:

node.s({
    'shape3d': 'billboard',
    'shape3d.image': imageUrl,
    'shape3d.image.cache': true
});
// Remember to use shape3d.Image.cacheCost?
g3d.invalidateShape3dCachedImage(node);

Of course, because billboard can't display different pictures on both sides, it's just a "side", so we have to create another node at the location of this node to display pictures on the "back" of this node, which is the same as the configuration of this node, but with a slight offset.

Camera slow offset

The rest of the animation is fairly simple, so I won't say much about it here. There's an animation where a double-click node moves the line of sight from the current camera position to the position directly in front of the double-click node.I encapsulated two functions, setEye and setCenter, to set the location and target location of cameras:

// Set Target Location
function setCenter(center, finish) {
    // Get the current "target" position as an array, and the getCenter array changes as the line of sight moves, so we'll copy one first
    var c = g3d.getCenter().slice(0), 
        // The difference between the current x-axis position and the target position
        dx = center[0] - c[0], 
        dy = center[1] - c[1],
        dz = center[2] - c[2];
    // Start 500 ms animation overrun
    ht.Default.startAnim({
        duration: 500,
        action: function(v, t) {
            // Slowly move the Target position from the current position to the set position
            g3d.setCenter([ 
                c[0] + dx * v,
                c[1] + dy * v,
                c[2] + dz * v
            ]);
        }
    });
};

// Set Eye Position
function setEye(eye, finish) {
    // Get the current Eye position as an array and the getEye array changes as the line of sight moves, so we'll copy one first
    var e = g3d.getEye().slice(0),
        dx = eye[0] - e[0],
        dy = eye[1] - e[1],
        dz = eye[2] - e[2];
    // Start 500 ms animation overrun
    ht.Default.startAnim({
        duration: 500,
        // Slowly move the Camera position from the current position to the set position
        action: function(v, t) {
            g3d.setEye([
                e[0] + dx * v,
                e[1] + dy * v,
                e[2] + dz * v
            ]);
        }
    });
};

Later, when we want to set these two functions, we can call them directly and set the parameter to the location of our target.For example, for each model in my scene, because the rotation angle of each model is different from different perspectives, I can only find four more typical angles: 0, 90, 180 and 360 degrees.So when I draw a 3D scene, I try to set the rotation angle of the nodes to one of the four (and for our scene, basically just rotated on the y-axis):

// Getting the three-dimensional coordinates of an event object
var p3 = e.data.p3(), 
    // Getting the three-dimensional dimensions of an event object
    s3 = e.data.s3(),
    // Gets the 3-D rotation value of the event object
    r3 = e.data.r3();
// Set the Target position to the three-dimensional coordinate value of the current event object
setCenter(p3);
// If the y-axis rotation value of the node is not zero
if (r3[1] !== 0) {
    // Negative floating-point numbers have to be converted for ratios
    if (parseFloat(r3[1].toFixed(5)) === parseFloat(-3.14159)) { 
        // Set the target location of the camera
        setEye([p3[0], p3[1]+s3[1], p3[2] * Math.abs(r3[1]*2.3/6)]);
    }
    else if (parseFloat(r3[1].toFixed(4)) === parseFloat(-1.5708)) {
        setEye([p3[0] * Math.abs(r3[1]/1.8), p3[1]+s3[1], p3[2]]);
    }
    else {
        setEye([p3[0] *r3[1], p3[1]+s3[1], p3[2]]);
    }
}
else {
    setEye([p3[0], p3[1]+s3[1]*2, p3[2]+1000]);
}

Accident simulation site

Finally, let's talk about the simulated accident scene, which is close to the actual project.The procedure is as follows: Double-click "Transformer"--> An "Accident Site" icon appears in the middle of the tunnel--> Click the icon, pop up the dialog box and display the current accident information--> Click OK, the lights before the accident site are displayed in red X, and the text on the information board of the tunnel entrance is "Overtake lane, two cars chase, slow down"--> Double-click one moreSecondary "transformer", the scene restores the state before the accident.

In HT, you can listen for interaction through Graph3dView#addInteractorListener (abbreviated as mi):

g3d.addInteractorListener(function(e) {
    if(e.kind === 'doubleClickData') {
        // Node with Accident icon exists
        if (e.data.getTag() === 'jam') return;
        // If the double-click object is a transformer
        if (e.data.s('shape3d') === 'models/Large transformer/Transformer.json') {
            index++;
            // Get Accident Icon Node Object from Unique Identification tag Tag
            var jam = dm.getDataByTag('jam');
            if(index === 1){
                var jam = dm.getDataByTag('jam');
                jam.s({
                    // Set node visible on 3d
                    '3d.visible': true,
                    // Set node to billboard type
                    'shape3d': 'billboard',
                    // Set billboard display picture
                    'shape3d.image': 'assets/traffic accident.png', 
                    // Set whether billboard pictures are cached
                    'shape3d.image.cache': true,
                    // Whether to always face the lens
                    'shape3d.autorotate': true,
                    // By default, keep the original size of the picture, and by setting it to Array mode, you can set the size of the picture displayed on the interface.
                    'shape3d.fixSizeOnScreen': [30, 30],
                });
                // The cost of cache is that the node needs to set this function
                g3d.invalidateShape3dCachedImage(jam);
             }
             else {
                 jam.s({
                     // The second double-click on the transformer restores everything to its state before the accident
                     '3d.visible': false
                });
                dm.each(function(data) {
                    var p3 = data.p3();
                    if ((p3[2] < jam.p3()[2]) && data.getDisplayName() === 'Lane Indicator 1') {
                        data.s('shape3d.image', 'assets/Lane Signal-too.png');
                    }
                    if(data.getTag() === 'board1') {
                        data.a('limitText', 'Speed limit 80, please drive light');
                    }
                });
                index = 0;
            }             
        }
    }
});

Now that the Accident node icon appears, click on the icon to bring up the Accident Information Popup Box. Listening for events is also in the mi (addInteractorListener), but this time listening for click events, we know that listening for double-click events triggers a click event. To avoid this, I demonstrated it in click events:

// Click on Primitives
else if (e.kind === 'clickData'){
    timer = setTimeout(function() {
        clearTimeout(timer);
        // If it is an Accident icon node
        if (e.data.getTag() === 'jam') {
            // Create a dialog box
            createDialog(e.data);
        }
    }, 200);
}

I don't have clearTimeout in the double-click event above. I'm afraid the sequencing problem will bother you. Please add one more time.

The pop-up box is as follows:

This pop-up box is made up of twoHt.widget.FormPaneThe form consists of one row on the left, 140 rows high, and five rows on the right. Click OK and the road lights before the Accident icon node will be replaced with red * icons:

// Form to the right of the pop-up box
function createForm4(node, dialog) {
    // Form Components
    var form = new ht.widget.FormPane();
    // Set the width of the form components
    form.setWidth(200);
    // Set the height of the form component
    form.setHeight(200);
    // Get the underlying div of the form component 
    var view = form.getView();
    // Add form components to body
    document.body.appendChild(view);

    var infos = [
        'Edit box content is: 2 vehicles',
        'The edit box is: Bus-Passenger car',
        'Edit box content is: No fire',
        'The contents of the edit box are: Overdrive'
    ];
    infos.forEach(function(info) {
        // Add rows to the form
        form.addRow([ 
            info
        // The second parameter is the row width, less than 1 is a relative value
        ], [0.1]);
    });
    
    form.addRow([
        {
            // Add a confirmation button for a line
            button: {
                label: 'confirm',
                // Button Click Event Trigger
                onClicked: function() {
                    // Hide dialog
                    dialog.hide();
                    dm.each(function(data) {
                        var p3 = data.p3();
                        // Change the display picture of the Lane Indicator to red * Here I can tell if the Lane Indicator is in front or behind based on the coordinates of the node of the Accident Icon
                        if ((p3[2] < node.p3()[2]) && data.getDisplayName() === 'Lane Indicator 1') {
                            data.s('shape3d.image', 'assets/Lane Signal-prohibit.png');
                        }
                        // Replace text on the information board of the tunnel entrance
                        if(data.getTag() === 'board1') {
                            data.a('limitText', 'Overdrive two cars are chasing tail, please slow down');
                        }
                    });
                }
            }
        }
    ], [0.1]);
    return form;
}

summary

With the rise of new infrastructure construction, the country is stepping into a new era of construction, which is driven by new development concepts, driven by technological innovation, based on information networks and facing the needs of high-quality development, and provides the complete infrastructure system of digital transformation, intelligent upgrade, integrated innovation and other services. The nation is entering a new era of construction, and also ushered in new era challenges and opportunities.Tunnel traffic monitoring can be summarized as the product of industrial control management and intelligent traffic construction, which is also of great significance.With experience gained in many industries, HT has achieved many cases in different areas, such as Visualization System of Intersection Regulation You can also find out if you are interested!

 

In 2019, we have also updated hundreds of industrial Internet 2D/3D visualization case sets, where you can find many novel examples and also discover different industrial Internet: https://mp.weixin.qq.com/s/ZbhB6LO2kBRPrRIfHlKGQA

You can also see more cases and effects: https://www.hightopo.com/demos/index.html

Topics: Javascript JSON less html5 Attribute