d3/test/geo/path-test.js

634 строки
36 KiB
JavaScript
Исходник Обычный вид История

require("../env");
var vows = require("vows"),
assert = require("assert");
var suite = vows.describe("d3.geo.path");
suite.addBatch({
"path": {
topic: function() {
return d3.geo.path()
.context(testContext)
.projection(d3.geo.equirectangular()
.scale(900 / Math.PI)
.precision(0));
},
"Point": function(path) {
path({
type: "Point",
coordinates: [-63, 18]
});
assert.deepEqual(testContext.buffer(), [
{type: "point", x: 165, y: 160},
]);
},
"MultiPoint": function(path) {
path({
type: "MultiPoint",
coordinates: [[-63, 18], [-62, 18], [-62, 17]]
});
assert.deepEqual(testContext.buffer(), [
{type: "point", x: 165, y: 160},
{type: "point", x: 170, y: 160},
{type: "point", x: 170, y: 165}
]);
},
"LineString": function(path) {
path({
type: "Feature",
geometry: {
type: "LineString",
coordinates: [[-63, 18], [-62, 18], [-62, 17]]
},
});
assert.deepEqual(testContext.buffer(), [
{type: "moveTo", x: 165, y: 160},
{type: "lineTo", x: 170, y: 160},
{type: "lineTo", x: 170, y: 165}
]);
},
"Polygon": function(path) {
path({
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [[[-63, 18], [-62, 18], [-62, 17], [-63, 18]]]
},
});
assert.deepEqual(testContext.buffer(), [
{type: "moveTo", x: 165, y: 160},
{type: "lineTo", x: 170, y: 160},
{type: "lineTo", x: 170, y: 165},
{type: "closePath"}
]);
},
"GeometryCollection": function(path) {
path({
type: "GeometryCollection",
geometries: [{type: "Point", coordinates: [0, 0]}]
});
assert.deepEqual(testContext.buffer(), [
{type: "point", x: 480, y: 250}
]);
},
"FeatureCollection": function(path) {
path({
type: "FeatureCollection",
features: [{type: "Feature", geometry: {type: "Point", coordinates: [0, 0]}}]
});
assert.deepEqual(testContext.buffer(), [
{type: "point", x: 480, y: 250}
]);
},
"returns null when passed null or undefined": function(path) {
assert.isNull(path(null));
assert.isNull(path(undefined));
assert.isNull(path());
},
"bogus type name": function(path) {
assert.isNull(path({
type: "Feature",
geometry: {
type: "__proto__",
coordinates: [[[-63.03, 18.02], [-63.14, 18.06], [-63.01, 18.07], [-63.03, 18.02]]]
},
}));
},
"projection": {
"returns the current projection when called with no arguments": function() {
var path = d3.geo.path(), projection = d3.geo.albers();
path.projection(projection);
assert.strictEqual(path.projection(), projection);
}
},
"pointRadius": {
"returns the current point radius when called with no arguments": function() {
var path = d3.geo.path(), radius = function() { return 5; };
assert.strictEqual(path.pointRadius(), 4.5);
assert.strictEqual(path.pointRadius(radius).pointRadius(), radius);
}
2012-10-06 03:02:12 +04:00
},
"area": {
topic: function(path) {
return path.area;
},
"no holes": function(area) {
assert.strictEqual(area({type: "Polygon", coordinates: [[[100, 0], [100, 1], [101, 1], [101, 0], [100, 0]]]}), 25);
2012-10-06 03:02:12 +04:00
},
"holes": function(area) {
assert.strictEqual(area({type: "Polygon", coordinates: [[[100, 0], [100, 1], [101, 1], [101, 0], [100, 0]],
2012-10-06 03:02:12 +04:00
[[100.2, .2], [100.8, .2], [100.8, .8], [100.2, .8], [100.2, .2]]]}), 16);
2012-12-06 00:04:18 +04:00
},
"Sphere": function(area) {
assert.strictEqual(area({type: "Sphere"}), 1620000);
2012-10-06 03:02:12 +04:00
}
},
"centroid": {
topic: function(path) {
return path.centroid;
},
"Point": function(centroid) {
assert.deepEqual(centroid({type: "Point", coordinates: [0, 0]}), [480, 250]);
},
"MultiPoint": {
"empty": function(centroid) {
assert.isNull(centroid({type: "MultiPoint", coordinates: []}));
},
"single point": function(centroid) {
assert.deepEqual(centroid({type: "MultiPoint", coordinates: [[0, 0]]}), [480, 250]);
},
"two points": function(centroid) {
assert.deepEqual(centroid({type: "MultiPoint", coordinates: [[-122, 37], [-74, 40]]}), [-10, 57.5]);
}
},
"LineString": {
"empty": function(centroid) {
assert.isNull(centroid({type: "LineString", coordinates: []}));
},
"two points": function(centroid) {
assert.deepEqual(centroid({type: "LineString", coordinates: [[100, 0], [0, 0]]}), [730, 250]);
assert.deepEqual(centroid({type: "LineString", coordinates: [[0, 0], [100, 0], [101, 0]]}), [732.5, 250]);
},
"two points, one unique": function(centroid) {
assert.isNull(centroid({type: "LineString", coordinates: [[-122, 37], [-122, 37]]}));
assert.isNull(centroid({type: "LineString", coordinates: [[ -74, 40], [ -74, 40]]}));
},
"three points; two unique": function(centroid) {
assert.deepEqual(centroid({type: "LineString", coordinates: [[-122, 37], [-74, 40], [-74, 40]]}), [-10, 57.5]);
},
"three points": function(centroid) {
assert.inDelta(centroid({type: "LineString", coordinates: [[-122, 37], [-74, 40], [-100, 0]]}), [17.389135, 103.563545], 1e-6);
}
},
"MultiLineString": function(centroid) {
assert.deepEqual(centroid({type: "MultiLineString", coordinates: [[[100, 0], [0, 0]], [[-10, 0], [0, 0]]]}), [705, 250]);
},
"Polygon": {
"single ring": function(centroid) {
assert.deepEqual(centroid({type: "Polygon", coordinates: [[[100, 0], [100, 1], [101, 1], [101, 0], [100, 0]]]}), [982.5, 247.5]);
},
"zero area": function(centroid) {
assert.isNull(centroid({type: "Polygon", coordinates: [[[1, 0], [2, 0], [3, 0], [1, 0]]]}));
},
"two rings, one zero area": function(centroid) {
assert.deepEqual(centroid({type: "Polygon", coordinates: [
[[100, 0], [100, 1], [101, 1], [101, 0], [100, 0]],
[[100.1, 0], [100.2, 0], [100.3, 0], [100.1, 0]
]]}), [982.5, 247.5]);
},
"clockwise exterior, anticlockwise interior": function(centroid) {
assert.inDelta(centroid({
type: "Polygon",
coordinates: [
[[-2, -2], [2, -2], [2, 2], [-2, 2], [-2, -2]].reverse(),
[[ 0, -1], [1, -1], [1, 1], [ 0, 1], [ 0, -1]]
]
}), [479.642857, 250], 1e-6);
}
},
"MultiPolygon": {
"empty": function(centroid) {
assert.isNull(centroid({type: "MultiPolygon", coordinates: []}));
},
"single polygon": function(centroid) {
assert.deepEqual(centroid({type: "MultiPolygon", coordinates: [[[[100, 0], [100, 1], [101, 1], [101, 0], [100, 0]]]]}), [982.5, 247.5]);
},
"two polygons": function(centroid) {
assert.deepEqual(centroid({type: "MultiPolygon", coordinates: [
[[[100, 0], [100, 1], [101, 1], [101, 0], [100, 0]]],
[[[0, 0], [1, 0], [1, -1], [0, -1], [0, 0]]]
]}), [732.5, 250]);
},
"two polygons, one zero area": function(centroid) {
assert.deepEqual(centroid({type: "MultiPolygon", coordinates: [
[[[100, 0], [100, 1], [101, 1], [101, 0], [100, 0]]],
[[[0, 0], [1, 0], [2, 0], [0, 0]]]
]}), [982.5, 247.5]);
}
},
"GeometryCollection": {
"is undefined": function(centroid) {
assert.isUndefined(centroid({type: "GeometryCollection", geometries: [{type: "Point", coordinates: [0, 0]}]}));
}
},
"FeatureCollection": {
"is undefined": function(centroid) {
assert.isUndefined(centroid({type: "FeatureCollection", features: [{type: "Feature", geometry: {type: "Point", coordinates: [0, 0]}}]}));
}
2012-12-06 00:04:18 +04:00
},
"Sphere": function(centroid) {
assert.deepEqual(centroid({type: "Sphere"}), [480, 250]);
2012-12-11 01:23:27 +04:00
},
"rotate([180, -248])": function() {
d3.geo.path()
.context(testContext)
.projection(d3.geo.equirectangular()
.rotate([-180, -248])
.scale(900 / Math.PI)
.precision(0))({type: "Polygon", coordinates: [[[-175.03150315031502, 66.57410661866186], [-174.34743474347434, 66.33097912391239], [-174.5994599459946, 67.0603616081608], [-171.86318631863185, 66.90406536153614], [-169.9189918991899, 65.96628788178816], [-170.89108910891088, 65.53213164116411], [-172.54725472547256, 65.42793414341432], [-172.5832583258326, 64.45542416441643], [-172.97929792979298, 64.2470291689169], [-173.91539153915392, 64.28176166816681], [-174.67146714671466, 64.62908666066605], [-176.003600360036, 64.90694665466546], [-176.21962196219621, 65.34110289528951], [-177.22772277227722, 65.51476539153916], [-178.37983798379838, 65.37583539453945], [-178.91989198919893, 65.72316038703869], [-178.7038703870387, 66.10521787878787], [-179.8919891989199, 65.8620903840384], [-179.45994599459945, 65.3932016441644], [-180, 64.97641165316531], [-180, 68.95328281728172], [-177.55175517551754, 68.18916783378336], [-174.95949594959495, 67.19929160516051], [-175.03150315031502, 66.57410661866186]]]});
assert.deepEqual(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }), [
{type: "moveTo", x: 1370, y: 243}
]);
}
},
"clipAngle(90)": {
topic: function() {
return d3.geo.path()
.context(testContext)
.projection(d3.geo.equirectangular()
.scale(900 / Math.PI)
.precision(0)
.clipAngle(90));
},
"Point": function(path) {
path({
type: "Point",
coordinates: [-63, 18]
});
assert.deepEqual(testContext.buffer(), [
{type: "point", x: 165, y: 160},
]);
},
"MultiPoint": function(path) {
path({
type: "MultiPoint",
coordinates: [[-63, 18], [-62, 18], [-62, 17]]
});
assert.deepEqual(testContext.buffer(), [
{type: "point", x: 165, y: 160},
{type: "point", x: 170, y: 160},
{type: "point", x: 170, y: 165}
]);
},
"Polygon": {
"inserts exterior along clip edge if polygon interior surrounds it": function(path) {
path({type: "Polygon", coordinates: [[[80, -80], [80, 80], [-80, 80], [-80, -80], [80, -80]]]});
assert.equal(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }).length, 2);
},
"inserts exterior along clip edge if polygon exterior surrounds it": function(path) {
path({type: "Polygon", coordinates: [[[100, -80], [-100, -80], [-100, 80], [100, 80], [100, -80]]]});
assert.equal(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }).length, 1);
}
2012-11-18 19:53:29 +04:00
},
2012-12-11 01:23:27 +04:00
"rotate([-17, -451])": function() {
var pole = d3.range(-180, 180, 10).map(function(x) { return [x, 70]; });
pole.push(pole[0]);
d3.geo.path()
.context(testContext)
.projection(d3.geo.equirectangular()
.rotate([-17, -451])
.scale(900 / Math.PI)
.precision(0)
.clipAngle(90))({type: "Polygon", coordinates: [pole]});
assert.deepEqual(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }), [
{type: "moveTo", x: 510, y: 160},
{type: "moveTo", x: 87, y: 700}
]);
},
2012-11-18 19:53:29 +04:00
"rotate([71.03, 42.37])": {
topic: function() {
return d3.geo.path()
.context(testContext)
.projection(d3.geo.equirectangular()
.rotate([71.03, 42.37])
.scale(900 / Math.PI)
.precision(0)
.clipAngle(90));
},
/*
"grid component": function(path) {
var yStepsBig = d3.range(-90, 90, 10);
path({type: "LineString", coordinates: yStepsBig.map(function(y) { return [110, y]; })});
assert.inDelta(testContext.buffer(), [[
[109.538009, -90],
[110, -80],
[110, -70],
[110, -60],
[110, -50],
[110, -47.625390]
]], 1e-6);
},
*/
"can completely clip a LineString": function(path) {
path({type: "LineString", coordinates: [[90.0, -42.37], [95.0, -42.37], [90.0, -42.37]]});
assert.deepEqual(testContext.buffer(), []);
},
"doesn't insert a duplicate point": function(path) {
path({type: "LineString", coordinates: [[0, 0]]});
assert.deepEqual(testContext.buffer(), [{type: "moveTo", x: 859, y: 187}]);
},
"Point": {
"visible": function(path) {
path({type: "Point", coordinates: [0, 0]});
assert.deepEqual(testContext.buffer(), [{type: "point", x: 859, y: 187}]);
},
"invisible": function(path) {
path({type: "Point", coordinates: [-180, 0]});
assert.deepEqual(testContext.buffer(), []);
}
},
"MultiPoint": function(path) {
path({type: "MultiPoint", coordinates: [[0, 0], [-180, 0]]});
assert.deepEqual(testContext.buffer(), [{type: "point", x: 859, y: 187}]);
}
},
"rotate(-24, -175.5])": {
topic: function() {
return d3.geo.path()
.context(testContext)
.projection(d3.geo.equirectangular()
.rotate([-24, -175.5])
.scale(900 / Math.PI)
.precision(0)
.clipAngle(90));
},
"Antarctica": function(path) {
path(antarctica);
assert.equal(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }).length, 2);
}
},
"circle.angle(60)": {
"rotate([0, 0])": function(path) {
path(d3.geo.circle().angle(60)());
assert.deepEqual(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }), [
{type: "moveTo", x: 276, y: 493}]);
},
"rotate([90, 0])": function(path) {
try {
path.projection().rotate([90, 0]);
path(d3.geo.circle().angle(60)());
assert.deepEqual(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }), [
{type: "moveTo", x: 930, y: 550}]);
} finally {
path.projection().rotate([0, 0]);
}
},
"rotate([180, 0])": function(path) {
try {
path.projection().rotate([180, 0]);
path(d3.geo.circle().angle(60)());
assert.deepEqual(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }), []);
} finally {
path.projection().rotate([0, 0]);
}
},
"rotate([270, 0])": function(path) {
try {
path.projection().rotate([270, 0]);
path(d3.geo.circle().angle(60)());
assert.deepEqual(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }), [
{type: "moveTo", x: 30, y: -50}]);
} finally {
path.projection().rotate([0, 0]);
}
}
},
"circle.angle(120)": {
"rotate([0, 0])": function(path) {
path(d3.geo.circle().angle(120)());
assert.deepEqual(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }), [
{type: "moveTo", x: 87, y: 700}]);
},
"rotate([90, 0])": function(path) {
try {
path.projection().rotate([90, 0]);
path(d3.geo.circle().angle(120)());
assert.deepEqual(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }), [
{type: "moveTo", x: 30, y: 550}]);
} finally {
path.projection().rotate([0, 0]);
}
},
"rotate([180, 0])": function(path) {
try {
path.projection().rotate([180, 0]);
path(d3.geo.circle().angle(120)());
assert.deepEqual(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }), [
{type: "moveTo", x: 276, y: 493},
{type: "moveTo", x: 87, y: 700}]);
} finally {
path.projection().rotate([0, 0]);
}
},
"rotate([270, 0])": function(path) {
try {
path.projection().rotate([270, 0]);
path(d3.geo.circle().angle(120)());
assert.deepEqual(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }), [
{type: "moveTo", x: 930, y: -50}]);
} finally {
path.projection().rotate([0, 0]);
}
},
"rotate([210, 1])": function(path) {
try {
path.projection().rotate([210, 1]);
path(d3.geo.circle().angle(120)());
assert.deepEqual(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }), [{type: "moveTo", x: 930, y: 250}]);
} finally {
path.projection().rotate([0, 0]);
}
},
"rotate([-150, 60])": function(path) {
try {
path.projection().rotate([-150, 60]);
path(d3.geo.circle().angle(120)());
assert.deepEqual(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }), [{type: "moveTo", x: 30, y: -87}]);
} finally {
path.projection().rotate([0, 0]);
}
}
},
"Sphere": function(path) {
path({type: "Sphere"});
assert.deepEqual(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }), [{type: "moveTo", x: 87, y: 700}]);
}
},
"clipAngle(170)": {
topic: function() {
return d3.geo.path()
.context(testContext)
.projection(d3.geo.equirectangular()
.scale(900 / Math.PI)
.precision(0)
.clipAngle(170));
},
"stripes": {
"rotate([0, 0])": function(path) {
path(stripes(80, -80));
assert.deepEqual(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }), [
{type: "moveTo", x: -420, y: -150},
{type: "moveTo", x: -420, y: 650},
{type: "moveTo", x: 1331, y: 259}]);
},
"rotate([0, -90])": function(path) {
try {
path.projection().rotate([0, -90]);
path(stripes(80, -80));
assert.deepEqual(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }), [
{type: "moveTo", x: 480, y: 200},
{type: "moveTo", x: 1350, y: 210}]);
} finally {
path.projection().rotate([0, 0]);
}
}
}
2012-11-14 15:49:47 +04:00
},
2012-11-21 13:55:00 +04:00
"antemeridian cutting": {
"rotate([98, 0])": {
topic: function() {
return d3.geo.path()
.context(testContext)
.projection(d3.geo.equirectangular()
.scale(900 / Math.PI)
.rotate([98, 0])
.precision(0));
},
"small U.S. county polygons": {
"Keweenaw": function(path) {
path({
type: "Polygon",
coordinates: [[[-88.23013, 47.198326], [-88.514931, 47.285957], [-88.383484, 47.285957], [-88.23013, 47.198326]]]
});
assert.equal(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }).length, 1);
},
"Accomack": function(path) {
path({
type: "MultiPolygon",
coordinates: [
[[[-75.397659, 38.013497], [-75.244304, 38.029928], [-75.666029, 37.465803], [-75.939876, 37.547957], [-75.671506, 37.95325], [-75.622213, 37.991589], [-75.397659, 38.013497]]],
[[[-76.016553, 37.95325], [-76.043938, 37.95325], [-75.994645, 37.95325], [-76.016553, 37.95325]]]
]
});
assert.equal(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }).length, 2);
},
"Hopewell": function(path) {
path({
type: "Polygon",
coordinates: [[[-77.298157, 37.312448], [-77.298157, 37.312448], [-77.336496, 37.312448], [-77.281726, 37.312448], [-77.298157, 37.312448]]]
});
assert.equal(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }).length, 1);
}
}
},
2012-11-21 13:55:00 +04:00
"rotate([330, 232])": {
topic: function() {
return d3.geo.path()
.context(testContext)
.projection(d3.geo.equirectangular()
.rotate([330, 232])
.scale(900 / Math.PI)
.precision(0));
},
"degenerate points": function(path) {
path(d3.geo.circle().angle(30)());
assert.equal(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }).length, 2);
}
2012-11-22 23:34:57 +04:00
},
"rotate([34.5, 90])": {
topic: function() {
return d3.geo.path()
.context(testContext)
.projection(d3.geo.equirectangular()
.rotate([34.5, 90])
.scale(900 / Math.PI)
.precision(0));
},
"clip point ordering": function(path) {
var line = d3.range(-90, 180, 10).map(function(x) { return [x, 20]; })
.concat(d3.range(170, -100, -10).map(function(x) { return [x, 0]; }))
.concat([[-90, 20]]);
path({type: "Polygon", coordinates: [line]});
assert.equal(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }).length, 3);
}
2012-11-21 13:55:00 +04:00
}
},
"stereographic.precision(1)": {
topic: function() {
return d3.geo.path()
.context(testContext)
.projection(d3.geo.stereographic()
.precision(1));
},
"correctly resamples points on antemeridian": function(path) {
path({type: "LineString", coordinates: [[0, 90], [90, 0]]});
assert.deepEqual(testContext.buffer(), [
{type: "moveTo", x: 480, y: 100},
{type: "lineTo", x: 509, y: 103},
{type: "lineTo", x: 537, y: 111},
{type: "lineTo", x: 563, y: 125},
{type: "lineTo", x: 586, y: 144},
{type: "lineTo", x: 605, y: 167},
{type: "lineTo", x: 619, y: 193},
{type: "lineTo", x: 627, y: 221},
{type: "lineTo", x: 630, y: 250}
]);
}
},
"albers.precision(1)": {
topic: function() {
return d3.geo.path()
.context(testContext)
.projection(d3.geo.albers()
.scale(140)
.rotate([0, 0])
.precision(1));
},
"resampling near poles": function(path) {
path({type: "LineString", coordinates: [[0, 88], [180, 89]]});
assert.isTrue(testContext.buffer().filter(function(d) { return d.type === "lineTo"; }).length > 1);
path({type: "LineString", coordinates: [[180, 90], [1, 89.5]]});
assert.isTrue(testContext.buffer().filter(function(d) { return d.type === "lineTo"; }).length > 1);
}
2012-11-16 13:08:46 +04:00
},
"rotate([0, 0, 0])": {
"longitudes wrap at ±180°": function(path) {
path({type: "Point", coordinates: [180 + 1e-6, 0]});
assert.deepEqual(testContext.buffer(), [{type: "point", x: -420, y: 250}]);
}
2012-11-14 15:49:47 +04:00
}
}
});
var testBuffer = [];
var testContext = {
point: function(x, y) { testBuffer.push({type: "point", x: Math.round(x), y: Math.round(y)}); },
moveTo: function(x, y) { testBuffer.push({type: "moveTo", x: Math.round(x), y: Math.round(y)}); },
lineTo: function(x, y) { testBuffer.push({type: "lineTo", x: Math.round(x), y: Math.round(y)}); },
closePath: function() { testBuffer.push({type: "closePath"}); },
buffer: function() { var result = testBuffer; testBuffer = []; return result; }
};
function feature(o) {
return {type: "Feature", geometry: o};
}
function stripes(a, b) {
return {type: "Polygon", coordinates: [a, b].map(function(d, i) {
var stripe = d3.range(-180, 180, 1).map(function(x) { return [x, d]; });
stripe.push(stripe[0]);
return i ? stripe.reverse() : stripe;
})};
}
2012-11-18 19:53:29 +04:00
var antarctica = {type: "Polygon", coordinates: [[[-58.61414,-64.15246],[-59.04507,-64.36800],[-59.78934,-64.21122],[-60.61192,-64.30920],[-61.29741,-64.54432],[-62.02210,-64.79909],[-62.51176,-65.09302],[-62.64885,-65.48494],[-62.59012,-65.85721],[-62.12007,-66.19032],[-62.80556,-66.42550],[-63.74569,-66.50384],[-64.29410,-66.83700],[-64.88169,-67.15047],[-65.50842,-67.58161],[-65.66508,-67.95388],[-65.31254,-68.36533],[-64.78371,-68.67890],[-63.96110,-68.91398],[-63.19729,-69.22755],[-62.78595,-69.61941],[-62.57051,-69.99174],[-62.27673,-70.38366],[-61.80666,-70.71676],[-61.51290,-71.08904],[-61.37580,-72.01007],[-61.08197,-72.38235],[-61.00366,-72.77426],[-60.69026,-73.16617],[-60.82736,-73.69524],[-61.37580,-74.10674],[-61.96336,-74.43984],[-63.29520,-74.57699],[-63.74569,-74.92974],[-64.35283,-75.26284],[-65.86098,-75.63512],[-67.19281,-75.79191],[-68.44628,-76.00745],[-69.79772,-76.22299],[-70.60072,-76.63449],[-72.20677,-76.67366],[-73.96953,-76.63449],[-75.55597,-76.71288],[-77.24037,-76.71288],[-76.92697,-77.10480],[-75.39929,-77.28106],[-74.28287,-77.55542],[-73.65611,-77.90811],[-74.77253,-78.22163],[-76.49610,-78.12365],[-77.92585,-78.37841],[-77.98466,-78.78991],[-78.02378,-79.18183],[-76.84863,-79.51493],[-76.63322,-79.88721],[-75.36009,-80.25954],[-73.24485,-80.41633],[-71.44294,-80.69062],[-70.01316,-81.00415],[-68.19164,-81.31767],[-65.70427,-81.47445],[-63.25603,-81.74875],[-61.55202,-82.04269],[-59.69141,-82.37585],[-58.71212,-82.84610],[-58.22248,-83.21843],[-57.00811,-82.86569],[-55.36289,-82.57175],[-53.61977,-82.25823],[-51.54364,-82.00352],[-49.76134,-81.72917],[-47.27393,-81.70958],[-44.82570,-81.84673],[-42.80836,-82.08191],[-42.16202,-81.65082],[-40.77143,-81.35689],[-38.24481,-81.33730],[-36.26666,-81.12171],[-34.38639,-80.90617],[-32.31029,-80.76902],[-30.09709,-80.59265],[-28.54980,-80.33793],[-29.25490,-79.98519],[-29.68580,-79.63250],[-29.68580,-79.26022],[-31.62480,-79.29939],[-33.68132,-79.45613],[-35.63991,-79.45613],[-35.91410,-79.08385],[-35.77700,-78.33924],[-35.32654,-78.12365],[-33.89676,-77.88852],[-32.21236,-77.65345],[-30.99805,-77.35951],[-29.78373,-77.06557],[-28.88277,-76.67366],[-27.51175,-76.49734],[-26.16033,-76.36014],[-25.47482,-76.28180],[-23.92755,-76.24258],[-22.45859,-76.10543],[-21.22469,-75.90947],[-20.01037,-75.67434],[-18.91354,-75.43921],[-17.52298,-75.12569],[-16.64158,-74.79253],[-15.70149,-74.49860],[-15.40771,-74.10674],[-16.46532,-73.87161],[-16.11278,-73.46011],[-15.44685,-73.14654],[-14.40880,-72.95058],[-13.31197,-72.71545],[-12.29350,-72.40193],[-11.51006,-72.01007],[-11.02043,-71.53976],[-10.29577,-71.26541],[-9.10101,-71.32422],[-8.61138,-71.65733],[-7.41662,-71.69650],[-7.37745,-71.32422],[-6.86823,-70.93231],[-5.79098,-71.03028],[-5.53637,-71.40261],[-4.34166,-71.46137],[-3.04898,-71.28505],[-1.79549,-71.16743],[-0.65948,-71.22624],[-0.22863,-71.63774],[0.86819,-71.30463],[1.88668,-71.12826],[3.02263,-70.99111],[4.13905,-70.85391],[5.15754,-70.61878],[6.27391,-70.46205],[7.13571,-70.24651],[7.74286,-69.89376],[8.48711,-70.14853],[9.52513,-70.01133],[10.24984,-70.48163],[10.81782,-70.83433],[11.95382,-70.63837],[12.40428,-70.24651],[13.42277,-69.97216],[14.73499,-70.03091],[15.12675,-70.40324],[15.94934,-70.03091],[17.02658,-69.91335],[18.20171,-69.87418],[19.25937,-69.89376],[20.37573,-70.01133],[21.45298,-70.07014],[21.92303,-70.40324],[22.56940,-70.69718],[23.66618,-70.52081],[24.84135,-70.48163],[25.97730,-70.48163],[27.09372,-70.46205],[28.09258,-70.32485],[29.15024,-70.20728],[30.03158,-69.93293],[30.97173,-69.75661],[31.99017,-69.65864],[32.75405,-69.38429],[33.30244,-68.83564],[33.87041,-68.50258],[34.90849,-68.65927],[35.30020,-69.01201],[36.16201,-69.24714],[37.20003,-69.16874],[37.90510,-69.52144],[38.64940,-69.77620],[39.66789,-69.54107],[40.02043,-69.10994],[40.92135,-68.93362],[41.95943,-68.60051],[42.93870,-68.46331],[44.11387,-68.26740],[44.89729,-68.05186],[45.71992,-67.81673],[46.50334,-67.60119],[47.44344,-67.71875],[48.34441,-67.36606],[48.99073,-67.09171],[49.93088,-67.11130],[50.75347,-66.87617],[50.94932,-66.52348],[51.79154,-
suite.export(module);