Dimensions issue in 3D plotting - scilab

I have wrote the following code in scilab and want to plot it but the plot is not look like 3D. Basically the problem is dimensions, x and y are 1 cross 5 matrices and the function f is 5 cross 5 matrix. I tried to make x and y 5 dimensional by using meshgrid but then the functions can't give me result with that modified values of meshgrid(x,y). The whole code is here.
clear; clc;
//Defining the range of Cartesian coordinates (x,y,z)
x = linspace(1,30,5);
y = linspace(0,30,5);
z = linspace(0,30,5);
//------------------------------------------------------------------------------
//This funciton transform Cartesian to Spherical coordinates
function [r, theta, phi]=cart2sph(x, y, z)
r = sqrt(x^2+y^2+z^2);
theta = atan(y./x)
phi = acos(z./sqrt(x^2+y^2+z^2))'
endfunction
//------------------------------------------------------------------------------
//To get the spherical coordinates from Cartesian uing the above funciton
[r, theta, phi]=cart2sph(x, y, z)
//------------------------------------------------------------------------------
//Defining spherical hormonic as a funciton of shperical coordinates here.
function [y]=Y(l, m, theta, phi)
if m >= 0 then
y = (-1)^m/(sqrt(2*%pi))*exp(%i*m*phi)*legendre(l, m, cos(theta), "norm")
else
y = 1/(sqrt(2*%pi))*exp(%i*m*phi)*legendre(l, -m, cos(theta), "norm")
end
endfunction
l = 1; m = -1;
f = Y(l,m,theta,phi);
//I got the funciton value in spherical coordinates and
//that spherical coordinates are funciton of Cartesian coordinates.
//So basically funciton Y is a funciton of Cartesian coordinates (x,y,z).
//Next to plot funciton Y against (x,y)
//------------------------------------------------------------------------------
clf();
plot3d(x,y,f,flag=[2 4 4]); xtitle("|Y31(x,y)|");

Your problem is due to the range of f which is very small compared to the x and y ones.
To get what you expect you can proceed as follow
plot3d(x,y,f,flag=[2 4 4]); xtitle("|Y31(x,y)|");
ax=gca();
ax.cube_scaling="on";

Related

Connecting two points with a 3D logarithmic spiral (Julia)

