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 details)

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 details)

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 details)

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 details)

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 details)

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 details)

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 details)

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 details)

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 details)

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 details)

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 details)

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

File details

Details for the file openstl-1.1.1-pp310-pypy310_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for openstl-1.1.1-pp310-pypy310_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 ae5a461e831e23f3789ab9c226c8cc88399d83f9d9100e206f6cf24704558e6a
MD5 086a23f6b24ea80b5bf1d9097991e987
BLAKE2b-256 d32a207418311b7b38507b29b24660de6ac7c9d2cd4fe775eec0c1e20366ff17

See more details on using hashes here.

File details

Details for the file openstl-1.1.1-pp39-pypy39_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for openstl-1.1.1-pp39-pypy39_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 42c29bdf1cfe2b76414fe7cc8da9c8103a9b5bcf8f731e995f13613e7c63d8a0
MD5 c9d1b4a39947549500cddc6e9d324291
BLAKE2b-256 186d78393d6c2d447a3b5f4143d180b5c9e3442426ea44d492fa29fde1e064b6

See more details on using hashes here.

File details

Details for the file openstl-1.1.1-pp38-pypy38_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for openstl-1.1.1-pp38-pypy38_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 b1a8a03a07785da02f8be9bf6389d580c6799e24a43b0f1a33c31aa1c024768d
MD5 edf7d1ceac82a79cfc1cf8b92953670c
BLAKE2b-256 1139074c81ea7defeb35e3c90d28b57f34b7686787174aa43268789c7e706a7f

See more details on using hashes here.

File details

Details for the file openstl-1.1.1-pp37-pypy37_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for openstl-1.1.1-pp37-pypy37_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 4a13ece9e28ee398f5fc835d1594d42f1a16f81a0841d1073e8fac607d380edb
MD5 9bbe697705c1aba4dd8cc3b0e608391a
BLAKE2b-256 66c6f02800db5dd89d21b80bc8ce868b1eb7d2e1d2e187048af2acf4950a0449

See more details on using hashes here.

File details

Details for the file openstl-1.1.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for openstl-1.1.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 b4406ee7561dd9cfe5853dc82577584712d2d3606022af0c845a65f369482df2
MD5 0c84fc1bbf1c7f4d5f4125ff83b322cc
BLAKE2b-256 a0c0895d59b743c7296480390940f09e3f4b0d11316ba07d7b527edb8087e84e

See more details on using hashes here.

File details

Details for the file openstl-1.1.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for openstl-1.1.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 f8cb3dff39ef9d17444ca8aa0eecb734910fe53fac0af00dd5c4601cb0fa1661
MD5 9f32cdde2c6eb1c15db334fa9f43b7e3
BLAKE2b-256 166ae597819b13be674f2dd57b093f4c1f082aa138c2128f6bb65ba941999194

See more details on using hashes here.

File details

Details for the file openstl-1.1.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for openstl-1.1.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 f78436e61bf4df160099f60b842f286757bd4d8e089624b540738e0ac3b3e20e
MD5 a0969ab08a021c8898eb5a80ab706c82
BLAKE2b-256 9b67769488cc529108bdf7db9ce7d3e75401b305320f518c156959adc1f497c1

See more details on using hashes here.

File details

Details for the file openstl-1.1.1-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for openstl-1.1.1-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 5250e74e49157e9f8a5ec1b7eae38e710ab5a86bcf38d2af90b3dc075d475dac
MD5 0fc951dc8953717efd2cb8c4dd774405
BLAKE2b-256 ef0eafd8a27c2bc82f096702e83b556d1743ecc3d5d4272e01c4968a5c9c619a

See more details on using hashes here.

File details

Details for the file openstl-1.1.1-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for openstl-1.1.1-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 c0bb2a9271f4ad1530869ec17fad4d1c837a59314c601a4babd3c3af3e937bf2
MD5 65cfeec5fe4847739f16afda356c63d3
BLAKE2b-256 a963d1c728ebe2bbe1095c857daeebc065016729981ac6524fbf237df2018926

See more details on using hashes here.

File details

Details for the file openstl-1.1.1-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for openstl-1.1.1-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 f4f680d19559b1f5518d4755b121246cfbc77d7064337f8f806b92448fa170ff
MD5 4985e2dd91f4de1bf858cb24c86548a1
BLAKE2b-256 bb9177abc444a23a8f5d05b4816b35bb151badd5a3400615cc400012ebf98a59

See more details on using hashes here.

File details

Details for the file openstl-1.1.1-cp36-cp36m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for openstl-1.1.1-cp36-cp36m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 1d6e7b0821025343b5e41f9fe2e58908c810a2cfdce4b7d73fb9b13b078c0dce
MD5 061ddeba60e076fb1a7d353964068b0c
BLAKE2b-256 17aa27aee83f6c216584c61b1766d8db96a5120f4a5c6ae0fb021ce2935ece6f

See more details on using hashes here.

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