Module pysect.sect.serial.stl

Expand source code
import struct
from typing import IO
import numpy as np

from ..primitives.stl import STL as prim_STL

FIELD_BUFFER_SIZE = 4096
FIELD_HEADER_SIZE = 80
FIELD_COUNT_SIZE = 4


def detect(filepath):
    try:
        with open(filepath, "r") as f:
            line = f.readline()
        return "r"
    except UnicodeDecodeError:
        return "rb"


def loadf(filepath):
    mode = detect(filepath)
    with open(filepath, mode) as f:
        return load(f, mode)


def load(fh: IO, mode):
    if "b" in mode:
        return prim_STL(_load_binary(fh))
    else:
        return prim_STL(_load_ascii(fh))


def _load_binary(fh: IO):
    fh.read(FIELD_HEADER_SIZE)  # Skip the header
    count_data = fh.read(FIELD_COUNT_SIZE)
    if len(count_data) != FIELD_COUNT_SIZE:
        count = 0
    else:
        (count,) = struct.unpack("<i", count_data)
    print(f"Loading {count} triangles")
    dtype = np.dtype(
        [
            ("normals", np.float32, (3,)),
            ("vectors", np.float32, (3, 3)),
            ("attr", np.uint16, (1,)),
        ]
    )
    dtype = dtype.newbyteorder("<")
    return np.fromfile(fh, dtype=prim_STL.dtype(), count=count)


def _load_ascii(fh: IO):
    fh.readline()  # Skip the header

    def get_facet(fh: IO):
        normals = ()
        v1 = ()
        v2 = ()
        v3 = ()
        attr = 0

        line = fh.readline().strip()
        line = line.split(" ")
        if not line[0] == "facet":
            return None
        normals = (float(line[-3]), float(line[-2]), float(line[-1]))
        fh.readline()  # throw away outer loop line

        def get_vertices(line):
            line = line.split(" ")
            if not line[0] == "vertex":
                raise Exception("Failed to read vertex")
            return float(line[-3]), float(line[-2]), float(line[-1])

        v1 = get_vertices(fh.readline())
        v2 = get_vertices(fh.readline())
        v3 = get_vertices(fh.readline())
        fh.readline()
        fh.readline()
        return (normals, (v1, v2, v3), attr)

    def itter_facet(fh):
        while True:
            facet = get_facet(fh)
            if facet is None:
                break
            yield facet

    return np.fromiter(itter_facet(fh), dtype=prim_STL.dtype())

Functions

def detect(filepath)
Expand source code
def detect(filepath):
    try:
        with open(filepath, "r") as f:
            line = f.readline()
        return "r"
    except UnicodeDecodeError:
        return "rb"
def load(fh: , mode)
Expand source code
def load(fh: IO, mode):
    if "b" in mode:
        return prim_STL(_load_binary(fh))
    else:
        return prim_STL(_load_ascii(fh))
def loadf(filepath)
Expand source code
def loadf(filepath):
    mode = detect(filepath)
    with open(filepath, mode) as f:
        return load(f, mode)