How can I detect if a point is inside a cone or not, in 3D space? - matlab

How is possible to detect if a 3D point is inside a cone or not?
Ross cone = (x1, y1, h1)
Cone angle = alpha
Height of the cone = H
Cone radius = R
Coordinates of the point of the cone = P1 (x2, y2, h2)
Coordinates outside the cone = P2( x3, y3, h3)
Result for point1 = true
Result for point2 = false

To expand on Ignacio's answer:
Let
x = the tip of the cone
dir = the normalized axis vector, pointing from the tip to the base
h = height
r = base radius
p = point to test
So you project p onto dir to find the point's distance along the axis:
cone_dist = dot(p - x, dir)
At this point, you can reject values outside 0 <= cone_dist <= h.
Then you calculate the cone radius at that point along the axis:
cone_radius = (cone_dist / h) * r
And finally calculate the point's orthogonal distance from the axis to compare against the cone radius:
orth_distance = length((p - x) - cone_dist * dir)
is_point_inside_cone = (orth_distance < cone_radius)

The language-agnostic answer:
Find the equation of the line defining the main axis of your cone.
Compute the distance from the 3D point to the line, along with the intersection point along the line where the distance is perpendicular to the line.
Find the radius of your cone at the intersection point and check to see if the distance between the line and your 3D point is greater than (outside) or less than (inside) that radius.

A cone is simply an infinite number of circles whose size is defined by a linear equation that takes the distance from the point. Simply check if it's inside the circle of the appropriate size.

Wouldn't it be easier to compute angle between vector to center of cone and vector from apex pointing at point under evaluation. If vector projection is used and the length of the resultant vector is shorter then the vector pointing at the center of the cone the between the angle and length you know if you are inside a cone.
https://en.wikipedia.org/wiki/Vector_projection

Related

How to find points inside, where sphere intersects with cylinder in MATLAB?

I am trying to identify points of sphere that are inside union of both sphere and cylinder, I have generated random points in side a cylinder as below
pts = 3000;
r= 3*((rand(pts,1)).^(1/3));
theta = 2*pi*rand(pts,1);
x= r.*cos(theta);
y= r.*sin(theta);
z=50*rand(size(x));
and generated random points inside a sphere as below
radius=10;
rvals = (2)*rand(pts,1)-(1);
elevation = asin(rvals);
azimuth = 2*pi*rand(pts,1);
radii =(rand(pts,1).^(1/3))*radius;
[point_x,point_y,point_z] = sph2cart(azimuth,elevation,radii);
The result will be as below
I need to find sphere points that is in intersection with cylinder and cylinder points that are in intersection with sphere.
Is there any general method to identify points inside intersection of different volumes ??
Can anyone help me? Thanks in advance,
Manu
Apparently, you have a sphere with center at (0, 0, 0) and radius 10. To check whether points of the cylinder are in the sphere, you can use:
cylinder_in_sphere = (x.^2 + y.^2 + z.^2) < 100
Your cylinder has radius 3 and a height of 50, so to check whether points of the sphere are in the cylinder, you can use:
sphere_in_cylinder = ((points_x.^2 + points_y.^2) < 9) & (points_z >= 0) & (points_z < 50)
Note that in this particular case points_z < 50 is always satisfied, so you can remove it in this particular case.

Estimating an ellipse with a multi-variate Gaussian

In MATLAB, say I have the parameters for an ellipse:
(x,y) center
Minor axis radius
Major axis radius
Angle of rotation
Now, I want to generate random points that lie within that ellipse, approximated from a 2D gaussian.
My attempt thus far is this:
num_samps = 100;
data = [randn(num_samps, 1)+x_center randn(num_samps, 1)+y_center];
This gives me a cluster of data that's approximately centered at the center, however if I draw the ellipse over the top some of the points might still be outside.
How do I enforce the axis rules and the rotation?
Thanks.
my assumptions
x_center = h
y_center = k
Minor Axis Radius = b
Major Axis Raduis = a
rotation angle = alpha
h=0;
k=0;
b=5;
a=10;
alpha=30;
num_samps = 100;
data = [randn(num_samps, 1)+h randn(num_samps, 1)+k];
chk=(((((data(:,1)-h).*cos(alpha)+(data(:,2)-k).*sin(alpha))./a).^2) +...
(((data(:,1)-h).*sin(alpha)+(data(:,2)-k).*cos(alpha))./b).^2)<=1;
idx=find(chk==0);
if ~isempty(idx)
data(idx,:)=data(idx,:)-.5*ones(length(idx),2);
end