I am calculating points along a three-dimensional logarithmic spiral between two points. I seem to be close, but I think I'm missing a conditional sign flip somewhere.
This code works relatively well:
using PlotlyJS
using LinearAlgebra
# Points to connect (`p2` spirals into `p1`)
p1 = [1,1,1]
p2 = [3,10,2]
# Number of curve revolutions
rev = 3
# Number of points defining the curve
rez = 500 # Number of points defining the line
r = norm(p1-p2)
t = range(0,r,rez)
theta_offset = atan((p1[2]-p2[2])/(p1[1]-p2[1]))
theta = range(0, 2*pi*rev, rez) .+ theta_offset
x = cos.(theta).*exp.(-t).*r.+p1[1];
y = sin.(theta).*exp.(-t).*r.+p1[2];
z = exp.(-t).*log.(r).+p1[3]
# Plot curve points
plot(scatter(x=x, y=y, z=z, marker=attr(size=2,color="red"),type="scatter3d"))
and produces the following plot. Values of the endpoints are shown on the plot, with an arrow from the coordinate to its respective marker. The first point is off, but it's close enough for my liking.
The problem comes when I flip p2 and p1 such that
p1 = [3,10,2]
p2 = [1,1,1]
In this case, I still get a spiral from p2 to p1, and the end point (p1) is highly accurate. However, the other endpoint (p2) is wildly off:
I think this is due to me changing the relative Z position of the two points, but I'm not sure, and I haven't been able to solve this riddle. Any help would be greatly appreciated. (Bonus points if you can help figure out why the Z value on p2 is off in the first example!)
Assuming this is a follow-up of your other question: Drawing an equiangular spiral between two known points in Julia
I assume you just want to add a third dimension to your previous 2D problem using cylindric coordinate system. This means that you need to separate the treatment of x and y coordinate on one side, and the z coordinate on the other side.
First you need to calculate your r on the first two coordinate:
r = norm(p1[1:2]-p2[1:2])
Then, when calculating z, you need to take only the third dimension in your formula (not sure why you used a log function there in the first place):
z = exp.(-t).*(p1[3]-p2[3]).+p2[3]
That will fix your z-axis.
Finally for your x and y coordinate, use the two argument atan function:
julia>?atan
help?> atan
atan(y)
atan(y, x)
Compute the inverse tangent of y or y/x, respectively.
For one argument, this is the angle in radians between the positive x-axis and the point (1, y), returning a value in the interval [-\pi/2, \pi/2].
For two arguments, this is the angle in radians between the positive x-axis and the point (x, y), returning a value in the interval [-\pi, \pi]. This corresponds to a standard atan2
(https://en.wikipedia.org/wiki/Atan2) function. Note that by convention atan(0.0,x) is defined as \pi and atan(-0.0,x) is defined as -\pi when x < 0.
like this:
theta_offset = atan( p1[2]-p2[2], p1[1]-p2[1] )
And finally, like in your previous question, add the p2 point instead of the p1 point at the end of x, y, and z:
x = cos.(theta).*exp.(-t).*r.+p2[1];
y = sin.(theta).*exp.(-t).*r.+p2[2];
z = exp.(-t).*(p1[3]-p2[3]).+p2[3]
In the end, I have this:
using PlotlyJS
using LinearAlgebra
# Points to connect (`p2` spirals into `p1`)
p2 = [1,1,1]
p1 = [3,10,2]
# Number of curve revolutions
rev = 3
# Number of points defining the curve
rez = 500 # Number of points defining the line
r = norm(p1[1:2]-p2[1:2])
t = range(0.,norm(p1-p2), length=rez)
theta_offset = atan( p1[2]-p2[2], p1[1]-p2[1] )
theta = range(0., 2*pi*rev, length=rez) .+ theta_offset
x = cos.(theta).*exp.(-t).*r.+p2[1];
y = sin.(theta).*exp.(-t).*r.+p2[2];
z = exp.(-t).*(p1[3]-p2[3]).+p2[3]
#show (x[begin], y[begin], z[begin])
#show (x[end], y[end], z[end]);
# Plot curve points
plot(scatter(x=x, y=y, z=z, marker=attr(size=2,color="red"),type="scatter3d"))
Which give the expected results:
p2 = [1,1,1]
p1 = [3,10,2]
(x[begin], y[begin], z[begin]) = (3.0, 10.0, 2.0)
(x[end], y[end], z[end]) = (1.0001877364735474, 1.0008448141309634, 1.0000938682367737)
and:
p1 = [1,1,1]
p2 = [3,10,2]
(x[begin], y[begin], z[begin]) = (0.9999999999999987, 1.0, 1.0)
(x[end], y[end], z[end]) = (2.9998122635264526, 9.999155185869036, 1.9999061317632263)
In 2D, let us assume the pole at the point C, and the spiral from P to Q, corresponding to a variation of the parameter in the interval [0, 1].
We have
X = Cx + cos(at+b).e^(ct+d)
Y = Cy + sin(at+b).e^(ct+d)
Using the known points,
Px - Cx = cos(b).e^d
Py - Cy = sin(b).e^d
Qx - Cx = cos(a+b).e^(c+d)
Qy - Cy = sin(a+b).e^(c+d)
From the first two, by a Cartesian to polar transformation (and logarithm), you can obtain b and d. From the last two, you similarly obtain a+b and c+d, and the spiral is now defined.
For the Z coordinate, I cannot answer precisely as you don't describe how you generalize the spiral to 3D. Anyway, we can assume a certain function Z(t), that you can map to [Pz, Qz] by the linear transformation
(Qz - Pz) . (Z(t) - Z(0)) / (Z(1) - Z(0)) + Pz.

Drawing an equiangular spiral between two known points in Julia

I have two random points in a 2D Cartesian grid, p1 and p2. I would like to define a curve between p1 and p2 of N points such that the curve forms an equiangular spiral (similar to what is done in this paper (Fig. 8)). I've tried converting the paper into a script, but something is still off, so I'm trying to build a "dumbed down" example. My closest attempt is this (p2 can be seen on zoom-in, but not shown in script's plot):
using PyPlot
using LinearAlgebra
p1 = [5,7]
p2 = [1,2]
r = norm(p1-p2)
theta_offset = tan((p1[2]-p2[2])/(p1[1]-p2[1]));
# Number of points
rez = 500
# Number of revolutions
rev = 5
# Radius as spiral decreases
t = range(0,r,rez)
# Angle as spiral decreases
theta = range(0, 2*pi*rev, rez) .+ theta_offset
x = cos.(theta).*exp.(-t).+p2[1];
y = sin.(theta).*exp.(-t).+p2[2];
figure()
plot(x,y)
scatter(p1[1],p1[2],c="red",s=5)
scatter(p2[1],p2[2],c="red",s=10)
show(); gcf()
which produces the following plot:
While the plot is centered on p2 (at coordinate [1,2]), the endpoint does not lie near / pass through my specified point p1. My ideal outcome would be something like this:
EDIT: Solved problem using #PaSTE's suggestion. Changing my theta_offset, x, and y coordinate calculations to:
theta_offset = atan((p1[2]-p2[2])/(p1[1]-p2[1]));
x = cos.(theta).*exp.(-t).*r.+p2[1]
y = sin.(theta).*exp.(-t).*r.+p2[2]
yields the following plot, exactly what I was hoping for. In my solution, handedness and number of loops are not important.
As PaSTE said, The issue is the algebra: you need get the angle with atan, not tan, and multiply your exponential factor by r to get the right radius.
using LinearAlgebra
using Plots
p1 = [5,7]
p2 = [1,2]
r = norm(p1-p2)
theta_offset = atan((p1[2]-p2[2])/(p1[1]-p2[1]));
# Number of points
rez = 1500
# Number of revolutions
rev = 5
# Radius as spiral decreases
t = range(0,r,rez)
# Angle as spiral decreases
theta = range(0, 2*pi*rev, rez) .+ theta_offset
x = cos.(theta) .* r .* exp.(-t) .+ p2[1]
y = sin.(theta) .* r .* exp.(-t) .+ p2[2]
plot(x, y)
scatter!([p1[1], p2[1]], [p1[2], p2[2]])

How to find points of certain distance on a circle perimeter?

Suppose, (x1, y1) is a point on the perimeter of a circle (x-420)^2 + (y-540)^2 = 260^2 what are the two points on the circle perimeter of distance d(euclidean) from the point (x1, y1)
Using trig
Assuming you are using a programming language. The answer is using pseudo code.
Using radians the distance d along a circle can be expressed as an angle a computed as a = d / r (where r is the radius)
Given an arbitrary point on the circle. (x1-420)^2 + (y1-540)^2 = 260^2 (NOTE assumes x1, y1 are known) we can extract the center is x = 420, y = 540, and radius r = 260
The angular distance d is then a = d / 260.
Most languages have the function atan2 which will compute the angle of a vector, We can get the angle from the circle center to the arbitrary point as ang = atan2(y1 - 540, x1 - 420) (Note y first then x)
Thus the absolute angles from the arbitrary point {x1, y1} to the points d distance along the circle (ang1 , ang2) is computed as...
// ? represents known unknowns
x = 420
y = 540
r = 260
d = ?
x1 = ?
y1 = ?
ang = atan2(y1 - y, x1 - x)
ang1 = ang + d / r
ang2 = ang - d / r
And the coordinates of the points (px1, py1, px2, py2) computed as...
px1 = cos(ang1) * r + x
py1 = sin(ang1) * r + y
px2 = cos(ang2) * r + x
py2 = sin(ang2) * r + y
Vector algebra
The problem can also be solved using vector algebra and does not require the trig function atan2
Compute the unit vector representing the angle a = d / r and then with the circle at the origin, transform (rotate) the point on the circle using the unit vector in both directions. Translate the points back to the circles original position for the solution.

Contour plot of an extrapolated anonymous function in Julia

I created a 64x64 random 2D array in Julia, and then interpolated it using Interpolations.jl:
using Interpolations
using Plots
gr()
x = range(-10., length=64, stop=10.)
y = range(-10., length=64, stop=10.)
v_unscaled = interpolate(potential, BSpline(Cubic(Line(OnCell()))))
v_scaled = Interpolations.scale(v_unscaled, x, y)
v = extrapolate(v_scaled, 0)
p_int = contour(x, y, v_scaled, fill=true)
display(p_int)
p = contour(x, y, v, fill=true)
display(p)
When I plot the extrapolated function v, the non-zero part of the contour is shrunk to the lower left corner which is not as expected, because in the specified domain, the two plots should look the same. What is wrong with the procedures above?

3D Vector defined by 2 angles

So basically I'm looking for a way to calculate the x, y and z component of a vector using 2 angles as shown:
Where alpha is the 2D angle and beta is the y angle.
What I've been using uptill now for 2D vectors was:
x = Math.sin(alpha);
z = Math.cos(alpha);
After searching on stackexchange math I've found this forumula doesn't really work correctly:
x = Math.sin(alpha)*Math.cos(beta);
z = Math.sin(alpha)*Math.sin(beta);
y = Math.cos(beta);
Note: when approaching 90 degrees with the beta angle the x and z components should approach zero.
All help would be appreciated.
The proper formulas would be
x = Math.cos(alpha) * Math.cos(beta);
z = Math.sin(alpha) * Math.cos(beta);
y = Math.sin(beta);
That formula just come from the transformation of Spherical coordinates (r, theta, phi) -> (x, y, z) to Cartesian coordinates.

Resources