Compute normals over a triangulated surface

    Parameters
    ----------

    vertices : ndarray (n,3)
        triangles vertices

    indices : ndarray (p,3)
        triangles indices
779748
def normals(vertices, indices):
    

    # Compact similar vertices
    vertices, indices, mapping = compact(vertices, indices)

    T = vertices[indices]
    N = np.cross(T[:, 1] - T[:, 0], T[:, 2]-T[:, 0])
    L = np.sqrt(np.sum(N * N, axis=1))
    L[L == 0] = 1.0  # prevent divide-by-zero
    N /= L[:, np.newaxis]
    normals = np.zeros_like(vertices)
    normals[indices[:, 0]] += N
    normals[indices[:, 1]] += N
    normals[indices[:, 2]] += N
    L = np.sqrt(np.sum(normals*normals, axis=1))
    L[L == 0] = 1.0
    normals /= L[:, np.newaxis]

    return normals[mapping]
405546
def vertices(self):
        
        if self._v_out is None:
            output = qhalf('Fp', self.halfspaces, self.interior_point)
            pts = []
            for l in output[2:]:
                pt = []
                for c in l.split():
                    c = float(c)
                    if c != 10.101 and c != -10.101:
                        pt.append(c)
                    else:
                        pt.append(np.inf)
                pts.append(pt)
            self._v_out = np.array(pts)
        return self._v_out
897374
def flip_normals(self):
        
        if self.faces.size % 4:
            raise Exception('Can only flip normals on an all triangular mesh')

        f = self.faces.reshape((-1, 4))
        f[:, 1:] = f[:, 1:][:, ::-1]
508477
public float getNormalZ(int vertex) {
        if (!hasNormals()) {
            throw new IllegalStateException("mesh has no normals");
        }
        
        checkVertexIndexBounds(vertex);
        
        return m_normals.getFloat((vertex * 3 + 2) * SIZEOF_FLOAT);
    }
56421
def all_coplanar(triangles):
    
    triangles = np.asanyarray(triangles, dtype=np.float64)
    if not util.is_shape(triangles, (-1, 3, 3)):
        raise ValueError('Triangles must be (n,3,3)!')

    test_normal = normals(triangles)[0]
    test_vertex = triangles[0][0]
    distances = point_plane_distance(points=triangles[1:].reshape((-1, 3)),
                                     plane_normal=test_normal,
                                     plane_origin=test_vertex)
    all_coplanar = np.all(np.abs(distances) < tol.zero)
    return all_coplanar
727172
def mesh(self):
        
        meshes = [surface.mesh for surface in self.surfaces]
        lons = numpy.concatenate([m.lons for m in meshes])
        lats = numpy.concatenate([m.lats for m in meshes])
        depths = numpy.concatenate([m.depths for m in meshes])
        return Mesh(lons, lats, depths)
1353746
private float[] restoreNormals(int[] intNormals, float[] vertices, int[] indices, float normalPrecision) {

        // Calculate smooth normals (nominal normals)
        float[] smoothNormals = calcSmoothNormals(vertices, indices);
        float[] normals = new float[vertices.length];

        int vc = vertices.length / CTM_POSITION_ELEMENT_COUNT;
        int ne = CTM_NORMAL_ELEMENT_COUNT;

        for (int i = 0; i < vc; ++i) {
            // Get the normal magnitude from the first of the three normal elements
            float magn = intNormals[i * ne] * normalPrecision;

            // Get phi and theta (spherical coordinates, relative to the smooth normal).
            double thetaScale, theta;
            int intPhi = intNormals[i * ne + 1];
            double phi = intPhi * (0.5 * PI) * normalPrecision;
            if (intPhi == 0) {
                thetaScale = 0.0f;
            } else if (intPhi <= 4) {
                thetaScale = PI / 2.0f;
            } else {
                thetaScale = (2.0f * PI) / intPhi;
            }
            theta = intNormals[i * ne + 2] * thetaScale - PI;

            // Convert the normal from the angular representation (phi, theta) back to
            // cartesian coordinates
            double[] n2 = new double[3];
            n2[0] = sin(phi) * cos(theta);
            n2[1] = sin(phi) * sin(theta);
            n2[2] = cos(phi);
            float[] basisAxes = makeNormalCoordSys(smoothNormals, i * ne);
            double[] n = new double[3];
            for (int j = 0; j < 3; ++j) {
                n[j] = basisAxes[j] * n2[0]
                       + basisAxes[3 + j] * n2[1]
                       + basisAxes[6 + j] * n2[2];
            }

            // Apply normal magnitude, and output to the normals array
            for (int j = 0; j < 3; ++j) {
                normals[i * ne + j] = (float) (n[j] * magn);
            }
        }

        return normals;
    }
