ply
- Author
-
Jim Wise ([email protected])
- Copyright
-
Copyright © 2013 Jim Wise
- License
-
2-clause BSD-Style (see LICENSE.txt)
DESCRIPTION:
Ply is a ruby gem for reading Stanford PLY-format 3D model files.
The PLY file format is a flexible format for storing semi-structured binary data, and is often used to stored polygonalized 3D models generated with range scanning hardware. You can find some examples of the format at the Stanford 3D Scanning Repository.
Ply provides a simple API for quick access to the data in a PLY file (including examining the structure of a particular file’s content), and an almost-as-simple event-driven API which can be used to process extremely large ply files in a streaming fashion, without needing to keep the full dataset represented in the file in memory. Ply handles all three types of PLY files (ascii, binary-big-endian and binary-little-endian).
If you don’t have any Stanford PLY files on hand, you probably don’t need this gem, but if you’re curious, the PLY file format is described at Wikipedia.
REQUIREMENTS:
Ply currently requires Ruby 1.9.3 or above (including 2.0.0) – if you have a need to run Ply with Ruby 1.8.7, drop me an email, and I’ll look into backporting it. Ply has no other dependencies.
INSTALL:
$ gem install ply
SYNOPSIS:
How to Use This Gem
To get started, include this gem using
require 'ply'
This gem provides the Ply module. This module provides a single class, Ply::PlyFile, which can be used directly to parse a PLY file into memory, or subclassed to take advantage of Ply’s event-driven API for handling large PLY files.
The Simple API
To parse a PLY file into memory, simply instantiate the Ply::PlyFile class, passing either the name of the PLY file or an IO object open on a PLY file to Ply::PlyFile.new. Thus this:
pf = Ply::PlyFile.new "horse.ply"
and this:
pf = Ply::PlyFile.new File.new("horse.ply")
do the same thing.
The PLY file is parsed at construction time, and provides the following read-only accessors:
- Ply::PlyFile#version
-
The version of the PLY format used in this file, as a String – at this time the only defined PLY version is 1.0.
- Ply::PlyFile#format
-
The format of this PLY file as a String– one of
ascii
,binary_big_endian
, orbinary_little_endian
. - Ply::PlyFile#elements
-
The structure of the data in this PLY file, as an array of Hashes, in the order the elements will appear in the file. Each Hash contains the following keys:
- :name
-
the name of this element type
- :count
-
the number of elements of this type in this PLY file
- :properties
-
an array of Hashes describing the properties of this element type. Each Hash in the
:properties
array contains the following keys:- :name
-
the name of this property of the current element
- :type
-
the type of this property (an integral or floating point type, as defined in the PLY file format, or
list
. If the current property is of typelist
(a PLY array type), its property Hash also contains the following keys: - :index_type
-
the type of the index of this list
- :element_type
-
the type of the elements in this list
If you are using the Ply::PlyFile class directly (as opposed to subclassing it in order to use Ply’s event-driven API for handling large PLY files), an additional read-only accessor is available
- Ply::PlyFile#data
-
The actual data in this file, in the structure defined by the return value of Ply::PlyFile#elements, as a Hash of Arrays of Hashes. This data is returned as a Hash keyed by the name of each element type in the file (as a String), and containing an array of Hashes for each element type in the file, keyed by the property names of that element, as Strings.
That’s not as complicated as it sounds! If the file
horse.ply
defines avertex
element, with propertiesx
,y
, andz
, thenpf = Ply::PlyFile.new "horse.ply" verts = pf.data["vertex"]
will return an array of all vertices in the file, and
verts[0]["x"]
will give you the value of the
x
property of the firstvertex
element in the file, as an Integer, Float, or Array, depending on the declared type of that property in the PLY file.
The Event-Driven API
The above API is easy to use, but has the disadvantage that the entire data stored in the PLY file must be able to fit in memory, in order to be returned by Ply::PlyFile::data. For this reason, a simple event-driven API for handling PLY data is also provided. To make use of this, simply subclass the class Ply::PlyFile, and provide your own version of the method Ply::PlyFile#element_callback. When a new object of your subclass is constructed from a PLY file, your implementation of this method will be called once for each element in the file, and passed two arguments:
-
The type of the current element, in the same format as a member of the array returned by Ply::PlyFile::elements
-
The current element, in the same format as a member of the arrays returned by Ply::PlyFile::data
Note that if your subclass provides a #initialize method, it is your responsibility to ensure that the initialize method of Ply::PlyFile is also called with an appropriate argument – see below for an example of how to do this using ruby’s super
keyword.
As an example, the following code defines a subclass of PlyFile which merely counts the elements of each type present in PLY file, without reading them all into memory at the same time:
require 'ply'
class PlyFileCounter < Ply::PlyFile
attr_reader :counts
def initialize f
@counts = {}
super f
end
def element_callback e, v
@counts[e[:name]] ||= 0
@counts[e[:name]] = @counts[e[:name]] + 1
end
end
p = PlyFileCounter.new "horse.ply"
puts "There are #{p.counts["vertex"]} vertices in the file."
Example Files
In addition to the large models in the Stanford 3D Scanning Repository, the examples/
subdirectory of this gem includes a simple triangulated cube model in all three PLY file formats, as well as a script to generate these three files, which also provides an example of how to write Ply files using ruby.
ply2ascii
Finally, this gem includes a simple script, ply2ascii
, which can be used to parse any of the three PLY file formats containing a triangulated scene with vertices in an element named vertex
with (at least) scalar properties x
, y
, and z
, and faces in an elemnt named face
containing a list property vertex_indices
, and produce a simple ASCII dump of the described scene in two files.
Run ply2ascii
with no arguments for (a little) more information.
DEVELOPERS:
After checking out the source, run:
$ rake newb
This task will install any missing dependencies, run the tests/specs, and generate the RDoc.
LICENSE:
(The BSD 2-clause License)
Copyright (c) 2013 Jim Wise
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.