File:Ballistic-trajectories-planet.svg

Uploaded by Geek3
Upload date 2020-10-13T13:03:58Z
MIME type image/svg+xml
Dimensions 600 × 600 px
File size 3.0 KB

Summary

Description
English: Plot of two ballistic trajectories with identical initial velocity, one with a uniform gravity field (blue) and one in the central potential field of a planet (orange). The trajectories are one parabola and one ellipse, respectively. The graphical representation is accurately computed using the script, given below.
Date
Source Own work
Author Geek3
Other versions Ballistic-trajectories-planet2.svg
SVG development
InfoField
 The SVG code is valid.
 This vector image was created with Python.
Source code
InfoField

Python code

Python svgwrite code
#!/usr/bin/python3
# -*- coding: utf8 -*-

try:
    import svgwrite
except ImportError:
    print("requires svgwrite library: https://pypi.org/project/svgwrite/")
    # documentation at https://svgwrite.readthedocs.io/
    exit(1)

from math import *

# document
size = 600, 600
name = "Ballistic-trajectories-planet"
doc = svgwrite.Drawing(name + ".svg", profile="full", size=size)
doc.set_desc(name, name + """.svg
https://commons.wikimedia.org/wiki/File:""" + name + """.svg
rights: Creative Commons Attribution-Share Alike 4.0 International license""")

# background
doc.add(doc.rect(id="background", insert=(0, 0), size=size, fill="white", stroke="none"))

cx, cy = 140, 530
R = 440
lw = 5
dash = "4,10"
c1, c2 = "#0072bd", "#d95319"
vx, vy = 0.5, 0.5 # in units of sqrt(R*g)

# gradients
rgrad = doc.defs.add(doc.radialGradient(id='rgrad', center=(0.5,0.5), r=0.5, gradientUnits='objectBoundingBox'))
rgrad.add_stop_color(offset=0.8, color='#ffffff')
rgrad.add_stop_color(offset=1, color='#ddc099')
lgrad = doc.defs.add(doc.linearGradient(id='lgrad', start=(0,0), end=(0,1), gradientUnits='objectBoundingBox'))
lgrad.add_stop_color(offset=0, color='#ddc099')
lgrad.add_stop_color(offset=1, color='#ffffff')

g = doc.add(doc.g(transform="translate({:.1f}, {:.1f})".format(cx, cy), fill="none"))
g.add(doc.rect(insert=(-cx, -R), size=(size[0], 0.2*R), fill="url(#lgrad)", stroke="none"))
g.add(doc.path(d="M {:.1f},{:.1f} h {:.1f}".format(-cx, -R, size[0]), stroke="black", stroke_width="3"))
g.add(doc.circle(r=str(R), center=(0,0), fill="url(#rgrad)", stroke="black", stroke_width="3"))

# trajectories
def parabola(x1, x2, abc): # using a quadratic Bezier curve
    a, b, c = abc
    y1 = a + b * x1 + c * x1**2
    y2 = a + b * x2 + c * x2**2
    txt = "M {:.1f},{:.1f} Q {:.1f},{:.1f} {:.1f},{:.1f}"
    return txt.format(x1, y1, (x1+x2)/2, (y1+y2)/2 - c/2*(x2-x1)**2, x2, y2)

def ellipse(p1, p2, abphi, l): # using arc
    a, b, phi = abphi
    c = 1
    if (pi/2-phi) % (2 * pi) > pi:
        c = 1 - c
    txt = "M {:.1f},{:.1f} A {:.1f},{:.1f} {:.1f} {:} {:} {:.1f},{:.1f}"
    return txt.format(p1[0], p1[1], a, b, degrees(phi), l, c, p2[0], p2[1])

p0 = (0, -R)
p1 = (2 * R * vx * vy, -R)
abc = -R, -vy / vx, 0.5 / R / vx**2
E2 = 2 - vx**2 - vy**2
a = R / E2
b = R * fabs(vx) / sqrt(E2)
phi = asin(vx / sqrt(E2) * sqrt((2 * a * R - b**2 - R**2) / (a**2 - b**2))) - pi/2
p2 = (-R * sin(2 * phi), R * cos(2 * phi))
abphi = a, b, phi
g.add(doc.path(d=ellipse(p2, p0, abphi, 1),
    stroke=c2, stroke_width=lw, stroke_dasharray=dash))
g.add(doc.path(d=parabola(-cx, 0, abc) + " " + parabola(2*R*vx*vy, size[0]-cx, abc),
    stroke=c1, stroke_width=lw, stroke_dasharray=dash))
g.add(doc.path(d=ellipse(p0, p2, abphi, 0), stroke=c2, stroke_width=lw))
g.add(doc.path(d=parabola(p0[0], p1[0], abc), stroke=c1, stroke_width=lw))

# arrows
arrowd = "M {:.1f},{:.1f} V {:.1f} M {:.1f},{:.1f} L {:.1f},{:.1f} L {:.1f},{:.1f}".format(
    0, 0, 0.25*R, -0.03*R, 0.2*R, 0, 0.25*R, 0.03*R, 0.2*R)
g.add(doc.path(transform="translate(0, {:.1f})".format(-R), d=arrowd,
    stroke="#777777", stroke_width="7", fill="none", stroke_linecap="butt"))
g.add(doc.path(transform="translate({:.1f}, {:.1f})".format(*p1), d=arrowd,
    stroke="#777777", stroke_width="7", fill="none", stroke_linecap="butt"))
g.add(doc.path(transform="rotate({:.2f}) translate(0, {:.1f})".format(degrees(2*phi-pi), -R), d=arrowd,
    stroke="#777777", stroke_width="7", fill="none", stroke_linecap="butt"))

g.add(doc.circle(r="6", center=(0,0), fill="black", stroke="none"))
g.add(doc.circle(r="6", center=p0, fill="black", stroke="none"))
g.add(doc.circle(r="6", center=p1, fill="black", stroke="none"))
g.add(doc.circle(r="6", center=p2, fill="black", stroke="none"))

# text
g.add(doc.text("g", font_size="30px", font_family="Bitstream Vera Sans",
    text_anchor="middle", transform="translate({:.1f}, {:.1f})".format(19, -0.87*R), stroke="none", fill="black"))
g.add(doc.text("g", font_size="30px", font_family="Bitstream Vera Sans",
    text_anchor="middle", transform="translate({:.1f}, {:.1f})".format(19+p1[0], -0.87*R), stroke="none", fill="black"))
g.add(doc.text("g'", font_size="30px", font_family="Bitstream Vera Sans",
    text_anchor="middle", transform="translate({:.1f}, {:.1f})".format(0.56*R,-0.63*R), stroke="none", fill="black"))

doc.save(pretty=True)

Licensing

I, the copyright holder of this work, hereby publish it under the following license:
w:en:Creative Commons
attribution share alike
This file is licensed under the Creative Commons Attribution-Share Alike 4.0 International 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.

Captions

Add a one-line explanation of what this file represents

Items portrayed in this file

depicts

image/svg+xml

e428c76eb2fec1e4a8bb802f1a4cd076772de585

3,049 byte

600 pixel

600 pixel