Catenary_animation.gif (150 × 80 pixels, file size: 75 KB, MIME type: image/gif, looped, 90 frames, 5.1 s)
This is a file from the Wikimedia Commons. Information from its description page there is shown below. Commons is a freely licensed media file repository. You can help. |
Summary
DescriptionCatenary animation.gif |
English: Animation of a catenary curve for different seperations of the endpoints. |
Date | |
Source |
Own work |
Author | Geek3 |
Source Code
The image is created by the following source-code. Requirements:
- unix-like command line interface
- python
- scipy
- librsvg
- imagemagick
- lxml archive copy at the Wayback Machine
- gifsicle
python source code:
#!/usr/bin/python
# -*- coding: utf8 -*-
from lxml import etree
import os
import scipy as sc
import scipy.optimize as op
import scipy.integrate as ig
from math import *
class SvgDocument:
'''
creates a svg document structure using lxml.etree
'''
def __init__ (self, name, width=800, height=600, bgcolor='#ffffff',
center=None, unit=1.0):
self.name = name
self.width = int(width)
self.height = int(height)
self.unit = float(unit)
if center == None: self.center = [width / 2., height / 2.]
else: self.center = [float(i) for i in center]
# create document structure
self.svg = etree.Element('svg',
nsmap={None:'http://www.w3.org/2000/svg',
'xlink':'http://www.w3.org/1999/xlink'})
self.svg.set('version', '1.1')
self.svg.set('baseProfile', 'full')
self.svg.set('width', str(int(width)))
self.svg.set('height', str(int(height)))
# title
self.title = etree.SubElement(self.svg, 'title')
self.title.text = self.name
# background
if bgcolor != None:
self.background = etree.SubElement(self.svg, 'rect')
self.background.set('id', 'background')
self.background.set('x', '0')
self.background.set('y', '0')
self.background.set('width', str(width))
self.background.set('height', str(height))
self.background.set('fill', bgcolor)
# image elements
self.content = etree.SubElement(self.svg, 'g')
self.content.set('id', 'image')
self.content.set('transform',
'translate({0},{1}) scale({2},-{2})'.format(
self.center[0], self.center[1], self.unit))
def draw_object(self, name, params, group=None):
'''
Draw arbitraty svg object.
Params must be a dictionary of valid svg parameters.
'''
if group == None:
obj = etree.SubElement(self.content, name)
else:
obj = etree.SubElement(group, name)
for i, j in params.iteritems():
obj.set(str(i), str(j))
return obj
def write(self, filename=None):
# write content to file
if filename == None: filename = self.name
outfile = open(filename + '.svg', 'w')
outfile.write(etree.tostring(self.svg, xml_declaration=True,
pretty_print=True, encoding='utf-8'))
outfile.close()
print 'image written to', filename + '.svg'
# physics: calculate the catenary curve
def catenary(x, r):
# catenary curve f(x) with l=2 and horizontal distance 2r
if r == 1.0:
return 0.0
# search a-value for given length and distance
def fct(a):
if a == 0.0: return r - 1.0
return sinh(r * a) / a - 1.0
x0 = 1.0
while fct(x0) > 0.0: x0 /= 2.0
while fct(2.0 * x0) < 0.0: x0 *= 2.0
a = 1.0 / op.brentq(fct, x0, 2*x0)
return a * (cosh(x / a) - cosh(r / a))
render_mult = 8 # supersampling to improve quality
folder = 'frames'
commands = ['mkdir ' + folder]
for c in commands: print c; os.system(c)
# render frames
frames = 100
names = []
for i in range(frames):
name = 'catenary_{0:0>2}'.format(i)
names.append(name)
w, h = 150, 80
r0 = 65.0
doc = SvgDocument(name, width=w, height=h, center=[w/2, 10], unit=1)
a = 0.5 + 0.5 * cos(i * 2*pi / frames)
r = a**1.5 + 12*a**2 - 21*a**2.5 + 9*a**3
for ri in [-r, r]:
doc.draw_object('circle', {'cx':str(ri*r0), 'cy':'0', 'r':'7',
'style':'fill:#888; stroke:none'})
if r != 0.0:
x = sc.linspace(-r, r, 401)
path_data = zip(r0 * x, [r0 * catenary(xx, r) for xx in x])
else:
path_data = [[0.0, 0.0], [0.0, -r0], [0.0, 0.0]]
# append extra segment to have last point displayed
v = sc.array(path_data[-1]) - sc.array(path_data[-2])
v *= 0.1 / r0 / sqrt(v[0]**2 + v[1]**2)
path_data.append(sc.array(path_data[-1]) + v)
path = 'M ' + ' L '.join([str(xy[0]) + ',' + str(xy[1]) for xy in path_data])
doc.draw_object('path', {'d':path, 'stroke-linecap':'round',
'style':'fill:none; stroke:black; stroke-width:4',
'stroke-linejoin':'round', 'stroke-dasharray':'0,5'})
doc.write(filename=folder + '/' + name)
for name in names:
commands = ['rsvg -w{0} -h{1} {3}/{2}.svg {3}/{2}.png'.format(
w * render_mult, h * render_mult, name, folder),
'rm {1}/{0}.svg'.format(name, folder),
'convert -scale {0}x{1} {3}/{2}.png {3}/{2}.gif'.format(
w, h, name, folder),
'rm {1}/{0}.png'.format(name, folder)]
for c in commands: print c; os.system(c)
commands = ['gifsicle -d5 -l0 --colors 256 '
+ folder + '/*.gif > catenary_animation.gif',
'rm -rf ' + folder]
for c in commands: print c; os.system(c)
Licensing
I, the copyright holder of this work, hereby publish it under the following licenses:
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled GNU Free Documentation License.http://www.gnu.org/copyleft/fdl.htmlGFDLGNU Free Documentation Licensetruetrue |
This file is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported license.
- You are free:
- to share – to copy, distribute and transmit the work
- to remix – to adapt the work
- Under the following conditions:
- attribution – You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
- share alike – If you remix, transform, or build upon the material, you must distribute your contributions under the same or compatible license as the original.
You may select the license of your choice.
Items portrayed in this file
depicts
author name string<\/a>"}},"text\/plain":{"en":{"":"author name string"}}},"{\"value\":\"Geek3\",\"type\":\"string\"}":{"text\/html":{"en":{"P2093":"Geek3","P4174":"Geek3<\/a>"}},"text\/plain":{"en":{"P2093":"Geek3","P4174":"Geek3"}}},"{\"value\":{\"entity-type\":\"property\",\"numeric-id\":4174,\"id\":\"P4174\"},\"type\":\"wikibase-entityid\"}":{"text\/html":{"en":{"":"Wikimedia username<\/a>"}},"text\/plain":{"en":{"":"Wikimedia username"}}},"{\"value\":{\"entity-type\":\"property\",\"numeric-id\":2699,\"id\":\"P2699\"},\"type\":\"wikibase-entityid\"}":{"text\/html":{"en":{"":"URL<\/a>"}},"text\/plain":{"en":{"":"URL"}}},"{\"value\":\"https:\\\/\\\/commons.wikimedia.org\\\/wiki\\\/user:Geek3\",\"type\":\"string\"}":{"text\/html":{"en":{"P2699":"https:\/\/commons.wikimedia.org\/wiki\/user:Geek3<\/a>"}},"text\/plain":{"en":{"P2699":"https:\/\/commons.wikimedia.org\/wiki\/user:Geek3"}}}}" class="wbmi-entityview-statementsGroup wbmi-entityview-statementsGroup-P170 oo-ui-layout oo-ui-panelLayout oo-ui-panelLayout-framed">
copyrighted<\/a>"}},"text\/plain":{"en":{"P6216":"copyrighted"}}}}" class="wbmi-entityview-statementsGroup wbmi-entityview-statementsGroup-P6216 oo-ui-layout oo-ui-panelLayout oo-ui-panelLayout-framed">
Creative Commons Attribution-ShareAlike 3.0 Unported<\/a>"}},"text\/plain":{"en":{"P275":"Creative Commons Attribution-ShareAlike 3.0 Unported"}}},"{\"value\":{\"entity-type\":\"item\",\"numeric-id\":50829104,\"id\":\"Q50829104\"},\"type\":\"wikibase-entityid\"}":{"text\/html":{"en":{"P275":"GNU Free Documentation License, version 1.2 or later<\/a>"}},"text\/plain":{"en":{"P275":"GNU Free Documentation License, version 1.2 or later"}}}}" class="wbmi-entityview-statementsGroup wbmi-entityview-statementsGroup-P275 oo-ui-layout oo-ui-panelLayout oo-ui-panelLayout-framed">
original creation by uploader<\/a>"}},"text\/plain":{"en":{"P7482":"original creation by uploader"}}}}" class="wbmi-entityview-statementsGroup wbmi-entityview-statementsGroup-P7482 oo-ui-layout oo-ui-panelLayout oo-ui-panelLayout-framed">
October 2010
image/gif
determination method or standard<\/a>"}},"text\/plain":{"en":{"":"determination method or standard"}}},"{\"value\":{\"entity-type\":\"item\",\"numeric-id\":13414952,\"id\":\"Q13414952\"},\"type\":\"wikibase-entityid\"}":{"text\/html":{"en":{"P459":"SHA-1<\/a>"}},"text\/plain":{"en":{"P459":"SHA-1"}}}}" class="wbmi-entityview-statementsGroup wbmi-entityview-statementsGroup-P4092 oo-ui-layout oo-ui-panelLayout oo-ui-panelLayout-framed">
c58f33fb2dba9864f699017027d46ad4c67095b6
77,108 byte
5.099999999999992 second
80 pixel
150 pixel
File history
Click on a date/time to view the file as it appeared at that time.
Date/Time | Thumbnail | Dimensions | User | Comment | |
---|---|---|---|---|---|
current | 10:26, 11 August 2014 | 150 × 80 (75 KB) | Ev9n | Background converted to transparent. | |
19:27, 16 October 2010 | 150 × 80 (81 KB) | Geek3 | own work |
File usage
The following page uses this file:
Global file usage
The following other wikis use this file:
- Usage on de.wikipedia.org
- Usage on es.wikipedia.org
- Usage on fa.wikipedia.org
- Usage on he.wikipedia.org
- Usage on hy.wikipedia.org
- Usage on it.wikipedia.org
- Usage on no.wikipedia.org
- Usage on sw.wikipedia.org
- Usage on zh.wikipedia.org
Metadata
This file contains additional information, probably added from the digital camera or scanner used to create or digitize it.
If the file has been modified from its original state, some details may not fully reflect the modified file.
Unique ID of original document | xmp.did:1426D522A0236811822A9F6CF5CCF9DF |
---|---|
Software used | Adobe Photoshop CS6 (Macintosh) |
Retrieved from "https://en.wikipedia.org/wiki/File:Catenary_animation.gif"