Skip to content

Instantly share code, notes, and snippets.

@jldiaz
Last active February 9, 2017 16:48
Show Gist options
  • Save jldiaz/c938af939173edbe5f6fcb7f7ea50dca to your computer and use it in GitHub Desktop.
Save jldiaz/c938af939173edbe5f6fcb7f7ea50dca to your computer and use it in GitHub Desktop.
# This code was used to create the answer
# http://tex.stackexchange.com/a/352766/12571
from scipy.optimize import fsolve
from math import *
import numpy as np
def ellipse(a,b,t):
return (a*cos(t), b*sin(t))
def distance(p1,p2):
return sqrt((p1[0]-p2[0])**2 + (p1[1]-p2[1])**2)
def generate_equations(n, a, b, x_0=0):
"""Generates a function suitable to be solved by scipy.optimize.fsolve
This functions creates the set of equations to solve to place n
points in the edge of an ellipse of radii (a,b), so that all points
are equi-distant. x_0 is the angle for the first point"""
result = []
result.append("def equations(p):")
result.append(" {unknowns} = p"
.format(unknowns = ",".join("x_{i}".format(i=i) for i in range(n+1)))
)
distance_equations = []
for i in range(n):
next_i = (i+1) % n
distance_to_next = "distance(ellipse(a,b,x_{i}), ellipse(a,b,x_{next_i}))"\
.format(a=a, b=b, i=i, next_i=next_i)
distance_equations.append(distance_to_next)
for i in range(n-1):
next_i = (i+1) % n
result.append(" f_{i} = {eq_i} - {eq_i_next}"
.format(i=i, eq_i=distance_equations[i],
eq_i_next = distance_equations[next_i])
)
result.append(" f_{i} = x_0 - {x_0}"
.format(i=n-1, x_0=x_0))
result.append(" f_{i} = {any_distance} - x_{n}"
.format(i=n, any_distance = distance_equations[-1], n=n))
result.append(" return({equations})"
.format(equations = ",".join("f_{i}".format(i=i) for i in range(n+1)))
)
return "\n".join(result)
def generate_equations_old(n, a, b, t_0=0):
"""Generates a function suitable to be solved by scipy.optimize.fsolve
This functions creates the set of equations to solve to place n
points in the edge of an ellipse of diameter (a,b), so that all points
are equi-distant. t_0 is the angle for the first point"""
result = []
result.append("from math import *")
result.append("def equations(p):")
result.append(" {unknowns} = p"
.format(unknowns = ",".join("t_{i}".format(i=i) for i in range(n+1)))
)
distance_equations = []
for i in range(n):
next_i = (i+1) % n
distance_to_next = "sqrt(({a}*cos(t_{i}) - {a}*cos(t_{next_i}))**2 "\
"+ ({b}*sin(t_{i}) - {b}*sin(t_{next_i}))**2)"\
.format(a=a, b=b, i=i, next_i=next_i)
distance_equations.append(distance_to_next)
for i in range(n-1):
next_i = (i+1) % n
result.append(" f_{i} = {eq_i} - {eq_i_next}"
.format(i=i, eq_i=distance_equations[i],
eq_i_next = distance_equations[next_i])
)
result.append(" f_{i} = t_0 - {t_0}"
.format(i=n-1, t_0=t_0))
result.append(" f_{i} = {any_distance} - t_{n}"
.format(i=n, any_distance = distance_equations[0], n=n))
result.append(" return({equations})"
.format(equations = ",".join("f_{i}".format(i=i) for i in range(n+1)))
)
return "\n".join(result)
def generate_tikz_list(r):
return ",".join(["%f/%f" % (ellipse(a,b,x)) for x in r])
def print_tikzpicture(a,b,n,l):
print(r"""
\begin{tikzpicture}
\fill[white] (-3.5, -1.5) rectangle (3.5, 1.5);
\draw[blue] (0,0) ellipse(%d and %d);
\foreach \x/\y [count=\n from 0] in {%s} {
\node[fill=blue,circle] (node-\n) at (\x,\y) {};
}
\foreach \n [remember=\n as \previous (initially 0)] in {1,...,%d} {
\draw[thick,red] (node-\previous.center) -- (node-\n.center);
}
\node[fill=yellow, circle] at (node-0) {};
\draw[thick,red] (node-%d.center) -- (node-0.center);
\end{tikzpicture}
""" % (a, b, l, n-1, n-1))
import sys
from math import *
# Parameters for the ellipse
a = 3
b = 1
n = 7 # Number of nodes
for angle in range(0,360,2):
# Generate the code which defines the equations
eqs = generate_equations(n,a,b,radians(angle))
# Execute that code to define function "equations"
exec(eqs)
# Use simpy to solve the equations
print("angle=", angle, file=sys.stderr)
r = fsolve(equations, np.append(np.linspace(radians(angle), radians(angle)+ 2*pi, n, endpoint=False), [2*a]))
# Convert the solution to tikz syntax
tikz_points = generate_tikz_list(r[:-1])
print_tikzpicture(a,b,n,tikz_points)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment