Finding intersection between straight line and contour - python

I am trying to find the intersection point of a straight(dashed red) with the contour-line highlighted in red(see plot). I used .get_paths in the second plot to isolate said contour line form the others(second plot).
I have looked at a contour intersection problem, How to find all the intersection points between two contour-set in an efficient way, and have tried to use it as a base but have not been able to reproduce anything useful.
http://postimg.org/image/hz01fouvn/
http://postimg.org/image/m6utofwb7/
Does any one have any ideas?
relevant functions to recreate plot,
#for contour
def p_0(num,t) :
esc_p = np.sum((((-1)**n)*(np.exp(t)**n)*((math.factorial(n)*((n+1)**0.5))**-1)) for n in range(1,num,1))
return esc_p+1
tau = np.arange(-2,3,0.1)
r=[]
p1 = p_0(51,tau)
p2 = p_0(51,tau)
for i in p1:
temp_r=i/p2
r.append(temp_r)
x,y= np.meshgrid(tau,tau)
cs = plt.contour(x, y, np.log(r),50,colors='k')
whichContour =20
pa = CS.collections[whichContour].get_paths()[0]
v = pa.vertices
xx = v[:, 0]
yy = v[:, 1]
plt.plot(xx, yy, 'r-', label='Crossing contour')
#straight line
p=0.75
logp = (np.log(p*np.exp(tau)))
plt.plot(tau,logp)
Current attempt,
import matplotlib
import numpy as np
import matplotlib.cm as cm
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
import math
def intercepting_line() :
matplotlib.rcParams['xtick.direction'] = 'out'
matplotlib.rcParams['ytick.direction'] = 'out'
#fake data
delta = 0.025
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-2.0, 2.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
Z = 10.0 * (Z2 - Z1)
#plot
cs = plt.contour(X,Y,Z)
whichContour = 2 # change this to find the right contour lines
#get the vertices to calculate an intercept with a line
p = cs.collections[whichContour].get_paths()[0]
#see: http://matplotlib.org/api/path_api.html#module-matplotlib.path
v = p.vertices
xx = v[:, 0]
yy = v[:, 1]
#this shows the innermost ring now
plt.plot(xx, yy, 'r--', label='inner ring')
#fake line
x = np.arange(-2, 3.0, 0.1)
y=lambda x,m:(m*x)
y=y(x,0.9)
lineMesh = np.meshgrid(x,y)
plt.plot(x,y,'r' ,label='line')
#get the intercepts, two in this case
x, y = find_intersections(v, lineMesh[1])
print x
print y
#plot the intercepting points
plt.plot(x[0], y[0], 'bo', label='first intercept')
#plt.plot(x[1], y[1], 'rs', label='second intercept')
plt.legend(shadow=True, fancybox=True, numpoints=1, loc='best')
plt.show()
#now we need to calculate the intercept of the vertices and whatever line
#this is pseudo code but works in case of two intercepting contour vertices
def find_intersections(A, B):
# min, max and all for arrays
amin = lambda x1, x2: np.where(x1<x2, x1, x2)
amax = lambda x1, x2: np.where(x1>x2, x1, x2)
aall = lambda abools: np.dstack(abools).all(axis=2)
slope = lambda line: (lambda d: d[:,1]/d[:,0])(np.diff(line, axis=0))
x11, x21 = np.meshgrid(A[:-1, 0], B[:-1, 0])
x12, x22 = np.meshgrid(A[1:, 0], B[1:, 0])
y11, y21 = np.meshgrid(A[:-1, 1], B[:-1, 1])
y12, y22 = np.meshgrid(A[1:, 1], B[1:, 1])
m1, m2 = np.meshgrid(slope(A), slope(B))
m1inv, m2inv = 1/m1, 1/m2
yi = (m1*(x21-x11-m2inv*y21) + y11)/(1 - m1*m2inv)
xi = (yi - y21)*m2inv + x21
xconds = (amin(x11, x12) < xi, xi <= amax(x11, x12),
amin(x21, x22) < xi, xi <= amax(x21, x22) )
yconds = (amin(y11, y12) < yi, yi <= amax(y11, y12),
amin(y21, y22) < yi, yi <= amax(y21, y22) )
return xi[aall(xconds)], yi[aall(yconds)]
At the moment it finds intersecting points but only where the line is uniform, the main reason why I cannot find a solution here is that I dont understand the original authors train of thinking here,
yi = (m1*(x21-x11-m2inv*y21) + y11)/(1 - m1*m2inv)
xi = (yi - y21)*m2inv + x21

