How to render geojson with three.js and d3.js

2019-08-12 03:45发布

I use three.js r49, d3.v2.js and d3-threeD.js i want to render my city(Mashhad) with three.js but i got a problem i can render europian countries with these codes but i cant render with existing json file.

d3.js Ref

d3-threeD.js Ref

these are my codes:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>GEO Bar</title>
    <link rel="stylesheet" href="">
    <script type="text/javascript" src="./scripts/jquery-1.7.2.js"></script>
    <script type="text/javascript" src="./scripts/d3.v2.js"></script>
    <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/three.js/r49/Three.min.js"></script>

    <script type="text/javascript" src="./scripts/d3-threeD.js"></script>
    <script type="text/javascript" src="./scripts/constants.js"></script>
    <script type="text/javascript" src="./scripts/util-geo.js"></script>
    <script type="text/javascript" src="./scripts/script.js"></script>
    <style type="text/css">
        .btns{
            position: fixed;
            right: 100px;
            top: 100px; 
        }

        .btn{
            width: 40px;
            height: 60px;
            background-color: #999;
            margin-top: 5px;
            text-align: center;
            color: #111;
        }

        .btn > div{
            margin-bottom: 5px;
            cursor: pointer;
        }

    </style>
</head>
<body>
    <div id="chart"></div>
    <div class="btns">
        <div class="btn x">
            <div class="plus">+</div>X
            <div class="minus">-</div>
        </div>
        <div class="btn y">
            <div class="plus">+</div>Y
            <div class="minus">-</div>
        </div>
        <div class="btn z">
            <div class="plus">+</div>Z
            <div class="minus">-</div>
        </div>
    </div>
</body>
 </html>

constants.js codes:

var appConstants  = {

TRANSLATE_0 : -360,
TRANSLATE_1 : 10040,
SCALE : 60000
 }

util-geo.js codes:

var geons = {};
geons.geoConfig = function() {
this.TRANSLATE_0 = appConstants.TRANSLATE_0;
this.TRANSLATE_1 = appConstants.TRANSLATE_1;
this.SCALE = appConstants.SCALE;

this.mercator = d3.geo.mercator();
this.path = d3.geo.path().projection(this.mercator);

this.setupGeo = function() {
    var translate = this.mercator.translate();
    translate[0] = this.TRANSLATE_0;
    translate[1] = this.TRANSLATE_1;

    this.mercator.translate(translate);
    this.mercator.scale(this.SCALE);
}
console.log(2,this.path);
 }

 // geoConfig contains the configuration for the geo functions
 geo = new geons.geoConfig();

script.js codes:

