Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const fs = require("fs");
- const path = require("path");
- const Jimp = require("jimp");
- const chargerImagePath = path.join(__dirname, '../assets/img/charger.png');
- const robotImagePath = path.join(__dirname, '../assets/img/robot.png');
- //Define Zones for Rendering, Get Coordinates from RoborockIP/Zone/
- const ZONES = [
- [23726, 23687, 26368, 26159],
- [26355, 23700, 28046, 26133],
- [19953, 22074, 22646, 26198],
- [22646, 22425, 23583, 26224],
- [19732, 19810, 23557, 22022],
- [21501, 17832, 23596, 19979],
- [20109, 17806, 20564, 19888],
- [23492, 18860, 25131, 23765],
- [25092, 19732, 28163, 21618],
- [25756, 19029, 28124, 19823]
- ];
- //Define some Stuff for Rendering
- var allowDraw = [];
- var maxheight = 0;
- var maxwidth = 0;
- var minheight = 0;
- var minwidth = 0;
- // Enable MapCleaning or not, could removed if function like "IF Zones !=NULL than enable..."
- const enableMapCleanUp = true;
- const Tools = {
- DIMENSION_PIXELS: 1024,
- DIMENSION_MM: 50 * 1024,
- MK_DIR_PATH: function(filepath) {
- var dirname = path.dirname(filepath);
- console.log("dir" + dirname);
- console.log(filepath);
- if (!fs.existsSync(dirname)) {
- Tools.MK_DIR_PATH(dirname);
- }
- if (!fs.existsSync(filepath)) {
- fs.mkdirSync(filepath);
- }
- },
- /**
- *
- * @param options {object}
- * @param options.parsedMapData
- * @param options.settings
- * @param callback {function}
- * @constructor
- */
- //Create Table with Drawable Coordinates, all coordinats from Zones calculated
- CreateAllowToDraw: function(zones, left, top) {
- zones.forEach(function(zone) {
- zone = {
- fromx: Math.trunc(zone[0] / 50 - left),
- fromy: Math.trunc(zone[1] / 50 - top),
- tox: Math.trunc(zone[2] / 50 - left),
- toy: Math.trunc(zone[3] / 50 - top)
- }
- //Build allowDraw array and check if position already exists
- for (x = zone.fromx; x < zone.tox; x++) {
- for (y = zone.fromy; y < zone.toy; y++) {
- if (!Tools.isItemInArray([x, y])) {
- allowDraw.push([x, y]);
- }
- }
- }
- });
- //Set new Max|Min vales to shrink the map size, because some data arround the importent stuff is deleted
- maxheight = Math.max.apply(Math, allowDraw.map(function(o) { return o[1]; }));
- maxwidth = Math.max.apply(Math, allowDraw.map(function(o) { return o[0]; }));
- minheight = Math.min.apply(Math, allowDraw.map(function(o) { return o[1]; }));
- minwidth = Math.min.apply(Math, allowDraw.map(function(o) { return o[0]; }));
- maxwidth = maxwidth - minwidth;
- maxheight = maxheight - minheight;
- },
- //function to check, if current location is allowed to draw
- isItemInArray: function(item) {
- for (var i = 0; i < allowDraw.length; i++) {
- // This if statement depends on the format of your array
- if (allowDraw[i][0] == item[0] && allowDraw[i][1] == item[1]) {
- return true; // Found it
- }
- }
- return false; // Not found
- },
- //only private stuff, to trigger my Smarthome when a new map exists :) this avoids constant reloading from map.
- TriggerMapUpdate: function() {
- var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
- var Http = new XMLHttpRequest();
- const url = 'http://localhost:8083/fhem/?cmd=setReading%20Roborock%20mapURL%20http://debian:3001/api/map/image?_='+Date.now()+'&fwcsrf=&XHR=1';
- Http.open("GET", url);
- Http.send();
- },
- DRAW_MAP_PNG: function(options, callback) {
- const COLORS = {
- floor: Jimp.rgbaToInt(0, 118, 255, 255),
- obstacle_weak: Jimp.rgbaToInt(102, 153, 255, 255),
- obstacle_strong: Jimp.rgbaToInt(82, 174, 255, 255),
- path: Jimp.rgbaToInt(255, 255, 255, 255)
- };
- //Activate Drawable Coordinates creation and overwrite the max values
- if (enableMapCleanUp) {
- Tools.CreateAllowToDraw(ZONES, options.parsedMapData.image.position.left, options.parsedMapData.image.position.top);
- options.parsedMapData.image.dimensions.height = maxheight;
- options.parsedMapData.image.dimensions.width = maxwidth;
- }
- else {
- minwidth = 0;
- minheight = 0;
- };
- const DIMENSIONS = {
- width: options.parsedMapData.image.dimensions.width,
- height: options.parsedMapData.image.dimensions.height
- };
- const settings = Object.assign({
- drawPath: true,
- drawCharger: true,
- drawRobot: true,
- border: 2,
- scale: 4
- }, options.settings);
- new Jimp(DIMENSIONS.width, DIMENSIONS.height, function(err, image) {
- if (!err) {
- //Step 1: Draw Map + calculate viewport
- Object.keys(options.parsedMapData.image.pixels).forEach(key => {
- const color = COLORS[key];
- options.parsedMapData.image.pixels[key].forEach(function drawPixel(px) {
- //check if this pixel is drawable/arrange the map with min values (default min values are 0)
- if (!enableMapCleanUp || Tools.isItemInArray([px[0], px[1]])) {
- image.setPixelColor(color, px[0] - minwidth, px[1] - minheight);
- }
- })
- });
- //Step 2: Scale
- image.scale(settings.scale, Jimp.RESIZE_NEAREST_NEIGHBOR);
- //Step 3: Draw Path
- const coords = options.parsedMapData.path.points.map(point => {
- return [
- //add image arrange, to center the map and cut unused space arround the coordinates, arrange the map with min values (default min values are 0)
- Math.floor(((point[0] / 50 - options.parsedMapData.image.position.left) - minwidth) * settings.scale),
- Math.floor(((point[1] / 50 - options.parsedMapData.image.position.top) - minheight) * settings.scale)
- ]
- });
- let first = true;
- let oldPathX, oldPathY; // old Coordinates
- let dx, dy; //delta x and y
- let step, x, y, i;
- coords.forEach(function(coord) {
- if (!first && settings.drawPath) {
- dx = (coord[0] - oldPathX);
- dy = (coord[1] - oldPathY);
- if (Math.abs(dx) >= Math.abs(dy)) {
- step = Math.abs(dx);
- }
- else {
- step = Math.abs(dy);
- }
- dx = dx / step;
- dy = dy / step;
- x = oldPathX;
- y = oldPathY;
- i = 1;
- while (i <= step) {
- image.setPixelColor(COLORS.path, x, y);
- x = x + dx;
- y = y + dy;
- i = i + 1;
- }
- }
- oldPathX = coord[0];
- oldPathY = coord[1];
- first = false;
- });
- Jimp.read(chargerImagePath, function(err, chargerImage) {
- if (!err) {
- Jimp.read(robotImagePath, function(err, robotImage) {
- if (!err) {
- //Step 6: Draw Charger
- if (settings.drawCharger === true && options.parsedMapData.charger) {
- const chargerCoords = {
- //add image arrange, to center the map and cut unused space arround the coordinates, arrange the map with min values (default min values are 0)
- x: (options.parsedMapData.charger[0] / 50 - options.parsedMapData.image.position.left) - minwidth,
- y: (options.parsedMapData.charger[1] / 50 - options.parsedMapData.image.position.top) - minheight
- };
- image.composite(
- chargerImage,
- chargerCoords.x * settings.scale - chargerImage.bitmap.width / 2,
- chargerCoords.y * settings.scale - chargerImage.bitmap.height / 2
- );
- }
- //Step 7: Draw Robot
- if (settings.drawRobot === true && options.parsedMapData.robot) {
- const robotCoords = {
- //add image arrange, to center the map and cut unused space arround the coordinates, arrange the map with min values (default min values are 0)
- x: (options.parsedMapData.robot[0] / 50 - options.parsedMapData.image.position.left) - minwidth,
- y: (options.parsedMapData.robot[1] / 50 - options.parsedMapData.image.position.top) - minheight
- };
- image.composite(
- robotImage.rotate(-1 * options.parsedMapData.path.current_angle - 90),
- robotCoords.x * settings.scale - robotImage.bitmap.width / 2,
- robotCoords.y * settings.scale - robotImage.bitmap.height / 2
- )
- }
- image.getBuffer(Jimp.AUTO, callback);
- Tools.TriggerMapUpdate();
- }
- else {
- callback(err);
- }
- })
- }
- else {
- callback(err);
- }
- });
- }
- else {
- callback(err);
- }
- });
- }
- };
- module.exports = Tools;
Advertisement
Add Comment
Please, Sign In to add comment