Check which side of a plane points are on - math

I'm trying to take an array of 3D points and a plane and divide the points up into 2 arrays based on which side of the plane they are on. Before I get to heavily into debugging I wanted to post what I'm planning on doing to make sure my understanding of how to do this will work.
Basically I have the plane with 3 points and I use (pseudo code):
var v1 = new vector(plane.b.x-plane.a.x, plane.b.y-plane.a.y, plane.b.z-plane.a.z);
var v2 = new vector(plane.c.x-plane.a.x, plane.c.y-plane.a.y, plane.c.z-plane.a.z);
I take the cross product of these two vectors to get the normal vector.
Then I loop through my array of points and turn them into vectors and calculate the dot product against the normal.
Then i use the dot product to determine the side that the point is on.
Does this sound like it would work?

Let a*x+b*y+c*z+d=0 be the equation determining your plane.
Substitute the [x,y,z] coordinates of a point into the left hand side of the equation (I mean the a*x+b*y+c*z+d) and look at the sign of the result.
The points having the same sign are on the same side of the plane.
Honestly, I did not examine the details of what you wrote. I guess you agree that what I propose is simpler.

Following the 'put points into the plane's equation and check the sign' approach given previously. The equation can be easily obtained using SymPy. I used it to find location of points (saved as numpy arrays) in a list of points.
from sympy import Point3D, Plane
plane=Plane(Point3D(point1), Point3D(point2), Point3D(point3))
for point in pointList:
if plane.equation(x=point[0], y=point[1],z=point[2]) > 0:
print "point is on side A"
else:
print "point is on side B"
I haven't tested its speed compared to other methods mentioned above but is definitely the easiest method.

Your approach sounds good. However, when you say "and turn them into vectors", it might not be good (depending on the meaning of your sentence).
You should "turn your points into vector" by computing the difference in terms of coordinates between the current point and one of the points in the plane (for example, one of the 3 points defining the plane). As you wrote it, it sounds like you might have misunderstood that ; but apart from that, it's ok!

take into account the normal vector of the plane
example: for the point A=[-243.815437431962, -41.7407630281635, 10.0]
equation= -2663.1860000000006*Z +21305.488000000005=0
RESULt POSITIVE
but if equation= 2663.1860000000006*Z -21305.488000000005=0
RESULT NEGATIVE

Related

Converting 2 point coords to vector coords for angleBetween()?

