ply_rs/ply/ply_data_structure.rs
1use std::fmt::{ Display, Formatter };
2use std::fmt;
3use super::PropertyType;
4use super::KeyMap;
5use super::PropertyAccess;
6
7/// Models all necessary information to interact with a PLY file.
8///
9/// The generic parameter `E` is the element type used to store the payload data.
10#[derive(Debug, Clone, PartialEq)]
11pub struct Ply<E: PropertyAccess> {
12 /// All header information found in a PLY file.
13 pub header: Header,
14 /// The payloud found after the `end_header` line in a PLY file.
15 ///
16 /// One line in an ascii PLY file corresponds to a single element.
17 /// The payload groups elments with the same type together in a vector.
18 ///
19 /// # Examples
20 ///
21 /// Assume you have a `Ply` object called `ply` and want to access the third `point` element:
22 ///
23 /// ```rust,no_run
24 /// # use ply_rs::ply::{Ply, DefaultElement};
25 /// # let ply = Ply::<DefaultElement>::new();
26 /// // get ply from somewhere ...
27 /// let ref a_point = ply.payload["point"][2];
28 /// let ref a_point_x = ply.payload["point"][2]["x"];
29 /// ```
30 pub payload: Payload<E>,
31}
32impl<E: PropertyAccess> Ply<E> {
33 /// Creates a new `Ply<E>`.
34 pub fn new() -> Self {
35 Ply::<E> {
36 header: Header::new(),
37 payload: Payload::new(),
38 }
39 }
40}
41
42// Header Types
43
44/// Models the header of a PLY file.
45#[derive(Debug, PartialEq, Eq, Clone)]
46pub struct Header {
47 /// In which format is the payload encoded?
48 ///
49 /// Ascii produces human readable files,
50 /// while binary encoding lets you choose between big and little endian.
51 pub encoding: Encoding,
52 /// Which file format standard is used?
53 ///
54 /// The only existing standard is 1.0.
55 pub version: Version,
56 pub obj_infos: Vec<ObjInfo>,
57 /// Ordered map of elements as they appear in the payload.
58 pub elements: KeyMap<ElementDef>,
59 /// File comments.
60 pub comments: Vec<Comment>,
61}
62
63impl Header {
64 /// Constructs an empty `Header` using Ascii encoding and version 1.0.
65 /// No object informations, elements or comments are set.
66 pub fn new() -> Self {
67 Header {
68 encoding: Encoding::Ascii,
69 version: Version{major: 1, minor: 0},
70 obj_infos: Vec::new(),
71 elements: KeyMap::new(),
72 comments: Vec::new(),
73 }
74 }
75}
76
77/// Alias to give object informations an explicit type.
78pub type ObjInfo = String;
79
80/// Alias to give comments an explicit type.
81pub type Comment = String;
82
83/// Models a version number.
84///
85/// At time of writing, the only existin version for a PLY file is "1.0".
86#[derive(Debug, PartialEq, Eq, Clone, Copy)]
87pub struct Version {
88 pub major: u16,
89 pub minor: u8,
90}
91
92impl Display for Version {
93 fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
94 f.write_str(&format!("{}.{}", self.major, self.minor))
95 }
96}
97
98/// Models possible encoding standards for the payload.
99#[derive(Debug, PartialEq, Eq, Clone, Copy)]
100pub enum Encoding {
101 /// Write numbers in their ascii representation (e.g. -13, 6.28, etc.).
102 /// Properties are separated by spaces and elements are separated by line breaks.
103 Ascii,
104 /// Encode payload using big endian.
105 BinaryBigEndian,
106 /// Encode payload using little endian.
107 BinaryLittleEndian,
108}
109
110impl Display for Encoding {
111 fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
112 f.write_str(
113 match *self {
114 Encoding::Ascii => "ascii",
115 Encoding::BinaryBigEndian => "binary_big_endian",
116 Encoding::BinaryLittleEndian => "binary_little_endian",
117 }
118 )
119 }
120}
121
122/// Models the definition of an element.
123///
124/// Elements describe single entities consisting of different properties.
125/// A single point is an element.
126/// We might model it as consisting of three coordinates: x, y, and z.
127/// Usually, one finds a list of elements in a ply file.
128#[derive(Debug, PartialEq, Eq, Clone)]
129pub struct ElementDef {
130 /// Name of the element.
131 ///
132 /// Each element within a PLY file needs a unique name.
133 /// There are common conventions like using "vertex" and "face" to assure interoperability between applications.
134 /// For further information, please consult your target applications or the [original specification](http://paulbourke.net/dataformats/ply/).
135 pub name: String,
136 /// Describes, how many elements appear in a PLY file.
137 ///
138 /// The `count` is used when reading since we need to know how many elements we should interprete as having this type.
139 /// The `count` is also needed for writing, since it will be written to the header.
140 pub count: usize,
141 /// An element is modeled by multiple properties, those are named values or lists.
142 ///
143 /// # Examples
144 ///
145 /// - Point: We can define a point by its three coordinates. Hence we have three properties: x, y, and z. Reasonable types would be float or double.
146 /// - Polygon: A polygon can be defined as a list of points. Since the points are stored in a list, we can define a list of indices. Good types would be some of the unsigned integer lists.
147 pub properties: KeyMap<PropertyDef>,
148}
149impl ElementDef {
150 /// Creates a new element definition.
151 ///
152 /// The name should be unique for each element in a PLY file.
153 ///
154 /// You should never need to set `count` manuall, since it is set by the consistency check (see `make_consistent()` of `Ply`).
155 ///
156 /// No properties are set.
157 pub fn new(name: String) -> Self {
158 ElementDef {
159 name: name,
160 count: 0,
161 properties: KeyMap::new(),
162 }
163 }
164}
165
166/// Defines a property of an element.
167#[derive(Debug, PartialEq, Eq, Clone)]
168pub struct PropertyDef {
169 /// Unique name of property.
170 ///
171 /// The name should be unique for each property of the same element.
172 pub name: String,
173 /// Data type of the property:
174 /// You can have simple scalars (ints, floats, etc.) or lists of scalars.
175 /// In the case of lists you need to decide in which type you want to store the list length and what type to use for the list elemetns.
176 pub data_type: PropertyType,
177}
178
179impl PropertyDef {
180 /// Creates a new property definition.
181 pub fn new(name: String, data_type: PropertyType) -> Self {
182 PropertyDef {
183 name: name,
184 data_type: data_type,
185 }
186 }
187}
188
189/// The part after `end_header`, contains the main data.
190pub type Payload<E> = KeyMap<Vec<E>>;