~$ 存档

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

 

依赖文件:js/myApp/measure.js

define(["esri/geometry/Point", "esri/geometry/Extent"], function (Point, Extent) {
    
    var measure = {};

    measure.getMidPoint = function (p1, p2) {
        var theReturn = null;
        if (p1 && p1.type && p1.type == "point" && p2 && p2.type && p2.type == "point") {
            var x = (p1.x + p2.x) / 2;
            var y = (p1.y + p2.y) / 2;
            theReturn = new Point(x, y, p1.spatialReference);
        }
        return theReturn;
    };

    measure.getAngle = function (p1, p2) {
        var theReturn = 0;
        if (p1 && p1.type && p1.type == "point" && p2 && p2.type && p2.type == "point") {
            var dx = (p1.x - p2.x);
            var dy = (p1.y - p2.y);
            var rad = Math.PI / 2;
            if (dx !== 0) {
                rad = Math.atan(dy / dx) * -1;
            }
            theReturn = measure.radiansToDegrees(rad);
        }
        return theReturn;
    };

    measure.radiansToDegrees = function (radians) {
        return radians * 180 / Math.PI;
    };

    measure.getRingExtent = function (polygon, ringIndex) {
        var ext = null;
        if (polygon && polygon.type && polygon.type == "polygon") {
            var minX = null;
            var maxX = null;
            var minY = null;
            var maxY = null;

            for (var j = 0; j < polygon.rings[ringIndex].length; j++) {
                x = polygon.rings[ringIndex][j][0];
                y = polygon.rings[ringIndex][j][1];

                if (minX) {
                    minX = Math.min(minX, x);
                }
                else {
                    minX = x;
                }

                if (minY) {
                    minY = Math.min(minY, y);
                }
                else {
                    minY = y;
                }

                if (maxX) {
                    maxX = Math.max(maxX, x);
                }
                else {
                    maxX = x;
                }

                if (maxY) {
                    maxY = Math.max(maxY, y);
                }
                else {
                    maxY = y;
                }
            }

            ext = new Extent(minX, minY, maxX, maxY, polygon.spatialReference);
        }
        return ext;
    };

    measure.calculateLength = function (polyline, isGeographic) {
        var length = [];
        if (polyline && polyline.type && polyline.type == "polyline") {
            for (var i in polyline.paths) {
                var l = 0;

                for (var j = 0; j < polyline.paths[i].length - 1; j++) {
                    var x1 = polyline.paths[i][j][0];
                    var y1 = polyline.paths[i][j][1];
                    var x2 = polyline.paths[i][j + 1][0];
                    var y2 = polyline.paths[i][j + 1][1];

                    var d;
                    if (isGeographic) {
                        d = measure.getGreatCircleDistance2(y1, x1, y2, x2);
                    }
                    else {
                        d = measure.getDistanceXYXY(x1, y1, x2, y2);
                    }

                    l += d;
                }
                length.push(l);
            }
        }
        return length;
    };

    measure.getDistanceXYXY = function (x1, y1, x2, y2) {
        return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
    };

    measure.getGreatCircleDistance2 = function (/*Number*/lat1, /*Number*/lon1, /*Number*/lat2, /*Number*/lon2) {
        try {
            var rlat1 = measure.degreesToRadians(lat1);
            var rlon1 = measure.degreesToRadians(lon1);
            var rlat2 = measure.degreesToRadians(lat2);
            var rlon2 = measure.degreesToRadians(lon2);

            var ellipse = {
                name: "WGS80",
                a: 6378.137 / 1.852,
                invf: 298.257223563
            };

            // Some util functions
            var mod = function (x, y) {
                return x - y * Math.floor(x / y);
            };

            var modcrs = function (x) {
                return mod(x, 2 * Math.PI);
            };

            var a = ellipse.a;
            var f = 1 / ellipse.invf;

            var r, tu1, tu2, cu1, su1, cu2, s1, b1, f1;
            var x, sx, cx, sy, cy, y, sa, c2a, cz, e, c, d;
            var EPS = 0.00000000005;
            var faz, baz, s;
            var iter = 1;
            var MAXITER = 100;
            if ((rlat1 + rlat2 === 0.0) && (Math.abs(rlon1 - rlon2) == Math.PI)) {
                alert("Course and distance between antipodal points is undefined");
                rlat1 = rlat1 + 0.00001; // allow algorithm to complete
            }
            if (rlat1 == rlat2 && (rlon1 == rlon2 || Math.abs(Math.abs(rlon1 - rlon2) - 2 * Math.PI) < EPS)) {
                //console.warn("Points 1 and 2 are identical- course undefined");
                return 0;
            }
            r = 1 - f;
            tu1 = r * Math.tan(rlat1);
            tu2 = r * Math.tan(rlat2);
            cu1 = 1.0 / Math.sqrt(1.0 + tu1 * tu1);
            su1 = cu1 * tu1;
            cu2 = 1.0 / Math.sqrt(1.0 + tu2 * tu2);
            s1 = cu1 * cu2;
            b1 = s1 * tu2;
            f1 = b1 * tu1;
            x = rlon2 - rlon1;
            d = x + 1; // force one pass

            while ((Math.abs(d - x) > EPS) && (iter < MAXITER)) {
                iter = iter + 1;
                sx = Math.sin(x);
                cx = Math.cos(x);
                tu1 = cu2 * sx;
                tu2 = b1 - su1 * cu2 * cx;
                sy = Math.sqrt(tu1 * tu1 + tu2 * tu2);
                cy = s1 * cx + f1;
                y = measure.atan2(sy, cy);
                sa = s1 * sx / sy;
                c2a = 1 - sa * sa;
                cz = f1 + f1;
                if (c2a > 0.0) {
                    cz = cy - cz / c2a;
                }
                e = cz * cz * 2.0 - 1.0;
                c = ((-3.0 * c2a + 4.0) * f + 4.0) * c2a * f / 16.0;
                d = x;
                x = ((e * cy * c + cz) * sy * c + y) * sa;
                x = (1.0 - c) * x * f + rlon2 - rlon1;
            }
            faz = modcrs(measure.atan2(tu1, tu2));
            baz = modcrs(measure.atan2(cu1 * sx, b1 * cx - su1 * cu2) + Math.PI);
            x = Math.sqrt((1 / (r * r) - 1) * c2a + 1);
            x += 1;
            x = (x - 2.0) / x;
            c = 1.0 - x;
            c = (x * x / 4.0 + 1.0) / c;
            d = (0.375 * x * x - 1.0) * x;
            x = e * cy;
            s = ((((sy * sy * 4.0 - 3.0) * (1.0 - e - e) * cz * d / 6.0 - x) * d / 4.0 + cz) * sy * d + y) * c * a * r;
            var out = {};
            out.d = s;
            out.dist = s * 1852; // to meters
            out.crs12 = faz;
            out.crs21 = baz;
            if (Math.abs(iter - MAXITER) < EPS) {
                alert("Algorithm did not converge");
            }
            return out.dist;
        }
        catch (err) {
            console.error("Error calculating great circle distance", err);
            return 0;
        }
    };

    measure.degreesToRadians = function (degrees) {
        return Math.PI * degrees / 180;
    };

    measure.atan2 = function (y, x) {
        var out;
        if (x < 0) { out = Math.atan(y / x) + Math.PI; }
        if ((x > 0) && (y >= 0)) { out = Math.atan(y / x); }
        if ((x > 0) && (y < 0)) { out = Math.atan(y / x) + 2 * Math.PI; }
        if ((x === 0) && (y > 0)) { out = Math.PI / 2; }
        if ((x === 0) && (y < 0)) { out = 3 * Math.PI / 2; }
        if ((x === 0) && (y === 0)) {
            console.error("com.esri.solutions.jsviewer.util.atan2(0,0) undefined");
            out = 0.0;
        }
        return out;
    };

    measure.convertDistanceUnits = function (distance, fromUnits, toUnits) {
        if (fromUnits == "DecimalDegrees") {
            console.error("convertDistanceUnits: DecimalDegrees are not a distance unit");
            return 0;
        }

        // Number of meters in a unit
        var cFactors = {
            "Feet": 0.3048,
            "Meters": 1,
            "Miles": 1609.344,
            "Kilometers": 1000,
            "Yards": 0.9144
        };

        if (!cFactors[fromUnits]) {
            console.error("convertDistanceUnits: Unknown units '" + fromUnits + "'");
            return 0;
        }
        if (!cFactors[toUnits]) {
            console.error("convertDistanceUnits: Unknown units '" + toUnits + "'");
            return 0;
        }

        // Convert to meters
        var dInMeters = distance * cFactors[fromUnits];

        // Convert to output units
        var convDistance = dInMeters / cFactors[toUnits];

        return convDistance;
    };

    measure.convertAreaUnits = function (area, fromUnits, toUnits) {
        if (fromUnits == "DecimalDegrees") {
            console.error("convertDistanceUnits: DecimalDegrees are not an area unit");
            return 0;
        }

        // Number of square meters in a unit
        var cFactors = {
            "Feet": 0.09290304,
            "Meters": 1,
            "Miles": 2589988.11,
            "Kilometers": 1000000,
            "Yards": 0.83612736,
            "Acres": 4046.85642,
            "Hectares": 10000
        };

        if (!cFactors[fromUnits]) {
            console.error("convertAreaUnits: Unknown units '" + fromUnits + "'");
            return 0;
        }
        if (!cFactors[toUnits]) {
            console.error("convertAreaUnits: Unknown units '" + toUnits + "'");
            return 0;
        }


        // Convert to meters
        var aInMeters = area * cFactors[fromUnits];

        // Convert to output units
        var convArea = aInMeters / cFactors[toUnits];

        return convArea;
    };

    measure.significantDigits = function (number, numSignificantDigits) {
        var text = number + "";
        //console.debug("significantDigits(" + text + ", " + numSignificantDigits + ")");
        var output = "";

        var bCounting = false;
        var count = 0;
        var bFoundDot = false;
        for (var i = 0; i < text.length; i++) {
            var char = text.substr(i, 1);
            bFoundDot = bFoundDot || char == ".";
            bCounting = bCounting || (char != "-" && char != "." && char != "0");

            if (bCounting && char != ".") {
                count++;
            }

            if (count == numSignificantDigits) {
                if (char == ".") {
                    break;
                }
                if (i == text.length - 1) {
                    output += char;
                }
                else {
                    var next = text.substr(i + 1, 1);
                    if (next == ".") {
                        next = text.substr(i + 2, 1);
                    }
                    var frag = char + "." + next;
                    output += Math.round(parseFloat(frag));
                }
            }
            else if (count > numSignificantDigits) {
                if (bFoundDot) {
                    break;
                }
                else {
                    output += 0;
                }
            }
            else {
                output += char;
            }
        }
        //console.debug(output);
        if (output.length > 0) {
            output = parseFloat(output);
        }
        return output;
    };

    measure.round = function (number, numPlaces) {
        //console.debug("round(" + number + ", " + numPlaces + ")");
        if (!numPlaces) { numPlaces = 0; }
        if (numPlaces > 5) { numPlaces = 5; }
        if (numPlaces < -5) { numPlaces = -5; }
        numPlaces = Math.round(numPlaces);

        //console.debug("rounding " + number + " to " + numPlaces + " places");
        var factor = Math.pow(10, numPlaces);

        return Math.round(number * factor) / factor;
    };

    return measure;

});
View Code

 

