#[cfg(feature = "compression")]
pub mod compression;
#[cfg(feature = "e57")]
pub mod e57;
pub mod error;
pub mod lidar;
pub mod mesh_attributes;
#[cfg(feature = "io-mmap")]
pub mod mmap;
pub mod obj;
#[cfg(feature = "las_laz")]
pub mod pasture;
pub mod pcd;
pub mod ply;
pub mod registry;
#[cfg(feature = "ros2")]
pub mod ros2;
#[cfg(feature = "rosbag")]
pub mod rosbag;
pub mod serialization;
pub mod stl;
pub mod xyz_csv;
#[cfg(test)]
pub mod tests;
#[cfg(feature = "compression")]
pub use compression::{draco_decode, draco_encode, DracoCompressorPipeline, DracoConfig};
#[cfg(feature = "e57")]
pub use e57::{E57WriteOptions, RobustE57Reader, RobustE57Writer};
pub use error::*;
pub use lidar::{
LivoxLvx2Reader, LivoxLvxReader, OusterPcapReader, VelodyneKittiBinReader, VelodyneModel,
VelodynePcapReader,
};
pub use mesh_attributes::{ExtendedTriangleMesh, MeshAttributeOptions, MeshMetadata, Tangent, UV};
pub use obj::{
Face, FaceVertex, Group, Material, ObjData, ObjWriteOptions, RobustObjReader, RobustObjWriter,
};
pub use pcd::{
PcdDataFormat, PcdFieldType, PcdHeader, PcdValue, PcdWriteOptions, RobustPcdReader,
RobustPcdWriter,
};
pub use ply::{PlyFormat, PlyValue, PlyWriteOptions, RobustPlyReader, RobustPlyWriter};
pub use registry::{FormatHandler, IoRegistry};
#[cfg(feature = "ros2")]
pub use ros2::{
colored_normals_to_pointcloud2, colored_to_pointcloud2, normals_to_pointcloud2,
organized_xyz_to_pointcloud2, pointcloud2_to_colored, pointcloud2_to_colored_normals,
pointcloud2_to_normals, pointcloud2_to_organized_xyz, pointcloud2_to_xyz, xyz_to_pointcloud2,
PointCloud2Data, PointCloud2Info, PointField,
};
pub use serialization::{
AttributePreservingReader, AttributePreservingWriter, SerializationOptions,
};
pub use stl::{read_stl, write_stl, StlReader, StlWriteOptions, StlWriter};
pub use xyz_csv::{
ColumnType, Delimiter, XyzCsvPoint, XyzCsvReader, XyzCsvSchema, XyzCsvStreamingReader,
XyzCsvWriteOptions, XyzCsvWriter,
};
use std::path::Path;
use threecrate_core::{Point3f, PointCloud, Result, TriangleMesh};
pub(crate) fn capacity_hint(count: usize) -> usize {
count.min(1 << 20)
}
pub trait PointCloudReader {
fn read_point_cloud<P: AsRef<std::path::Path>>(path: P) -> Result<PointCloud<Point3f>>;
}
pub trait PointCloudWriter {
fn write_point_cloud<P: AsRef<std::path::Path>>(
cloud: &PointCloud<Point3f>,
path: P,
) -> Result<()>;
}
pub trait MeshReader {
fn read_mesh<P: AsRef<std::path::Path>>(path: P) -> Result<TriangleMesh>;
}
pub trait MeshWriter {
fn write_mesh<P: AsRef<std::path::Path>>(mesh: &TriangleMesh, path: P) -> Result<()>;
}
lazy_static::lazy_static! {
static ref IO_REGISTRY: IoRegistry = {
let mut registry = IoRegistry::new();
registry.register_point_cloud_handler("ply", Box::new(ply::PlyReader));
registry.register_mesh_handler("ply", Box::new(ply::PlyReader));
registry.register_point_cloud_writer("ply", Box::new(ply::PlyWriter));
registry.register_mesh_writer("ply", Box::new(ply::PlyWriter));
registry.register_mesh_handler("obj", Box::new(obj::ObjReader));
registry.register_mesh_writer("obj", Box::new(obj::ObjWriter));
registry.register_mesh_handler("stl", Box::new(stl::StlReader));
registry.register_mesh_writer("stl", Box::new(stl::StlWriter));
#[cfg(feature = "las_laz")]
{
registry.register_point_cloud_handler("las", Box::new(pasture::PastureReader));
registry.register_point_cloud_handler("laz", Box::new(pasture::PastureReader));
registry.register_point_cloud_writer("las", Box::new(pasture::PastureWriter));
registry.register_point_cloud_writer("laz", Box::new(pasture::PastureWriter));
}
registry.register_point_cloud_handler("pcd", Box::new(pcd::PcdReader));
registry.register_point_cloud_writer("pcd", Box::new(pcd::PcdWriter));
registry.register_point_cloud_handler("xyz", Box::new(xyz_csv::XyzCsvReader));
registry.register_point_cloud_handler("csv", Box::new(xyz_csv::XyzCsvReader));
registry.register_point_cloud_handler("txt", Box::new(xyz_csv::XyzCsvReader));
registry.register_point_cloud_writer("xyz", Box::new(xyz_csv::XyzCsvWriter));
registry.register_point_cloud_writer("csv", Box::new(xyz_csv::XyzCsvWriter));
registry.register_point_cloud_writer("txt", Box::new(xyz_csv::XyzCsvWriter));
registry.register_point_cloud_handler("bin", Box::new(lidar::VelodyneBinRegistryReader));
registry.register_point_cloud_handler("pcap", Box::new(lidar::VelodynePcapRegistryReader));
registry.register_point_cloud_handler("lvx", Box::new(lidar::LivoxLvxRegistryReader));
registry.register_point_cloud_handler("lvx2", Box::new(lidar::LivoxLvx2RegistryReader));
#[cfg(feature = "e57")]
{
registry.register_point_cloud_handler("e57", Box::new(e57::E57Reader));
registry.register_mesh_handler("e57", Box::new(e57::E57Reader));
registry.register_point_cloud_writer("e57", Box::new(e57::E57Writer));
registry.register_mesh_writer("e57", Box::new(e57::E57Writer));
}
#[cfg(feature = "compression")]
{
registry.register_point_cloud_handler("drc", Box::new(compression::DracoReader));
registry.register_point_cloud_writer("drc", Box::new(compression::DracoWriter));
}
registry
};
}
pub fn read_point_cloud<P: AsRef<Path>>(path: P) -> Result<PointCloud<Point3f>> {
let path = path.as_ref();
let extension = path.extension().and_then(|s| s.to_str()).ok_or_else(|| {
threecrate_core::Error::UnsupportedFormat("No file extension found".to_string())
})?;
IO_REGISTRY.read_point_cloud(path, extension)
}
pub fn read_mesh<P: AsRef<Path>>(path: P) -> Result<TriangleMesh> {
let path = path.as_ref();
let extension = path.extension().and_then(|s| s.to_str()).ok_or_else(|| {
threecrate_core::Error::UnsupportedFormat("No file extension found".to_string())
})?;
let mesh = IO_REGISTRY.read_mesh(path, extension)?;
mesh.validate_faces()?;
Ok(mesh)
}
pub fn write_point_cloud<P: AsRef<Path>>(cloud: &PointCloud<Point3f>, path: P) -> Result<()> {
let path = path.as_ref();
let extension = path.extension().and_then(|s| s.to_str()).ok_or_else(|| {
threecrate_core::Error::UnsupportedFormat("No file extension found".to_string())
})?;
IO_REGISTRY.write_point_cloud(cloud, path, extension)
}
pub fn write_mesh<P: AsRef<Path>>(mesh: &TriangleMesh, path: P) -> Result<()> {
let path = path.as_ref();
let extension = path.extension().and_then(|s| s.to_str()).ok_or_else(|| {
threecrate_core::Error::UnsupportedFormat("No file extension found".to_string())
})?;
IO_REGISTRY.write_mesh(mesh, path, extension)
}
pub fn get_io_registry() -> &'static IoRegistry {
&IO_REGISTRY
}
pub fn read_point_cloud_iter<P: AsRef<Path>>(
path: P,
chunk_size: Option<usize>,
) -> Result<Box<dyn Iterator<Item = Result<Point3f>> + Send + Sync>> {
let path = path.as_ref();
let extension = path.extension().and_then(|s| s.to_str()).ok_or_else(|| {
threecrate_core::Error::UnsupportedFormat("No file extension found".to_string())
})?;
match extension {
"ply" => {
let iter = ply::PlyStreamingReader::new(path, chunk_size.unwrap_or(1000))?;
Ok(Box::new(iter))
}
"obj" => {
let iter = obj::ObjStreamingReader::new(path, chunk_size.unwrap_or(1000))?;
Ok(Box::new(iter))
}
"xyz" | "csv" | "txt" => {
let iter = xyz_csv::XyzCsvStreamingReader::new(path, chunk_size.unwrap_or(1000))?;
Ok(Box::new(iter))
}
_ => Err(threecrate_core::Error::UnsupportedFormat(format!(
"Streaming not supported for format: {}",
extension
))),
}
}
pub fn read_mesh_iter<P: AsRef<Path>>(
path: P,
chunk_size: Option<usize>,
) -> Result<Box<dyn Iterator<Item = Result<[usize; 3]>> + Send + Sync>> {
let path = path.as_ref();
let extension = path.extension().and_then(|s| s.to_str()).ok_or_else(|| {
threecrate_core::Error::UnsupportedFormat("No file extension found".to_string())
})?;
match extension {
"ply" => {
let iter = ply::PlyMeshStreamingReader::new(path, chunk_size.unwrap_or(1000))?;
Ok(Box::new(iter))
}
"obj" => {
let iter = obj::ObjMeshStreamingReader::new(path, chunk_size.unwrap_or(1000))?;
Ok(Box::new(iter))
}
_ => Err(threecrate_core::Error::UnsupportedFormat(format!(
"Streaming not supported for format: {}",
extension
))),
}
}