Use shapely can find the intersection point, than use the point as the init guess value for fsolve() to find the real solution:
#for contour
def p_0(num,t) :
esc_p = np.sum((((-1)**n)*(np.exp(t)**n)*((math.factorial(n)*((n+1)**0.5))**-1)) for n in range(1,num,1))
return esc_p+1
tau = np.arange(-2,3,0.1)
x,y= np.meshgrid(tau,tau)
cs = plt.contour(x, y, np.log(p_0(51, y)/p_0(51, x)),[0.2],colors='k')
p=0.75
logp = (np.log(p*np.exp(tau)))
plt.plot(tau,logp)
from shapely.geometry import LineString
v1 = cs.collections[0].get_paths()[0].vertices
ls1 = LineString(v1)
ls2 = LineString(np.c_[tau, logp])
points = ls1.intersection(ls2)
x, y = points.x, points.y
from scipy import optimize
def f(p):
x, y = p
e1 = np.log(0.75*np.exp(x)) - y
e2 = np.log(p_0(51, y)/p_0(51, x)) - 0.2
return e1, e2
x2, y2 = optimize.fsolve(f, (x, y))
plt.plot(x, y, "ro")
plt.plot(x2, y2, "gx")
print x, y
print x2, y2
Here is the output:
0.273616328952 -0.0140657435002
0.275317387697 -0.0123646847549
and the plot:

See your contour lines as polylines and plug the vertex coordinates into the implicit line equation (F(P) = a.X + b.Y + c = 0). Every change of sign is an intersection, computed by solving 2x2 linear equations. You need no sophisticated solver.
If you need to detect the contour lines simultaneously, it is not much more complicated: consider the section of the terrain by a vertical plane through the line. You will obtain altitudes by linear interpolation along the edges of the grid tiles that are crossed. Finding the intersections with the grid is closely related to the Bresenham line drawing algorithm.
Then what you get is a profile, i.e. a function of a single variable. Locating the intersections with the horizontal planes (iso-values) is also done by detecting changes of sign.

This is a way that I used to solve this problem
def straight_intersection(straight1, straight2):
p1x = straight1[0][0]
p1y = straight1[0][1]
p2x = straight1[1][0]
p2y = straight1[1][1]
p3x = straight2[0][0]
p3y = straight2[0][1]
p4x = straight2[1][0]
p4y = straight2[1][1]
x = p1y * p2x * p3x - p1y * p2x * p4x - p1x * p2y * p4x + p1x * p2y * p3x - p2x * p3x * p4y + p2x * p3y * p4x + p1x * p3x * p4y - p1x * p3y * p4x
x = x / (p2x * p3y - p2x * p4y - p1x * p3y + p1x * p4y + p4x * p2y - p4x * p1y - p3x * p2y + p3x * p1y)
y = ((p2y - p1y) * x + p1y * p2x - p1x * p2y) / (p2x - p1x)
return (x, y)

While this question is old now, i want to share my answer for this problem for future generations to come.
Actually, there is two more solutions i found to this problem that is relatively efficient.
First solution is using pointPolygonTest in opencv recursively like that.
# Enumerate the line segment points between 2 points
for pt in zip(*line(*p1, *p2)):
if cv2.pointPolygonTest(conts[0], pt, False) == 0: # If the point is on the contour
return pt
Second solution, you can simply draw the contour and line and make a np.logical_and() to get the answer
blank = np.zeros((1000, 1000))
blank_contour = drawContour(blank.copy(), cnt[0], 0, 1, 1)
blank_line = cv2.line(blank.copy(), line[0], line[1], 1, 1)
intersections = np.logical_and(blank_contour, black_line)
points = np.where(intersections == 1)