I'm working on a PyMEL script that allows the user to duplicate a selected object multiple times, using a CV curve and its points coordinates to transform & rotate each copy to a certain point in space.
In order to achieve this, Im using the adjacent 2 points of each CV (control vertex) to determine the rotation for the object.
I have managed to retrieve the coordinates of the curve's CVs
#Add all points of the curve to the cvDict dictionary
int=0
cvDict={}
while int<selSize:
pointName='point%s' % int
coords= pointPosition ('%s.cv[%s]' % (obj,int), w=1)
#Setup the key for the current point
cvDict[pointName]={}
#add coords to x,y,z subkeys to dict
cvDict[pointName]['x']= coords[0]
cvDict[pointName]['y']= coords[1]
cvDict[pointName]['z']= coords[2]
int += 1
Now the problem I'm having is figuring out how to get the angle for each CV.
I stumbled upon the angleBetween() function:
http://download.autodesk.com/us/maya/2010help/CommandsPython/angleBetween.html
In theory, this should be my solution, since I could find the "middle vector" (not sure if that's the mathematical term) of each of the curve's CVs (using the adjacent CVs' coordinates to find a fourth point) and use the above mentioned function to determine how much I'd have to rotate the object using a reference vector, for example on the z axis.
At least theoretically - the issue is that the function only takes 1 set of coords for each vector and I have absolutely no Idea how to convert my point coords to that format (since I always have at least 2 sets of coordinates, one for each point).
Thanks.
If you wanna go the long way and not grab the world transforms of the curve, definitely make use of pymel's datatypes module. It has everything that python's native math module does and a few others that are Maya specific. Also the math you would require to do this based on CVs can be found here.
Hope that puts you in the right direction.
If you're going to skip the math, maybe you should just create a locator, path-animate it along the curve, and then sample the result. That would allow you to get completely continuous orientations along the curve. The midpoint-constraint method you've outlined above is limited to 1 valid sample per curve segment -- if you wanted 1/4 of the way or 3/4 of the way between two cv's your orientation would be off. Plus you don't have to reinvent all of the manu different options for deciding on the secondary axis of rotation, reading curves with funky parameterization, and so forth.

Vector to closest isosurface point on metaballs

I'm currently making a prototype game where the player walks along the isosurface of a collection of moving metaballs. I've already implemented walking along a sphere with a forward and up vector. To extend this to the metaballs I need to be able to query for an arbitrary point the direction to the closest surface and the distance to the closest surface to be able to snap the player back to the surface after I've moved him along the forward vector. I can calculate the direction by taking a weighted average of all vectors but how do I get the distance?
I'm using the 1 / (x*x + y*y + z*z) function with an isosurface of 1 for my metaballs but I would appreciate any generalization so that I can use the same approach for other shapes.
In general, you would just derive your function to get the normal on the surface. Blackpawn has a nice explanation how to do it with your specific case here.
Once you got the normal, move along its direction until you hit the isosurface (this is generic "root" finding).

Bicubic Interpolation for Non-regular grids?

I am working on a project where I have a set of known measurements (x,y,z,a) and an input (z,a). I need to be able to interpolate the (x,y,z) so that I can get a list of possible (x,y) coordinates from a given z.
I was looking at bicubic interpolation, but I can only find examples pertaining to regular grids, and my (x,y) pairs are most certainly not regular.
Basically I am looking for some guidance on algorithms/models to achieve this goal. I am considering a triangulated irregular network, which is attractive because it breaks down into planes which are easy to determine the (x,y) from a given Z. But I would like a little more finesse.
I know it sounds like homework, its not.
Efficiency is not a concern.
Thanks!
I actually ended up using Delauney Triangulation to break down the fields into 3 dimensional X,Y,Z surfaces with an Identifier. Then given a set of (Identity,Z) pairs I form a field line from each surface, and from these lines compute the polygon formed from the shortest edges between lines. This gives me an area of potential x,y coordinates.
Take a look at Kd-tree.
These first take a set of scattered points in 2d or 3d or 10d,
then answers queries like "find the 3 points nearest P".
Are your queries z a pairs ?
For example, given a bunch of colored pins on a map, a table of x y size color,
one could put all the [x y] in a kd tree, then ask for pins near a given x0 y0.
Or, one could put all the [size color[ in a tree, then ask for pins with a similar size and color.
(Note that most kd-tree implementations use the Euclidean metric,
so sqrt( (size - size2)^2 + (color - color2)^2 ) should make sense.)
In Python, I highly recommend scipy.spatial.cKDTree.
See also SO questions/tagged/kdtree .

how to determine whether a point is above or below a polygon,not inside of the polygon?

I am taking Computer Graphics course.In 3D,I have a point and a polygon and I want to determine this point is located above or below my polygon.Thanks for your replies,in advance.
If above or below the plane on which the polygon is resting will do, you can compare the dot product of the point onto the plane normal and that of any point on the plane. Or look at the sign of the dot product between the normal and a vector from a point on the plane to the point, if you prefer.
To check whether it is actually 'above' or 'below' in the sense of being directly above or below (ie, not off to the side somewhere) then do a point in polygon by projecting the whole thing into 2d along the normal and then a distance along normal test.
It depends on your definition of above and below, let me first talk about the easy case:
If you think of above/below in terms of a global direction (typically the y-axis or z-axis), just compare the values on that axis.
Ok, now the more difficult interpretation: On which side of the polygon is the point.
Unless it is complanar you cannot decide it for the polygon at once. So if it is non-complanar you have to tesselate it into triangles and decide for each of them.
For a triangle you can decide whether a point is above or below it (in 3D), first calculate the cross product of 2 vectors that make up the sides of the triangle; this will define a direction (= the definition of "above" and "below"), this depends on the order in which you use those 2 vectors so be careful. Then calculate the dot-product of the new vector (which is called the perpendicular of that triangle) and the difference-vector of the point-to-test and the triangle-base.

Calculating rotation along a path

I am trying to animate an object, let's say its a car. I want it go from point
x1,y1,z1
to point x2,y2,z2 . It moves to those points, but it appears to be drifting rather than pointing in the direction of motion. So my question is: how can I solve this issue in my updateframe() event? Could you point me in the direction of some good resources?
Thanks.
First off how do you represent the road?
I recently done exactly this thing and I used Catmull-Rom splines for the road. To orient an object and make it follow the spline path you need to interpolate the current x,y,z position from a t that walks along the spline, then orient it along the Frenet Coordinates System or Frenet Frame for that particular position.
Basically for each point you need 3 vectors: the Tangent, the Normal, and the Binormal. The Tangent will be the actual direction you will like your object (car) to point at.
I choose Catmull-Rom because they are easy to deduct the tangents at any point - just make the (vector) difference between 2 other near points to the current one. (Say you are at t, pick t-epsilon and t+epsilon - with epsilon being a small enough constant).
For the other 2 vectors, you can use this iterative method - that is you start with a known set of vectors on one end, and you work a new set based on the previous one each updateframe() ).
You need to work out the initial orientation of the car, and the final orientation of the car at its destination, then interpolate between them to determine the orientation in between for the current timestep.
This article describes the mathematics behind doing the interpolation, as well as some other things to do with rotating objects that may be of use to you. gamasutra.com in general is an excellent resource for this sort of thing.
I think interpolating is giving the drift you are seeing.
You need to model the way steering works .. your update function should 1) move the car always in the direction of where it is pointing and 2) turn the car toward the current target .. one should not affect the other so that the turning will happen and complete more rapidly than the arriving.
In general terms, the direction the car is pointing is along its velocity vector, which is the first derivative of its position vector.
For example, if the car is going in a circle (of radius r) around the origin every n seconds then the x component of the car's position is given by:
x = r.sin(2πt/n)
and the x component of its velocity vector will be:
vx = dx/dt = r.(2π/n)cos(2πt/n)
Do this for all of the x, y and z components, normalize the resulting vector and you have your direction.
Always pointing the car toward the destination point is simple and cheap, but it won't work if the car is following a curved path. In which case you need to point the car along the tangent line at its current location (see other answers, above).
going from one position to another gives an object a velocity, a velocity is a vector, and normalising that vector will give you the direction vector of the motion that you can plug into a "look at" matrix, do the cross of the up with this vector to get the side and hey presto you have a full matrix for the direction control of the object in motion.

Resources