One element of a PLY file — a named, counted collection of rows sharing
a property schema (element vertex 8 followed by its properties).
Fixed-width vs variable-width
The distinction that governs everything downstream is whether an element contains any list property:
Fixed width — every row is the same number of bytes. The element is seekable, can be decoded columnar, and an arbitrary row can be addressed in constant time.
Variable width — a row's size depends on its own list counts, so the element can only be read sequentially, and there is no offset table in the format to help.
This is a per-element property, not a per-file one: the common mesh
layout has a fixed-width vertex element followed by a variable-width
face element.
A consequence worth stating plainly, because it is invisible from the outside: reaching element N means walking every element before it, so streaming a late element is only cheap when everything preceding it is fixed width.
Summary
Functions
Total byte size of this element's data in a binary file, or :variable
when it cannot be known without reading.
Whether every row of this element occupies the same number of bytes.
Builds an element, computing record_size from the properties.
Looks up a property by name.
Property names, in declaration order — which is also on-disk order.
Renders the element and its properties as PLY header lines.
Types
@type t() :: %Ply.Element{ count: non_neg_integer(), name: String.t(), properties: [Ply.Property.t()], record_size: pos_integer() | :variable }
Functions
@spec byte_size(t()) :: non_neg_integer() | :variable
Total byte size of this element's data in a binary file, or :variable
when it cannot be known without reading.
iex> element = Ply.Element.new("vertex", 8, [Ply.Property.scalar("x", :float32)])
iex> Ply.Element.byte_size(element)
32
Whether every row of this element occupies the same number of bytes.
iex> element = Ply.Element.new("vertex", 1, [Ply.Property.scalar("x", :float32)])
iex> Ply.Element.fixed_width?(element)
true
@spec new(String.t(), non_neg_integer(), [Ply.Property.t()]) :: t()
Builds an element, computing record_size from the properties.
@spec property(t(), String.t()) :: {:ok, Ply.Property.t()} | :error
Looks up a property by name.
Property names, in declaration order — which is also on-disk order.
Renders the element and its properties as PLY header lines.