Related

how to create a square on top of a given Vector. This square should be orthogonal to the given vector

Programming in Python (Blender):
I want to create a square and print all vertices (A;B;C;D) into my console on top of a given Vector. The square should be orthogonal to this vector, like this:
def create_verts_around_point(radius, vert):
# given Vector
vec = np.array([vert[0], vert[1], vert[2]])
# side_length of square
side_length = radius
# Vctor x-direction (1,0,0)
x_vec = np.array([1,0,0])
# Vekctor y-direction (0,1,0)
y_vec = np.array([0,1,0])
# Vector z-direction (0,0,1)
z_vec = np.array([0,0,1])
p1 = vec + (side_length/2) * x_vec + (side_length/2) * y_vec + (side_length/2) * z_vec
p2 = vec - (side_length/2) * x_vec + (side_length/2) * y_vec + (side_length/2) * z_vec
p3 = vec - (side_length/2) * x_vec - (side_length/2) * y_vec + (side_length/2) * z_vec
p4 = vec + (side_length/2) * x_vec - (side_length/2) * y_vec + (side_length/2) * z_vec
But my output looks like this in the end (Square is always parallel to my x-axis and y-axis):
I don't think you're really thinking about this problem in 3D, but see if this is close.
I create a square, perpendicular to the X axis. I then rotate that square based on the angles in x, y, and z. I then position the square at the end of the vector and plot it. I add plot points for the origin and the end of the vector, and I duplicate the last point in the square do it draws all the lines.
import math
import numpy as np
from mpl_toolkits import mplot3d
import matplotlib.pyplot as plt
def create_verts_around_point(sides, vert):
x0, y0, z0 = vert
# Here is the unrotated square.
half = sides/2
square = [
[0, -half,-half],
[0, -half, half],
[0, half, half],
[0, half,-half],
]
# Now find the rotation in each direction.
thetax = math.atan2( z0, y0 )
thetay = math.atan2( z0, x0 )
thetaz = math.atan2( y0, x0 )
# Now rotate the cube, first in x.
cubes = []
txcos = math.cos(thetax)
txsin = math.sin(thetax)
tycos = math.cos(thetay)
tysin = math.sin(thetay)
tzcos = math.cos(thetaz)
tzsin = math.sin(thetaz)
for x,y,z in square:
x,y,z = (x, y * txcos - z * txsin, y * txsin + z * txcos)
x,y,z = (x * txcos - z * txsin, y, x * txsin + z * txcos)
x,y,z = (x * txcos - y * txsin, x * txsin + y * txcos, z)
cubes.append( (x0+x, y0+y, z0+z) )
return cubes
point = (10,10,10)
square = create_verts_around_point(5, point)
points = [(0,0,0),point] + square + [square[0]]
x = [p[0] for p in points]
y = [p[1] for p in points]
z = [p[2] for p in points]
ax = plt.figure().add_subplot(111, projection='3d')
ax.plot( x, y, z )
plt.show()
Output:

Measure integral between 2 curves (linear func & arbitrary curve)

