hapPLY C++ Library

repository·master·Indexed 19 days ago

https://github.com/nmwsharp/happly

A header-only C++ library for reading and writing the PLY (Polygon File Format), supporting both ASCII and binary formats. It provides the `happly::PLYData` class for managing elements and properties, automatic type promotion for numeric data, and specialized mesh data helpers for handling vertex positions, colors, and face indices.

Tokens
2.2K
Snippets
5
Records
9
Agent score
15%

What's inside hapPLY

  1. How PLYData and Elements work together

    master

    The core abstraction in hapPLY is the happly::PLYData class, which represents a complete .ply file containing multiple elements (like vertex or face). Each element contains one or more properties (like x, y, z, or red, green, blue).

    To work with data, you typically:

    1. Construct a PLYData object (either empty or by reading a file).
    2. Access or create elements using getElement() or addElement().
    3. Access or add properties to those elements using getProperty() or addProperty().
    4. Write the resulting object to a file using write().
    happly::PLYData plyIn("my_file.ply");
    // Access an element and its property
    auto prop = plyIn.getElement("elementA").getProperty<float>("prop1");
  2. Install and use hapPLY

    master

    hapPLY is a header-only C++ library for reading and writing the .ply file format. To use it, simply drop the happly.h header into your project and include it in your source files.

    It supports both plaintext (ASCII) and binary variants of the PLY format and provides automatic type promotion for numeric data (e.g., reading a float field as a double).

    #include "happly.h"
  3. Troubleshooting: Known issues in hapPLY

    master

    When using hapPLY, be aware of the following limitations:

    • NaN/Inf in ASCII: Writing inf or nan values in DataFormat::ASCII mode is not supported due to inconsistencies in C++ ofstream. Use Binary mode for these values.
    • List Property Type: The size of elements in a list property is always hardcoded to uchar. If your data exceeds this, an error will be thrown.
    • Endianness: The library is primarily tested on little-endian platforms. While it supports reading/writing both big and little-endian files, running the code on a big-endian machine may result in bugs.
  4. Write basic PLY data

    master

    To create a new .ply file, instantiate an empty happly::PLYData object, define your elements and properties, and then call write().

    #include "happly.h"
    
    // Suppose these hold your data
    std::vector<float> elementA_prop1;
    std::vector<int> elementA_prop2;
    std::vector<std::vector<double>> elementB_listProp;
    
    // Create an empty object
    happly::PLYData plyOut;
    
    // Add elements
    plyOut.addElement("elementA", 20);
    plyOut.addElement("elementB", 42);
    
    // Add properties to those elements
    plyOut.getElement("elementA").addProperty<float>("prop1", elementA_prop1);
    plyOut.getElement("elementA").addProperty<int>("prop2", elementA_prop2);
    plyOut.getElement("elementB").addListProperty<double>("listprop1", elementB_listProp);
    
    // Write the object to file
    plyOut.write("my_output_file.ply", happly::DataFormat::Binary);
  5. Read basic PLY data

    master

    You can read elements and their properties from a .ply file. hapPLY supports automatic type promotion, meaning you can request a double even if the file stores the data as a float.

    #include "happly.h"
    
    // Construct a data object by reading from file
    happly::PLYData plyIn("my_file.ply");
    
    // Get data from the object
    std::vector<float> elementA_prop1 = plyIn.getElement("elementA").getProperty<float>("prop1");
    std::vector<double> elementA_prop2 = plyIn.getElement("elementA").getProperty<double>("prop1");
    std::vector<std::vector<double>> elementB_listProp = 
        plyIn.getElement("elementB").getListProperty<double>("listprop1");
    
    // Type promotion is automatic for numeric types
    std::vector<double> elementA_prop1_as_double = 
        plyIn.getElement("elementA").getProperty<double>("prop1"); 
  6. Read and write mesh-like data

    master

    hapPLY provides specialized helpers for common 3D mesh data conventions (vertices, colors, and faces) to simplify working with geometric models.

    #include "happly.h"
    
    // --- Reading mesh-like data ---
    happly::PLYData plyIn("my_mesh_file.ply");
    std::vector<std::array<double, 3>> vPos = plyIn.getVertexPositions();
    std::vector<std::vector<size_t>> fInd = plyIn.getFaceIndices<size_t>();
    
    // --- Writing mesh-like data ---
    std::vector<std::array<double, 3>> meshVertexPositions;
    std::vector<std::array<double, 3>> meshVertexColors;
    std::vector<std::vector<size_t>> meshFaceIndices;
    
    happly::PLYData plyOut;
    plyOut.addVertexPositions(meshVertexPositions);
    plyOut.addVertexColors(meshVertexColors);
    plyOut.addFaceIndices(meshFaceIndices);
    
    plyOut.write("my_output_mesh_file.ply", happly::DataFormat::ASCII);
  7. Mesh Data Helpers Reference

    master

    Specialized methods for common mesh elements (conventionally named "vertex" and "face").

    Vertex Helpers

    • std::vector<std::array<double, 3>> getVertexPositions(std::string vertexElementName = "vertex"): Gets x,y,z positions.
    • void addVertexPositions(std::vector<std::array<double, 3>>& vertexPositions): Adds x,y,z positions.
    • std::vector<std::array<unsigned char, 3>> getVertexColors(std::string vertexElementName = "vertex"): Gets r,g,b colors.
    • void addVertexColors(std::vector<std::array<unsigned char, 3>>& vertexColors): Adds r,g,b colors (0-255).
    • void addVertexColors(std::vector<std::array<double, 3>>& vertexColors): Adds r,g,b colors (expects [0.0, 1.0], converts to 0-255).

    Face Helpers

    • std::vector<std::vector<T>> getFaceIndices(): Gets vertex indices for each face. Supports type promotion and signed/unsigned conversion.
    • void addFaceIndices(std::vector<std::vector<T>>& indices): Adds vertex indices. Automatically converts to a 32-bit integer type and throws if conversion fails.
  8. PLYData API Reference

    master

    The happly::PLYData class is the primary interface for managing PLY data. It handles file I/O, element management, and mesh-specific helpers.

    Constructors

    • PLYData(): Creates an empty object.
    • PLYData(std::string filename, bool verbose = false): Reads from a file. Automatically detects ASCII or Binary. If verbose=true, prints file info to stdout.
    • PLYData(std::istream& inStream, bool verbose = false): Reads from an input stream.

    File I/O

    • void write(std::string filename, DataFormat format = DataFormat::ASCII): Writes to a file. Supported formats: DataFormat::ASCII, DataFormat::Binary, DataFormat::BinaryBigEndian.
    • void write(std::ostream& outStream, DataFormat format = DataFormat::ASCII): Writes to an output stream.
    • void validate(): Performs sanity checks (called internally before writing).

    Element Management

    • void addElement(std::string name, size_t count): Adds a new element type with a specific count.
    • Element& getElement(std::string target): Returns a reference to an existing element.
    • bool hasElement(std::string target): Checks if an element exists.
    • std::vector<std::string> getElementNames(): Returns a list of all element names.

    Metadata

    • std::vector<std::string> comments: Accesses .ply comments.
    • std::vector<std::string> objInfoComments: Accesses obj_info lines (an ad-hoc extension).