mesh_helper.py 2.14 KB
Newer Older
Dario Seyb's avatar
Dario Seyb committed
1
from .indexed_attribute import FaceAttribute, PointAttribute, resolve_attributes, stretch_vertices
2 3 4
import numpy as np


Dario Seyb's avatar
Dario Seyb committed
5
def calculateNormalEdges(vertices, face_indices, normals, length):
Dario Seyb's avatar
Dario Seyb committed
6 7 8 9 10 11 12

    resolved_normals = None

    if isinstance(normals, FaceAttribute):
        resolved_normals = normals.values
        face_centers = []
        for face in face_indices:
13
            face_centers.append(np.average(vertices[face], axis=0, weights=face!=-1))
Dario Seyb's avatar
Dario Seyb committed
14
        vertices = face_centers
15
    elif face_indices is not None:
Dario Seyb's avatar
Dario Seyb committed
16 17
        resolved_normals = resolve_attributes(face_indices, [normals])[0]
        vertices, face_indices = stretch_vertices(vertices, face_indices)
18 19
    else:
        resolved_normals = normals
20

Dario Seyb's avatar
Dario Seyb committed
21 22 23
    edge_vertices = []
    edge_indices = []
    for i, vert in enumerate(vertices):
Dario Seyb's avatar
Dario Seyb committed
24

Dario Seyb's avatar
Dario Seyb committed
25 26 27 28 29 30 31 32 33
        norm = np.array(resolved_normals[i])
        vert = np.array(vert)

        edge_vertices.append(vert)
        edge_vertices.append(np.add(norm*length, vert))

        edge_indices.append([i*2, i*2 + 1])

    return edge_vertices, edge_indices
34 35 36 37

def calculateFaceNormals(vertices, face_indices):
    values = []
    for face in face_indices:
38
        # Assuming face is planar
39 40 41
        v1 = np.array(vertices[face[0]])
        v2 = np.array(vertices[face[1]])
        v3 = np.array(vertices[face[2]])
Dario Seyb's avatar
Dario Seyb committed
42

43 44
        v12 = np.subtract(v2, v1)
        v13 = np.subtract(v3, v1)
Dario Seyb's avatar
Dario Seyb committed
45

46 47 48 49
        norm = np.cross(v12, v13)
        norm = norm / np.linalg.norm(norm)
        values.append(norm)

Dario Seyb's avatar
Dario Seyb committed
50 51
    return FaceAttribute(values)

Dario Seyb's avatar
Dario Seyb committed
52
def calculatePointNormals(vertices, face_indices):
Dario Seyb's avatar
Dario Seyb committed
53 54 55
    normals = np.zeros_like(vertices)
    counts = np.zeros(vertices.shape[0])

Dario Seyb's avatar
Dario Seyb committed
56
    for face in face_indices:
57
        # Assuming face is planar
Dario Seyb's avatar
Dario Seyb committed
58 59 60
        v1 = np.array(vertices[face[0]])
        v2 = np.array(vertices[face[1]])
        v3 = np.array(vertices[face[2]])
Dario Seyb's avatar
Dario Seyb committed
61

Dario Seyb's avatar
Dario Seyb committed
62 63
        v12 = np.subtract(v2, v1)
        v13 = np.subtract(v3, v1)
Dario Seyb's avatar
Dario Seyb committed
64

Dario Seyb's avatar
Dario Seyb committed
65 66
        norm = np.cross(v12, v13)

67 68 69
        filtered_face = face[np.where(face != -1)]
        normals[filtered_face] += norm
        counts[filtered_face] += 1
Dario Seyb's avatar
Dario Seyb committed
70

Dario Seyb's avatar
Dario Seyb committed
71 72 73
    normals /= counts.reshape(-1, 1)
    normals /= np.linalg.norm(normals, axis=1).reshape(-1, 1)
    return PointAttribute(normals)