1

I want to shift the coordinates of a .laz pointcloud by tx, and ty with laspy. After reading more about the offset and scale attributes of a las header.

I see that Xcoordinate = (Xrecord * Xscale) + Xoffset and Ycoordinate = (Yrecord * Yscale) + Yoffset.

So, my guess is that if tx = 10 if I would change the first value of the offset, the coordinates would shift as well but that is not the case.

las =  laspy.read("C://Users//avenianakis//Desktop//temp_laz//BLK_0233_LAZ.laz")
print(las.x[0])
# >> -2065.2048234334543
las.header.offset[0] = 10
print(las.x[0])
# >> -2065.2048234334543

How can I understand what is going on?

1 Answer 1

0

I have found out for this use case that is more efficient to edit the header of the .laz file using binary file I/O to modify the offset values.

Here is my code:

def read_las_header(file):
    file.seek(0)
    header = file.read(227)  # LAS 1.2 header

    point_data_offset = struct.unpack('<I', header[96:100])[0]
    point_record_length = struct.unpack('<H', header[105:107])[0]
    num_point_records = struct.unpack('<I', header[107:111])[0]

    x_scale = struct.unpack('<d', header[131:139])[0]
    y_scale = struct.unpack('<d', header[139:147])[0]
    z_scale = struct.unpack('<d', header[147:155])[0]

    x_offset = struct.unpack('<d', header[155:163])[0]
    y_offset = struct.unpack('<d', header[163:171])[0]
    z_offset = struct.unpack('<d', header[171:179])[0]

    return (header, point_data_offset, point_record_length, num_point_records, x_scale, y_scale, z_scale, x_offset, y_offset, z_offset)

def shift_laz_header(input_file_path, output_file_path, tx=0, ty=0, tz=0):
    with open(input_file_path, 'rb') as infile:
        header_data = read_las_header(infile)
        header, point_data_offset, point_record_length, num_point_records, x_scale, y_scale, z_scale, x_offset, y_offset, z_offset = header_data

        new_x_offset = x_offset + tx
        new_y_offset = y_offset + ty
        new_z_offset = z_offset + tz

        print(f"Original X Offset: {x_offset}, New X Offset: {new_x_offset}")
        print(f"Original Y Offset: {y_offset}, New Y Offset: {new_y_offset}")
        print(f"Original Z Offset: {z_offset}, New Z Offset: {new_z_offset}")

        updated_header = update_offsets_in_header(header, new_x_offset, new_y_offset, new_z_offset)

        with open(output_file_path, 'wb') as outfile:
            outfile.write(updated_header)

            # Copy the rest of the file
            infile.seek(227)
            shutil.copyfileobj(infile, outfile)

            print(f"Updated offsets in header: X={new_x_offset}, Y={new_y_offset}, Z={new_z_offset}")

Notice: You can modify the scale in similar fashion. Also, beware that this does not alter the bounding box defined from the .laz header, if you want that to be adjusted you have to change the min & max values of each axis.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.