Examples of the development of three-dimensional map with three.js

Fire companies to do intelligence visualization floor, need to use web3d, open-source engine to study the three-dimensional Earth cesium, cesium but do floor feeling is overkill, but the experience is not good, the final choices are powerful, more suitable for small scene three.

three is the graphics engine, and web-based 2D and 3D maps are graphics engine, so take three simple requirements to develop a three-dimensional map application is no problem.

1. Coordinate Transformation

      The actual geographical coordinates longitude, latitude, altitude, and three.js using a right-handed coordinate system x, y, z, have been considered is to convert the latitude and longitude coordinates into Mercator, and again the coordinate system corresponding to three. The actual project, the longitude and latitude turn Mercator, Mercator value is too large, corresponding to the three coordinate system, the origin of the coordinate distance is too far, the user interaction, there will be loss of precision, thus defining a first intermediate point, and then the Mercator result of subtracting the value of the intermediate point. (I longitude corresponding to the z-axis, x-axis corresponds to the latitude, the height of the corresponding y-axis)

function lonlatToMercator(lon,lat,height){
    var z = height ? height:0;
    var x = (lon / 180.0) * 20037508.3427892;
    var y = (Math.PI / 180.0) * lat;
    var tmp = Math.PI / 4.0 + y / 2.0;
    y = 20037508.3427892 * Math.log(Math.tan(tmp)) / Math.PI;
    return {x: x,y: y,z: z};
}
var center = lonlatToMercator(lonVal,latVal,heightVal);
function lonlatToThree(lon,lat,height){
    var z = height? height:0;
    var x = (lon / 180.0) * 20037508.3427892;
    var y = (Math.PI / 180.0) * lat;
    var tmp = Math.PI / 4.0 + y / 2.0;
    y = 20037508.3427892 * Math.log(Math.tan(tmp)) / Math.PI;
    var result = {
        x: x - center.x,
        y: y - center.y,
        z: z -center.z
    };
    return result;
}

2. Load Model

 

    three.js supports a variety of models loaded, I used to build model Sketch Master, then transferred directly into collada model, and then use the three collada model loader loading model. Because three.js and correspond to, and located xz axis default model, so the model reversing operation.

3. Create a label

    three, create a label always facing the camera POI can use Sprite class, you can also use the canvas to create an icon + text type of graphics as Sprite texture. The default sprite 3d is a fixed length, from the camera closer sprite, the sprite on the screen larger, the smaller the contrary, too large or too small will cause the sprite fuzzy canvas distortion, solutions are calculated with the point of the screen pixel 3d coordinates length ratio, the sprite is then scaled to a suitable length 3d.

var position = sprite.position;
var canvas = sprite.material.map.image;
if(canvas){
    var poiRect = {w:canvas.width,h:canvas.height};
    var scale = getPoiScale(position,poiRect);
    sprite.scale.set(scale[0],scale[1],1.0);
}
 
