Skip to content

Commit 6218358

Browse files
committed
Allow any AbstractArray with plyname() defined as properties
This much improves the ability to get at the data once a ply file has been loaded, without resorting to unwrapping via peeking at the `.data` field of the properties. Also included here are various improvements for documentation: * Include a quickstart for loading ply files * Briefly document the API * Add the quickstart example to an easily runnable julia file
1 parent 33e6649 commit 6218358

File tree

6 files changed

+248
-76
lines changed

6 files changed

+248
-76
lines changed

README.md

+76-10
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ the Stanford triangle format.
66

77
## Quick start
88

9+
### Writing ply
10+
911
Here's an example of how to write a basic ply file containing random triangles
1012
and edges:
1113

@@ -42,22 +44,86 @@ end
4244
push!(ply, PlyElement("edge", vertex_index))
4345

4446
# For the sake of the example, ascii format is used, the default binary mode is faster.
45-
save_ply(ply, "test.ply", ascii=true)
47+
save_ply(ply, "example1.ply", ascii=true)
4648
```
4749

4850
Opening this file using a program like
49-
[displaz](https://github.com/c42f/displaz), for example using `displaz test.ply`,
51+
[displaz](https://github.com/c42f/displaz), for example using `displaz example1.ply`,
5052
you should see something like
5153

5254
![Example one](doc/example1.png)
5355

54-
## The file format
5556

56-
In the abstract, the ply format is a container for a set of named tables of
57-
numeric data. Each table, or **element**, has several named columns or
58-
**properties**. Properties can be either simple numeric values (floating point
59-
or signed/unsigned integers), or variable length lists of such numeric values.
57+
### Reading ply
58+
59+
Reading the ply file generated above is quite simple:
60+
61+
```julia
62+
julia> using PlyIO
63+
64+
julia> ply = load_ply("example1.ply")
65+
PlyIO.Ply with header:
66+
ply
67+
format ascii 1.0
68+
comment An example ply file
69+
element vertex 1000
70+
property float64 x
71+
property float64 y
72+
property float64 z
73+
property float64 r
74+
property float64 g
75+
property float64 b
76+
element face 1000
77+
property list int32 int32 vertex_index
78+
element edge 1000
79+
property list int32 int32 vertex_index
80+
end_header
81+
82+
julia> ply["vertex"]
83+
PlyElement "vertex" of length 1000 with properties ["x", "y", "z", "r", "g", "b"]
84+
85+
julia> ply["vertex"]["x"]
86+
1000-element PlyIO.ArrayProperty{Float64,String} "x":
87+
-0.472592
88+
1.04326
89+
-0.982202
90+
91+
-2.55605
92+
0.773923
93+
-2.10675
94+
```
95+
96+
## API
97+
98+
### The file format
99+
100+
Conceptually, the ply format is a container for a set of named tables of numeric
101+
data. Each table, or **element**, has several named columns or **properties**.
102+
Properties can be either simple numeric arrays (floating point or
103+
signed/unsigned integers), or arrays of variable length lists of such numeric
104+
values.
105+
106+
As described, ply is quite a generic format but it's primarily used for
107+
geometric data. For this use there are some loose
108+
[naming conventions](http://paulbourke.net/dataformats/ply/) which attach
109+
geometric meaning to certian combinations of element and property names.
110+
Unfortunately there's no official standard.
111+
112+
### Document object model
113+
114+
Ply elements are represented with the `PlyElement` type which is a list of
115+
properties which may be looked up by name.
116+
117+
Properties may be represented by an `AbstractArray` type which has the the
118+
`plyname` function defined, which should return a name for the property. The
119+
builtin types `ArrayProperty` and `ListProperty` are used as containers for data
120+
when reading a ply file.
121+
122+
The `Ply` type is a container for several interleaved `PlyElement` and
123+
`PlyComment` fields, in the order which would be observed in a standard ply
124+
header.
125+
126+
### Reading and writing
60127

61-
For geometric data, there are some loose
62-
[naming conventions](http://paulbourke.net/dataformats/ply/). Unfortunately
63-
there's no official standard.
128+
To read and write `Ply` objects from files or `IO` streams, use the functions
129+
`load_ply()` and `save_ply()`.

doc/example1.jl

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using PlyIO
2+
3+
ply = Ply()
4+
push!(ply, PlyComment("An example ply file"))
5+
6+
nverts = 1000
7+
8+
# Random vertices with position and color
9+
vertex = PlyElement("vertex",
10+
ArrayProperty("x", randn(nverts)),
11+
ArrayProperty("y", randn(nverts)),
12+
ArrayProperty("z", randn(nverts)),
13+
ArrayProperty("r", rand(nverts)),
14+
ArrayProperty("g", rand(nverts)),
15+
ArrayProperty("b", rand(nverts)))
16+
push!(ply, vertex)
17+
18+
# Some triangular faces
19+
vertex_index = ListProperty("vertex_index", Int32, Int32)
20+
for i=1:nverts
21+
push!(vertex_index, rand(0:nverts-1,3))
22+
end
23+
push!(ply, PlyElement("face", vertex_index))
24+
25+
# Some edges
26+
vertex_index = ListProperty("vertex_index", Int32, Int32)
27+
for i=1:nverts
28+
push!(vertex_index, rand(0:nverts-1,2))
29+
end
30+
push!(ply, PlyElement("edge", vertex_index))
31+
32+
# For the sake of the example, ascii format is used, the default binary mode is faster.
33+
save_ply(ply, "example1.ply", ascii=true)

src/PlyIO.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ __precompile__()
33
module PlyIO
44

55
# Types for the ply data model
6-
export Ply, PlyElement, PlyComment, PlyProperty, ArrayProperty, ListProperty
6+
export Ply, PlyElement, PlyComment, ArrayProperty, ListProperty
7+
export plyname # Is there something in base we could overload for this?
78

89
# High level file IO
910
# (TODO: FileIO?)

src/io.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ function read_header(ply_file)
4343
@assert readline(ply_file) == "ply\n"
4444
element_name = ""
4545
element_numel = 0
46-
element_props = PlyProperty[]
46+
element_props = Vector{AbstractVector}()
4747
elements = PlyElement[]
4848
comments = PlyComment[]
4949
format = nothing
@@ -64,7 +64,7 @@ function read_header(ply_file)
6464
elseif startswith(line, "element")
6565
if !isempty(element_name)
6666
push!(elements, PlyElement(element_name, element_numel, element_props))
67-
element_props = PlyProperty[]
67+
element_props = Vector{AbstractVector}()
6868
end
6969
tok, element_name, element_numel = split(line)
7070
@assert tok == "element"

0 commit comments

Comments
 (0)