# FindGeometricTransform from 3D object external surfaces to a positional point cloud data

I am looking for another way to approach this problem. Any suggestion on how to optimize the computing speed is welcome.

I have a BSplineFunction which accurately represents the curved surface of a turbine blade. I have a set of points which represent the real position of the turbine blade surface, we will call it a point could.

I need to find a geometric transformation that would bring the surface into the point cloud.

I took the brute force approach of scattering a large amount of points on the model surface. Then I used Nearest and FindGeometricTransform functions. Here is the code:

F = BsplineFunction[model]; (* Model surface as B spline Function *)
(* Surface Sampling Function *)
SurfaceSampling[p_] := Flatten[Table[F[u, v], {u, 0, 1, p}, {v, 0, 1, p}], 1];

ModelSurface = SurfaceSampling[0.005]; (* Actual sampling *)
g = Drop[T1[[2]][[1]].Append[vec, 1], -1] (* T1 Geometric Transform of point "vec" *)

(* CtrlPts is the point could *)
T1 = FindGeometricTransform[Nearest[CtrlPts, ModelSurface], CtrlPts,
"Transformation"- > "Rigid", Method -> "FindFit"];

(* Apply found transformation to the ModelSurface *)
ModelSurface = Map[g, ModelSurface]
(* After a couple of iterations, T will become the optimal transformation *)
T = T1[[2]][[1]].T;


This is an iterative process, so you can add a Do or a While loop, which would end when the model does not move anymore. You will find CtrlPts and ModelSurface at:

I found this brute force method too slow and instead of using a large amount of points, I would like to perform direct orthogonal projection of the point cloud on the model surface. I think using continuous function would be way faster than handling large amount of points.

I was thinking about directly minimising the Euclidian distance from a point to the surface? Is that feasible/doable ? I am open to suggestions.

Before posting the solution I found, let me reformulate the problem and give more details about what I am trying to acheive.

A Robotic arm grabs a turbine blade. All the robot positional data is available and the blade geometry as well. I need to find the exact position of the blade relative to the grabber, using positional information provided as a point cloud. The picture below shows the blade External surface as well as the point cloud.

The turbine blade external surface are provided as an ordered set of points. These points were exported from another piece software that extract a surface parametrization from a STEP file. The software offers a couple of different type of parametrization, I choose fourth order B-spline and Bilinear. From both parametrization I extracted a map of {u,v} ordered points, defining the surface.

Here is the solution I found

I started with the bilinear interpolation which is the simplest. Here is the sequence of operation I used in Pseudo code/Code. Note two things, this is an iterative process and it has to be started with a reasonably good guess, otherwise it will not converge.

Cloud=Import["PositionalData.csv","Data"]*Import Positional data*

*In a bilinear interpolation, three adjacent points must be contained in a flat surface*
VertexSurface=Table[Polygon[{CtrlPts[[1+i]][[2+j]],CtrlPts[[1+i]][[1+j]],CtrlPts[[2+i]][[1+j]]}],{i,0,Length[CtrlPts]},{j,0,Length[CtrlPts]}]

*This will create "MeshRegion" from the Graphics3D[...] object*

*Compute Euclidian Closest point for each Point in the cloud*
*The output of this function is a point which belongs to the blade surface*

*This function will find the optimal point to point geometric transform*
*For some unknown reason, Mathematica could not recognize "FindFit" Method...*
T = FindGeometricTransform[Cloud, projection,
TransformationClass -> "Rigid", Method -> "Linear"];

*Apply the transformation to the set of CtrlPts and iterate*
CtrlPts=Map[T,CtrlPts]


Transforming the blade surface into a "region" object is the key, after you can use all the powerful tools related to this type of object within mathematica. here is how I used this function "DiscretizeGraphics" for higher order interpolation.

Blade=DiscretizeGraphics[Graphics3D[BSplineSurface[CtrlPts,SplieDegree->4,SplineClosed->False]], MeshQualityGoal -> "Maximal", MaxCellMeasure -> {"Area" -> 0.001}]

• I transformed the *.STEP file into a *.STL mesh using FREE CAD software. Since now I can control the mesh resolution, it works even better! – Franckyboy Dec 6 '14 at 17:17