Source code for ddg.conversion.halfedge.obj

import re

import numpy as np

import ddg


def _read_obj(filename):

    data = {
        "filetype": None,
        "indexedfs": None,
        "halfedgeds": None,
        "v": [],
        "f": [],
        "vt": [],
        "vn": [],
        "vt_face_idx": [],
        "vn_face_idx": [],
    }

    f = open(filename, "r", encoding="utf8", errors="ignore")

    for line in f:
        if line.startswith(("v", "vt", "vn")):
            data[line.split()[0]].append(
                [
                    float(s)
                    for s in re.findall(
                        r"[-+]?\d*\.\d+(?:[eE][-+]?\d+)?|[-+]?\d+(?:[eE][-+]?\d+)?",
                        line,
                    )
                ]
            )
        if line.startswith("f"):
            data["f"].append(line[1:])
    f.close()

    if not data["vt"] and not data["vn"]:
        data["filetype"] = "0"
    if data["vt"] and not data["vn"]:
        data["filetype"] = "T"
    if not data["vt"] and data["vn"]:
        data["filetype"] = "N"
    if data["vt"] and data["vn"]:
        data["filetype"] = "TN"

    for face in data["f"]:
        if data["filetype"] == "T":
            data["vt_face_idx"].append(
                [int(s[1:]) - 1 for s in re.findall(r"/\d+", face)]
            )
        if data["filetype"] == "N":
            data["vn_face_idx"].append(
                [int(s[1:]) - 1 for s in re.findall(r"/\d+", face)]
            )
        if data["filetype"] == "TN":
            data["vt_face_idx"].append(
                [int(s[1:-1]) - 1 for s in re.findall(r"/\d+/", face)]
            )
            data["vn_face_idx"].append(
                [int(s.split("/")[-1]) - 1 for s in re.findall(r"/\d+/\d+", face)]
            )

    if not data["f"]:
        raise ValueError(
            "Faces in the input file do not have any of the specified forms"
        )

    data["f"] = [
        [int(s[1:]) - 1 for s in re.findall(r" \d+", face)] for face in data["f"]
    ]

    return data


def _set_vt_and_vn(data):

    if data["filetype"] == "T":
        data["halfedgeds"].edges.add_attribute("vt")
        data["halfedgeds"].edges.add_attribute("vt_index")
    if data["filetype"] == "N":
        data["halfedgeds"].edges.add_attribute("vn")
        data["halfedgeds"].edges.add_attribute("vn_index")
    if data["filetype"] == "TN":
        data["halfedgeds"].edges.add_attribute("vt")
        data["halfedgeds"].edges.add_attribute("vn")
        data["halfedgeds"].edges.add_attribute("vt_index")
        data["halfedgeds"].edges.add_attribute("vn_index")

    for face in data["halfedgeds"].faces:
        edge = face.edge
        dataface = data["f"][face.ifs_face_index]
        while edge.head.ifs_index != dataface[0]:
            edge = edge.nex

        for i, edg in enumerate(ddg.halfedge.edge_loop(edge)):
            j = i
            if (
                edge.nex.head.ifs_index != dataface[1]
            ):  # edgeloop is reverse orientation to the given
                # vertex order
                j = -i
            if data["filetype"] == "T":
                edg.vt_index = data["vt_face_idx"][face.ifs_face_index][j]
                edg.vt = data["vt"][edg.vt_index]
            if data["filetype"] == "N":
                edg.vn_index = data["vn_face_idx"][face.ifs_face_index][j]
                edg.vn = data["vn"][edg.vn_index]
            if data["filetype"] == "TN":
                edg.vt_index = data["vt_face_idx"][face.ifs_face_index][j]
                edg.vt = data["vt"][edg.vt_index]
                edg.vn_index = data["vn_face_idx"][face.ifs_face_index][j]
                edg.vn = data["vn"][edg.vn_index]


def _initialize_indexedfs(data):

    """

    Creates an IndexedFaceSet as self.indexedfs of the given obj file.

    """

    faceSet = ddg.indexedfaceset.GeneralizedIndexedFaceSet(data["f"])
    data["indexedfs"] = faceSet
    return data


def _initialize_halfedgeds(filename):

    """
    Creates a halfedge surface of the given obj file.

    Sets attributes "vn" and "vt" to edges pointing to the corresponding
    vertex if given.

    """
    data = _read_obj(filename)

    if not data["indexedfs"]:
        _initialize_indexedfs(data)
    hds = ddg.indexedfaceset.indexed_face_set_to_surface(data["indexedfs"])

    hds.verts.add_attribute("co")

    for vert in hds.verts:
        vert.co = np.array(data["v"][vert.ifs_index])

    data["halfedgeds"] = hds

    if data["filetype"] != "0":
        _set_vt_and_vn(data)

    return data


[docs]def obj_to_hds(filename): """ | Converts an obj file to a ddg.halfedge.Surface with vertex attribute | "co", and edge attributes "vt" and "vn", if given. | Reads an obj file with given v and faces of the form f 1 2 3 | or given v,vt and faces of the form f 1/1 2/1 3/1 | or given v,vn and faces of the form f 1//1 2//1 3//1 | or given v,vt,vn and faces of the form f 1/1/2 2/1/2 3/1/2. Parameters ---------- filename : str (path and) name of the obj file, like "path/file.obj" Returns ------- ddg.halfedge.Surface """ encoder = _initialize_halfedgeds(filename) return encoder["halfedgeds"]