Skip to main content

A simple STL serializer and deserializer

Project description

OpenSTL

The fastest and most intuitive library to manipulate STL files (stereolithography) for C++ and Python, header-only.
🌟 Please consider starring the GitHub repo to show your support! 🌟

Commitizen friendly Conventional Commits PyPI license
pypi build Python

Performances benchmark

Discover the staggering performance of OpenSTL in comparison to numpy-stl, meshio and stl-reader, thanks to its powerful C++ backend. See benchmark.py. Benchmark performed on an Intel i5-9600KF CPU @ 3.70GHz.

Performance gains over numpy-stl, meshio and stl-reader
Write:  1.3 to 4+ X faster
Read:   1 to 2.3+ X faster
Rotate: 1 to 12+  X faster

Note: meshio has no straightfoward way of rotating vertices, so it was not benchmarked. Benchmark Results

Python Usage

Install

pip install openstl or pip install -U git+https://github.com/Innoptech/OpenSTL@main

Read and write from a STL file

import openstl
import numpy as np

# Define an array of triangles
# Following the STL standard, each triangle is defined with : normal, v0, v1, v2
quad = np.array([
    # normal,          vertices 0,      vertices 1,      vertices 2
    [[0.0, 0.0, 1.0], [0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [1.0, 1.0, 0.0]], # Triangle 1
    [[0.0, 0.0, 1.0], [0.0, 0.0, 0.0], [0.0, 1.0, 0.0], [1.0, 1.0, 0.0]], # Triangle 2
])

# Serialize the triangles to a file
success = openstl.write("quad.stl", quad, openstl.format.binary) # Or openstl.format.ascii (slower but human readable)

if not success:
    raise Exception("Error: Failed to write to the specified file.")

# Deserialize triangles from a file
deserialized_quad = openstl.read("quad.stl")

# Print the deserialized triangles
print("Deserialized Triangles:", deserialized_quad)

Rotate, translate and scale a mesh

import openstl
import numpy as np

quad = openstl.read("quad.stl")

# Rotating
rotation_matrix = np.array([
    [0,-1, 0],
    [1, 0, 0],
    [0, 0, 1]
])
rotated_quad = np.matmul(rotation_matrix, quad.reshape(-1,3).T).T.reshape(-1,4,3)

# Translating
translation_vector = np.array([1,1,1])
quad[:,1:4,:] += translation_vector # Avoid translating normals

# Scaling
scale = 1000.0
quad[:,1:4,:] *= scale # Avoid scaling normals

Converting Triangles --> Vertices and Faces

import openstl

# Define an array of triangles
triangles = [
    # normal,          vertices 0,      vertices 1,      vertices 2
    [[0.0, 0.0, 1.0], [0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [1.0, 1.0, 0.0]], # Triangle 1
    [[0.0, 0.0, 1.0], [0.0, 0.0, 0.0], [0.0, 1.0, 0.0], [1.0, 1.0, 0.0]], # Triangle 2
]

# Convert triangles to vertices and faces
vertices, faces = openstl.convert.verticesandfaces(triangles)

Converting Vertices and Faces --> Triangles

import openstl

# Define vertices and faces
vertices = [
    [0.0, 0.0, 0.0],
    [1.0, 1.0, 1.0],
    [2.0, 2.0, 2.0],
    [3.0, 3.0, 3.0],
]

faces = [
    [0, 1, 2],  # Face 1 
    [1, 3, 2]   # Face 2 
]

# Convert vertices and faces to triangles
triangles = openstl.convert.triangles(vertices, faces)

C++ Usage

Read STL from file

std::ifstream file(filename, std::ios::binary);
if (!file.is_open()) {
    std::cerr << "Error: Unable to open file '" << filename << "'" << std::endl;
}

// Deserialize the triangles in either binary or ASCII format
std::vector<openstl::Triangle> triangles = openstl::deserializeStl(file);
file.close();

Write STL to a file

std::ofstream file(filename, std::ios::binary);
if (!file.is_open()) {
    std::cerr << "Error: Unable to open file '" << filename << "'" << std::endl;
}

std::vector<openstl::Triangle> originalTriangles{}; // User triangles
openstl::serialize(originalTriangles, file, openstl::StlFormat::Binary); // Or StlFormat::ASCII

if (file.fail()) {
    std::cerr << "Error: Failed to write to file " << filename << std::endl;
} else {
    std::cout << "File " << filename << " has been successfully written." << std::endl;
}
file.close();

Serialize STL to a stream

std::stringstream ss;

std::vector<openstl::Triangle> originalTriangles{}; // User triangles
openstl::serialize(originalTriangles, ss, openstl::StlFormat::Binary); // Or StlFormat::ASCII

Integrate to your codebase

Smart method

Include this repository with CMAKE Fetchcontent and link your executable/library to openstl::core library.
Choose weither you want to fetch a specific branch or tag using GIT_TAG. Use the main branch to keep updated with the latest improvements.

include(FetchContent)
FetchContent_Declare(
    openstl
    GIT_REPOSITORY https://github.com/Innoptech/OpenSTL.git
    GIT_TAG main
    GIT_SHALLOW TRUE
    GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(openstl)

Naïve method

Simply add stl.h to your codebase.

Test

git clone https://github.com/Innoptech/OpenSTL
mkdir OpenSTL/build && cd OpenSTL/build
cmake -DOPENSTL_BUILD_TESTS=ON .. && cmake --build .
ctest .

Requirements

C++11 or higher.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

openstl-1.1.1-pp310-pypy310_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (129.6 kB view hashes)

Uploaded PyPy manylinux: glibc 2.24+ x86-64 manylinux: glibc 2.28+ x86-64

openstl-1.1.1-pp39-pypy39_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (129.6 kB view hashes)

Uploaded PyPy manylinux: glibc 2.24+ x86-64 manylinux: glibc 2.28+ x86-64

openstl-1.1.1-pp38-pypy38_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (129.2 kB view hashes)

Uploaded PyPy manylinux: glibc 2.24+ x86-64 manylinux: glibc 2.28+ x86-64

openstl-1.1.1-pp37-pypy37_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (128.8 kB view hashes)

Uploaded PyPy manylinux: glibc 2.24+ x86-64 manylinux: glibc 2.28+ x86-64

openstl-1.1.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (136.5 kB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.24+ x86-64 manylinux: glibc 2.28+ x86-64

openstl-1.1.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (136.6 kB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.24+ x86-64 manylinux: glibc 2.28+ x86-64

openstl-1.1.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (135.2 kB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.24+ x86-64 manylinux: glibc 2.28+ x86-64

openstl-1.1.1-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (135.4 kB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.24+ x86-64 manylinux: glibc 2.28+ x86-64

openstl-1.1.1-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (134.9 kB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.24+ x86-64 manylinux: glibc 2.28+ x86-64

openstl-1.1.1-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (133.9 kB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.24+ x86-64 manylinux: glibc 2.28+ x86-64

openstl-1.1.1-cp36-cp36m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (134.0 kB view hashes)

Uploaded CPython 3.6m manylinux: glibc 2.24+ x86-64 manylinux: glibc 2.28+ x86-64

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page