Merge two polygons not sharing vertices.
Built with blockbuilder.org
Merge two polygons not sharing vertices.
Built with blockbuilder.org
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<script src="//d3js.org/d3.v3.min.js"></script> | |
<script src="//d3js.org/d3.geo.projection.v0.min.js"></script> | |
<script src="//d3js.org/topojson.v1.min.js"></script> | |
<style> | |
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } | |
svg { width:100%; height: 100% } | |
.A { | |
fill: red; | |
stroke: yellow; | |
stroke-width: 0.5; | |
} | |
.B { | |
fill: orange; | |
stroke: blue; | |
stroke-width: 0.5; | |
} | |
.pointA { | |
stroke: black; | |
stroke-width: 1.5; | |
fill: none; | |
} | |
.pointB { | |
stroke: blue; | |
stroke-width: 1.5; | |
fill: none; | |
} | |
.merged { | |
fill: green; | |
} | |
</style> | |
</head> | |
<body> | |
<div id='map'></div> | |
<script> | |
var width = 960, | |
height = 500; | |
var scale = Math.min(width,height) * 0.5; | |
var svg = d3.select("#map") | |
.append("svg") | |
.attr("width", width) | |
.attr("height", height); | |
var geojObj = { | |
"type": "FeatureCollection", | |
"features": [ | |
{ | |
"type": "Feature", | |
"geometry": {"type": "Polygon", | |
"coordinates": [ | |
[ | |
[ 4, 41], | |
[ 4, 47], | |
[ 6, 47], | |
[ 6, 46], | |
[ 6, 44], | |
[ 6, 43], | |
[ 6, 41], | |
[ 4, 41] | |
] | |
]}, | |
"properties": {"name": "A"} | |
}, | |
{ | |
"type": "Feature", | |
"geometry": {"type": "Polygon", | |
"coordinates": [ | |
[ | |
[ 7, 43], | |
[ 6, 44], | |
[ 6, 46], | |
[ 7, 47], | |
[ 7, 53], | |
[11, 53], | |
[11, 43], | |
[ 7, 43] | |
] | |
]}, | |
"properties": {"name": "B"} | |
} | |
] | |
}; | |
// geojObj converted to topojson via http://jeffpaine.github.io/geojson-topojson/ | |
// the following needs the lib.js from above link to work | |
// var topojsonOutput = topojson.topology({ | |
// collection: geojObj | |
// }); | |
var topoObj = { | |
"type": "Topology", | |
"objects": { | |
"collection": { | |
"type": "GeometryCollection", | |
"geometries": [ | |
{ | |
"type": "Polygon", | |
"arcs": [ | |
[ | |
0, | |
1 | |
] | |
] | |
}, | |
{ | |
"type": "Polygon", | |
"arcs": [ | |
[ | |
-1, | |
2 | |
] | |
] | |
} | |
] | |
} | |
}, | |
"arcs": [ | |
[ | |
[ | |
2857, | |
4166 | |
], | |
[ | |
0, | |
-1666 | |
] | |
], | |
[ | |
[ | |
2857, | |
2500 | |
], | |
[ | |
0, | |
-833 | |
], | |
[ | |
0, | |
-1667 | |
], | |
[ | |
-2857, | |
0 | |
], | |
[ | |
0, | |
5000 | |
], | |
[ | |
2857, | |
0 | |
], | |
[ | |
0, | |
-834 | |
] | |
], | |
[ | |
[ | |
2857, | |
4166 | |
], | |
[ | |
1428, | |
834 | |
], | |
[ | |
0, | |
4999 | |
], | |
[ | |
5714, | |
0 | |
], | |
[ | |
0, | |
-8332 | |
], | |
[ | |
-5714, | |
0 | |
], | |
[ | |
-1428, | |
833 | |
] | |
] | |
], | |
"bbox": [ | |
4, | |
41, | |
11, | |
53 | |
], | |
"transform": { | |
"scale": [ | |
0.0007000700070007002, | |
0.0012001200120012002 | |
], | |
"translate": [ | |
4, | |
41 | |
] | |
} | |
}; | |
// find proper scale and translation from bounds of europe polygon | |
var projection = d3.geo.azimuthalEqualArea() | |
.scale(1) | |
.translate([0,0]) | |
.clipAngle(180 - 1e-3) | |
.precision(0.1); | |
var path = d3.geo.path().projection(projection); | |
var b = path.bounds(geojObj), | |
s = .95 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height), | |
t = [(width - s * (b[1][0] + b[0][0])) / 2, (height - s * (b[1][1] + b[0][1])) / 2]; | |
// Update the projection to use computed scale & translate. | |
projection | |
.scale(s) | |
.translate(t); | |
var graticule = d3.geo.graticule(); | |
svg.selectAll(".geojson").data(geojObj.features) | |
.enter() | |
.append("path") | |
.attr("class",function(d){return d.properties.name;}) | |
.attr("d", path); | |
var pointsA = geojObj.features[0].geometry.coordinates[0], | |
pointsB = geojObj.features[1].geometry.coordinates[0]; | |
svg.selectAll(".pointA") | |
.data(pointsA) | |
.enter() | |
.append("circle") | |
.attr("class", "pointA") | |
.attr("cx", function(d) { | |
console.log(d); | |
return projection([d[0], d[1]])[0]; | |
}) | |
.attr("cy", function(d) { | |
return projection([d[0], d[1]])[1]; | |
}) | |
.attr("r", 5); | |
svg.selectAll(".pointB") | |
.data(pointsB) | |
.enter() | |
.append("path") | |
.attr("transform", function(d) { | |
return "translate(" + | |
projection([d[0], d[1]])[0] + "," + | |
projection([d[0], d[1]])[1] + ")"; | |
}) | |
.attr("d", d3.svg.symbol().type("triangle-up")); | |
svg.append("path") | |
.datum( | |
topojson.merge( | |
topoObj, | |
topoObj.objects.collection.geometries.filter( | |
function(d){ | |
return true; | |
} | |
))) | |
.attr("class", "merged") | |
.attr("transform", "translate(240, 0)") | |
.attr("d", path); | |
</script> | |
</body> | |