├── .gitignore ├── utils ├── package.json ├── .jshintrc ├── Gruntfile.js └── README.md ├── src ├── RosMap.js └── Editor │ ├── EditorMap.js │ └── Editor.js ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rosmapjs", 3 | "devDependencies": { 4 | "grunt": ">=1.3.0", 5 | "grunt-contrib-concat": "~0.1.3", 6 | "grunt-contrib-jshint": "~0.1.1", 7 | "grunt-karma": ">=4.0.1", 8 | "grunt-contrib-watch": "~0.3.1", 9 | "grunt-contrib-uglify": "~0.2.0", 10 | "grunt-jsdoc": "~0.3.0", 11 | "grunt-contrib-clean": "~0.4.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /utils/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "globals": { 3 | "module": true, 4 | "EventEmitter2": true, 5 | "ROSLIB": true, 6 | "ROS2D": true, 7 | "createjs": true 8 | }, 9 | "curly": true, 10 | "eqeqeq": true, 11 | "immed": true, 12 | "latedef": false, 13 | "newcap": true, 14 | "noarg": true, 15 | "sub": true, 16 | "undef": true, 17 | "boss": false, 18 | "eqnull": false, 19 | "browser": true, 20 | "devel": true, 21 | "es5": true, 22 | "strict": false, 23 | "trailing": true, 24 | "quotmark": "single", 25 | "proto": true, 26 | "laxbreak": true 27 | } 28 | 29 | -------------------------------------------------------------------------------- /src/RosMap.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Raffaello Bonghi raffaello.bonghi@officinerobotiche.it 3 | */ 4 | 5 | var ROSMAP = ROSMAP || { 6 | REVISION: '0.0.2' 7 | }; 8 | 9 | ROSMAP.VALUE_OBSTACLE = 100; 10 | ROSMAP.VALUE_FREE_SPACE = 0; 11 | ROSMAP.VALUE_UNKNOWN = -1; 12 | ROSMAP.VALUE_UNWRITTEN = 120; 13 | 14 | /** 15 | * 16 | */ 17 | Array.prototype.repeat = function(what, L){ 18 | while(L) { 19 | this[--L]= what; 20 | } 21 | return this; 22 | }; 23 | 24 | /** 25 | * 26 | */ 27 | ROSMAP.square = function(options) { 28 | options = options || {}; 29 | var map = options.EditorMap; 30 | var color = options.color || 'red'; 31 | var lineWidth = options.lineWidth; 32 | 33 | var width = map.width/map.scaleX; 34 | var height = map.height/map.scaleY; 35 | map.context.beginPath(); 36 | map.context.lineWidth = lineWidth; 37 | map.context.rect(map.context.lineWidth/2, map.context.lineWidth/2, 38 | width-map.context.lineWidth, height-map.context.lineWidth); 39 | map.context.strokeStyle = color; 40 | map.context.stroke(); 41 | }; 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Software License Agreement (BSD License) 2 | 3 | Copyright (c) 2015, Worcester Polytechnic Institute. 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above 13 | copyright notice, this list of conditions and the following 14 | disclaimer in the documentation and/or other materials provided 15 | with the distribution. 16 | * Neither the name of Worcester Polytechnic Institute nor the 17 | names of its contributors may be used to endorse or promote 18 | products derived from this software without specific prior 19 | written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | rosmap 2 | ======= 3 | 4 | #### ROS Map controller 5 | 6 | ### Usage 7 | Pre-built files can be found in either [rosmap.js](build/rosmap.js) or [rosmap.min.js](build/rosmap.min.js). 8 | 9 | ### Dependencies 10 | rosmap depends on: 11 | 12 | [EventEmitter2](https://github.com/hij1nx/EventEmitter2). The current supported version is 0.4.14. The current supported version can be found on the Robot Web Tools CDN ([full](http://cdn.robotwebtools.org/EventEmitter2/0.4.14/eventemitter2.js)) | ([min](http://cdn.robotwebtools.org/EventEmitter2/0.4.14/eventemitter2.min.js)) 13 | 14 | [roslibjs](https://github.com/RobotWebTools/roslibjs). The current supported version is 0.14.0. The current supported version can be found on the Robot Web Tools CDN: ([full](http://cdn.robotwebtools.org/roslibjs/0.14.0/roslib.js)) | ([min](http://cdn.robotwebtools.org/roslibjs/0.14.0/roslib.min.js)) 15 | 16 | [EaselJS](https://github.com/CreateJS/EaselJS/). The current supported version is 0.7.1. The current supported version can be found on the Robot Web Tools CDN: ([full](http://cdn.robotwebtools.org/EaselJS/0.7.1/easeljs.js)) | ([min](http://cdn.robotwebtools.org/EaselJS/0.7.1/easeljs.min.js)) 17 | 18 | [ros2djs](https://github.com/RobotWebTools/ros2djs). The current supported version is 0.6.0. The current supported version can be found on the Robot Web Tools CDN: ([full](http://cdn.robotwebtools.org/ros2djs/0.6.0/ros2d.js)) | ([min](http://cdn.robotwebtools.org/ros2djs/0.6.0/ros2d.min.js)) 19 | 20 | ### Build 21 | Checkout [utils/README.md](utils/README.md) for details on building. 22 | 23 | ### License 24 | rosmap is released with a BSD license. For full terms and conditions, see the [LICENSE](LICENSE) file. 25 | 26 | ### Authors 27 | See the [AUTHORS.md](AUTHORS) file for a full list of contributors. 28 | 29 | -------------------------------------------------------------------------------- /utils/Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | 3 | grunt.initConfig({ 4 | pkg: grunt.file.readJSON('package.json'), 5 | concat: { 6 | build: { 7 | src : ['../src/*.js', '../src/**/*.js'], 8 | dest : '../build/rosmap.js' 9 | } 10 | }, 11 | jshint: { 12 | options: { 13 | jshintrc: '.jshintrc' 14 | }, 15 | files: [ 16 | 'Gruntfile.js', 17 | '../build/rosmap.js' 18 | ] 19 | }, 20 | karma: { 21 | build: { 22 | configFile: '../test/karma.conf.js', 23 | singleRun: true, 24 | browsers: ['PhantomJS'] 25 | } 26 | }, 27 | uglify: { 28 | options: { 29 | report: 'min' 30 | }, 31 | build: { 32 | src: '../build/rosmap.js', 33 | dest: '../build/rosmap.min.js' 34 | } 35 | }, 36 | watch: { 37 | dev: { 38 | options: { 39 | interrupt: true 40 | }, 41 | files: [ 42 | '../src/*.js', 43 | '../src/**/*.js' 44 | ], 45 | tasks: ['concat'] 46 | }, 47 | build_and_watch: { 48 | options: { 49 | interrupt: true 50 | }, 51 | files: [ 52 | 'Gruntfile.js', 53 | '.jshintrc', 54 | '../src/*.js', 55 | '../src/**/*.js' 56 | ], 57 | tasks: ['build'] 58 | } 59 | }, 60 | clean: { 61 | options: { 62 | force: true 63 | }, 64 | doc: ['../doc'] 65 | }, 66 | jsdoc: { 67 | doc: { 68 | src: [ 69 | '../src/*.js', 70 | '../src/**/*.js' 71 | ], 72 | options: { 73 | destination: '../doc' 74 | } 75 | } 76 | } 77 | }); 78 | 79 | grunt.loadNpmTasks('grunt-contrib-concat'); 80 | grunt.loadNpmTasks('grunt-contrib-jshint'); 81 | grunt.loadNpmTasks('grunt-contrib-watch'); 82 | grunt.loadNpmTasks('grunt-contrib-uglify'); 83 | grunt.loadNpmTasks('grunt-contrib-clean'); 84 | grunt.loadNpmTasks('grunt-jsdoc'); 85 | grunt.loadNpmTasks('grunt-karma'); 86 | 87 | grunt.registerTask('dev', ['concat', 'watch']); 88 | grunt.registerTask('build', ['concat', 'jshint', 'uglify']); 89 | grunt.registerTask('build_and_watch', ['watch']); 90 | grunt.registerTask('doc', ['clean', 'jsdoc']); 91 | }; 92 | -------------------------------------------------------------------------------- /utils/README.md: -------------------------------------------------------------------------------- 1 | nav2djs Build Setup 2 | =================== 3 | 4 | [Grunt](http://gruntjs.com/) is used for building, including concatenating, minimizing, documenting, linting, and testing. 5 | 6 | ### Install Grunt and its Dependencies 7 | 8 | #### Ubuntu 14.04 9 | 10 | 1. Install Node.js and its package manager, NPM 11 | * `sudo apt-get install nodejs npm` 12 | * `sudo ln -s /usr/bin/nodejs /usr/bin/node` 13 | 2. Install Grunt 14 | * `sudo npm install -g grunt-cli` 15 | * `sudo rm -rf ~/.npm ~/tmp` 16 | 3. Install the Grunt tasks specific to this project 17 | * `cd /path/to/nav2djs/utils/` 18 | * `npm install .` 19 | 4. (Optional) To generate the documentation, you'll need to setup Java. Documentation generation is not required for patches. 20 | * `echo "export JAVA_HOME=/usr/lib/jvm/default-java/jre" >> ~/.bashrc` 21 | * `source ~/.bashrc` 22 | 23 | #### Ubuntu 12.04 24 | 25 | 1. Install Node.js and its package manager, NPM 26 | * `sudo apt-get install python-software-properties` 27 | * `sudo add-apt-repository ppa:chris-lea/node.js` 28 | * `sudo apt-get update && sudo apt-get install nodejs phantomjs` 29 | 2. Install Grunt 30 | * `sudo npm install -g grunt-cli` 31 | * `sudo rm -rf ~/.npm ~/tmp` 32 | 3. Install the Grunt tasks specific to this project 33 | * `cd /path/to/nav2djs/utils/` 34 | * `npm install .` 35 | 4. (Optional) To generate the documentation, you'll need to setup Java. Documentation generation is not required for patches. 36 | * `echo "export JAVA_HOME=/usr/lib/jvm/default-java/jre" >> ~/.bashrc` 37 | * `source ~/.bashrc` 38 | 39 | #### OS X 40 | 41 | 1. Install Node.js and its package manager, NPM 42 | * Go to [Node.js Downloads](http://nodejs.org/download/) 43 | * Download and install the Universal pkg file. 44 | 2. Install Grunt and the test runner [Karma](http://karma-runner.github.io/) 45 | * `sudo npm install -g grunt-cli karma` 46 | 3. Install the Grunt tasks specific to this project 47 | * `cd /path/to/nav2djs/utils/` 48 | * `npm install .` 49 | 50 | ### Build with Grunt 51 | 52 | Before proceeding, please confirm you have installed the dependencies above. 53 | 54 | To run the build tasks: 55 | 56 | 1. `cd /path/to/nav2djs/utils/` 57 | 2. `grunt build` 58 | 59 | `grunt build` will concatenate and minimize the files under src and replace nav2d.js and nav2d.min.js in the build directory. It will also run the linter and test cases. This is what [Travis CI](https://travis-ci.org/RobotWebTools/nav2djs) runs when a Pull Request is submitted. 60 | 61 | `grunt dev` will watch for any changes to any of the src/ files and automatically concatenate and minimize the files. This is ideal for those developing as you should only have to run `grunt dev` once. 62 | 63 | `grunt doc` will rebuild all JSDoc for the project. 64 | 65 | -------------------------------------------------------------------------------- /src/Editor/EditorMap.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Raffaello Bonghi raffaello.bonghi@officinerobotiche.it 3 | */ 4 | 5 | /** 6 | * 7 | */ 8 | ROSMAP.EditorMap = function(options) { 9 | options = options || {}; 10 | var rootObject = options.rootObject; 11 | var currentGrid = options.currentGrid; 12 | 13 | // internal drawing canvas 14 | this.canvas = document.createElement('canvas'); 15 | this.context = this.canvas.getContext('2d'); 16 | 17 | if (typeof currentGrid.width !== 'undefined') { 18 | this.width = currentGrid.width/currentGrid.scaleX; 19 | this.height = currentGrid.height/currentGrid.scaleY; 20 | } else { 21 | this.width = rootObject.canvas.width; 22 | this.height = rootObject.canvas.height; 23 | } 24 | this.canvas.width = this.width; 25 | this.canvas.height = this.height; 26 | 27 | //TODO improve with use Stage 28 | //this.stage = new createjs.Stage(canvas); 29 | // create the bitmap 30 | createjs.Bitmap.call(this, this.canvas); 31 | // change Y direction 32 | this.y = -this.height * currentGrid.scaleX; 33 | 34 | this.scaleX = currentGrid.scaleX; 35 | this.scaleY = currentGrid.scaleY; 36 | 37 | this.width *= this.scaleX; 38 | this.height *= this.scaleY; 39 | if (typeof currentGrid.width !== 'undefined') { 40 | this.x += currentGrid.pose.position.x; 41 | this.y -= currentGrid.pose.position.y; 42 | } 43 | }; 44 | ROSMAP.EditorMap.prototype.__proto__ = createjs.Bitmap.prototype; 45 | 46 | /** 47 | * 48 | * 49 | */ 50 | ROSMAP.EditorMap.prototype.updateSize = function(currentGrid) { 51 | var that = this; 52 | var canvasPic = new Image(); 53 | canvasPic.src = this.canvas.toDataURL(); 54 | 55 | this.width = currentGrid.width/currentGrid.scaleX; 56 | this.height = currentGrid.height/currentGrid.scaleY; 57 | this.canvas.width = that.width; 58 | this.canvas.height = that.height; 59 | 60 | this.y = -this.height * currentGrid.scaleX; 61 | 62 | this.scaleX = currentGrid.scaleX; 63 | this.scaleY = currentGrid.scaleY; 64 | 65 | this.width *= this.scaleX; 66 | this.height *= this.scaleY; 67 | 68 | this.x = currentGrid.pose.position.x; 69 | this.y -= currentGrid.pose.position.y; 70 | 71 | canvasPic.onload = function () { 72 | that.context.drawImage(canvasPic, 0, 0); 73 | }; 74 | }; 75 | 76 | /** 77 | * 78 | */ 79 | ROSMAP.EditorMap.prototype.getMatrix = function() { 80 | var widthPX = this.width/this.scaleX; 81 | var heightPX = this.height/this.scaleY; 82 | // Get image matrix 83 | var imageData = this.context.getImageData(0, 0, widthPX, heightPX); 84 | //TODO use this function if you use Stage 85 | //var imageData = this.stage.canvas.getContext('2d').getImageData(0, 0, widthPX, heightPX); 86 | var data = []; 87 | // Flip map matrix on y axis 88 | for (var y = heightPX; y > 0; y--) { 89 | for (var x = 0; x < widthPX; x++) { 90 | var i = (widthPX*y + x) * 4; 91 | // Check if alpha value is zero 92 | if(imageData.data[i + 3] === 0) { 93 | data.push(ROSMAP.VALUE_UNWRITTEN); 94 | } else { 95 | switch(imageData.data[i]) { 96 | // Obstacle 97 | case 0: 98 | data.push(ROSMAP.VALUE_OBSTACLE); 99 | break; 100 | // Free space 101 | case 255: 102 | data.push(ROSMAP.VALUE_FREE_SPACE); 103 | break; 104 | // Unknown 105 | default: 106 | data.push(ROSMAP.VALUE_UNKNOWN); 107 | break; 108 | } 109 | } 110 | } 111 | } 112 | return data; 113 | }; 114 | 115 | /** 116 | * 117 | */ 118 | ROSMAP.EditorMap.prototype.clearMap = function() { 119 | this.context.clearRect(0, 0, this.width/this.scaleX, this.height/this.scaleY); 120 | }; 121 | -------------------------------------------------------------------------------- /src/Editor/Editor.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Raffaello Bonghi raffaello.bonghi@officinerobotiche.it 3 | */ 4 | 5 | /** 6 | * Build a map editor 7 | * 8 | * @constructor 9 | * @param options - object with following keys: 10 | * * ros - the ROSLIB.Ros connection handle 11 | * * client - The occupancy Grid client 12 | * * topic (optional) - the map meta data topic to listen to 13 | * * rootObject (optional) - the root object to add this marker to 14 | * * strokeSize (optional) - stroke for the pen editor 15 | * * strokeColor (optional) - Color for the pen 16 | */ 17 | ROSMAP.Editor = function(options) { 18 | var that = this; 19 | options = options || {}; 20 | var client = options.client || null; 21 | var ros = options.ros; 22 | var mapeditortopic = options.topic || '/map_editor'; 23 | var start_index = options.index || 0; 24 | this.rootObject = options.rootObject || new createjs.Container(); 25 | // Draw information 26 | this.strokeSize = options.strokeSize || 1; 27 | this.strokeColor = options.strokeColor || createjs.Graphics.getRGB(0, 0, 0); 28 | 29 | // subscribe to the topic 30 | var mapEditorTopic = new ROSLIB.Topic({ 31 | ros : ros, 32 | name : mapeditortopic, 33 | messageType : 'nav_msgs/OccupancyGrid', 34 | //compression : 'png' 35 | }); 36 | var map_message = new ROSLIB.Message({ 37 | header : { 38 | seq: 0, 39 | stamp : {secs : 0, nsecs : 100}, 40 | frame_id: '' 41 | }, 42 | info : { 43 | map_load_time: {secs : 0, nsecs : 100}, 44 | resolution: 0, 45 | width: 0, 46 | height: 0, 47 | origin: 0, 48 | }, 49 | data : 0 50 | }); 51 | 52 | var pressed = false; 53 | // Map information 54 | this.map = new createjs.Shape(); 55 | this.cPushArray = []; 56 | this.cStep = -1; 57 | // Add in client 58 | this.rootObject.addChildAt(this.map, start_index); 59 | this.index = that.rootObject.getChildIndex(this.map); 60 | // Border 61 | this.frameBorder = new ROSMAP.EditorMap({ 62 | rootObject: this.rootObject, 63 | currentGrid: client.currentGrid 64 | }); 65 | this.rootObject.addChildAt(this.frameBorder, start_index+1); 66 | 67 | // Points 68 | var oldPt; 69 | var oldMidPt; 70 | 71 | var cPush = function(dataImage) { 72 | that.cStep++; 73 | if (that.cStep < that.cPushArray.length) { that.cPushArray.length = that.cStep; } 74 | that.cPushArray.push(dataImage.toDataURL()); 75 | }; 76 | 77 | this.sendMap = function() { 78 | map_message.data = this.map.getMatrix(); 79 | //Send Map message 80 | mapEditorTopic.publish(map_message); 81 | }; 82 | 83 | client.on('change', function() { 84 | //Prepare ROS message 85 | map_message.info.resolution = client.currentGrid.scaleX; 86 | map_message.info.width = client.currentGrid.width/client.currentGrid.scaleX; 87 | map_message.info.height = client.currentGrid.height/client.currentGrid.scaleY; 88 | map_message.info.origin = client.currentGrid.pose; 89 | // Add frame border 90 | that.frameBorder.updateSize(client.currentGrid); 91 | //that.rootObject.removeChild(that.frameBorder); 92 | //that.frameBorder = new ROSMAP.EditorMap({ 93 | // currentGrid: client.currentGrid 94 | //}); 95 | //that.rootObject.addChildAt(that.frameBorder, that.index+1); 96 | // Add editor map 97 | that.rootObject.removeChild(that.map); 98 | that.map = new ROSMAP.EditorMap({ 99 | currentGrid: client.currentGrid 100 | }); 101 | that.rootObject.addChildAt(that.map, that.index); 102 | // Add in history 103 | cPush(that.map.canvas); 104 | }); 105 | 106 | var handleMouseMove = function(event) { 107 | if (!event.primary) { return; } 108 | var position = that.rootObject.globalToRos(event.stageX, -event.stageY); 109 | position.x = (position.x - that.map.x)/that.map.scaleX; 110 | position.y = (position.y + that.map.y)/that.map.scaleY; 111 | var midPt = new createjs.Point(oldPt.x + position.x >> 1, oldPt.y + position.y >> 1); 112 | 113 | //console.log("OLD [" + oldPt.x + "," + oldPt.y + "] - MID [" + oldMidPt.x + "," + oldMidPt.y + "]"); 114 | 115 | that.map.context.beginPath(); 116 | that.map.context.moveTo(midPt.x, midPt.y); 117 | that.map.context.quadraticCurveTo(oldPt.x, oldPt.y, oldMidPt.x, oldMidPt.y); 118 | that.map.context.lineWidth = that.strokeSize; 119 | that.map.context.strokeStyle = that.strokeColor; 120 | that.map.context.stroke(); 121 | that.map.context.lineCap = 'round'; 122 | /// Update all points 123 | oldPt.x = position.x; 124 | oldPt.y = position.y; 125 | oldMidPt.x = midPt.x; 126 | oldMidPt.y = midPt.y; 127 | }; 128 | 129 | this.handleMouseUp = function(event) { 130 | if(!pressed) { return; } 131 | else { pressed = false; } 132 | if (!event.primary) { return; } 133 | that.rootObject.removeEventListener('stagemousemove', handleMouseMove); 134 | // Save old map 135 | cPush(that.map.canvas); 136 | 137 | that.sendMap(); 138 | //that.map_message.data = that.map.getMatrix(); 139 | //Send Map message 140 | //that.mapEditorTopic.publish(map_message); 141 | }; 142 | 143 | this.handleMouseDown = function(event) { 144 | if(!pressed) { pressed = true; } 145 | if (!event.primary) { return; } 146 | var position = that.rootObject.globalToRos(event.stageX, -event.stageY); 147 | position.x = (position.x - that.map.x)/that.map.scaleX; 148 | position.y = (position.y + that.map.y)/that.map.scaleY; 149 | oldPt = new createjs.Point(position.x, position.y); 150 | oldMidPt = oldPt.clone(); 151 | that.rootObject.addEventListener('stagemousemove', handleMouseMove); 152 | }; 153 | 154 | // Add listener 155 | this.rootObject.addEventListener('stagemousedown', this.handleMouseDown); 156 | this.rootObject.addEventListener('stagemouseup', this.handleMouseUp); 157 | }; 158 | 159 | /** 160 | * load last draw 161 | */ 162 | ROSMAP.Editor.prototype.undo = function() { 163 | if (this.cStep > 0) { 164 | var that = this; 165 | this.cStep--; 166 | var canvasPic = new Image(); 167 | canvasPic.src = this.cPushArray[this.cStep]; 168 | canvasPic.onload = function () { 169 | that.map.clearMap(); 170 | that.map.context.drawImage(canvasPic, 0, 0); 171 | that.sendMap(); 172 | }; 173 | } 174 | }; 175 | 176 | /** 177 | * 178 | */ 179 | ROSMAP.Editor.prototype.redo = function() { 180 | if (this.cStep < this.cPushArray.length-1) { 181 | var that = this; 182 | this.cStep++; 183 | var canvasPic = new Image(); 184 | canvasPic.src = this.cPushArray[this.cStep]; 185 | canvasPic.onload = function () { 186 | that.map.clearMap(); 187 | that.map.context.drawImage(canvasPic, 0, 0); 188 | that.sendMap(); 189 | }; 190 | } 191 | }; 192 | 193 | /** 194 | * Enable or disable draw controller 195 | */ 196 | ROSMAP.Editor.prototype.enable = function(enable) { 197 | if(enable) { 198 | // Draw square 199 | ROSMAP.square({ 200 | EditorMap: this.frameBorder, 201 | color: 'blue', 202 | lineWidth: 5 203 | }); 204 | this.rootObject.addEventListener('stagemousedown', this.handleMouseDown); 205 | this.rootObject.addEventListener('stagemouseup', this.handleMouseUp); 206 | } else { 207 | if(this.frameBorder !== null) { this.frameBorder.clearMap(); } 208 | this.rootObject.removeEventListener('stagemousedown', this.handleMouseDown); 209 | this.rootObject.removeEventListener('stagemouseup', this.handleMouseDown); 210 | } 211 | }; 212 | --------------------------------------------------------------------------------