Skip to content

Instantly share code, notes, and snippets.

@LuisSevillano
Created February 9, 2017 15:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LuisSevillano/a3810c934666b307c1a646ac85d546e7 to your computer and use it in GitHub Desktop.
Save LuisSevillano/a3810c934666b307c1a646ac85d546e7 to your computer and use it in GitHub Desktop.
Geo2rect test using nmap

Test using geo2rect and nmap. Dont know how to use nmap to extract a well-look grid.
Now I'm taking those coordinates from the bounding box of each map path but obviously there are some space betweet rects. Any idea?
The map shows the districts of Madrid, Spain.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2008 Google Inc. All Rights Reserved.
// http://www.hobsonassoc.com/scripts/closure/goog/docs/class_goog_graphics_AffineTransform.html
/**
* @fileoverview Provides an object representation of an AffineTransform and
* methods for working with it.
*/
var goog = {
isNumber : function(val) {
return typeof val == 'number';
},
graphics:{
AffineTransform:null
}
};
/**
* Creates a 2D affine transform. An affine transform performs a linear
* mapping from 2D coordinates to other 2D coordinates that preserves the
* "straightness" and "parallelness" of lines.
*
* Such a coordinate transformation can be represented by a 3 row by 3 column
* matrix with an implied last row of [ 0 0 1 ]. This matrix transforms source
* coordinates (x,y) into destination coordinates (x',y') by considering them
* to be a column vector and multiplying the coordinate vector by the matrix
* according to the following process:
* <pre>
* [ x'] [ m00 m01 m02 ] [ x ] [ m00x + m01y + m02 ]
* [ y'] = [ m10 m11 m12 ] [ y ] = [ m10x + m11y + m12 ]
* [ 1 ] [ 0 0 1 ] [ 1 ] [ 1 ]
* </pre>
*
* This class is optimized for speed and minimizes calculations based on its
* knowledge of the underlying matrix (as opposed to say simply performing
* matrix multiplication).
*
* @param {number} opt_m00 The m00 coordinate of the transform.
* @param {number} opt_m10 The m10 coordinate of the transform.
* @param {number} opt_m01 The m01 coordinate of the transform.
* @param {number} opt_m11 The m11 coordinate of the transform.
* @param {number} opt_m02 The m02 coordinate of the transform.
* @param {number} opt_m12 The m12 coordinate of the transform.
* @constructor
*/
goog.graphics.AffineTransform = function(opt_m00, opt_m10, opt_m01,
opt_m11, opt_m02, opt_m12) {
if (arguments.length == 6) {
this.setTransform(/** @type {number} */ (opt_m00),
/** @type {number} */ (opt_m10),
/** @type {number} */ (opt_m01),
/** @type {number} */ (opt_m11),
/** @type {number} */ (opt_m02),
/** @type {number} */ (opt_m12));
} else if (arguments.length != 0) {
throw Error('Insufficient matrix parameters');
} else {
this.m00_ = this.m11_ = 1;
this.m10_ = this.m01_ = this.m02_ = this.m12_ = 0;
}
};
/**
* @return {boolean} Whether this transform is the identity transform.
*/
goog.graphics.AffineTransform.prototype.isIdentity = function() {
return this.m00_ == 1 && this.m10_ == 0 && this.m01_ == 0 &&
this.m11_ == 1 && this.m02_ == 0 && this.m12_ == 0;
};
/**
* @return {!goog.graphics.AffineTransform} A copy of this transform.
*/
goog.graphics.AffineTransform.prototype.clone = function() {
return new goog.graphics.AffineTransform(this.m00_, this.m10_, this.m01_,
this.m11_, this.m02_, this.m12_);
};
/**
* Sets this transform to the matrix specified by the 6 values.
*
* @param {number} m00 The m00 coordinate of the transform.
* @param {number} m10 The m10 coordinate of the transform.
* @param {number} m01 The m01 coordinate of the transform.
* @param {number} m11 The m11 coordinate of the transform.
* @param {number} m02 The m02 coordinate of the transform.
* @param {number} m12 The m12 coordinate of the transform.
* @return {!goog.graphics.AffineTransform} This affine transform.
*/
goog.graphics.AffineTransform.prototype.setTransform = function(m00, m10, m01,
m11, m02, m12) {
if (!goog.isNumber(m00) || !goog.isNumber(m10) || !goog.isNumber(m01) ||
!goog.isNumber(m11) || !goog.isNumber(m02) || !goog.isNumber(m12)) {
throw Error('Invalid transform parameters');
}
this.m00_ = m00;
this.m10_ = m10;
this.m01_ = m01;
this.m11_ = m11;
this.m02_ = m02;
this.m12_ = m12;
return this;
};
/**
* Sets this transform to be identical to the given transform.
*
* @param {!goog.graphics.AffineTransform} tx The transform to copy.
* @return {!goog.graphics.AffineTransform} This affine transform.
*/
goog.graphics.AffineTransform.prototype.copyFrom = function(tx) {
this.m00_ = tx.m00_;
this.m10_ = tx.m10_;
this.m01_ = tx.m01_;
this.m11_ = tx.m11_;
this.m02_ = tx.m02_;
this.m12_ = tx.m12_;
return this;
};
/**
* Concatentates this transform with a scaling transformation.
*
* @param {number} sx The x-axis scaling factor.
* @param {number} sy The y-axis scaling factor.
* @return {!goog.graphics.AffineTransform} This affine transform.
*/
goog.graphics.AffineTransform.prototype.scale = function(sx, sy) {
this.m00_ *= sx;
this.m10_ *= sx;
this.m01_ *= sy;
this.m11_ *= sy;
return this;
};
/**
* Concatentates this transform with a translate transformation.
*
* @param {number} dx The distance to translate in the x direction.
* @param {number} dy The distance to translate in the y direction.
* @return {!goog.graphics.AffineTransform} This affine transform.
*/
goog.graphics.AffineTransform.prototype.translate = function(dx, dy) {
this.m02_ += dx * this.m00_ + dy * this.m01_;
this.m12_ += dx * this.m10_ + dy * this.m11_;
return this;
};
/**
* Concatentates this transform with a rotation transformation around an anchor
* point.
*
* @param {number} theta The angle of rotation measured in radians.
* @param {number} x The x coordinate of the anchor point.
* @param {number} y The y coordinate of the anchor point.
* @return {!goog.graphics.AffineTransform} This affine transform.
*/
goog.graphics.AffineTransform.prototype.rotate = function(theta, x, y) {
return this.concatenate(
goog.graphics.AffineTransform.getRotateInstance(theta, x, y));
};
/**
* Concatentates this transform with a shear transformation.
*
* @param {number} shx The x shear factor.
* @param {number} shy The y shear factor.
* @return {!goog.graphics.AffineTransform} This affine transform.
*/
goog.graphics.AffineTransform.prototype.shear = function(shx, shy) {
var m00 = this.m00_;
var m10 = this.m10_;
this.m00_ += shy * this.m01_;
this.m10_ += shy * this.m11_;
this.m01_ += shx * m00;
this.m11_ += shx * m10;
return this;
};
/**
* @return {string} A string representation of this transform. The format of
* of the string is compatible with SVG matrix notation, i.e.
* "matrix(a,b,c,d,e,f)".
*/
goog.graphics.AffineTransform.prototype.toString = function() {
return 'matrix(' + [this.m00_, this.m10_, this.m01_, this.m11_,
this.m02_, this.m12_].join(',') + ')';
};
/**
* @return {number} The scaling factor in the x-direction (m00).
*/
goog.graphics.AffineTransform.prototype.getScaleX = function() {
return this.m00_;
};
/**
* @return {number} The scaling factor in the y-direction (m11).
*/
goog.graphics.AffineTransform.prototype.getScaleY = function() {
return this.m11_;
};
/**
* @return {number} The translation in the x-direction (m02).
*/
goog.graphics.AffineTransform.prototype.getTranslateX = function() {
return this.m02_;
};
/**
* @return {number} The translation in the y-direction (m12).
*/
goog.graphics.AffineTransform.prototype.getTranslateY = function() {
return this.m12_;
};
/**
* @return {number} The shear factor in the x-direction (m01).
*/
goog.graphics.AffineTransform.prototype.getShearX = function() {
return this.m01_;
};
/**
* @return {number} The shear factor in the y-direction (m10).
*/
goog.graphics.AffineTransform.prototype.getShearY = function() {
return this.m10_;
};
/**
* Concatenates an affine transform to this transform.
*
* @param {!goog.graphics.AffineTransform} tx The transform to concatenate.
* @return {!goog.graphics.AffineTransform} This affine transform.
*/
goog.graphics.AffineTransform.prototype.concatenate = function(tx) {
var m0 = this.m00_;
var m1 = this.m01_;
this.m00_ = tx.m00_ * m0 + tx.m10_ * m1;
this.m01_ = tx.m01_ * m0 + tx.m11_ * m1;
this.m02_ += tx.m02_ * m0 + tx.m12_ * m1;
m0 = this.m10_;
m1 = this.m11_;
this.m10_ = tx.m00_ * m0 + tx.m10_ * m1;
this.m11_ = tx.m01_ * m0 + tx.m11_ * m1;
this.m12_ += tx.m02_ * m0 + tx.m12_ * m1;
return this;
};
/**
* Pre-concatenates an affine transform to this transform.
*
* @param {!goog.graphics.AffineTransform} tx The transform to preconcatenate.
* @return {!goog.graphics.AffineTransform} This affine transform.
*/
goog.graphics.AffineTransform.prototype.preConcatenate = function(tx) {
var m0 = this.m00_;
var m1 = this.m10_;
this.m00_ = tx.m00_ * m0 + tx.m01_ * m1;
this.m10_ = tx.m10_ * m0 + tx.m11_ * m1;
m0 = this.m01_;
m1 = this.m11_;
this.m01_ = tx.m00_ * m0 + tx.m01_ * m1;
this.m11_ = tx.m10_ * m0 + tx.m11_ * m1;
m0 = this.m02_;
m1 = this.m12_;
this.m02_ = tx.m00_ * m0 + tx.m01_ * m1 + tx.m02_;
this.m12_ = tx.m10_ * m0 + tx.m11_ * m1 + tx.m12_;
return this;
};
/**
* Transforms an array of coordinates by this transform and stores the result
* into a destination array.
*
* @param {!Array.<number>} src The array containing the source points
* as x, y value pairs.
* @param {number} srcOff The offset to the first point to be transformed.
* @param {!Array.<number>} dst The array into which to store the transformed
* point pairs.
* @param {number} dstOff The offset of the location of the first transformed
* point in the destination array.
* @param {number} numPts The number of points to tranform.
*/
goog.graphics.AffineTransform.prototype.transform = function(src, srcOff, dst,
dstOff, numPts) {
var i = srcOff;
var j = dstOff;
var srcEnd = srcOff + 2 * numPts;
while (i < srcEnd) {
var x = src[i++];
var y = src[i++];
dst[j++] = x * this.m00_ + y * this.m01_ + this.m02_;
dst[j++] = x * this.m10_ + y * this.m11_ + this.m12_;
}
};
/**
* @return {number} The determinant of this transform.
*/
goog.graphics.AffineTransform.prototype.getDeterminant = function() {
return this.m00_ * this.m11_ - this.m01_ * this.m10_;
};
/**
* Returns whether the transform is invertible. A transform is not invertible
* if the determinant is 0 or any value is non-finite or NaN.
*
* @return {boolean} Whether the transform is invertible.
*/
goog.graphics.AffineTransform.prototype.isInvertible = function() {
var det = this.getDeterminant();
return goog.math.isFiniteNumber(det) &&
goog.math.isFiniteNumber(this.m02_) &&
goog.math.isFiniteNumber(this.m12_) &&
det != 0;
};
/**
* @return {!goog.graphics.AffineTransform} An AffineTransform object
* representing the inverse transformation.
*/
goog.graphics.AffineTransform.prototype.createInverse = function() {
var det = this.getDeterminant();
return new goog.graphics.AffineTransform(
this.m11_ / det,
-this.m10_ / det,
-this.m01_ / det,
this.m00_ / det,
(this.m01_ * this.m12_ - this.m11_ * this.m02_) / det,
(this.m10_ * this.m02_ - this.m00_ * this.m12_) / det);
};
/**
* Creates a transform representing a scaling transformation.
*
* @param {number} sx The x-axis scaling factor.
* @param {number} sy The y-axis scaling factor.
* @return {!goog.graphics.AffineTransform} A transform representing a scaling
* transformation.
*/
goog.graphics.AffineTransform.getScaleInstance = function(sx, sy) {
return new goog.graphics.AffineTransform().setToScale(sx, sy);
};
/**
* Creates a transform representing a translation transformation.
*
* @param {number} dx The distance to translate in the x direction.
* @param {number} dy The distance to translate in the y direction.
* @return {!goog.graphics.AffineTransform} A transform representing a
* translation transformation.
*/
goog.graphics.AffineTransform.getTranslateInstance = function(dx, dy) {
return new goog.graphics.AffineTransform().setToTranslation(dx, dy);
};
/**
* Creates a transform representing a shearing transformation.
*
* @param {number} shx The x-axis shear factor.
* @param {number} shy The y-axis shear factor.
* @return {!goog.graphics.AffineTransform} A transform representing a shearing
* transformation.
*/
goog.graphics.AffineTransform.getShearInstance = function(shx, shy) {
return new goog.graphics.AffineTransform().setToShear(shx, shy);
};
/**
* Creates a transform representing a rotation transformation.
*
* @param {number} theta The angle of rotation measured in radians.
* @param {number} x The x coordinate of the anchor point.
* @param {number} y The y coordinate of the anchor point.
* @return {!goog.graphics.AffineTransform} A transform representing a rotation
* transformation.
*/
goog.graphics.AffineTransform.getRotateInstance = function(theta, x, y) {
return new goog.graphics.AffineTransform().setToRotation(theta, x, y);
};
/**
* Sets this transform to a scaling transformation.
*
* @param {number} sx The x-axis scaling factor.
* @param {number} sy The y-axis scaling factor.
* @return {!goog.graphics.AffineTransform} This affine transform.
*/
goog.graphics.AffineTransform.prototype.setToScale = function(sx, sy) {
return this.setTransform(sx, 0, 0, sy, 0, 0);
};
/**
* Sets this transform to a translation transformation.
*
* @param {number} dx The distance to translate in the x direction.
* @param {number} dy The distance to translate in the y direction.
* @return {!goog.graphics.AffineTransform} This affine transform.
*/
goog.graphics.AffineTransform.prototype.setToTranslation = function(dx, dy) {
return this.setTransform(1, 0, 0, 1, dx, dy);
};
/**
* Sets this transform to a shearing transformation.
*
* @param {number} shx The x-axis shear factor.
* @param {number} shy The y-axis shear factor.
* @return {!goog.graphics.AffineTransform} This affine transform.
*/
goog.graphics.AffineTransform.prototype.setToShear = function(shx, shy) {
return this.setTransform(1, shy, shx, 1, 0, 0);
};
/**
* Sets this transform to a rotation transformation.
*
* @param {number} theta The angle of rotation measured in radians.
* @param {number} x The x coordinate of the anchor point.
* @param {number} y The y coordinate of the anchor point.
* @return {!goog.graphics.AffineTransform} This affine transform.
*/
goog.graphics.AffineTransform.prototype.setToRotation = function(theta, x, y) {
var cos = Math.cos(theta);
var sin = Math.sin(theta);
return this.setTransform(cos, sin, -sin, cos,
x - x * cos + y * sin, y - x * sin - y * cos);
};
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.geo2rect = global.geo2rect || {})));
}(this, function (exports) { 'use strict';
function compute (data) {
//TODO: check if data is in a valid format
data.features.forEach(function (d, di) {
//Preserve original coordinates
d.geometry["ocoordinates"] = d.geometry.coordinates;
//As we can only transform one polygon into a rectangle, we need to get rid of holes and small additional polygons (islands and stuff)
if (d.geometry.type === "MultiPolygon") {
//choose the largest polygon
d.geometry.coordinates = largestPoly(d.geometry);
d.geometry.type = "Polygon";
}
//Getting rid of holes
if (d.geometry.coordinates.length > 1) {
//We are too lazy to calculate if poly is clockwise or counter-clockwise, so we again just keep the largest poly
d.geometry.coordinates = largestPoly(d.geometry);
}
var b = turf.bbox(d);
d.geometry["centroid"] = [(b[2] - b[0]) / 2 + b[0], (b[1] - b[3]) / 2 + b[3]];
//Not supported geometries (length<4) we simply duplicate the first point
//TODO: the new points could be evenly distributed between the existing points
//TODO: but this only for triangles anyway, anything with (length<3) is actually an error
if (d.geometry.coordinates[0].length < 4) {
while (d.geometry.coordinates[0].length < 4) {
d.geometry.coordinates[0].push(d.geometry.coordinates[0][0]);
}
}
var geom = d.geometry.coordinates[0],
corners = [];
//Moving through the four corners of the rectangle we find the closest point on the polygon line, making sure the next point is always after the last
var _loop = function _loop(i) {
var corner = void 0,
dist = Number.MAX_VALUE,
pc = void 0;
switch (i) {
case 0:
pc = [b[0], b[3]];
break;
case 1:
pc = [b[2], b[3]];
break;
case 2:
pc = [b[2], b[1]];
break;
case 3:
pc = [b[0], b[1]];
break;
}
geom.forEach(function (dd, ddi) {
var t_dist = Math.abs(Math.sqrt(Math.pow(pc[0] - dd[0], 2) + Math.pow(pc[1] - dd[1], 2)));
if (t_dist < dist && (ddi < corners[0] || ddi > corners[corners.length - 1] || corners.length === 0)) {
dist = t_dist;
corner = ddi;
}
});
if (corners.length >= 1) {
//Counting the points already used up
var pointCount = 0;
if (corners.length >= 2) {
for (var _j = 1; _j < corners.length; _j++) {
var _c3 = corners[_j],
_c4 = corners[_j - 1],
_numPoints2 = void 0;
if (_c4 < _c3) {
_numPoints2 = _c3 - _c4;
} else {
_numPoints2 = _c3 + (geom.length - _c4);
}
pointCount += _numPoints2;
}
}
//get numpoints for new potential point
var _c = corners[corners.length - 1],
_c2 = corner,
_numPoints = void 0;
if (_c < _c2) {
_numPoints = _c2 - _c;
} else {
_numPoints = _c2 + (geom.length - _c);
}
//If there are not enough points left to finish the rectangle go step back
if (geom.length - _numPoints - pointCount < 4 - i) {
corner -= 4 - i;
if (corner < 0) {
corner += geom.length;
}
}
}
corners.push(corner);
};
for (var i = 0; i < 4; i++) {
_loop(i);
}
//NOTE: to myself Outer rings are counter clockwise
//Finding the closest point to each corner
var ngeom = {};
for (var i = 0; i < 4; i++) {
var p1 = void 0,
p2 = void 0,
ox = void 0,
oy = void 0;
switch (i) {
case 0:
ox = 0;oy = 0;
p1 = [b[0], b[3]];
p2 = [b[2], b[3]];
break;
case 1:
ox = 1;oy = 0;
p1 = [b[2], b[3]];
p2 = [b[2], b[1]];
break;
case 2:
ox = 1;oy = 1;
p1 = [b[2], b[1]];
p2 = [b[0], b[1]];
break;
case 3:
ox = 0;oy = 1;
p1 = [b[0], b[1]];
p2 = [b[0], b[3]];
break;
}
var x = p2[0] - p1[0],
y = p2[1] - p1[1];
if (x != 0) {
x = x / Math.abs(x);
}
if (y != 0) {
y = y / Math.abs(y);
}
y *= -1;
var c1 = corners[i],
c2 = i === corners.length - 1 ? corners[0] : corners[i + 1],
numPoints = void 0;
if (c1 < c2) {
numPoints = c2 - c1;
} else {
numPoints = c2 + (geom.length - c1);
}
for (var j = 0; j < numPoints; j++) {
var tp = c1 + j;
if (tp > geom.length - 1) {
tp -= geom.length;
}
ngeom[tp] = {
c: d.geometry.centroid,
x: ox + x / numPoints * j,
y: oy + y / numPoints * j
};
}
}
d.geometry['qcoordinates'] = [];
//Okey, i have no clue why the first point is broken (i=0 > i=1)
for (var _i = 1; _i < geom.length; _i++) {
if (_i === geom.length - 1) {
d.geometry.qcoordinates.push(ngeom[0]);
} else {
d.geometry.qcoordinates.push(ngeom[_i]);
}
}
});
//polys: d.geometry object (GeoJSON)
function largestPoly(geom) {
var size = -Number.MAX_VALUE,
poly = null;
//We will select the largest polygon from the multipolygon (this has worked out so far, for your project you might need to reconsider or just provide (single) polygons in the first place)
for (var c = 0; c < geom.coordinates.length; c++) {
//we are using turf.js area function
//if you don't want to include the full turf library, turf is build in modular fashion, npm install turf-area
var tsize = turf.area({
type: 'Feature',
properties: {},
geometry: {
type: 'Polygon',
coordinates: geom.type === 'MultiPolygon' ? [geom.coordinates[c][0]] : [geom.coordinates[c]]
}
});
if (tsize > size) {
size = tsize;
poly = c;
}
}
return [geom.type === 'MultiPolygon' ? geom.coordinates[poly][0] : geom.coordinates[poly]];
}
return data;
};
var asyncGenerator = function () {
function AwaitValue(value) {
this.value = value;
}
function AsyncGenerator(gen) {
var front, back;
function send(key, arg) {
return new Promise(function (resolve, reject) {
var request = {
key: key,
arg: arg,
resolve: resolve,
reject: reject,
next: null
};
if (back) {
back = back.next = request;
} else {
front = back = request;
resume(key, arg);
}
});
}
function resume(key, arg) {
try {
var result = gen[key](arg);
var value = result.value;
if (value instanceof AwaitValue) {
Promise.resolve(value.value).then(function (arg) {
resume("next", arg);
}, function (arg) {
resume("throw", arg);
});
} else {
settle(result.done ? "return" : "normal", result.value);
}
} catch (err) {
settle("throw", err);
}
}
function settle(type, value) {
switch (type) {
case "return":
front.resolve({
value: value,
done: true
});
break;
case "throw":
front.reject(value);
break;
default:
front.resolve({
value: value,
done: false
});
break;
}
front = front.next;
if (front) {
resume(front.key, front.arg);
} else {
back = null;
}
}
this._invoke = send;
if (typeof gen.return !== "function") {
this.return = undefined;
}
}
if (typeof Symbol === "function" && Symbol.asyncIterator) {
AsyncGenerator.prototype[Symbol.asyncIterator] = function () {
return this;
};
}
AsyncGenerator.prototype.next = function (arg) {
return this._invoke("next", arg);
};
AsyncGenerator.prototype.throw = function (arg) {
return this._invoke("throw", arg);
};
AsyncGenerator.prototype.return = function (arg) {
return this._invoke("return", arg);
};
return {
wrap: function (fn) {
return function () {
return new AsyncGenerator(fn.apply(this, arguments));
};
},
await: function (value) {
return new AwaitValue(value);
}
};
}();
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
var draw = function () {
function draw() {
classCallCheck(this, draw);
this._data = null;
this._svg = null;
this._col_size = 1;
this._row_size = 1;
this._cols = 1;
this._rows = 1;
this._init = false;
this._mode = 'geo';
this._rPath = d3.line();
this._path = d3.geoPath();
this._config = {
width: null,
height: null,
padding: 20,
key: null,
projection: d3.geoMercator(),
grid: null,
duration: 500
};
}
createClass(draw, [{
key: "update",
value: function update() {
var _this2 = this;
if (this._data !== null && this._config.width !== null && this._config.height !== null) {
(function () {
var init_zoom = 200;
_this2._config.projection.center(d3.geoCentroid(_this2._data)).scale(init_zoom).translate([_this2._config.width / 2, _this2._config.height / 2]);
_this2._path.projection(_this2._config.projection);
//Calculate optimal zoom
var bounds = _this2._path.bounds(_this2._data),
dx = bounds[1][0] - bounds[0][0],
dy = bounds[1][1] - bounds[0][1],
scale = Math.max(1, 0.9 / Math.max(dx / (_this2._config.width - 2 * _this2._config.padding), dy / (_this2._config.height - 2 * _this2._config.padding)));
_this2._config.projection.scale(scale * init_zoom);
_this2._data.features.forEach(function (f) {
f.geometry.qcoordinates.forEach(function (d) {
var pc = _this2._config.projection(d.c);
d["pc"] = pc;
});
});
var _this = _this2;
_this2._rPath.x(function (d) {
return (d.x - 0.5) * _this._col_size + d.pc[0];
}).y(function (d) {
return (d.y - 0.5) * _this._row_size + d.pc[1];
});
})();
}
this._init = true;
}
}, {
key: "draw",
value: function draw() {
var _this3 = this;
if (this._init) {
(function () {
var _this = _this3;
var tPath = _this3._svg.selectAll("path").data(_this3._data.features);
tPath.exit();
tPath.enter().append("path").attr('class', function (d) {
return 'id-' + _this.config.key(d);
});
_this3._svg.selectAll("path").transition().duration(_this3._config.duration).attr('transform', function (d) {
var tx = 0,
ty = 0;
if (_this.mode != 'geo') {
var g = _this.config.grid[_this.config.key(d)];
var pc = _this.config.projection(d.geometry.centroid);
tx = g.ox - pc[0];
ty = g.oy - pc[1];
}
return 'translate(' + tx + ',' + ty + ')';
}).attr('d', function (d, i) {
if (_this._mode === 'geo') {
return _this._path(d);
} else {
return _this._rPath(d.geometry.qcoordinates) + "Z";
}
});
})();
} else {
console.error('You must run update() first.');
}
}
}, {
key: "toggle",
value: function toggle() {
if (this._mode == 'geo') {
this._mode = 'rect';
} else {
this._mode = 'geo';
}
}
}, {
key: "data",
get: function get() {
return this._data;
},
set: function set(d) {
if (d) {
this._data = d;
this.update();
}
}
}, {
key: "mode",
get: function get() {
return this._mode;
},
set: function set(m) {
if (m) {
this._mode = m;
}
}
}, {
key: "svg",
get: function get() {
return this._svg;
},
set: function set(s) {
if (s) {
this._svg = s;
this.update();
}
}
}, {
key: "config",
get: function get() {
return this._config;
},
set: function set(c) {
if (c) {
for (var key in this._config) {
if (this._config[key] === null && !(key in c)) {
console.error('The config object must provide ' + key);
} else if (key in c) {
this._config[key] = c[key];
}
}
var _g = this._config.grid;
for (var _key in _g) {
if (_g[_key].x + 1 > this._cols) {
this._cols = _g[_key].x + 1;
}
if (_g[_key].y + 1 > this._rows) {
this._rows = _g[_key].y + 1;
}
}
this._col_size = (this._config.width - this._config.padding * 2) / this._rows;
this._row_size = (this._config.height - this._config.padding * 2) / this._cols;
if (this._col_size < this._row_size) {
this._row_size = this._col_size;
} else {
this._col_size = this._row_size;
}
for (var _g in this._config.grid) {
this._config.grid[_g]['ox'] = this._config.width / 2 - this._cols / 2 * this._col_size + this._config.grid[_g].x * this._col_size + this._col_size / 2;
this._config.grid[_g]['oy'] = this._config.height / 2 - this._rows / 2 * this._row_size + this._config.grid[_g].y * this._row_size + this._row_size / 2;
}
this.update();
}
}
}]);
return draw;
}();
exports.compute = compute;
exports.draw = draw;
Object.defineProperty(exports, '__esModule', { value: true });
}));
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
path{
fill:transparent;
stroke:rgba(0,0,0,1);
}
.class-4 circle{
fill:red;
}
</style>
<body>
<script src="affinetransform.js"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://npmcdn.com/@turf/turf/turf.min.js"></script>
<script src="nmap.min.js"></script>
<script src="geo2rect.js"></script>
<script>
var elements = [];
var config = {
width : 500,
height : 350,
padding : 10,
duration : 1000,
key:function(d){;return d.properties.CODDISTRIT; },
// empty grid
grid : {
'01':{x:0,y:0},
'02':{x:0,y:0},
'03':{x:0,y:0},
'04':{x:0,y:0},
'05':{x:0,y:0},
'06':{x:0,y:0},
'07':{x:0,y:0},
'08':{x:0,y:0},
'09':{x:0,y:0},
'10':{x:0,y:0},
'11':{x:0,y:0},
'12':{x:0,y:0},
'13':{x:0,y:0},
'14':{x:0,y:0},
'15':{x:0,y:0},
'16':{x:0,y:0},
'17':{x:0,y:0},
'18':{x:0,y:0},
'19':{x:0,y:0},
'20':{x:0,y:0},
'21':{x:0,y:0}
}
};
var svg = d3.select('body').append('svg').attr('width', config.width).attr('height', config.height);
var g2r = new geo2rect.draw();
d3.json('distritos.geojson', function(err, data){
var geojson = geo2rect.compute(data);
g2r.config = config;
g2r.data = geojson;
g2r.svg = svg.append('g');
g2r.draw();
for (var i = 0; i < data.features.length; i++) {
var cod = data.features[i].properties.CODDISTRIT,
pathEL = d3.select(".id-" + cod);
var bounds = g2r._path.bounds(pathEL._groups[0][0].__data__),
x = (bounds[0][0] + bounds[1][0]) / 2,
y = (bounds[0][1] + bounds[1][1]) / 2;
elements.push(new nmap_element({
id:cod,
x:x,
y:y,
weight:1000+Math.random(),
klass:"id-" + cod
}));
}
//initializing the nmap function and setting the bounding box
var map = new nmap({x:0, y:0, width:10, height:10});
//Equal Weight Approach
var ac = map.equalWeight({elements:elements});
for (var i = 0; i < data.features.length; i++) {
var cod = ac[i].attr().element.getId();
config.grid[cod].x = ac[i].attr().x;
config.grid[cod].y = ac[i].attr().y;
}
g2r.config = config;
console.log();
});
d3.select('body').append('a').text('Toggle').on('click', function(){
g2r.toggle();
g2r.draw();
console.log(g2r.mode);
});
</script>
</body>
</html>
function nmap_extend(t,e){var a={};for(var r in t)a[r]=t[r];for(r in e)a[r]=e[r];return a}var nmap_element=function(t){function e(){}var a={id:1,klass:1,weight:1,x:0,y:0},r=nmap_extend(a,t);return e.attr=function(){return r},e.getX=function(){return parseFloat(r.x)},e.setX=function(t){r.x=t},e.getY=function(){return parseFloat(r.y)},e.setY=function(t){r.y=t},e.getId=function(){return r.id},e.setId=function(t){r.id=t},e.getKlass=function(){return parseFloat(r.klass)},e.setKlass=function(t){r.klass=t},e.getWeight=function(){return parseFloat(r.weight)},e.setWeight=function(t){r.weight=t},e},nmap_boundingbox=function(t){function e(){}var a={x:0,y:0,width:0,height:0,element:null},r=nmap_extend(a,t);return e.attr=function(){return r},e.setBounds=function(t){r=nmap_extend(r,t)},e.getElement=function(){return r.element},e.setElement=function(t){r.element=t},e},nmap=function(t){function e(){null===r.visualSpace&&(r.visualSpace=new nmap_boundingbox({x:r.x,y:r.y,height:r.height,width:r.width}))}var a={x:0,y:0,width:1,height:1,visualSpace:null,HORIZONTAL:!0,VERTICAL:!1},r=nmap_extend(a,t);return e(),e.attr=function(){return r},e.normalize=function(t){if(null!==t){for(var e=Number.MIN_VALUE,a=Number.MAX_VALUE,i=Number.MIN_VALUE,n=Number.MAX_VALUE,h=0;h<t.length;h++)e=Math.max(e,t[h].getX()),a=Math.min(a,t[h].getX()),i=Math.max(i,t[h].getY()),n=Math.min(n,t[h].getY());for(isFinite(e)||(e=0),isFinite(i)||(i=0),isFinite(a)||(a=0),isFinite(n)||(n=0),h=0;h<t.length;h++){var s;s=e-a===0?0:(t[h].getX()-a)/(e-a)*r.visualSpace.attr().width+r.visualSpace.attr().x;var l;l=i-n===0?0:(t[h].getY()-n)/(i-n)*r.visualSpace.attr().height+r.visualSpace.attr().y,t[h].setX(s),t[h].setY(l)}}return t},e.sortByX=function(t,e){return t.getX()<e.getX()?-1:t.getX()>e.getX()?1:0},e.sortByY=function(t,e){return t.getY()<e.getY()?-1:t.getY()>e.getY()?1:0},e.alternateCut=function(t){var a={elements:null,visualSpace:r.visualSpace,bisection:null};if(t=nmap_extend(a,t),t.elements=e.normalize(t.elements),null===t.bisection){var i;t.visualSpace.attr().width>t.visualSpace.attr().height?t.bisection=r.HORIZONTAL:t.bisection=r.VERTICAL}var n=[];if(1===t.elements.length){var h=new nmap_boundingbox({x:t.visualSpace.attr().x,y:t.visualSpace.attr().y,width:t.visualSpace.attr().width,height:t.visualSpace.attr().height,element:t.elements[0]});n.push(h)}else{t.bisection===r.HORIZONTAL?t.elements.sort(e.sortByX):t.elements.sort(e.sortByY);for(var s=Math.floor(t.elements.length/2),l=t.elements.slice(0,s),g=t.elements.slice(s,t.elements.length),u=0,o=0;o<l.length;o++)u+=l[o].getWeight();var c=0;for(o=0;o<g.length;o++)c+=g[o].getWeight();var p=null,v=null,d,m;if(t.bisection===r.HORIZONTAL){var x=u/(u+c)*t.visualSpace.attr().width,f=c/(u+c)*t.visualSpace.attr().width,w=(l[l.length-1].getX()+g[0].getX())/2;p=new nmap_boundingbox({x:t.visualSpace.attr().x,y:t.visualSpace.attr().y,width:w-t.visualSpace.attr().x,height:t.visualSpace.attr().height}),v=new nmap_boundingbox({x:t.visualSpace.attr().x+p.attr().width,y:t.visualSpace.attr().y,width:t.visualSpace.attr().width-p.attr().width,height:t.visualSpace.attr().height});var y=new goog.graphics.AffineTransform(x/p.attr().width,0,0,1,t.visualSpace.attr().x*(1-x/p.attr().width),0);for(o=0;o<l.length;o++)d=[l[o].getX(),l[o].getY()],m=[],y.transform(d,0,m,0,1),l[o].setX(m[0]),l[o].setY(m[1]);d=[p.attr().x,p.attr().y,p.attr().x,p.attr().y+p.attr().height,p.attr().x+p.attr().width,p.attr().y+p.attr().height,p.attr().x+p.attr().width,p.attr().y],m=[],y.transform(d,0,m,0,4),p.setBounds({x:m[0],y:m[1],width:m[4]-m[0],height:m[5]-m[1]});var S=new goog.graphics.AffineTransform(f/v.attr().width,0,0,1,(t.visualSpace.attr().x+t.visualSpace.attr().width)*(1-f/v.attr().width),0);for(o=0;o<g.length;o++)d=[g[o].getX(),g[o].getY()],m=[],S.transform(d,0,m,0,1);d=[v.attr().x,v.attr().y,v.attr().x,v.attr().y+v.attr().height,v.attr().x+v.attr().width,v.attr().y+v.attr().height,v.attr().x+v.attr().width,v.attr().y],m=[],S.transform(d,0,m,0,4),v.setBounds({x:m[0],y:m[1],width:m[4]-m[0],height:m[5]-m[1]})}else if(t.bisection===r.VERTICAL){var b=u/(u+c)*t.visualSpace.attr().height,X=c/(u+c)*t.visualSpace.attr().height,Y=(l[l.length-1].getY()+g[0].getY())/2,A=Y-t.visualSpace.attr().y;0===A&&(A=1),p=new nmap_boundingbox({x:t.visualSpace.attr().x,y:t.visualSpace.attr().y,width:t.visualSpace.attr().width,height:A}),v=new nmap_boundingbox({x:t.visualSpace.attr().x,y:t.visualSpace.attr().y+p.attr().height,width:t.visualSpace.attr().width,height:t.visualSpace.attr().height-p.attr().height});var _=new goog.graphics.AffineTransform(1,0,0,b/p.attr().height,0,t.visualSpace.attr().y*(1-b/p.attr().height));for(o=0;o<l.length;o++)d=[l[o].getX(),l[o].getY()],m=[],_.transform(d,0,m,0,1),l[o].setX(m[0]),l[o].setY(m[1]);d=[p.attr().x,p.attr().y,p.attr().x,p.attr().y+p.attr().height,p.attr().x+p.attr().width,p.attr().y+p.attr().height,p.attr().x+p.attr().width,p.attr().y],m=[],_.transform(d,0,m,0,4),p.setBounds({x:m[0],y:m[1],width:m[4]-m[0],height:m[5]-m[1]});var T=new goog.graphics.AffineTransform(1,0,0,X/v.attr().height,0,(t.visualSpace.attr().y+t.visualSpace.attr().height)*(1-X/v.attr().height));for(o=0;o<g.length;o++)d=[g[o].getX(),g[o].getY()],m=[],T.transform(d,0,m,0,1);d=[v.attr().x,v.attr().y,v.attr().x,v.attr().y+v.attr().height,v.attr().x+v.attr().width,v.attr().y+v.attr().height,v.attr().x+v.attr().width,v.attr().y],m=[],T.transform(d,0,m,0,4),v.setBounds({x:m[0],y:m[1],width:m[4]-m[0],height:m[5]-m[1]})}n=n.concat(e.alternateCut({visualSpace:p,elements:l,bisection:!t.bisection})),n=n.concat(e.alternateCut({visualSpace:v,elements:g,bisection:!t.bisection}))}return n},e.equalWeight=function(t){var a={elements:null,visualSpace:r.visualSpace,bisection:r.VERTICAL};t=nmap_extend(a,t),t.elements=e.normalize(t.elements);var i=[];if(1===t.elements.length){var n=new nmap_boundingbox({x:t.visualSpace.attr().x,y:t.visualSpace.attr().y,width:t.visualSpace.attr().width,height:t.visualSpace.attr().height,element:t.elements[0]});i.push(n)}else{t.visualSpace.attr().width>t.visualSpace.attr().height&&(t.bisection=r.HORIZONTAL),t.bisection===r.HORIZONTAL?t.elements.sort(e.sortByX):t.elements.sort(e.sortByY);for(var h=0,s=0,l=0,g=0,u=1,o=0;o<t.elements.length;o++)g+=t.elements[o].getWeight();var c=Number.MAX_VALUE;for(o=1;o<t.elements.length;++o)l+=t.elements[o-1].getWeight(),g-=t.elements[o-1].getWeight(),Math.abs(l-g)<c&&(c=Math.abs(l-g),u=o,h=l,s=g);var p=t.elements.slice(0,u),v=t.elements.slice(u,t.elements.length),d=null,m=null,x=[],f=[];if(t.bisection===r.HORIZONTAL){var w=h/(h+s)*t.visualSpace.attr().width,y=s/(h+s)*t.visualSpace.attr().width,S=(p[p.length-1].getX()+v[0].getX())/2;d=new nmap_boundingbox({x:t.visualSpace.attr().x,y:t.visualSpace.attr().y,width:S-t.visualSpace.attr().x,height:t.visualSpace.attr().height}),m=new nmap_boundingbox({x:t.visualSpace.attr().x+d.attr().width,y:t.visualSpace.attr().y,width:t.visualSpace.attr().width-d.attr().width,height:t.visualSpace.attr().height});var b=new goog.graphics.AffineTransform(w/d.attr().width,0,0,1,t.visualSpace.attr().x*(1-w/d.attr().width),0);for(o=0;o<p.length;o++)x=[p[o].getX(),p[o].getY()],f=[],b.transform(x,0,f,0,1),p[o].setX(f[0]),p[o].setY(f[1]);x=[d.attr().x,d.attr().y,d.attr().x,d.attr().y+d.attr().height,d.attr().x+d.attr().width,d.attr().y+d.attr().height,d.attr().x+d.attr().width,d.attr().y],f=[],b.transform(x,0,f,0,4),d.setBounds({x:f[0],y:f[1],width:f[4]-f[0],height:f[5]-f[1]});var X=new goog.graphics.AffineTransform(y/m.attr().width,0,0,1,(t.visualSpace.attr().x+t.visualSpace.attr().width)*(1-y/m.attr().width),0);for(o=0;o<v.length;o++)x=[v[o].getX(),v[o].getY()],f=[],X.transform(x,0,f,0,1);x=[m.attr().x,m.attr().y,m.attr().x,m.attr().y+m.attr().height,m.attr().x+m.attr().width,m.attr().y+m.attr().height,m.attr().x+m.attr().width,m.attr().y],f=[],X.transform(x,0,f,0,4),m.setBounds({x:f[0],y:f[1],width:f[4]-f[0],height:f[5]-f[1]})}else if(t.bisection===r.VERTICAL){var Y=h/(h+s)*t.visualSpace.attr().height,A=s/(h+s)*t.visualSpace.attr().height,_=(p[p.length-1].getY()+v[0].getY())/2;d=new nmap_boundingbox({x:t.visualSpace.attr().x,y:t.visualSpace.attr().y,width:t.visualSpace.attr().width,height:_-t.visualSpace.attr().y}),m=new nmap_boundingbox({x:t.visualSpace.attr().x,y:t.visualSpace.attr().y+d.attr().height,width:t.visualSpace.attr().width,height:t.visualSpace.attr().height-d.attr().height});var T=new goog.graphics.AffineTransform(1,0,0,Y/d.attr().height,0,t.visualSpace.attr().y*(1-Y/d.attr().height));for(o=0;o<p.length;o++)x=[p[o].getX(),p[o].getY()],f=[],T.transform(x,0,f,0,1),p[o].setX(f[0]),p[o].setY(f[1]);x=[d.attr().x,d.attr().y,d.attr().x,d.attr().y+d.attr().height,d.attr().x+d.attr().width,d.attr().y+d.attr().height,d.attr().x+d.attr().width,d.attr().y],f=[],T.transform(x,0,f,0,4),d.setBounds({x:f[0],y:f[1],width:f[4]-f[0],height:f[5]-f[1]});var L=new goog.graphics.AffineTransform(1,0,0,A/m.attr().height,0,(t.visualSpace.attr().y+t.visualSpace.attr().height)*(1-A/m.attr().height));for(o=0;o<v.length;o++)x=[v[o].getX(),v[o].getY()],f=[],L.transform(x,0,f,0,1);x=[m.attr().x,m.attr().y,m.attr().x,m.attr().y+m.attr().height,m.attr().x+m.attr().width,m.attr().y+m.attr().height,m.attr().x+m.attr().width,m.attr().y],f=[],L.transform(x,0,f,0,4),m.setBounds({x:f[0],y:f[1],width:f[4]-f[0],height:f[5]-f[1]})}i=i.concat(e.equalWeight({visualSpace:d,elements:p})),i=i.concat(e.equalWeight({visualSpace:m,elements:v}))}return i},e};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment