Source: api/SpwDrawToolbar.js

Retour à la documentation
define([
    'dojo/_base/declare',
    'dojo/_base/array',
    'dojo/_base/lang',
    'dojo/_base/connect',
    'dojo/on',
    'dojo/keys',

    'spw/api/GeometryUtils',
    'spw/api/SpwViewer',

    'esri/toolbars/draw'
], function(declare, array, lang, connect, on, keys, GeometryUtils, SpwViewer, Draw) {

    /**
     * @class spw.api.SpwDrawToolbar
     * @classdesc classe permettant d'encapsuler le widget de dessin ESRI
     * @extends {esri/toolbars/draw}
     */
    var spwdrawtoolbar = declare([Draw], {

        _angleActivated: false,
        _activated: false,

        angleStepValue: 45,
        _previousAngle: null,

        constructor: function(map) {
            on(window.document, 'keydown', lang.hitch(this, this.onKeyDown));
            on(window.document, 'keyup', lang.hitch(this, this.onKeyUp));
        },

        _onClickHandler: function(c) {
            if (this._angleActivated && this._points && this._points.length > 1) {
                var firstpt = (this._tGraphic && this._tGraphic.geometry ? this._tGraphic.geometry.getPoint(0, 1) : this._points[this._points.length - 1]);

                this._points[this._points.length - 1] = firstpt;
                this._graphic.geometry.setPoint(0, this._points.length - 1, firstpt);

                c.mapPoint = (this._tGraphic && this._tGraphic.geometry ? this._tGraphic.geometry.getPoint(0, 0) : c.mapPoint);
            }
            this.inherited(arguments);
        },

        _onMouseMoveHandler: function(c) {
            var a;

            this.map.snappingManager && (a = this.map.snappingManager._snappingPoint);

            var nbPoints = this._points.length;
            var b = this._points[nbPoints - 1];

            c = a || c.mapPoint;
            a = this._tGraphic;

            var d = a.geometry;

            if (d == null) {
                return;
            }

            switch (this._geometryType) {
                case spwdrawtoolbar.POLYLINE:
                case spwdrawtoolbar.POLYGON:
                    var previous = null;
                    var projected = null;

                    d.setPoint(0, 0, {
                        x: b.x,
                        y: b.y
                    });

                    d.setPoint(0, 1, {
                        x: c.x,
                        y: c.y
                    });

                    if (!this._angleActivated) {
                        a.setGeometry(d);
                        break;
                    }

                    if (nbPoints === 1) {
                        // chercher le graphics le plus proche
                        var minDis = Infinity;

                        var allGraphics = [].concat(SpwViewer.getInstance().get('spwMap').getMapServices({
                            visible: true,
                            type: 'DRAW_LAYER'
                        }));

                        allGraphics = [].concat.apply([], allGraphics.map(function(g) {
                            return g && g.layer ? g.layer.graphics : null;
                        }));//.concat(this.map.graphics.graphics);

                        array.forEach(allGraphics, lang.hitch(this, function(g) {
                            if (g == null || g.geometry == null || ['polyline', 'polygon'].indexOf(g.geometry.type) < 0) {
                                return false;
                            }

                            var geom = g.geometry;

                            // en fonction du type de la géometrie, trouver la ligne la plus proche...
                            var pathsOrRings = geom.paths == null ? geom.rings == null ? null : geom.rings : geom.paths;

                            array.forEach(pathsOrRings, lang.hitch(this, function(pr) {
                                if (pr == null || pr.length < 2) {
                                    return;
                                }

                                for (var i = 1; i < pr.length; ++i) {
                                    var tmpLine = new esri.geometry.Polyline(geom.spatialReference);
                                    tmpLine.addPath([pr[i-1], pr[i]]);

                                    var dis = GeometryUtils.distance(tmpLine, b);

                                    if (minDis > dis) {
                                        previous = tmpLine;
                                        minDis = dis;
                                    }
                                }
                            }));
                        }));

                        if (previous) {
                            projected = GeometryUtils.projectOnLine(previous, this._points[nbPoints-1]);
                            d.setPoint(0, 0, projected);
                        }
                    }
                    else {
                        previous = new esri.geometry.Polyline(this._points[nbPoints-2].spatialReference);
                        previous.addPath([this._points[nbPoints-2], this._points[nbPoints-1]]);

                        projected = this._points[nbPoints-1];
                    }

                    if (previous == null) {
                        a.setGeometry(d);
                        break;
                    }

                    // trouver l'angle et calculer le deuxième point en fonction de la ligne précédente
                    // et gérer le changement de distance
                    var angle = GeometryUtils.angleBetweenLines(previous, d);

                    var tmp = angle / this.angleStepValue;
                    var nearestAngle = Math.round(tmp) * this.angleStepValue;

                    var dis2 = GeometryUtils.length(d);
                    var realAngle = 180 - nearestAngle;

                    if (GeometryUtils.distance(projected, previous.getPoint(0, 0)) < 0.001) {
                        realAngle = -nearestAngle;

                        var tmpPt = previous.getPoint(0, 0);
                        previous.setPoint(0, 0, previous.getPoint(0, 1));
                        previous.setPoint(0, 1, tmpPt);
                    }
                    else {
                        previous.setPoint(0, 1, projected);
                    }

                    var rotated = GeometryUtils.rotate(previous, realAngle, previous.getPoint(0, 1));

                    var dis1 = GeometryUtils.length(rotated);
                    var dt = dis2 / dis1;

                    var pt1 = rotated.getPoint(0, 0);
                    var pt2 = rotated.getPoint(0, 1);

                    rotated.setPoint(0, 0, {
                        x: ((1 - dt) * pt2.x) + (dt * pt1.x),
                        y: ((1 - dt) * pt2.y) + (dt * pt1.y)
                    });

                    a.setGeometry(rotated);

                    this._previousAngle = nearestAngle;
                    break;

                // case spwdrawtoolbar.POLYGON:
                //     d.setPoint(0, 0, {
                //         x: b.x,
                //         y: b.y
                //     });
                //     d.setPoint(0, 1, {
                //         x: c.x,
                //         y: c.y
                //     });
                //     a.setGeometry(d);
            }

            var toSend = null;

            if (this._geometryType === spwdrawtoolbar.POLYLINE) {
                toSend = (this._graphic && this._graphic.geometry ? new esri.geometry.Polyline(this._graphic.geometry.toJson()) : null);
            }
            else if (this._geometryType === spwdrawtoolbar.POLYGON) {
                toSend = (this._graphic && this._graphic.geometry ? new esri.geometry.Polygon(this._graphic.geometry.toJson()) : null);
            }

            if (toSend && this._angleActivated && previous) {
                toSend._insertPoints([a.geometry.getPoint(0, 0)], 0);
            }
            else if (toSend) {
                toSend._insertPoints([a.geometry.getPoint(0, 1)], 0);
            }

            this.emit('mouse-move', {
                geometry: toSend
            });
        },

        /**
         * Active l'outil de dessin
         */
        activate: function() {
            this.inherited(arguments);
            this._activated = true;
        },

        /**
         * Désactive l'outil de dessin
         */
        deactivate: function() {
            this.inherited(arguments);
            this._activated = false;
        },

        /**
         * Méthode appelée lors d'un keydown sur le clavier
         * @param evt l'événement KeyDown
         */
        onKeyDown: function(evt) {
            if (['polyline', 'polygon'].indexOf(this._graphic && this._graphic.geometry ? this._graphic.geometry.type : '') > -1) {
                this._angleActivated = evt.ctrlKey;
            }
            else {
                this._angleActivated = false;
            }
        },

        /**
         * Méthode appelée lors d'un keyup sur le clavier
         * @param evt l'événement KeyUp
         */
        onKeyUp: function(evt) {
            this._angleActivated = ['polyline', 'polygon'].indexOf(this._graphic && this._graphic.geometry ? this._graphic.geometry.type : '') > -1 && evt.ctrlKey;

            if (!this._activated) {
                return;
            }

            var charOrCode = evt.charCode || evt.keyCode;

            if (charOrCode === keys.F2) {
                this.finishDrawing();
            }
            else if (evt.ctrlKey && charOrCode === 'Z'.charCodeAt(0)) {
                if ([spwdrawtoolbar.POLYLINE, spwdrawtoolbar.POLYGON].indexOf(this._geometryType) < 0) {
                    return;
                }

                this._points.pop();

                if (this._points.length === 0) {
                    connect.disconnect(this._onMouseMoveHandler_connect);
                    this._clear();
                    this._setTooltipMessage(0);
                    return;
                }

                // on vire le dernier point
                var curPath = this._graphic.geometry.type === 'polyline' ? this._graphic.geometry.paths[0] : this._graphic.geometry.rings[0];
                this._graphic.geometry.removePoint(0, curPath.length - 1);
                this._graphic.setGeometry(this._graphic.geometry).setSymbol(this.lineSymbol);

                // modification de la dernière ligne affichée
                var graph = this._tGraphic;
                var geom = graph.geometry;

                geom.setPoint(0, 0, this._points[this._points.length - 1]);
                graph.draw();
            }
        }

    });

    ["ARROW", "CIRCLE", "DOWN_ARROW", "ELLIPSE", "EXTENT", "FREEHAND_POLYGON", "FREEHAND_POLYLINE", "LEFT_ARROW", "LINE", "MULTI_POINT", "POINT", "POLYGON", "POLYLINE", "RECTANGLE", "RIGHT_ARROW", "TRIANGLE", "UP_ARROW"].forEach(function(key) {
        spwdrawtoolbar[key] = Draw[key];
    });

    return spwdrawtoolbar;

});