forked from springmeyer/arc.js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbezier.html
139 lines (126 loc) · 4.5 KB
/
bezier.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
<!DOCTYPE html>
<html>
<head>
<title>Draw Great Circle Arcs with Leaflet</title>
<meta charset="utf-8" />
<script src='polymaps.js'></script>
<script src='sphericalmercator.js'></script>
<script src='bezier.js'></script>
<style>
path {
stroke:#2fa;
fill:transparent;
}
body {
margin:40px auto;
width:800px;
font:14px/20px 'Helvetica';
}
</style>
</head>
<body>
<div style="padding:20px;">
<p><a href="https://github.com/springmeyer/arc.js">source code on github</a></p>
<div id="map" style="width: 800px; height: 600px"></div>
<input type='range' id='spread' min=0 max=7000000 />
spread - the amount that control points are spread around origins
<br />
<input type='range' id='rotate' min=0 max=314 />
rotate - the amount each exit point rotates around the origin
<br />
input
<textarea id='input'></textarea>
<br />
output
<textarea id='output'></textarea>
<button id='load_from_input'>load from input</button>
</div>
<script>
var po = org.polymaps;
var map = po.map()
.container(document.getElementById("map").appendChild(po.svg("svg")))
.zoomRange([0, 9])
.zoom(3)
.center({ lat: 0, lon: 0 })
.add(po.image().url("http://c.tiles.mapbox.com/v3/tmcw.map-cx8atc2i/{Z}/{X}/{Y}.png"))
.add(po.interact());
var lines = po.geoJson();
map.add(lines);
function interpolate_rotate(coordinates, rotate, spread) {
var angle = rotate + Math.atan2(
coordinates[0][1] - coordinates[0][1],
coordinates[1][1] - coordinates[1][1]);
var addone = [
spread * Math.cos(angle) + coordinates[0][0],
spread * Math.sin(angle) + coordinates[0][1]];
var addtwo = [
spread * Math.cos(-angle + Math.PI) + coordinates[1][0],
spread * Math.sin(-angle + Math.PI) + coordinates[1][1]];
return [
coordinates[0],
addone,
addtwo,
coordinates[1]];
}
var espread = document.getElementById('spread');
var erotate = document.getElementById('rotate');
var eload = document.getElementById('load_from_input');
var einput = document.getElementById('input');
var eoutput = document.getElementById('output');
po.queue.json('bezier.geojson', function(gj) {
bindgj(gj);
});
var sm = new SphericalMercator();
function bindgj(gj) {
var overlaps = {};
for (var i = 0; i < gj.features.length; i++) {
var count = 0;
if (overlaps[gj.features[i].geometry.coordinates.join(',')] === undefined) {
count = overlaps[gj.features[i].geometry.coordinates.join(',')] = 0;
} else {
count = ++overlaps[gj.features[i].geometry.coordinates.join(',')];
}
gj.features[i]._idx = gj.features[i].geometry.coordinates.join(',');
gj.features[i]._count = count;
}
refeature = function() {
var spread = espread.value;
var rotate = erotate.value / 100;
var feat = gj.features.map(function(x) {
var f = {
'type': 'Feature',
'geometry': {
'type': 'LineString',
'coordinates': x.geometry.coordinates.slice()
}
};
for (var i = 0; i < f.geometry.coordinates.length; i++) {
f.geometry.coordinates[i] = sm.forward(f.geometry.coordinates[i]);
}
if (x._count) {
var turn = Math.ceil(x._count / 2) * ((x._count % 2) ? 1 : -1)
/ (overlaps[x._idx] / 2);
f.geometry.coordinates = interpolate_rotate(f.geometry.coordinates, turn * rotate, spread);
f.geometry.coordinates = bezier(f.geometry.coordinates);
} else {
f.geometry.coordinates = f.geometry.coordinates;
}
for (var i = 0; i < f.geometry.coordinates.length; i++) {
f.geometry.coordinates[i] = sm.inverse(f.geometry.coordinates[i]);
}
return f;
});
lines.features(feat);
eoutput.value = JSON.stringify({type: 'FeatureCollection', features: feat });
}
espread.onchange = refeature;
erotate.onchange = refeature;
refeature();
}
eload.onclick = function() {
var gj = JSON.parse(einput.value);
bindgj(gj);
}
</script>
</body>
</html>