959463
def kdtree(self):
        

        kdtree = KDTree(self.vertices.view(np.ndarray))
        return kdtree
248973
function () {
        if (!this.vertexCount) {
            return;
        }

        var indices = this.indices;
        var attributes = this.attributes;
        var positions = attributes.position.value;
        var normals = attributes.normal.value;

        if (!normals || normals.length !== positions.length) {
            normals = attributes.normal.value = new vendor.Float32Array(positions.length);
        }
        else {
            // Reset
            for (var i = 0; i < normals.length; i++) {
                normals[i] = 0;
            }
        }

        var p1 = vec3Create();
        var p2 = vec3Create();
        var p3 = vec3Create();

        var v21 = vec3Create();
        var v32 = vec3Create();

        var n = vec3Create();

        var len = indices ? indices.length : this.vertexCount;
        var i1, i2, i3;
        for (var f = 0; f < len;) {
            if (indices) {
                i1 = indices[f++];
                i2 = indices[f++];
                i3 = indices[f++];
            }
            else {
                i1 = f++;
                i2 = f++;
                i3 = f++;
            }

            vec3Set$2(p1, positions[i1*3], positions[i1*3+1], positions[i1*3+2]);
            vec3Set$2(p2, positions[i2*3], positions[i2*3+1], positions[i2*3+2]);
            vec3Set$2(p3, positions[i3*3], positions[i3*3+1], positions[i3*3+2]);

            vec3.sub(v21, p1, p2);
            vec3.sub(v32, p2, p3);
            vec3.cross(n, v21, v32);
            // Already be weighted by the triangle area
            for (var i = 0; i < 3; i++) {
                normals[i1*3+i] = normals[i1*3+i] + n[i];
                normals[i2*3+i] = normals[i2*3+i] + n[i];
                normals[i3*3+i] = normals[i3*3+i] + n[i];
            }
        }

        for (var i = 0; i < normals.length;) {
            vec3Set$2(n, normals[i], normals[i+1], normals[i+2]);
            vec3.normalize(n, n);
            normals[i++] = n[0];
            normals[i++] = n[1];
            normals[i++] = n[2];
        }
        this.dirty();
    }
973975
def triangle_normal(a, b, c):
    
    normal = np.cross(a - c, b - c)
    norm = np.linalg.norm(normal)
    return normal/norm
1165325
def _compute_edges(self):
        
        nodes1, nodes2, nodes3 = _surface_helpers.compute_edge_nodes(
            self._nodes, self._degree
        )
        edge1 = _curve_mod.Curve(nodes1, self._degree, _copy=False)
        edge2 = _curve_mod.Curve(nodes2, self._degree, _copy=False)
        edge3 = _curve_mod.Curve(nodes3, self._degree, _copy=False)
        return edge1, edge2, edge3
603292
def edge_refine_triangulation_by_vertices(self, vertices):
        

        triangles = self.identify_vertex_triangles(vertices)

        return self.edge_refine_triangulation_by_triangles(triangles)
