CloudComPy icon indicating copy to clipboard operation
CloudComPy copied to clipboard

Rotate point cloud to the XY plane

Open HollowHeartNet opened this issue 3 years ago • 2 comments

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

HollowHeartNet avatar Oct 31 '22 17:10 HollowHeartNet

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"))

prascle avatar Nov 02 '22 20:11 prascle

I Paul, as you said, after removing the abs function, rotation in the XY plane does work. Thanks!

Best,

HollowHeartNet avatar Nov 03 '22 09:11 HollowHeartNet