代码示例:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Label Points</title>
    <link rel="stylesheet" href="http://js.arcgis.com/3.9/js/dojo/dijit/themes/tundra/tundra.css" />
    <link rel="stylesheet" href="http://js.arcgis.com/3.9/js/esri/css/esri.css" />
    <style>
        html, body{
            padding: 0;
            margin: 0;
            width: 100%;
            height: 100%;
        }
    </style>
    <script>
        var dojoConfig = {
            packages: [{
                name: "myApp",
                location: location.pathname.replace(/\/[^/]+$/, "") + "/js/myApp"
            }]
        };    
    </script>
    <script src="http://js.arcgis.com/3.9/"></script>
    <script type="text/javascript">
        var map, tb, markerSymbol, lineSymbol, fillSymbol;
        var bMapIsDegrees = true;
        var geometryService = null;
        var displayDistUnits = "Kilometers", displayDistUnitsAbbr = "km";
        var displayAreaUnits = "Kilometers", displayAreaUnitsAbbr = "sq km";
        var fontFace = "Arial";

        require(["dojo/parser", "dijit/registry", "esri/geometry/Point",
            "esri/map", "esri/layers/ArcGISTiledMapServiceLayer", "esri/toolbars/draw", "esri/graphic", "esri/SpatialReference",
            "esri/symbols/SimpleMarkerSymbol", "esri/symbols/SimpleLineSymbol", "esri/symbols/SimpleFillSymbol",
            "esri/symbols/TextSymbol",
            "esri/Color", "esri/tasks/ProjectParameters", "esri/tasks/AreasAndLengthsParameters",
            "esri/tasks/GeometryService", "myApp/measure",
            "dojo/domReady!"],
            function (parser, registry, Point, Map, ArcGISTiledMapServiceLayer, Draw, Graphic, SpatialReference,
                SimpleMarkerSymbol, SimpleLineSymbol, SimpleFillSymbol, TextSymbol, Color, ProjectParameters,
                AreasAndLengthsParameters, GeometryService, measure) {
                parser.parse();

                map = new Map("mapDiv");
                var agoServiceURL = "http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer";
                var agoLayer = new ArcGISTiledMapServiceLayer(agoServiceURL);
                map.addLayer(agoLayer);

                markerSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 10, /**点符号**/
                          new SimpleLineSymbol(SimpleLineSymbol.STYLE_CIRCLE,
                          new Color([0, 0, 255]), 2));

                lineSymbol = new SimpleLineSymbol(SimpleLineSymbol.STYLE_DASHDOT,
                              new Color([255, 0, 0]), 2);

                fillSymbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID,
                  new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([0, 0, 0]), 2),
                  new Color([0, 0, 255, 0.5])
                );

                var geometryUrl = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer";
                geometryService = new GeometryService(geometryUrl);

                map.on("load", createToolbar);

                registry.forEach(function (d) {
                    if (d.declaredClass === "dijit.form.Button") {
                        d.on("click", activateTool);
                    }
                });

                function createToolbar(themap) {
                    toolbar = new Draw(map);
                    toolbar.on("draw-end", addToMap);
                }

                function activateTool() {
                    var tool = null;
                    switch (this.label) {
                        case "":
                            tool = "POINT";
                            break;
                        case "多点":
                            tool = "MULTIPOINT";
                            break;
                        case "线":
                            tool = "POLYLINE";
                            break;
                        case "徒手线":
                            tool = "FREEHAND_POLYLINE";
                            break;
                        case "多边形":
                            tool = "POLYGON";
                            break;
                    }
                    toolbar.activate(Draw[tool]);
                    map.hideZoomSlider();
                }

                function addToMap(evt) {
                    map.graphics.clear();

                    var geometry = evt.geometry;
                    var symbol;
                    // 将用户绘制的几何对象加入到地图中
                    switch (geometry.type) {
                        case "point":
                            symbol = markerSymbol;
                            break;
                        case "multipoint":
                            symbol = markerSymbol;
                            break;
                        case "polyline":
                            symbol = lineSymbol;
                            break;
                        case "polygon":
                            symbol = fillSymbol;
                            break;
                    }

                    var graphic = new Graphic(geometry, symbol);
                    map.graphics.add(graphic);

                    // 增加标注
                    addLabel(geometry);
                }

                function addLabel(geometry) {
                    var x, y, g;
                    switch (geometry.type) {
                        case "point":
                            x = measure.round(geometry.x, 2);
                            y = measure.round(geometry.y, 2);
                            g = getPointLabel(x + ", " + y, geometry);
                            map.graphics.add(g);
                            break;

                        case "multipoint":
                            for (var i in geometry.points) {
                                var coords = geometry.points[i];
                                x = measure.round(coords[0], 2);
                                y = measure.round(coords[1], 2);
                                g = getPointLabel(x + ", " + y, new Point(coords, geometry.spatialReference));
                                map.graphics.add(g);
                            }
                            break;

                        case "polyline":
                            if (displayDistUnits) {
                                var length = measure.calculateLength(geometry, bMapIsDegrees);
                                for (var i in geometry.paths) {
                                    if (bMapIsDegrees) {
                                        mapUnits = "Meters";
                                    }
                                    var len = measure.convertDistanceUnits(length[i], mapUnits, displayDistUnits);
                                    var text = measure.significantDigits(len, 4) + " " + displayDistUnitsAbbr;
                                    g = getPathLabel(text, geometry, i);
                                    map.graphics.add(g);
                                }
                            }
                            break;

                        case "polygon":
                            if (displayDistUnits || displayAreaUnits) {
                                var measureFunc = function (result) {
                                    for (var i in result.areas) {
                                        var perimeter = result.lengths[i];
                                        var area = result.areas[i];
                                        // 标注周长
                                        if (displayDistUnits) {
                                            var peri = measure.convertDistanceUnits(perimeter, mapUnits, displayDistUnits);
                                            var text = measure.significantDigits(peri, 4) + " " + displayDistUnitsAbbr;
                                            map.graphics.add(getPathLabel(text, geometry, i));
                                        }
                                        // 标注面积
                                        if (displayAreaUnits) {
                                            var a = measure.convertAreaUnits(area, mapUnits, displayAreaUnits);
                                            text = measure.significantDigits(a, 6) + " " + displayAreaUnitsAbbr;
                                            map.graphics.add(getAreaLabel(text, geometry, i));
                                        }
                                    }
                                };

                                var polyGraphic = new Graphic(geometry);
                                if (bMapIsDegrees) {
                                    mapUnits = "Meters";
                                    var outSR = new SpatialReference({
                                        wkid: 54034 //World_Cylindrical_Equal_Area
                                    });
                                    var params = new ProjectParameters();
                                    params.geometries = [geometry];
                                    params.outSR = outSR;

                                    geometryService.project(params, function (geometries) {
                                        var areasAndLengthParams = new AreasAndLengthsParameters();
                                        areasAndLengthParams.lengthUnit = GeometryService.UNIT_METER;
                                        areasAndLengthParams.areaUnit = GeometryService.UNIT_SQUARE_METERS;
                                        areasAndLengthParams.polygons = geometries;
                                        geometryService.areasAndLengths(areasAndLengthParams, measureFunc);
                                    });
                                }
                                else {
                                    geometryService.areasAndLengths([geometry], measureFunc);
                                }
                            }
                            break;
                    }
                }

                function getFont() {
                    var size = 18;
                    var f = new esri.symbol.Font(size + "pt",
                          esri.symbol.Font.STYLE_NORMAL,
                          esri.symbol.Font.VARIANT_NORMAL,
                          esri.symbol.Font.WEIGHT_BOLD,
                          fontFace);
                    return f;
                }

                function getPointLabel(text, point) {
                    var sym = new TextSymbol(text, getFont(), new Color([0, 0, 0]));
                    sym.setAlign(TextSymbol.ALIGN_START);
                    var g = new Graphic(point, sym);
                    return g;
                }

                function getPathLabel(text, polyline, pathIndex) {
                    try {
                        var sym = new TextSymbol(text, getFont(), new Color([0, 0, 0]));
                        if (polyline.paths) {
                            var path = polyline.paths[pathIndex];
                        }
                        else {
                            var path = polyline.rings[pathIndex];
                        }
                        var idx = Math.floor(path.length / 2);
                        var p1 = polyline.getPoint(pathIndex, idx - 1);
                        var p2 = polyline.getPoint(pathIndex, idx);
                        var point = measure.getMidPoint(p1, p2);
                        var angle = measure.getAngle(p1, p2);
                        sym.setAngle(angle);
                        sym.setOffset(0, 2);
                        var g = new Graphic(point, sym);
                        return g;
                    }
                    catch (err) {
                        console.error("创建标注出错:", err);
                    }
                }

                function getAreaLabel(text, polygon, ringIndex) {
                    try {
                        var sym = new TextSymbol(text, getFont(), new Color([0, 0, 0]));
                        var point = measure.getRingExtent(polygon, ringIndex).getCenter();
                        var g = new Graphic(point, sym);
                        return g;
                    }
                    catch (err) {
                        console.error("创建面积标注出错:", err);
                    }
                }
            }
        );
    </script>
</head>

<body class="tundra">
    <button data-dojo-type="dijit/form/Button"></button>
    <button data-dojo-type="dijit/form/Button">多点</button>
    <button data-dojo-type="dijit/form/Button">线</button>
    <button data-dojo-type="dijit/form/Button">徒手线</button>
    <button data-dojo-type="dijit/form/Button">多边形</button>
    <div id="mapDiv" style="width:900px; height:600px; border:1px solid #000;"></div>
</body>
</html>

 

posted on 2017-07-26 00:26  LuoTian  阅读(492)  评论(0编辑  收藏  举报