Rotate point cloud to the XY plane
Hi,
I would like to use CC to rotate a point cloud in the XY plane so that all Z values are approximately the same size. My point cloud has approximately the shape of a plane. I have tried the following approach:
pcd = cc.loadPointCloud("mypcd.xyz")
plane = cc.ccPlane.Fit(pcd)
plane_eq = plane.getEquation()
normVec = [abs(plane_eq[0]), abs(plane_eq[1]), abs(plane_eq[2])]
rotMat = cc.ccGLMatrix.FromToRotation(normVec, (0., 0., 1.))
pcd.applyRigidTransformation(rotMat)
I first fit a plane to my point cloud and use the normal vector of the plane to get the rotation matrix for the rotation of the plane to [0,0,1] using the function cc.ccGLMatrix.FromToRotation. Then I apply the rotation matrix in applyRigidTransformation to rotate my point cloud. However, this approach only works for point clouds that are aligned along the coordinate axes. For point clouds with random orientation in 3D space, the rotation in the XY plane does not work at all.
Any idea how I could achieve my goal more easily and reliably?
best
Hello,
I don't understand the abs function in normVec = [abs(plane_eq[0]), abs(plane_eq[1]), abs(plane_eq[2])]. When the vector components do not have the same sign, you break the vector.
If you use the normal vector without modification, it works.
Regards, Paul
My test:
import os
import sys
import math
os.environ["_CCTRACE_"]="ON" # only if you want C++ debug traces
from gendata import getSampleCloud, getSampleCloud2, dataDir, isCoordEqual
import cloudComPy as cc
# --- build a cloud and apply a rotation to get something not aligned with the 3 axes
cloud1 = cc.loadPointCloud(getSampleCloud2(3.0,0, 0.1))
cloud1.setName("cloud1")
tr1 = cc.ccGLMatrix()
tr1.initFromParameters(0.2*math.pi, (1., 1., 1.), (0.0, 0.0, 10.0))
cloud1.applyRigidTransformation(tr1)
# --- get the normal vector to the fit plane, the FromToRotation to return to Z, and apply
plane = cc.ccPlane.Fit(cloud1)
equation = plane.getEquation()
vec=equation[0:3]
rotMat = cc.ccGLMatrix.FromToRotation(vec, (0., 0., 1.))
cloud2 = cloud1.cloneThis()
cloud2.applyRigidTransformation(rotMat)
# -- check if the result is aligned with Z axis.
plane2 = cc.ccPlane.Fit(cloud2)
equ2 = plane2.getEquation()
vec2=equ2[0:3]
if not isCoordEqual(vec2, (0., 0., 1.), abs_tol = 1.e-6):
raise RuntimeError
cc.SaveEntities([cloud1, plane, cloud2], os.path.join(dataDir, "cloudsRotation.bin"))
I Paul,
as you said, after removing the abs function, rotation in the XY plane does work.
Thanks!
Best,