(function($) {
$(function(){
    // get the correct geo for d3s
    geo.setupGeo();
    var 
        dataURL = "area.json",
        scene,
        renderer,
        camera;
        btnXPlus = $(".btns .x .plus"),
        btnXMinus = $(".btns .x .minus"),
        btnYPlus = $(".btns .y .plus"),
        btnYMinus = $(".btns .y .minus"),
        btnZPlus = $(".btns .z .plus"),
        btnZMinus = $(".btns .z .minus"),
        translate = geo.mercator.translate();

    // get the data
    $.getJSON( dataURL, function(data, textStatus, jqXHR) {
        initScene();
        addGeoObject();
        renderer.render( scene, camera );

        // Set up the three.js scene. This is the most basic setup without
        // any special stuff
        function initScene() {
            // set the scene size
            var 
                WIDTH = 600, 
                HEIGHT = 600;

            // set some camera attributes
            var 
                VIEW_ANGLE = 45, 
                ASPECT = WIDTH / HEIGHT,
                NEAR = 1, FAR = 10000;

            // create a WebGL renderer, camera, and a scene
            renderer = new THREE.WebGLRenderer({antialias:true});
            camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
            scene = new THREE.Scene();

            // add and position the camera at a fixed position
            scene.add(camera);
            camera.position.z = 550;
            camera.position.x = 0;
            camera.position.y = 550;
            console.log("scene.position: ",scene.position);
            camera.lookAt( scene.position );

            // start the renderer, and black background
            renderer.setSize(WIDTH, HEIGHT);
            renderer.setClearColor(0x321);

            // add the render target to the page
            $("#chart").append(renderer.domElement);

            // add a light at a specific position
            var pointLight = new THREE.PointLight(0xFFFFFF);
            scene.add(pointLight);
            pointLight.position.x = 800;
            pointLight.position.y = 800;
            pointLight.position.z = 800;

            // add a base plane on which we'll render our map
            var planeGeo = new THREE.PlaneGeometry(10000, 10000, 10, 10);
            var planeMat = new THREE.MeshLambertMaterial({color: 0x666699});
            var plane = new THREE.Mesh(planeGeo, planeMat);

            // rotate it to correct position
            plane.rotation.x = -Math.PI/2;
            scene.add(plane);
            console.log(1);
        }

        // add the loaded gis object (in geojson format) to the map
        function addGeoObject() {
            // keep track of rendered objects
            var meshes = [];
            var colors = [];
            var averageValues = [];
            var totalValues = [];
            // keep track of min and max, used to color the objects
            var maxValueAverage = 0;
            var minValueAverage = -1;

            // keep track of max and min of total value
            var maxValueTotal = 0;
            var minValueTotal = -1;

            // convert to mesh and calculate values
            for (var i = 0 ; i < data.features.length ; i++) {
                console.log(data.features[i]);
                var geoFeature = data.features[i];
                var feature = geo.path(geoFeature);
                console.log("feature:",feature);
                // we only need to convert it to a three.js path
                var mesh = transformSVGPathExposed(feature);
                console.log(mesh);
                // add to array
                meshes.push(mesh);

                // we get a property from the json object and use it
                // to determine the color later on
                var value = parseInt(geoFeature.properties.bev_dichth);
                if (value > maxValueAverage) maxValueAverage = value;
                if (value < minValueAverage || minValueAverage == -1) minValueAverage = value;
                averageValues.push(value);

                // var style = JSON.parse(geoFeature.properties.style);
                // colors.push(hexToRgb(style.strokeColor));
                // colors.push(style.strokeColor);

                // and we get the max values to determine height later on.
                value = parseInt(geoFeature.properties.aant_inw);
                if (value > maxValueTotal) maxValueTotal = value;
                if (value < minValueTotal || minValueTotal == -1) minValueTotal = value;

                totalValues.push(value);
            }

            console.log(averageValues,totalValues,colors);

            // we've got our paths now extrude them to a height and add a color
            for (var i = 0 ; i < averageValues.length ; i++) {

                // create material color based on average
                var scale = ((averageValues[i] - minValueAverage) / (maxValueAverage - minValueAverage)) * 255;
                var mathColor = gradient(Math.round(scale),255);
                console.log(scale,mathColor);
                var material = new THREE.MeshLambertMaterial({
                  color: mathColor
                });
                // var material = new THREE.MeshLambertMaterial({
                //   // color: hexToRgb(colors[i])
                // });
                // material.color.setHex(colors[i]);
                console.log("material:", material);

                // create extrude based on total
                var extrude = ((totalValues[i] - minValueTotal) / (maxValueTotal - minValueTotal)) * 100;
                var shape3d = meshes[i].extrude({amount: Math.round(extrude), bevelEnabled: false});
                console.log("extrude: ",extrude, "shape3d:", shape3d);
                // create a mesh based on material and extruded shape
                var toAdd = new THREE.Mesh(shape3d, material);

                // rotate and position the elements nicely in the center
                toAdd.rotation.x = Math.PI/2;
                toAdd.translateX(-490);
                toAdd.translateZ(50);
                toAdd.translateY(extrude/2);

                console.log("toAdd: ",toAdd);

                // add to scene
                scene.add(toAdd);
            }
        }

        // simple gradient function
        // function gradient(length, maxLength) {
        //  var i = (length * 255 / maxLength);
        //  var r = i;
        //  var g = 255-(i);
        //  var b = 0;

        //  var rgb = b | (g << 8) | (r << 16);
        //  console.log(rgb);
        //  return rgb;
        // }
        function gradient(color, maxLength) {
            var i = (length * 255 / maxLength);
            var r = i;
            var g = 255-(i);
            var b = 0;

            var rgb = b | (g << 8) | (r << 16);
            console.log("rgb: ",rgb);
            return rgb;
        }

        function hexToRgb(hex) {
            // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
            var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
            hex = hex.replace(shorthandRegex, function(m, r, g, b) {
                return r + r + g + g + b + b;
            });

            var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
            // return result ? {
            //  r: parseInt(result[1], 16),
            //  g: parseInt(result[2], 16),
            //  b: parseInt(result[3], 16)
            // } : null;
            return result ? parseInt(result[1], 16) | (parseInt(result[2], 16) << 8) | (parseInt(result[3], 16) << 16) : null;
        }
    });

    btnXPlus.click(function(){
        camera.position.x +=10;
        console.log(camera.position.x);
        renderer.render( scene, camera );
    });

    btnXMinus.click(function(){
        camera.position.x -=10;
        console.log(camera.position.x);
        renderer.render( scene, camera );
    });

    btnYPlus.click(function(){
        camera.position.y +=10;
        console.log(camera.position.y);
        renderer.render( scene, camera );
    });

    btnYMinus.click(function(){
        camera.position.x -=10;
        console.log(camera.position.y);
        renderer.render( scene, camera );
    });

    btnZPlus.click(function(){
        camera.position.z +=10;
        console.log(camera.position.z);
        renderer.render( scene, camera );
    });

    btnZMinus.click(function(){
        camera.position.z -=10;
        console.log(camera.position.z);
        renderer.render( scene, camera );
    });

});
 })(jQuery);

my geo json file: omidgharib.ir/area.json

0条回答
登录 后发表回答