|
function decodeCoordinate(coordinate, encodeOffset) {
|
var result = []
|
var cx, cy
|
var offset = encodeOffset.slice()
|
|
for (var i = 0, L = coordinate.length; i < L; i += 2) {
|
cx = coordinate.charCodeAt(i) - 64
|
cy = coordinate.charCodeAt(i + 1) - 64
|
cx = ((cx >> 1) ^ (-(cx & 1))) + offset[0]
|
cy = ((cy >> 1) ^ (-(cy & 1))) + offset[1]
|
offset[0] = cx
|
offset[1] = cy
|
result.push([cx / 1024, cy / 1024])
|
}
|
|
return result
|
}
|
|
function decodeGeoJSON(geoJSON) {
|
var decoder = {
|
MultiPolygon: function (coordinates, encodeOffset) {
|
return coordinates.map(function (coordinate, index) {
|
return decodeCoordinate(coordinate, encodeOffset[index])
|
})
|
},
|
Polygon: decodeCoordinate
|
}
|
var features = []
|
|
if (typeof geoJSON === 'string') {
|
geoJSON = JSON.parse(geoJSON)
|
}
|
features = geoJSON.features
|
// If is unminified json format, do nothing
|
if (!geoJSON.UTF8Encoding) {
|
return geoJSON
|
}
|
|
for (var i = 0, M = features.length; i < M; i++) {
|
var geometry = features[i].geometry
|
var coordinates = geometry.coordinates
|
var encodeOffsets = geometry.encodeOffsets
|
|
coordinates.forEach(function (coordinate, index) {
|
coordinates[index] = decoder[geometry.type](
|
coordinate,
|
encodeOffsets[index]
|
)
|
})
|
}
|
geoJSON.UTF8Encoding = false
|
|
return geoJSON
|
}
|
|
function Region(name, contours, center) {
|
this.name = name
|
this.contours = contours
|
|
if (!center) {
|
var boundingRect = this.getBoundingRect()
|
|
center = [
|
(boundingRect.xMin + boundingRect.xMax) / 2,
|
(boundingRect.yMin + boundingRect.yMax) / 2
|
]
|
}
|
this.center = center
|
}
|
|
Region.prototype.getBoundingRect = function () {
|
var LIMIT = Number.MAX_VALUE
|
var getBoundingRect = function (contour) {
|
var min = [LIMIT, LIMIT], max = [-LIMIT, -LIMIT]
|
|
contour.forEach(function (coordinate) {
|
min[0] = Math.min(min[0], coordinate[0])
|
max[0] = Math.max(max[0], coordinate[0])
|
min[1] = Math.min(min[1], coordinate[1])
|
max[1] = Math.max(max[1], coordinate[1])
|
})
|
|
return { xMin: min[0], yMin: min[1], xMax: max[0], yMax: max[1] }
|
}
|
var result = { xMin: LIMIT, yMin: LIMIT, xMax: -LIMIT, yMax: -LIMIT }
|
|
this.contours.forEach(function (contour) {
|
contour.forEach(function (coordinates) {
|
var boundingRect = getBoundingRect(coordinates)
|
|
result.xMin = Math.min(result.xMin, boundingRect.xMin)
|
result.xMax = Math.max(result.xMax, boundingRect.xMax)
|
result.yMin = Math.min(result.yMin, boundingRect.yMin)
|
result.yMax = Math.max(result.yMax, boundingRect.yMax)
|
})
|
})
|
|
return result
|
}
|
|
var geoJSONParser = function (geoJSON) {
|
var decodedGeoJSON = decodeGeoJSON(geoJSON)
|
var features = decodedGeoJSON.features.filter(function (feature) {
|
return (
|
feature.properties
|
&& feature.geometry
|
&& feature.geometry.coordinates.length > 0
|
)
|
})
|
|
return features.map(function (feature) {
|
var geometry = feature.geometry
|
var coordinates = geometry.coordinates
|
|
if (geometry.type === 'Polygon') {
|
coordinates = coordinates.map(function (coordinate) {
|
return [coordinate]
|
})
|
}
|
|
return new Region(
|
feature.properties.name,
|
coordinates,
|
feature.properties.cp
|
)
|
})
|
}
|
geoJSONParser.Region = Region;
|
geoJSONParser.decodeCoordinate = decodeCoordinate;
|
geoJSONParser.decodeGeoJSON = decodeGeoJSON;
|
if (typeof module === "undefined") {
|
this.geoJSONParser = geoJSONParser;
|
} else {
|
module.exports = geoJSONParser;
|
}
|
if (typeof define === "function") {
|
define(function () { return geoJSONParser; });
|
}
|