File: mesh.py

package info (click to toggle)
python-vispy 0.15.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 8,868 kB
  • sloc: python: 59,799; javascript: 6,800; makefile: 69; sh: 6
file content (122 lines) | stat: -rw-r--r-- 3,559 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# -*- coding: utf-8 -*-
# Copyright (c) Vispy Development Team. All Rights Reserved.
# Distributed under the (new) BSD License. See LICENSE.txt for more info.

"""Reading and writing of data like images and meshes."""

import os
from os import path as op

from .wavefront import WavefrontReader, WavefrontWriter
from .stl import load_stl


def read_mesh(fname):
    """Read mesh data from file.

    Parameters
    ----------
    fname : str
        File name to read. Format will be inferred from the filename.
        Currently only '.obj' and '.obj.gz' are supported.

    Returns
    -------
    vertices : array
        Vertices.
    faces : array | None
        Triangle face definitions.
    normals : array
        Normals for the mesh.
    texcoords : array | None
        Texture coordinates.
    """
    # Check format
    fmt = op.splitext(fname)[1].lower()
    if fmt == '.gz':
        fmt = op.splitext(op.splitext(fname)[0])[1].lower()

    if fmt in ('.obj'):
        return WavefrontReader.read(fname)
    elif fmt in ('.stl'):
        file_obj = open(fname, mode='rb')
        mesh = load_stl(file_obj)
        vertices = mesh['vertices']
        faces = mesh['faces']
        normals = mesh['face_normals']
        texcoords = None
        return vertices, faces, normals, texcoords
    else:
        try:
            import meshio
        except ImportError:
            raise ValueError('read_mesh does not understand format %s.' % fmt)

        try:
            mesh = meshio.read(fname)
        except meshio.ReadError:
            raise ValueError('read_mesh does not understand format %s.' % fmt)

        triangles = mesh.get_cells_type("triangle")
        if len(triangles) == 0:
            raise ValueError('mesh file does not contain triangles.')

        return mesh.points, triangles, None, None


def write_mesh(fname, vertices, faces, normals, texcoords, name='',
               format=None, overwrite=False, reshape_faces=True):
    """Write mesh data to file.

    Parameters
    ----------
    fname : str
        Filename to write. Must end with ".obj" or ".gz".
    vertices : array
        Vertices.
    faces : array | None
        Triangle face definitions.
    normals : array
        Normals for the mesh.
    texcoords : array | None
        Texture coordinates.
    name : str
        Name of the object.
    format : str
        Currently only "obj" is supported.
    overwrite : bool
        If the file exists, overwrite it.
    reshape_faces : bool
        Reshape the `faces` array to (Nf, 3). Set to `False`
        if you need to write a mesh with non triangular faces.
    """
    # Check file
    if op.isfile(fname) and not overwrite:
        raise IOError('file "%s" exists, use overwrite=True' % fname)

    if format is None:
        format = os.path.splitext(fname)[1][1:]

    # Check format
    if format == 'obj':
        WavefrontWriter.write(fname, vertices, faces,
                              normals, texcoords, name, reshape_faces)
        return

    try:
        import meshio
    except ImportError:
        raise ValueError('write_mesh does not understand format %s.' % format)

    cell_data = {}
    if normals is not None:
        cell_data["normals"] = [normals]
    if texcoords is not None:
        cell_data["texcoords"] = [texcoords]

    mesh = meshio.Mesh(vertices, [("triangle", faces)], cell_data=cell_data)

    try:
        mesh.write(fname, file_format=format)
    except meshio.WriteError:
        raise ValueError('write_mesh does not understand format %s.' % format)