I'd like to find an object / surface normal (tangent vector) for a given point in space. More in detail I have an object and a spline following the objects surface and I want to get the object normal for each spline point.

I couldn't find a way how to approach this, yet ....

Maybe someone has a tip or an idea?

(I want to do this in python)

best, Index

]]>without further questions or replies, we will consider this topic as solved by Thursday and flag it accordingly.

Thank you for your understanding,

Ferdinand

that's a roadmap !!

gosh, it looks like i have quite some work ahead of me!

dunno yet, if i'm crazy enough to give it a try :))

ps. that also means that the nearest intersection between

a point and an object without vector is not possible with GeRayCollider (?)

as a disclaimer upfront, this is a private posting of mine, your case is still being handled by @m_adam.

When I see your case correctly, you are interested in the point *p* and its normal *n* on a polygonal mesh *M* that is closest to a given point *q* on a spline *S*. Or in short, you are interested in the projection of *q* onto *M*. Ray-casting, e.g., `GeRayCollider`

, will not help you much here I would say, since coming up with a ray-casting direction is the same problem as the one you are trying to solve; as you already did find out yourself.

Cinema 4D's Python SDK has no projection helper class, so, you would have to do that on your own. The general procedure would be:

- Find the the vertex
*v*in*M*that is closest to*q*. - Get the list
*L*of all polygons that are attached to*v*- you can use`c4d.utils.Neighbor`

for that. - Project
*q*onto all polygons in*L*and store the results in*R*. Principally, what one has to do here is point-plane projections. The concrete procedure is something like the following for a single polygon*P*.

a. Compute the point-plane projection*proj*of*q*for each triangle*T*in*P*.

b. Convert*proj*from Cartesian into Barycentric coordinates and clamp the point to the interval [0, 1]. We have to do this since there is no guarantee that the point we projected onto the plane of*T*actually does lie within*T*. So, we ware using Barycentric coordinates to rectify this.

c. Convert the clamped points back into Cartesian coordinates and then select the one closest to*q*. This point is the clamped projection of*q*onto*P*. - Select the point in
*R*that is closest to*q*, that point is*p*, the projection of your query point*q*onto*M*. - Define the normal of
*p*as one of the normals of the polygon*P*the point*p*is associated with. That polygon is already known to us due to the prior computations. How to compute the normal exactly depends on what you would consider to be the*object*normal.

For all that you do not need any fancy classes or libraries, but it can be a bit slow if you do this for very large meshes. The expensive part is the first step, finding the closest vertex *v* in *M*. Which is probably why Maxime mentioned kd-trees. They are a form Binary-Space-Partitioning, i.e., a performant way to find the closest point *p* out of a point cloud *C* for a query point *q*. Since the Cinema Python SDK has no kd-Tree, you would have to write your own BSP implementation, a octree would be enough in this case (which is effectively just a clever form of a 3D-lattice). But this is not really needed functionality-wise, it will just make your solution more performant.

Cheers,

Ferdinand

hm.. looking at c4d.utils.GeRayCollider ...

is it correct that i always have to define a ray vector ?

as i understand it GetNearestIntersection() is just the nearest intersection with the given vector, right?

is possible to eval the nearest intersection between a point and an object without vector?

or is that what KdTree is used for ?

best, index

]]>One things could be to use a c4d.utils.GeRayCollider to retrieve the polygon attached to the point and then compute yourself the surface normal.

Another way would be to create a KdTree and retrieve the nearest point and compute this tangent vector yourself.But there is no KdTree in the Python Cinema 4D SDK, so you will need to build it yourself.

Cheers,

Maxime.