955940
function ( contour, indices ) {

		var n = contour.length;

		if ( n < 3 ) return null;

		var result = [],
			verts = [],
			vertIndices = [];

		/* we want a counter-clockwise polygon in verts */

		var u, v, w;

		if ( area( contour ) > 0.0 ) {

			for ( v = 0; v < n; v ++ ) verts[ v ] = v;

		} else {

			for ( v = 0; v < n; v ++ ) verts[ v ] = ( n - 1 ) - v;

		}

		var nv = n;

		/*  remove nv - 2 vertices, creating 1 triangle every time */

		var count = 2 * nv;   /* error detection */

		for ( v = nv - 1; nv > 2; ) {

			/* if we loop, it is probably a non-simple polygon */

			if ( ( count -- ) <= 0 ) {

				//** Triangulate: ERROR - probable bad polygon!

				//throw ( "Warning, unable to triangulate polygon!" );
				//return null;
				// Sometimes warning is fine, especially polygons are triangulated in reverse.
				console.log( 'Warning, unable to triangulate polygon!' );

				if ( indices ) return vertIndices;
				return result;

			}

			/* three consecutive vertices in current polygon, <u,v,w> */

			u = v; 	 	if ( nv <= u ) u = 0;     /* previous */
			v = u + 1;  if ( nv <= v ) v = 0;     /* new v    */
			w = v + 1;  if ( nv <= w ) w = 0;     /* next     */

			if ( snip( contour, u, v, w, nv, verts ) ) {

				var a, b, c, s, t;

				/* true names of the vertices */

				a = verts[ u ];
				b = verts[ v ];
				c = verts[ w ];

				/* output Triangle */

				result.push( [ contour[ a ],
					contour[ b ],
					contour[ c ] ] );


				vertIndices.push( [ verts[ u ], verts[ v ], verts[ w ] ] );

				/* remove v from the remaining polygon */

				for ( s = v, t = v + 1; t < nv; s++, t++ ) {

					verts[ s ] = verts[ t ];

				}

				nv --;

				/* reset error detection counter */

				count = 2 * nv;

			}

		}

		if ( indices ) return vertIndices;
		return result;

	}
606745
public float getNormalX(int vertex) {
        if (!hasNormals()) {
            throw new IllegalStateException("mesh has no normals");
        }
        
        checkVertexIndexBounds(vertex);
        
        return m_normals.getFloat(vertex * 3 * SIZEOF_FLOAT);
    }
1110908
function (face, v) {
                //Get the indices of triangles for each polygon
                getTriangles(face, v);
                for (var k = 0; k < triangles.length; k++) {
                    //triangle[k] = "1/1/1"
                    //Split the data for getting position, uv, and normals
                    var point = triangles[k].split("/"); // ["1", "1", "1"]
                    // Set position indice
                    var indicePositionFromObj = parseInt(point[0]) - 1;
                    // Set uv indice
                    var indiceUvsFromObj = parseInt(point[1]) - 1;
                    // Set normal indice
                    var indiceNormalFromObj = parseInt(point[2]) - 1;
                    setData(indicePositionFromObj, indiceUvsFromObj, indiceNormalFromObj, positions[indicePositionFromObj], uvs[indiceUvsFromObj], normals[indiceNormalFromObj] //Set the vector for each component
                    );
                }
                //Reset variable for the next line
                triangles = [];
            }
448741
def vertices
      verts = Array.new(8)
      length_ary = self.length
      verts[0] = @min_point.clone
      verts[1] = @min_point + Vector3.new(length_ary[0],             0,            0 )
      verts[2] = @min_point + Vector3.new(length_ary[0], length_ary[1],            0 )
      verts[3] = @min_point + Vector3.new(            0, length_ary[1],            0 )
      verts[4] = @min_point + Vector3.new(            0,             0, length_ary[2])
      verts[5] = @min_point + Vector3.new(length_ary[0],             0, length_ary[2])
      verts[6] = @min_point + Vector3.new(length_ary[0], length_ary[1], length_ary[2])
      verts[7] = @min_point + Vector3.new(            0, length_ary[1], length_ary[2])
      return verts
    end
550623
def midpoint_refine_triangulation_by_vertices(self, vertices):
        

        mlons, mlats = self.segment_midpoints_by_vertices(vertices=vertices)

        lonv1 = np.concatenate((self.lons, mlons), axis=0)
        latv1 = np.concatenate((self.lats, mlats), axis=0)

        return lonv1, latv1