In the img. below my goal is to locate the integral in area 1 / 2 / 3.
In that way that I know how much area below the linear line (area 1 / 3),
and how much area that are above the linear line (area 2)
Im not looking for the exact integral, just an approximately value to measure on. an approx that would work in the same fashion for other version of the curves I have represented.
y1: The blue line is a linear function y= -0.148x + 1301.35
y2:The yellow line is a arbitrary curve
Both curves share the same x axis.
image of curves linear & arbitrary curve
I have tried several methods, found here on stackoverflow, mainly theese 2 methods cought my attention:
https://stackoverflow.com/a/57827807
&
https://stackoverflow.com/a/25447819
They give me the exact same output for the whole area, my issue is to seperate it above / below.
Example of my best try:
(Modified version of https://stackoverflow.com/a/25447819/20441461)
y1 / y2 / x - is the data used for the curves in the img. above
y1 = [1298.54771845, 1298.40019417, 1298.2526699, 1298.10514563,
1297.95762136,1297.81009709, 1297.66257282, 1297.51504854]
y2 = [1298.59, 1297.31, 1296.04, 1297.31, 1296.95, 1299.18, 1297.05, 1297.45]
x = np.arange(len(y1))
z = y1-y2
dx = x[1:] - x[:-1]
cross_test = np.sign(z[:-1] * z[1:])
x_intersect = x[:-1] - dx / (z[1:] - z[:-1]) * z[:-1]
dx_intersect = - dx / (z[1:] - z[:-1]) * z[:-1]
areas_pos = abs(z[:-1] + z[1:]) * 0.5 * dx # signs of both z are same
areas_neg = 0.5 * dx_intersect * abs(z[:-1]) + 0.5 * (dx - dx_intersect) * abs(z[1:])
negatives = np.where(cross_test < 0)
negative_sum = np.sum(x_intersect[negatives])
positives = np.where(cross_test >= 0)
positive_sum = np.sum(x_intersect[positives])`
is give me this result:
Negative integral = 10.15
Positive integral = 9.97
Just from looking at the picture, I can tell that can not be the correct value. ( there is alot more area below the linear line than above.)
I have spend loads of time now on this, and are quite stuck - any advise or suggestion are welcome.
Here is a little bit of code that calculates exactly all the areas, and does so in a vectorized way (fast):
def areas(x, y1, y2, details=None):
dy = y1 - y2
b0 = dy[:-1]
b1 = dy[1:]
b = np.c_[b0, b1]
r = np.abs(b0) / (np.abs(b0) + np.abs(b1))
rr = np.c_[r, 1-r]
dx = np.diff(x)
h = rr * dx[:, None]
br = (b * rr[:, ::-1]).sum(1)
a = (b + br[:, None]) * h / 2
result = np.sum(a[a > 0]), np.sum(a[a < 0])
if details is not None:
details.update(locals()) # for debugging
return result
Example:
x = np.array([0,1,2])
y1 = np.array([1,0,3])
y2 = np.array([0,3,4])
>>> areas(x, y1, y2)
(0.125, -3.125)
Your original example:
y1 = np.array([
1298.54771845, 1298.40019417, 1298.2526699, 1298.10514563,
1297.95762136,1297.81009709, 1297.66257282, 1297.51504854])
y2 = np.array([1298.59, 1297.31, 1296.04, 1297.31, 1296.95, 1299.18, 1297.05, 1297.45])
x = np.arange(len(y1))
>>> areas(x, y1, y2)
(5.228440802728334, -0.8687563377282332)
Explanation
To understand how it works, let us consider the quadrilateral of four points: [a, b, c, d], where a and b are at the same x position, and so are c and d. It can be "straight" if none of the edges intersect, or "twisted" otherwise. In both cases, we consider the x-position of the intersection where the twisted version would intersect, and the actual vertical section of the quadrilateral at that position (0 if twisted, or the weighted average of the vertical sides if straight).
Say we call the vertical distances b0 and b1. They are oriented (positive if y1 > y2). The intersection is at x-coordinate x + r * dx, where r = |b0| / (|b0| + |b1|) and is a factor between 0 and 1.
For a twisted quad, the left (triangular) area is b0*r*dx/2 and the right one is b1*(1-r)*dx/2.
For a straight quad, the left area (trapeze) is (b0 + br)/2 * r * dx and the right is (b1 + br) / 2 * (1 - r) * dx, where br is the height at the r horizontal proportion, and br = b0 * (1 - r) + b1 * r.
To generalize, we always use br in the calculation. For twisted quads, it is 0 and we can use the same expression as for straight quads. This is the key to eliminate any tests and produce a pure vectorized function.
The rest is a bit of numpy expressions to calculate all these values efficiently.
Example detail
def plot_details(details, ax=None):
x, y1, y2, dx, r, a = [details[k] for k in 'x y1 y2 dx r a'.split()]
ax = ax if ax else plt.gca()
ax.plot(x, y1, 'b.-')
ax.plot(x, y2, 'r.-')
xmid = x[:-1] + dx * r
[ax.axvline(xi) for xi in xmid]
xy1 = np.c_[x, y1]
xy2 = np.c_[x, y2]
for A,B,C,D,r,(a0,a1) in zip(xy1, xy2, xy1[1:], xy2[1:], r, a):
ACmid = A*(1-r) + C*r
BDmid = B*(1-r) + D*r
q0 = np.c_[A,ACmid,BDmid,B]
q1 = np.c_[ACmid,C,D,BDmid]
ax.fill(*q0, alpha=.2)
ax.fill(*q1, alpha=.2)
ax.text(*q0.mean(1), f'{a0:.3f}', ha='center')
ax.text(*q1.mean(1), f'{a1:.3f}', ha='center')
Taking the earlier example:
x = np.array([0,1,2])
y1 = np.array([1,0,3])
y2 = np.array([0,3,4])
details = {}
>>> areas(x, y1, y2, details)
(0.125, -3.125)
>>> details
{'x': array([0, 1, 2]),
'y1': array([1, 0, 3]),
'y2': array([0, 3, 4]),
'details': {...},
'dy': array([ 1, -3, -1]),
'b0': array([ 1, -3]),
'b1': array([-3, -1]),
'b': array([[ 1, -3],
[-3, -1]]),
'r': array([0.25, 0.75]),
'rr': array([[0.25, 0.75],
[0.75, 0.25]]),
'dx': array([1, 1]),
'h': array([[0.25, 0.75],
[0.75, 0.25]]),
'br': array([ 0. , -1.5]),
'a': array([[ 0.125 , -1.125 ],
[-1.6875, -0.3125]]),
'result': (0.125, -3.125)}
And:
plot_details(details)
Perhaps you can integrate the absolute difference of both arrays:
>>> np.trapz(np.abs(y2 - y1))
7.1417718350001

Nullcline Plot for Nonlinear System of ODEs

I am attempting to plot the nullcline (steady state) curves of the Oregonator model to assert the existence of a limit cycle by applying the Poincare-Bendixson Theorem. I am close, but for some reason the plot that is produced shows two straight lines. I think it has something to do with the plotting stage. Any ideas?
Also any hints for how to construct a quadrilateral to apply the theorem with would be most appreciated.
Code:
import numpy as np
import matplotlib.pyplot as plt
# Dimensionless parameters
eps = 0.04
q = 0.0008
f = 1
# Oregonator model as numpy array
def Sys(Y, t = 0):
return np.array((Y[0] * (1 - Y[0] - ((Y[0] - q) * f * Y[1]) / (Y[0] + q)) / eps, Y[0] - Y[1] ))
# Oregonator model steady states
def g(x,z):
return (x * (1 - x) + ((q - x) * f * z) / (q + x)) / eps
def h(x,z):
return x - z
# Initial lists containing values
x = []
z = []
def sys(iv1, iv2, dt, time):
# initial values:
x.append(iv1)
z.append(iv2)
# Compute and fill lists
for i in range(time):
x.append(x[i] + (g(x[i],z[i])) * dt)
z.append(z[i] + (h(x[i],z[i])) * dt)
return x, z
sys(1, 0.5, 0.01, 30)
# Locate and find equilibrium points
eqp = []
def find_fixed_points(r):
for x in range(r):
for z in range(r):
if ((g(x, z) == 0) and (h(x, z) == 0)):
eqp.append((x,z))
return eqp
# Plot nullclines
plt.plot([0,2],[2,0], 'r-', lw=2, label='x-nullcline')
plt.plot([1,1],[0,2], 'b-', lw=2, label='z-nullcline')
# Plot equilibrium points
for point in eqp:
plt.plot(point[0],point[1],"red", marker = "o", markersize = 10.0)
plt.legend(loc='best')
x = np.linspace(0, 2, 20)
z = np.linspace(0, 2, 20)
X1 , Z1 = np.meshgrid(x, z) # Create a grid
DX1, DZ1 = Sys([X1, Z1]) # Compute reaction rate on the grid
M = (np.hypot(DX1, DZ1)) # Norm reaction rate
M[ M == 0] = 1. # Avoid zero division errors
DX1 /= M # Normalise each arrows
DZ1 /= M
plt.quiver(X1, Z1, DX1, DZ1, M, pivot='mid')
plt.xlabel("x(\u03C4)")
plt.ylabel("z(\u03C4)")
plt.legend()
plt.grid()
plt.show()

How to plot array with condition (r < 1.5*rs)?

I'm coding photons orbiting a black hole. When the photons go right into the black hole, the trajectory is really weird due to a division by zero. I'd like to ignore the photons of my array with r < 1.5*rs but I don't know how
I've tried using while True and if, it didn't work
h0=[t0, r2, theta, phi2, pt2, pr2, ptheta, pphi2]
T = np.linspace(0, 1000, 9000)
zz=odeint(func, h0, T, args=(rs,))
r22 = zz[:, 1]
theta22 = zz[:, 2]
phi22 = zz[:, 3]
pt22 = zz[:, 4]
pr22 = zz[:, 5]
pphi22 = zz[:, 7]
def sph2cart(r, phi, theta):
X = r * np.cos(phi) * np.sin(theta)
Y = r * np.sin(phi) * np.sin(theta)
Z = r * np.cos(theta)
return(X, Y, Z)
X2, Y2, Z2 = sph2cart(r22, phi22, theta22)
plt.plot(X2, Y2, Z2, 'g')
I don't think you really need the code to help me, but does anyone know how to plot X2, Y2, Z2 for radius r < 1.5*rs (rs is defined in the code)?
Numpy has built in masks which work quite well
r=np.arange(20)
r_mask = np.ma.masked_where(r < 10 , r)
So, since you want to generate X,Y, and Z values only when r<1.5*rs (i think you said it the opposite way at one point, but you'll just need to flip the sign in any case), your code could look like this
import numpy as np
h0=[t0, r2, theta, phi2, pt2, pr2, ptheta, pphi2]
T = np.linspace(0, 1000, 9000)
zz=odeint(func, h0, T, args=(rs,))
r22 = zz[:, 1]
theta22 = zz[:, 2]
phi22 = zz[:, 3]
pt22 = zz[:, 4]
pr22 = zz[:, 5]
pphi22 = zz[:, 7]
def sph2cart(r, phi, theta):
X = r * np.cos(phi) * np.sin(theta)
Y = r * np.sin(phi) * np.sin(theta)
Z = r * np.cos(theta)
return(X, Y, Z)
r22_masked = np.ma.masked_where(r22 > 1.5*rs , r22)
X2, Y2, Z2 = sph2cart(r22_masked, phi22, theta22)
This would generate X2,Y2, and Z2 values only for the unmasked values of r22 (aka where r22 is less than 1.5*rs

Bezier curve surface

I have Bezier curve and I need to make surface of revolution based on this curve. Bezier curve should be rotating around an axis of rotation. How it can be done? Maybe some examples? Dots can be fixed, but only 3
import matplotlib as mpl
import numpy as np
from scipy.misc import comb
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import math
import pylab
def bernstein_poly(i, n, t):
return comb(n, i) * (t**(n - i)) * (1 - t)**i
def bezier_curve(points, nTimes=1000):
nPoints = len(points)
xPoints = np.array([p[0] for p in points])
yPoints = np.array([p[1] for p in points])
zPoints = np.array([p[2] for p in points])
t = np.linspace(0.0, 1.0, nTimes)
polynomial_array = np.array(
[bernstein_poly(i, nPoints - 1, t) for i in range(0, nPoints)])
xvals = np.dot(xPoints, polynomial_array)
yvals = np.dot(yPoints, polynomial_array)
zvals = np.dot(zPoints, polynomial_array)
return xvals, yvals, zvals
from math import pi ,sin, cos
def R(theta, u):
return [[cos(theta) + u[0]**2 * (1-cos(theta)),
u[0] * u[1] * (1-cos(theta)) - u[2] * sin(theta),
u[0] * u[2] * (1 - cos(theta)) + u[1] * sin(theta)],
[u[0] * u[1] * (1-cos(theta)) + u[2] * sin(theta),
cos(theta) + u[1]**2 * (1-cos(theta)),
u[1] * u[2] * (1 - cos(theta)) - u[0] * sin(theta)],
[u[0] * u[2] * (1-cos(theta)) - u[1] * sin(theta),
u[1] * u[2] * (1-cos(theta)) + u[0] * sin(theta),
cos(theta) + u[2]**2 * (1-cos(theta))]]
def Rotate(pointToRotate, point1, point2, theta):
u= []
squaredSum = 0
for i,f in zip(point1, point2):
u.append(f-i)
squaredSum += (f-i) **2
u = [i/squaredSum for i in u]
r = R(theta, u)
rotated = []
for i in range(3):
rotated.append(round(sum([r[j][i] * pointToRotate[j] for j in range(3)])))
return rotated
And main part
if __name__ == "__main__":
nPoints = 3
points = [[0,0,0],[0,1,2],[0,2,1]]#3 points of curve
xvals, yvals, zvals = bezier_curve(points, nTimes=1000)
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot(xvals, yvals, zvals, label='bezier')
p1=[0,0,0]#axis of rotation
p2=[0,0,1]#axis of rotation
angle = pi/12
while angle <= 2*pi:
pp1 = Rotate(points[0], p1, p2, angle)
pp2 = Rotate(points[1], p1, p2, angle)
pp3 = Rotate(points[2], p1, p2, angle)
npoints=[pp1,pp2,pp3]
xnvals, ynvals, znvals = bezier_curve(npoints, nTimes=1000)
ax.plot(xnvals, ynvals, znvals, label='bezier')
angle= angle + pi/24
plt.show()
upd: I do something on this task. But this is not exactly what I need.Now its many lines, not surface. I tried to make a surface, but failed
Upd2:
This is my attempt to make surface of revolution, but its failed too
x = np.arange (0, 0.1, 0.005)
y = np.arange (0, 0.1, 0.005)
xgrid, ygrid = np.meshgrid(x, y)
points = [[0,0,0],[0,1,2],[0,2,1]] #Bezier curve points
p1=[0,0,0]#axis of rotation
p2=[0,0,1]#axis of rotation
angle = pi/12
xval, yval, zval = bezier_curve(points, nTimes=20)
x=xgrid
y=ygrid
z=zval
fig = pylab.figure()
axes = Axes3D(fig)
axes.plot_surface(x, y, z)
while angle <= 2*pi:
pp1 = Rotate(points[0], p1, p2, angle)
pp2 = Rotate(points[1], p1, p2, angle)
pp3 = Rotate(points[2], p1, p2, angle)
npoints=[pp1,pp2,pp3]
x = np.arange (0, 0.1, 0.005)
y = np.arange (0, 0.1, 0.005)
xgrid, ygrid = np.meshgrid(x, y)
xval, yval, zval = bezier_curve(npoints, nTimes=20)
zgrid= zval
x=xgrid
y=ygrid
z=zgrid
axes.plot_surface(x, y, z)
angle= angle + pi/24

Categories

Resources