#!/usr/bin/env python
#
# Author: Fredrik Sandin, fredrik.sandin@gmail.com
#
# This is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with dircheck; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
"""
SYNOPSIS
./make_shellmap.py [radius] [sections] [overlap]
ARGUMENTS
radius: The radius of the shell in mm.
sections: Number of sections. The number of sections
that you need in order to avoid wrinkles
and difficulties when pasting the paper
depends on the radius and the thickness
of the paper. 3 is an absolute minimum,
which might be ok for small hemispheres.
overlap: Approximate overlap along the seams in-
between the sections, in mm.
DESCRIPTION
Creates a 2d map that can be used to cut paper
for the manufacturing of paper (hemi)spheres,
e.g., for firework aerial shells. This program
uses XMGrace, which can be downloaded from:
http://plasma-gate.weizmann.ac.il/Grace/
Author: Fredrik Sandin
E-mail: fredrik.sandin@gmail.com
"""
import os
from math import *
from sys import argv
from tempfile import NamedTemporaryFile
# A few notes - well-documented code ;-)
# O_uv = 2 pi r theta (spherical coordinates)
# O_hs = 2 pi r sin(theta)
#
# Delta O = 2 pi r (theta - sin(theta))
# r_uv = r theta
#
# Delta O = 2 pi r_uv - 2 pi r sin(r_uv / r)
def make_seam(x,y,r,steps,N):
r_uv = r*0.5*pi / steps
while r_uv <= r*0.5*pi+1e-9:
odiff = 2*pi*(r_uv - r*sin(r_uv / r))
dphi = odiff / (r_uv * N)
phi = -dphi/2
x.append(r_uv*cos(phi))
y.append(r_uv*sin(phi))
r_uv += r*0.5*pi / steps
def make_overlap_seam(x,y,r,steps,N,overlap):
make_seam(x,y,r,steps,N)
for i in range(len(y)-1,-1,-1):
y[i] += overlap
if y[i]>0:
y.remove(y[i])
x.remove(x[i])
def make_circle(x,y,r,steps,N,overlap):
# overlap ~ r_uv*dphi2 --> dphi2 ~ overlap/r_uv
r_uv = r*0.5*pi
odiff = 2*pi*(r_uv - r*sin(r_uv / r))
dphi = odiff / (r_uv * N)
dphi2 = 0.8*overlap / r_uv
phi = -2*pi/N+dphi/2-dphi2
while phi <= -dphi/2+dphi2:
x.append(r_uv*cos(phi))
y.append(r_uv*sin(phi))
phi += (0.5*pi-dphi)/steps
def make_cut_line(x,y,r,steps,N,overlap):
make_circle(x,y,r,steps,N,overlap)
tx = list()
ty = list()
make_overlap_seam(tx,ty,r,steps,N,overlap)
tx.reverse()
ty.reverse()
for xi in tx:
x.append(xi)
for yi in ty:
y.append(yi)
x.append(min(tx)-2*overlap)
y.append(0)
tx.reverse()
ty.reverse()
for xi in tx:
x.append(xi)
for yi in ty:
y.append(-yi)
n = len(x)
for i in range(1,N):
phi = 2*pi*i/N
# Use 2d rotation matrix to assemble all sections
for j in range(0,n):
x.append(cos(phi)*x[j] - sin(phi)*y[j])
y.append(sin(phi)*x[j] + cos(phi)*y[j])
if len(argv) != 4:
print """Expected ./make_shellmap.py [radius] [sections] [overlap]
radius: The radius of the shell in mm.
sections: Number of sections. The number of sections
that you need in order to avoid wrinkles
and difficulties when pasting the paper
depends on the radius and the thickness
of the paper. 3 is an absolute minimum,
which might be ok for small hemispheres.
overlap: Approximate overlap along the seams in-
between the sections, in mm.
"""
exit(1)
# Create datafile
radius = float(argv[1])
sections = int(argv[2])
overlap = float(argv[3])
radialsteps=100
dat = NamedTemporaryFile()
x = []
y = []
make_cut_line(x,y,radius,radialsteps,sections,overlap)
for i in range(0,len(x)):
dat.write('%g %g\n' % (x[i], y[i]))
dat.flush()
# Create configuration file for XMGrace
conf = NamedTemporaryFile()
size = int((radius*pi/2)/10+1)*10
conf.write("""
frame type 0
world -%d, -%d, %d, %d
view 0.000000, 0.000000, 1.000000, 1.000000
xaxis ticklabel off
yaxis ticklabel off
xaxis tick major 10
xaxis tick minor ticks 0
yaxis tick major 10
yaxis tick minor ticks 0
with string
string on
string loctype view
string 0.38, 0.52
string color 1
string rot 0
string font 0
string just 0
string char size 1.000000
string def \"R: %gmm, O: %gmm\\n10mm between ticks\\n%gmm x %gmm frame\"
""" % (size,size,size,size,radius,overlap,2*size,2*size))
conf.flush()
os.system('xmgrace -hardcopy -hdevice EPS -printfile map.eps -batch %s %s 2> /dev/null ; epstopdf map.eps ; rm ./map.eps' % (conf.name, dat.name))
print 'map.pdf created'
# EOF