Source code for ddg.conversion.indexedfaceset.obj

import copy
import re

import ddg


def _read_obj(filename):
    """Read an obj file and saves the vertex coordinates and face indices in a
    dictionary: `data = {"v":[], "f":[]}`
    For each geometric object, a data dictionary of vertices and faces is
    created. If multiple geometric objects exist in the obj file, multiples of
    such dictionaries are created, one for each object. These dictionaries are
    then saved in another dictionary, whose keys are the object names in the
    obj file.
    For the case that the obj file only contains a single geometric object and
    no name is specified for it, it is saved under the name "ifs_obj" is the
    nested dictionary of the output.

    Parameters
    ----------
    filename : string
        Path to the obj file.

    Returns
    -------
    dict
        Nested dictionary of the obj data.

    """
    objects = dict()
    name = "ifs_obj"
    data = {"v": [], "f": []}
    objects[name] = copy.deepcopy(data)
    default_name_duplicate_in_obj_flag = False

    file = open(filename, "r", encoding="utf8", errors="ignore")
    for line in file:
        if line.startswith("o"):
            name = line[2:-1]
            if name == "ifs_obj":
                objects[name] = copy.deepcopy(data)
                default_name_duplicate_in_obj_flag = True
            elif "ifs_obj" in objects and not default_name_duplicate_in_obj_flag:
                objects[name] = objects.pop("ifs_obj")
            else:
                objects[name] = copy.deepcopy(data)
        if line.startswith("v "):
            objects[name][line.split()[0]].append(
                [float(s) for s in re.findall(r"-?\d+(?:\.\d+)?", line)]
            )
        if line.startswith("f"):
            objects[name]["f"].append(line[1:])
    file.close()

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


[docs]def obj_to_ifs(filename, attribute_name): """ Convert an obj file into an IndexedFaceSet. If there are multiple objects in the obj file, the output is a dictionary, whose keys are the object names. If only one object is in the obj file, the corresponding IndexedFaceSet is returned directly. Parameters ---------- filename : string (path and) name of the obj file attribute_name : string Name of the vertex attribute storing the coordinates Returns ------- dict dict of ddg.datastructures.IndexedFaceSet for each object data in the obj file. The keys are the names of the objects. """ data = _read_obj(filename) surfaces = dict() for key in data.keys(): faceSet = ddg.indexedfaceset.ifs.IndexedFaceSet(data[key]["f"]) faceSet.set_attribute(attribute_name, "verts", data[key]["v"]) surfaces[str(key)] = faceSet if len(surfaces.keys()) == 1: return list(surfaces.values())[0] else: return surfaces