function getPoiScale(position,poiRect){
    if(!position) return;
    var distance = camera.position.distanceTo(position);
    var top = Math.tan(camera.fov / 2Math.PI * / 180 [ ) * Distance;     // photographing angle of the camera camera.fov 
    var meterPerPixel = 2 * Top / container.clientHeight;
     var the scaleX = poiRect.w * meterPerPixel;
     var scaleY = poiRect.h * meterPerPixel;
     return [ the scaleX, scaleY, 1.0 ]; 
}

 

 4. The collision marked

      After creating the label, labeling each case there will inevitably be covered when zooming, so that not only affects the appearance will cover the map information, there needs to be detected between the cover label, display, and do not show some marked.

        The main point here is denoted 3d coordinates into screen coordinates of the rpm, then the sprite canvas according to the length and height, can know the screen sprite rectangle. Then there is the calculation of each label points intersected sprite rectangle.

 var sprite1 = {X: X1, Y: Y1, W: W1, H: h1 of};     // bottom left sprite1 x, y, width, height 
    var sprite2 = {X: X2, Y: Y2, W: w2 of, H : H2};     // sprite2 lower left corner x, y, width, height
   // detect whether two marked sprite collision 
    function isPOIRect (sprite1, sprite2) {
         var X1 = sprite1.x, sprite1.y = Y1, W1 = sprite1. W, = h1 of sprite1.h;
         var X2 = sprite2.x, Y2 = sprite2.y, W1 = sprite2.w, = h1 of sprite2.h;
         IF (X1> X2 = X1 &&> = X2 + w2 of) {
             return  to false ; 
        } the else  IF (X1 <X2 = X1 + W1 && <= X2) {
             return  to false ;
        } else if (y1 >= y2 && y1 >= y2 + h2) {
            return false;
        } else if (y1 <= y2 && y1 + h1 <= y2) {
            return false;
        }else{
            return true;
        }
    }

 

The loading device

      Create a device, I also use the Sprite class, create a label with a similar, after scaling, sprite on the screen size remains unchanged.

6. Click on Device

    3d raycaster class for the mouse to select the object, which may be the same sprite object is selected, then clicking this method simulation device. Which is deviceGroup save object3d target all devices sprite.

onDocumentMouseDown function (E) { 
        e.preventDefault (); 
        mouse.x = (e.clientX / window.innerWidth) * 2 - . 1 ; 
        mouse.y = - (e.clientY / window.innerHeight) * 2 + . 1 ;
         / / create a three-dimensional unit vector in the z direction is assumed 0.5
         // the camera, to convert this vector into a viewpoint coordinate system 
        var vector = new new THREE.Vector3 (mouse.x, mouse.y, 0.5 ) .unproject (camera);
         // form the starting point of the vector-rays, the rays of the viewpoint coordinate system is a camera, a camera-ray direction vector to the clicked point, this vector should be normalized standardized. 
        var Raycaster = new newTHREE.Raycaster (camera.position, vector.sub (camera.position) .normalize ());
         // rays and intersection model, the selected series of straight lines 
        var the intersects raycaster.intersectObjects = ([devicegroup], to true );          
         IF ( intersects.length> 0 ) {
             var intersected the intersects = [ 0 ]. Object ;
             IF (intersected the instanceof THREE.Sprite) {
                 // click to the device icon 
            }   
        } 
    }

 

7. pop-up box

       After the clicking device, usually specific information presentation device in a popup style, where the need to define the style pop-up box and then three-dimensional coordinates converted into the pop-up screen coordinate point device, set a certain offset, then put popup screen position shifted to the rear. Then each time you change the camera, recalculate the pop-up position.

// Three world coordinates into screen coordinates 
function threeToScreen (position, Camera) {
     var worldVector = new new THREE.Vector3 ( 
            position.x, 
            position.y, 
            position.z 
    ); 
    var standardVector = worldVector.project (Camera); // world coordinate to a standard device coordinates 
    var A = window.innerWidth / 2 ;
     var B = window.innerHeight / 2 ;
     var X = Math.round (standardVector.x * A + A); // standard device coordinates of the screen coordinate rotation 
    var Y Math.round = (-standardVector.y + B * B); // standard device coordinates of the screen coordinate rotation 
    return{ 
        X: x, 
        y: y 
    }; 
}

 

8. Equipment animation

        Simple devices such as animation can be implemented to achieve the device icon flashing through the timing to change the device by changing the material of the device material, size, location.

        vertices project to simulate fire, and therefore spent some time with online reference and made a flame particle system animation, where the first loop to create all of the dots flame by using a THREE.Vector3 objects, put objects in THREE.Geometry ; then use to create flames canvas grain pattern, the object passed THREE.PointsMaterial (transparent material and disposed transparent: true mixing and addition THREE.AddictiveBlending), and finally the foregoing THREE.Geometry THREE.Points THREE.PointsMaterial create objects, complete the flame particle system initialization.

        Each particle has a single coordinate, the last movement driving particles with certain rules to achieve the effect of animation.

 

9. mouse to draw

        In 3d, the mouse position corresponds to the three-dimensional coordinates is a ray, it is necessary to add the drawing plane, obtain an intersection of the plane of drawing and mouse clicks, as plotting points. Monitor mouse click and move events to draw upon.

        When drawing lines, click and move the mouse, direct line to change the geometry of the vertices; when drawing surface, not only to change the vertices have to calculate all the vertices of triangles combination (I use the Earcut.js), as the geometry of faces, and finally create a polygon mesh with this geometry is geometry.

//positions 三维坐标数组[[x,y,z],[x,y,z],...]
function createPolygon(positions){
    var shapePositons = [];
     for(var i=0;i<positions.length;i++){
        var position = positions[i];
        shapePositons.push(new THREE.Vector3(position[0],position[1],position[2]));
    }
    var data = [];
    for(var i=0;i<positions.length;i++){
        var position = positions[i];
        data.push(position[0],position[1]);
    }
    var faces = [];
    var triangles = Earcut.triangulate(data);
    if(triangles && triangles.length != 0){
        for(var i=0;i<triangles.length;i++){
            var length = triangles.length;
            if(i%3==0 && i < length-2){
                faces.push(new THREE.Face3(triangles[i],triangles[i+1],triangles[i+2]));
            }
        }
    }
    var geometry = new THREE.BufferGeometry();
    geometry.vertices = shapePositons;
    geometry.faces = faces;
    
    var mesh = new THREE.Mesh(geometry,material);
    return mesh;
}

 

Guess you like

Origin www.cnblogs.com/smedas/p/12440987.html