Ply.Element (Ply v0.1.0)

Copy Markdown View Source

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

t()

@type t() :: %Ply.Element{
  count: non_neg_integer(),
  name: String.t(),
  properties: [Ply.Property.t()],
  record_size: pos_integer() | :variable
}

Functions

byte_size(element)

@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

fixed_width?(element)

@spec fixed_width?(t()) :: boolean()

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

new(name, count, properties)

@spec new(String.t(), non_neg_integer(), [Ply.Property.t()]) :: t()

Builds an element, computing record_size from the properties.

property(element, name)

@spec property(t(), String.t()) :: {:ok, Ply.Property.t()} | :error

Looks up a property by name.

property_names(element)

@spec property_names(t()) :: [String.t()]

Property names, in declaration order — which is also on-disk order.

to_header_lines(element)

@spec to_header_lines(t()) :: [String.t()]

Renders the element and its properties as PLY header lines.