Calculating a spiral in MATLAB

We have these logarithmic spirals which are circling around the centre of the coordinate system:
x = ebθ cos(θ)
y = ebθ sin(θ)
where the ebθ is the distance between the point (which is on the spiral) and the centre; and the θ is the angle between the line connecting the point and the origin and the axis x.
Consider a spiral where the angle is θ ϵ <0,10π> and the parameter is b=0.1. By thickening points on the spirals (and the angle θ) calculate the circumference with the relative precision better than 1%. Draw the spiral!
I'm preparing for a (MATLAB) test and I'm stuck with this exercise. Please help, any hint is appreciated.
Start by computing a list of x,y for your range of theta and value of b. For more accurate results, have your theta increment in smaller steps (I chose 5000 arbitrarily). Then, its simply computing the distance for each pair of consecutive points and summing them up.
t = linspace(0,10*pi,5000);
b = 0.1;
x = exp(b*t).*cos(t);
y = exp(b*t).*sin(t);
result = sum(sqrt((x(2:end) - x(1:end-1)).^2 + (y(2:end)-y(1:end-1)).^2))

Approximating relative angle between two line segments on sphere surface

I am in need of an idea! I want to model the vascular network on the eye in 3D. I have made statistics on the branching behaviour in relation to vessel diameter, length etc. What I am stuck at right now is the visualization:
The eye is approximated as a sphere E with center in origo C = [0, 0, 0] and a radius r.
What I want to achieve is that based on the following input parameters, it should be able to draw a segment on the surface/perimeter of E:
Input:
Cartesian position of previous segment ending: P_0 = [x_0, y_0, z_0]
Segment length: L
Segment diameter: d
Desired angle relative to the previous segment: a (1)
Output:
Cartesian position of resulting segment ending: P_1 = [x_1, y_1, z_1]
What I do now, is the following:
From P_0, generate a sphere with radius L, representing all the points we could possibly draw to with the correct length. This set is called pool.
Limit pool to only include points with a distance to C between r*0.95 and r, so only the points around the perimeter of the eye are included.
Select only the point that would generate a relative angle (2) closest to the desired angle a.
The problem is, that whatever angle a I desire, is actually not what is measured by the dot product. Say I want an angle at 0 (i.e. that the new segment is following the same direction as the previous`, what I actually get is an angle around 30 degrees because of the curvature of the sphere. I guess what I want is more the 2D angle when looking from an angle orthogonal from the sphere to the branching point. Please take a look at the screenshots below for a visualization.
Any ideas?
(1) The reason for this is, that the child node with the greatest diameter is usually follows the path of the previous segment, whereas smaller child nodes tend to angle differently.
(2) Calculated by acos(dot(v1/norm(v1), v2/norm(v2)))
Screenshots explaining the problem:
Yellow line: previous segment
Red line: "new" segment to one of the points (not neccesarily the correct one)
Blue x'es: Pool (text=angle in radians)
I will restate the problem with my own notation:
Given two points P and Q on the surface of a sphere centered at C with radius r, find a new point T such that the angle of the turn from PQ to QT is A and the length of QT is L.
Because the segments are small in relation to the sphere, we will use a locally-planar approximation of the sphere at the pivot point Q. (If this isn't an okay assumption, you need to be more explicit in your question.)
You can then compute T as follows.
// First compute an aligned orthonormal basis {U,V,W}.
// - {U,V} should be a basis for the plane tangent at Q.
// - W should be normal to the plane tangent at Q.
// - U should be in the direction PQ in the plane tangent at Q
W = normalize(Q - C)
U = normalize(Q - P)
U = normalize(U - W * dotprod(W, U))
V = normalize(crossprod(W, U))
// Next compute the next point S in the plane tangent at Q.
// In a regular plane, the parametric equation of a unit circle
// centered at the origin is:
// f(A) = (cos A, sin A) = (1,0) cos A + (0,1) sin A
// We just do the same thing, but with the {U,V} basis instead
// of the standard basis {(1,0),(0,1)}.
S = Q + L * (U cos A + V sin A)
// Finally project S onto the sphere, obtaining the segment QT.
T = C + r * normalize(S - C)

Turtle line intersection, coordinates

I need to make a small program that draws three circles, a line between the first two, and then determines if the third touches or intersects the line. I have done everything but the last part. I am trying to use the points to determine if the area is 0, which would mean that the third point is, in fact, intersecting the line. Right? Or I could use another way. Technically the third circle can be within 3 pixels of the line. The problem is near the bottom at the hashtag. I would appreciate any help or suggestions that move this in another direction. Thank you.
import turtle
x1, y1 = eval(input("Enter coordinates for the first point x, y: "))
x2, y2 = eval(input("Enter coordinates for the second point x, y: "))
x3, y3 = eval(input("Enter coordinates for the third point x, y: "))
turtle.penup()
turtle.goto(x1, y1)
turtle.pendown()
turtle.circle(3)
turtle.penup()
turtle.goto(x2, y2)
turtle.pendown()
turtle.circle(3)
turtle.penup()
turtle.goto(x3, y3)
turtle.pendown()
turtle.circle(3)
turtle.penup()
turtle.color("red")
turtle.goto(x1, y1)
turtle.pendown()
turtle.goto(x2, y2)
a = (x1, y1)
c = (x3, y3)
#can't multiply sequence by non-int of type 'tuple'
area = (a * c) / 2
if area == 0:
print("Hit")
else:
print("Miss")
Ther center of 3rd circle is (x3,y3) and have a radius 3 and you are trying to determine any intersection with ([x1,y1],[x2,y2]) line segment.
If any point in the line is within the circle, then there is an intersection.
Circle region formula is: (x-x3)^2 + (y-y3)^2 < 3^2
You should test for every point on the line whether this inequality holds and if any single point satisfies this condition, then you can conclude that the line and circle intersect.
The first step would be to determine coordinate points of line segment (all points between [x1,y1],[x2,y2] points in a straight line) then you can try to test these points in a loop.
You can calculate the area of the triangle by defining vectors from one vertex to the other two (adding a third constant coordinate to embed the plane in 3-dimensional space (so cross-products make sense)),
#pseudocode
b = (x2, y2, 1) - (x1, y1, 1) = (x2-x1, y2-y1, 0)
c = (x3, y3, 1) - (x1, y1, 1) = (x3-x1, y3-y1, 0)
then take the cross-product of these,
a = b cross c = (by*cz-bz*cy, bz*cx-bx*cz, bx*cy-by*cx)
then take the magnitude of this resulting vector which is the area of the parallelogram defined by the two vectors,
pa = |a| = ax^2 + ay^2 + az^2
then divide by two to get the area of the triangle (half of the parallelogram).
ta = pa/2
Source: http://en.wikipedia.org/wiki/Triangle_area#Using_vectors
Am I wright? The position of the circles to each other does not matter?
Make a linear function from the line between the two center points. (ax+b=y)
Where a is the gradient and b is the y-intersection.
To rotate a through 90° is easy. Inverse and negate a.
Find b of the second linear function. b'=y-a'*x .
At once replace the x,y with the coordinates of your 3. circle point.
Now you have a linear function which is rectangular to the old one and where the third circle point is part of.
Intersect the old linear function with the new one.
You'll get the lot point.
You need to find out the distance between the 3. circle point and the lot point and whether it is greater than the radius.
You need there functions (JS):
function makelinear (x1,y1,x2,y2){
var temp=x2-x1;
if(temp==0)temp=0.00000000000001;//not clean but fast.
var a=(y2-y1)/temp,
b=y1-a*x1;
return[a,b];
}
function ninetydeg(a,b,x,y){
var aout=1/a,
bout=y+aout*x;
return [aout,bout];
}
function lineintersection(a1,b1,a2,b2){
var temp=a1-a2;
if(temp==0)temp=0.00000000000001;
var x=(b2-b1)/temp,
y=a1*x+b1;
return[x,y];
}
function distance(x1,y1,x2,y2){
var x=x1-x2,
y=y1-y2;
return(Math.sqrt(x*x+y*y));
}
Sorry for to be complicate, I've found no other solution in short time. May be there is a vector solution.