Skip to content

Commit

Permalink
Improved calculation for max packet points
Browse files Browse the repository at this point in the history
  • Loading branch information
cry-inc committed Aug 17, 2024
1 parent 2f4172c commit 8c932fc
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 10 deletions.
24 changes: 17 additions & 7 deletions src/pc_writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,19 +64,15 @@ impl<'a, T: Read + Write + Seek> PointCloudWriter<'a, T> {
// Make sure the prototype is not invalid or incomplete
Self::validate_prototype(&prototype)?;

// Calculate max number of points per packet
let max_points_per_packet = get_max_packet_points(&prototype);

let mut section_header = CompressedVectorSectionHeader::default();
let section_offset = writer.physical_position()?;
section_header.data_offset = section_offset + CompressedVectorSectionHeader::SIZE;
section_header.section_length = CompressedVectorSectionHeader::SIZE;
section_header.write(writer)?;

// Each data packet can contain up to 2^16 bytes, but we need some reserved
// space for header data. We also need to consider some "incomplete" bytes
// from record value sizes that are not a multiple of 8 bits.
// So lets round down a bit to have some spare bytes.
let point_size_bits: usize = prototype.iter().map(|p| p.data_type.bit_size()).sum();
let max_points_per_packet = (64000 * 8) / point_size_bits;

// Prepare bounds
let has_cartesian = prototype.iter().any(|p| p.name == RecordName::CartesianX);
let cartesian_bounds = if has_cartesian {
Expand Down Expand Up @@ -686,3 +682,17 @@ fn validate_return(prototype: &[Record]) -> Result<()> {
}
Ok(())
}

/// Calculate maximum number of points per packet.
/// Each data packet can contain up to 2^16 bytes, but we need some reserved
/// space for header data. We also need to consider some "incomplete" bytes
/// from record value sizes that are not a multiple of 8 bits.
fn get_max_packet_points(prototype: &[Record]) -> usize {
const SAFETY_MARGIN: usize = 500;
let point_size_bits: usize = prototype.iter().map(|p| p.data_type.bit_size()).sum();
let bs_size_headers = prototype.len() * 2; // u16 for each byte stream header
let headers_size = DataPacketHeader::SIZE + bs_size_headers;
let max_incomplete_bytes = prototype.len();
let u16_max = u16::MAX as usize;
((u16_max - headers_size - max_incomplete_bytes - SAFETY_MARGIN) * 8) / point_size_bits
}
7 changes: 4 additions & 3 deletions tests/writer_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -947,8 +947,8 @@ fn custom_xml_test() {
}

#[test]
fn writer_bug_reproduction() {
let file = "writer_repro_bug.e57";
fn writer_bug_regression_test() {
let file = "writer_bug_regression.e57";
{
let mut writer = e57::E57Writer::from_file(file, "file_uuid").unwrap();
let proto = vec![
Expand All @@ -966,7 +966,8 @@ fn writer_bug_reproduction() {
},
];
let mut pc_writer = writer.add_pointcloud("pc_guid", proto).unwrap();
for _ in 0..4785 {
// exactly the the max packet point count of the internal writer
for _ in 0..4861 {
let point = vec![
RecordValue::Single(0.0),
RecordValue::Single(0.0),
Expand Down

0 comments on commit 8c932fc

Please sign in to comment.