Skip to content

Commit

Permalink
add bezier examples back as part of examples folder
Browse files Browse the repository at this point in the history
  • Loading branch information
Dane Springmeyer committed Feb 11, 2014
1 parent dd8ac10 commit 04a16f7
Show file tree
Hide file tree
Showing 5 changed files with 2,735 additions and 0 deletions.
69 changes: 69 additions & 0 deletions example/bezier/bezier.geojson
@@ -0,0 +1,69 @@
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": { },
"geometry": {
"type": "LineString",
"coordinates": [ [ -77.032660, 38.913245 ], [ 77.032660, 38.913245 ] ]
}
},
{
"type": "Feature",
"properties": { },
"geometry": {
"type": "LineString",
"coordinates": [ [ -77.032660, 38.913245 ], [ 77.032660, 38.913245 ] ]
}
},
{
"type": "Feature",
"properties": { },
"geometry": {
"type": "LineString",
"coordinates": [ [ -77.032660, 38.913245 ], [ 77.032660, 38.913245 ] ]
}
},
{
"type": "Feature",
"properties": { },
"geometry": {
"type": "LineString",
"coordinates": [ [ -77.032660, 38.913245 ], [ 77.032660, 38.913245 ] ]
}
},
{
"type": "Feature",
"properties": { },
"geometry": {
"type": "LineString",
"coordinates": [ [ -77.032660, 38.913245 ], [ 77.032660, 38.913245 ] ]
}
},
{
"type": "Feature",
"properties": { },
"geometry": {
"type": "LineString",
"coordinates": [ [ -77.032660, 38.913245 ], [ 77.032660, 38.913245 ] ]
}
},
{
"type": "Feature",
"properties": { },
"geometry": {
"type": "LineString",
"coordinates": [ [ -77.032660, 50.913245 ], [ 0, 20.913245 ] ]
}
},
{
"type": "Feature",
"properties": { },
"geometry": {
"type": "LineString",
"coordinates": [ [ -77.032660, 50.913245 ], [ 0, 20.913245 ] ]
}
}
]
}
139 changes: 139 additions & 0 deletions example/bezier/bezier.html
@@ -0,0 +1,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>
35 changes: 35 additions & 0 deletions example/bezier/bezier.js
@@ -0,0 +1,35 @@
function bezier(pts) {
function curve(points) {
var c = [];
var steps = 40;

for (var i = 0; i <= steps; i++) {
var t = i / steps;

var pt = [
Math.pow(1 - t, 3) * points[0][0]
+ 3 * t * Math.pow(1 - t, 2) * points[1][0]
+ 3 * (1 - t) * Math.pow(t, 2) * points[2][0]
+ Math.pow(t, 3) * points[3][0],
Math.pow(1 - t, 3) * points[0][1]
+ 3 * t * Math.pow(1-t,2) * points[1][1]
+ 3 * (1-t) * Math.pow(t,2) * points[2][1]
+ Math.pow(t, 3) * points[3][1]
];
c.push(pt);
}
return c;
}

var c = [];

if (pts.length < 4) return pts;

for (var i = 0; i < pts.length; i += 3) {
if (i + 4 <= pts.length) {
c = c.concat(curve(pts.slice(i, i + 4)));
}
}

return c;
}
87 changes: 87 additions & 0 deletions example/bezier/bezier.py
@@ -0,0 +1,87 @@
from PIL import Image
import math

# http://stackoverflow.com/questions/3515909/question-about-the-implementation-of-bezier-curves

# draws a single point on our image
def drawPoint( img, loc, size=5, color=(0,0,0) ):
px = img.load()
for x in range(size):
for y in range(size):
xloc = loc[0] + x - size/2
yloc = loc[1] + y - size/2
px[ xloc, yloc ] = color


# draws a simple bezier curve with 4 points
def drawCurve( img, points ):

steps = 20
for i in range(steps):

t = i / float(steps)

xloc = math.pow(1-t,3) * points[0][0] \
+ 3*t*math.pow(1-t,2) * points[1][0] \
+ 3*(1-t)*math.pow(t,2) * points[2][0] \
+ math.pow(t,3) * points[3][0]
yloc = math.pow(1-t,3) * points[0][1] \
+ 3*t*math.pow(1-t,2) * points[1][1] \
+ 3*(1-t)*math.pow(t,2) * points[2][1] \
+ math.pow(t,3) * points[3][1]

drawPoint( img, (xloc,yloc), size=2 )


# draws a bezier curve with any number of points
def drawBezier( img, points ):

for i in range(0,len(points),3):
if( i+4 < len(points) ):
drawCurve( img, points[i:i+4] )


# draws a smooth bezier curve by adding points that
# force smoothness
def drawSmoothBezier( img, points ):

newpoints = []

for i in range(len(points)):

# add the next point (and draw it)
newpoints.append(points[i])
drawPoint( img, points[i], color=(255,0,0) )

if( i % 2 == 0 and i>0 and i+1<len(points) ):

# calculate the midpoint
xloc = (points[i][0] + points[i+1][0]) / 2.0
yloc = (points[i][1] + points[i+1][1]) / 2.0

# add the new point (and draw it)
newpoints.append( (xloc, yloc) )
drawPoint( img, (xloc, yloc), color=(0,255,0) )

drawBezier( img, newpoints )



# Create the image
myImage = Image.new("RGB",(627,271),(255,255,255))

# Create the points
points = [ (54,172),
(121,60),
(220,204),
(284,56),
(376,159),
(444,40),
(515,228),
(595,72) ]

# Draw the curve
drawSmoothBezier( myImage, points )

# Save the image
myImage.save("myfile.png","PNG")

0 comments on commit 04a16f7

Please sign in to comment.