I have written an equation of cylinder in matlab as follows
z=0;
r=1/33;
a=1/2+1/4-1/8-1/16;
b=1/2+1/4-1/8-1/16;
if (x-a).^2+(y-b).^2<=r^2
z=1;
end
N=1-t(any number)
now I want to move it along x-axis with interval of time as above. I want to move it along x-axis
How can I do it?
Your equation (x-a).^2+(y-b).^2<=r^2 means that the cylinder's center is at [a, b]. Moving it along the x-axis by an amount da means increasing a to a+da, so that the new center moves to [a+da, b].
Just as a word of advice -- there is also the Matlab command [x,y,z] = cylinder. Type help cylinder for more info.
And for completeness and rigor -- your equation is not that of a cylinder, it is the equation of a plane (z=0) with a solid circular protrusion of height 1 and radius 1/33 centered at [a,b]. A "solid cylinder" like the one you've defined is best referred to as a "rod", whereas a mathematical "cylinder" is only the outer surface ("the collection of all points equidistant to a line segment"). Very often cylinders are defined through a set of parametric equations, so what are your reasons for this particular style of defining the rod?
Related
I want to morph sphere, using the following equation:
R=1+k*(cos(4*elev)+sin(4*az)),
Spherical coordinates elev and az are transferred as gl_Vertex. The problem is to calculate normals for such morphing. I may calculate them, just shifting az and elev a bit, the obtain 2 more "virtual" vertices and use standard approach with cross-product, but it looks rather ugly and expensive approach.
Is their are any way to calculate normals also parametrically for such kind of morphing?
UPDATE:
Thanks to #meowgoesthedog, but I still have problems. My implementation of this formula (code below) did not work:
Am i correct and it should be:
cos(theta)*(k*(cos(4*theta)+sin(4*phi))+1) or cos(theta*(k*(cos(4*theta)+sin(4*phi))+1))?
Are normals calculated in cartesian coordinate system?
My code in Matlab:
close all
clear all
N=100;
phi_range=linspace(-pi,pi,N+2);
theta_range=linspace(-pi/2,pi/2,N);
phi_range([1,end])=[];
k=6;
% generate morphed sphere
PHI=repmat(phi_range,N,1);
THETA=repmat(theta_range',1,N);
R=1+k*cos(4*THETA)+k*sin(4*PHI);
% convert to cartesian coordinates
[X,Y,Z]=sph2cart(PHI,THETA,R);
%% meowgoesthedog formula
S=k.*(cos(4.*THETA)+sin(4.*PHI))+1;
V1_x = cos(PHI).*(cos(THETA).*S-4.*k.*sin(THETA).*sin(4.*THETA));
V1_y = sin(PHI).*(cos(THETA).*S-4.*k.*sin(THETA).*sin(4.*THETA));
V1_z = -sin(THETA).*S-4.*k.*sin(4.*THETA).*cos(THETA);
V2_x = sin(THETA).*(4.*k.*cos(PHI).*cos(4.*PHI)-sin(PHI).*S);
V2_y = sin(THETA).*(4.*k.*sin(PHI).*cos(4.*PHI)+cos(PHI).*S);
V2_z = 4.*k.*cos(THETA).*cos(4.*THETA);
V1=cat(3,V1_x,V1_y,V1_z);
V2=cat(3,V2_x,V2_y,V2_z);
Normals=cross(V1,V2);
% normalize
Normals=Normals./sqrt(sum(Normals.^2,3));
%% plot and compare results:
hold all
surfnorm(X,Y,Z,'EdgeAlpha',0.5)
quiver3(X,Y,Z,Normals(:,:,1),Normals(:,:,2),Normals(:,:,3),'m')
On figures below red - correct normals, magenta which I calculate.
We can compute an analytical expression for the normal using differential geometry. Let's first state the form of the Cartesian parametric coordinate:
Locally at any point on the surface, there is a 2D coordinate system spanned by the unit vectors in the directions of increasing θ and φ.
These vectors are given by:
The normal is simply given by the cross-product of these two vectors (un-normalized):
After some very tedious algebra we obtain:
(The formula becomes too long to legibly display past this point, and probably not as efficient to evaluate either.)
EDIT
It appears that I have used the conventional definition of θ (angle from the +Z axis) instead of Matlab's elev. Redefining the equations this would give:
Where ψ = ½π - θ is the elevation.
I have two independent 3D shapes; one is a square and another is a cone.
Let's assume the cone lies inside the square. How can I find out that the surface of the cone touches the square's surface when I move the cone in any direction?
It will be helpful if anyone can suggest an algorithm to check whether the surface touches another shape.
I am working with MATLAB, but the underlying logic will be appreciated in any language will be appriciated.
https://in.mathworks.com/matlabcentral/answers/367565-findout-surface-to-surface-intersection-between-two-3d-shapes
There is a relatively easy solution, thanks to the fact that the truncated cone is a convex shape, and finding its AABB is not so hard.
First rotate space so that the cube become axis aligned (and the cone in arbitrary position). Then to find the AABB of the base, is suffices to get the maxima an minima of the coordinates, using the parametric equation, C + R cos t + R' sin t, where C is the position vector of the center, and R, R' two orthogonal radii. You find the limit angles by canceling the derivative.
After finding the extrema on the three coordinates, the global bounding box is the one that surrounds these six points plus the apex.
By comparing the AABB to the cube, you can tell what distance remains before a collision, in any direction.
Using plot::tube function in MuPAD, I can generate tubes with varying spine but the cross-section is always a circle, although the radius can vary along the spine. For instance:
plot::Tube([cos(t), sin(t), 0], 0.4 + 0.3*sin(t)*cos(t),t = -0.5*PI..0.5*PI,Mesh=[60,12]):
I want to plot tubes with (non-circular) elliptical cross-sections. Is there a way to achieve this in MuPAD?
P.S. I can generate tubes with arbitrary cross-sections using MATLAV, so please avoid including answers that use pure MATLAB commands.
As for your first question whether this can be done with plot::Tube: I don't think so. Consider the help of this function (emphasis mine):
plot::Tube creates generalized tubular plots, known as "canal
surfaces", with special cases known as "tube surface", "pipe surface"
or "tubular surfaces."
Intuitively, canal surfaces are space curves with thickness. More formally, a canal surface plot::Tube([x(t), y(t), z(t)], r(t), t = t_min..t_max) is the envelope of spheres with center [x(t), y(t), z(t)] and radius r(t), i.e., the thickness of the curve can vary with
the curve parameter t
The fact that a tube is defined as an envelope of a collection of spheres suggests that their cross-section is inherently circular.
I'm not familiar with MuPAD, so I don't know the elegant solution to your problem. For your simple example of a semi-circular base line I could put together this kludgy solution using the low-level plot::Surface, manually constructing the surface:
plot(
plot::Surface(
matrix([cos(t),sin(t),0])
+ numeric::rotationMatrix(t,[0,0,1]) * matrix([(0.2+0.1*sin(2*t))*cos(u),0,(0.2+0.1*cos(2*t))*sin(u)]),
t = -PI/2..PI/2,
u = 0..2*PI,
Mesh = [30,30]),
Scaling=Constrained)
Here t stands for the angular parameter along the semi-circular base line (toroidal direction), and u is the angle along the cross-section (poloidal direction). A given cross-section at angle t looks like this:
[(0.2+0.1*sin(2*t))*cos(u), 0, (0.2+0.1*cos(2*t))*sin(u)]
I.e. the semimajor axes are (0.2+0.1*sin(2*t)) and (0.2+0.1*cos(2*t)) along the cross-section of the tube.
You can see that I used a rotation matrix around the z axis to construct the surface. This made heavy use of the fact that the base line is a semi-circle. However, in general cases it should be possible to compute the derivative of your parameterized base line (with respect to t), and compute the necessary rotation angle (with parameter t) from that.
In MATLAB's function of Voronoi diagram, the vertices of edges at infinity are plotted at some distant point. Have a look at the first diagram on the page here. The first point from the top on Y-axis is (0,0.75). (Though it is extended beyond the bounds of the image). I know if I run the following matlab function:
[vx,vy]=voronoi(x,y)
I can get the coordinates of the vertices, but they will be beyond the bounds of the plot. Is there any way to get the coordinate in bounds of the plot (for example, (0,0.75) as mentioned above).
All you need is to detect which of the vx,vy crosses the axes (using find or logical conditions, find(vx<0) , find(vy>1) etc...) , and then apply the equation of the line y=a*x+b. For the point you wanted (which happens to be the 19th col of vx,vy, the slope a is:
a=diff(vy(:,19))/diff(vx(:,19));
and the intersection with y axis is given by b:
b=vy(1,19)-a*vx(1,19)
b =
0.7546
To calc b I picked the first point [vx(1,19),vy(1,19)] but this of course works also for the second point, i.e. b=vy(2,19)-a*vx(2,19)
Suppose you have f(x)=x-floor(x).
By this, you can generate the grooves by gluing the top side and the
bottom side together and then squeezing the left to zero -- now you
have a conical helix: the line spins around the cone until it hits the
bottom. You already have one form of the equations for the conical
helix namely x=a*cos(a); y=a*sin(a); z=a. Now like
here:
How can you project the conical helix on the cone in Matlab?
I'd approach your problem without using plot3, instead I'd use meshgrid and sinc. Note that sinc is a matlab built in functions that just do sin(x)./x, for example:
So in 1-D, if I understand you correctly you want to "project" sinc(x) on sqrt(x.^2). The problem with your question is that you mention projection with the dot product, but a dot product reduces the dimensionality, so a dot product of two vectors gives a scalar, and of two 2D surfaces - a vector, so I don't understand what you mean. From the 2-D plot you added I interpreted the question as to "dress" one function with the other, like in addition...
Here's the implementation:
N=64;
[x y]=meshgrid(linspace(-3*pi,3*pi,N),linspace(-3*pi,3*pi,N));
t=sqrt(x.^2+y.^2);
f=t+2*sinc(t);
subplot(1,2,1)
mesh(x,y,f) ; axis vis3d
subplot(1,2,2)
mesh(x,y,f)
view(0,0) ; axis square
colormap bone
The factor 2 in the sinc was placed for better visualization of the fluctuations of the sinc.