Cut point cloud into regions of interest

121 Views Asked by At

I have a point cloud and the trajectory of it. I want to cut it to smaller chunks so I will be able to process it more easily.

The problem of my code is that creates gaps and overlaps between the chunks. The methodology i followed is: first step is to split the trajectory and return a list of points along to it. Secondly, I used these points as boundaries for my chunks and i generated cylindrical regions of interest (ROIs) (I provided also the radius of the cylinder). The result I get is point cloud chunks that have gaps and overlaps between them. Here is my code:

def split(trajectory, chunks, is_distance=True, endpoints=True):
    """
    Return a list of evenly spaced points along a trajectory.

    Parameters
    ----------
    trajectory : numpy.ndarray
        Trajectory represented through a 2D NumPy array. Rows
        represent  trajectory points and the columns are the
        spatial coordinates X, Y and Z (in this order).
    chunks : int or float 
        Distance between consecutive points or number of points.
    is_distance : boolean, optional (default `True`) 
        If True, then `chunks` is the separation distance between two
        consecutive points Expressed in meters). Otherwise `chunks`
        is the number of parts into which the input line is partitioned
        (must be a whole number).
    endpoints : boolean, optional (default `True`) 
        If True, then the returned points are the edges of the parts
        into which the line is divided. Otherwise the returned points
        are the midpoints of the trajectory chunks.

    Returns 
    -------
    points : numpy.ndarray
        Sequence of equally spaced points sampled from the
        interpolated input trajectory. The points are bundled
        in a 2D NumPy array: one row per point and three spatial
        coordinates X, Y and Z (in this order) as columns.

    Notes
    -----
    The equally spaced points are obtained through the `interpolate`
    method, which returns points at specified distances along the
    line, as described in [1]_.
    """
    
    line = LineString(trajectory)
    if is_distance:
        n_parts = round(line.length/chunks)
    else:
        n_parts = chunks
    if endpoints:
        distances = np.arange(0, n_parts + 1)
    else:
        distances = (0.5 + np.arange(0, n_parts))
    distances = distances / n_parts
    seq = [line.interpolate(dist, normalized=True) for dist in distances]
    points = np.array(LineString(seq).coords)
    return points

traj_N = np.loadtxt('my_trajectory.poly')
limits = split(traj_N, 20, is_distance=True)
np.savetxt('My_limits.txt', limits)
    

def cylindrical_roi(cloud, start, end, radius):
    """Return the points of a point cloud inside a cylinder.

    Parameters
    ----------
    cloud : pandas.DataFrame
        Point cloud data. Columns must include 'X', 'Y', 'Z'.
    start : Array-like[three floats]
        X, Y and Z coordinates (in this order) of the start point
        the of axis of the cylinder.
    end : Array-like[three floats]
        X, Y and Z coordinates (in this order) of the end point of
        the axis of the cylinder.
    radius : float
        Radius of the cylinder.

    Returns
    -------
    pandas.DataFrame
        Points inside the cylinder of given radius and axis from
        start to end.
   """
   axis = end - start
    length = np.linalg.norm(axis) 
    unit = axis / length

    from_start = cloud[['X', 'Y', 'Z']] - start
    proj_on_axis = np.dot(from_start, unit)
    parallel = np.outer(proj_on_axis, unit)
    
    orthogonal = from_start - parallel
    dist_to_axis = np.linalg.norm(orthogonal, axis=1)
    
    masks = (0 <= proj_on_axis,
             proj_on_axis <= length,
             dist_to_axis <= radius)
    inside = np.logical_and.reduce(masks)
    
    return cloud[inside]

rois = []
for start, end in zip(limits[:-1], limits[1:]):
    rois.append(cylindrical_roi(road_N, start, end, 10))
# Assuming `rois` is a list of DataFrames
for i, df in enumerate(rois):
    file_name = path.join(output_path, f'road_L_roi_{i}.txt') # Name for the text file
    df.to_csv(file_name, sep=' ', index=False)  # Save DataFrame to text file with tab-separated values
    

0

There are 0 best solutions below