Identifies a Gaussian-splat PLY without decoding it.
This is the admission gate. A splat capture is 62 float32 per vertex — 248 bytes each — so a gigabyte file holds roughly 4.2 million rows and 260 million values. Handing one to a converter that then rejects it costs minutes of CPU and gigabytes of memory; reading the header costs a few kilobytes.
Everything here works from the PLY header alone.
Summary
Types
@type kind() :: :splat | :mesh | :point_cloud
What a file turned out to be.
:splat— a Gaussian-splat point cloud:mesh— an ordinary PLY with faces:point_cloud— vertices with no splat properties and no faces
@type t() :: %{ kind: kind(), splat_count: non_neg_integer(), sh_bands: 0..3, sh_coefficients: non_neg_integer(), bytes_per_splat: pos_integer() | :variable, format: Ply.Header.format(), properties: [String.t()], has_normals: boolean() }
Functions
@spec require_splat(Ply.source()) :: {:ok, t()} | {:error, SplatTools.Error.t()}
Asserts that a source really is a splat, for callers that go on to convert it.
Conversion is minutes of CPU and gigabytes of memory, so it is worth spending a few kilobytes to find out first.
@spec run(Ply.source()) :: {:ok, t()} | {:error, SplatTools.Error.t()}
Inspects a PLY and reports what it is.
Accepts anything Ply.info/1 accepts — a path, or {:binary, contents}.
{:ok, info} = SplatTools.Inspect.run("capture.ply")
info.kind #=> :splat
info.splat_count #=> 1_284_331
info.sh_bands #=> 3
@spec run!(Ply.source()) :: t()
Same as run/1, raising on error.
@spec splat?(Ply.source()) :: boolean()
Whether a file is a Gaussian-splat point cloud.
A convenience over run/1 for callers that only need a yes or no; an
unreadable file answers false rather than raising.