Generate data for a single face in a geometry. If the face is a quad then split it into 2 tris
764512
function ( buffers, geoInfo, facePositionIndexes, materialIndex, faceNormals, faceColors, faceUVs, faceWeights, faceWeightIndices, faceLength ) {

			for ( var i = 2; i < faceLength; i ++ ) {

				buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ 0 ] ] );
				buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ 1 ] ] );
				buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ 2 ] ] );

				buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ ( i - 1 ) * 3 ] ] );
				buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ ( i - 1 ) * 3 + 1 ] ] );
				buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ ( i - 1 ) * 3 + 2 ] ] );

				buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i * 3 ] ] );
				buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i * 3 + 1 ] ] );
				buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i * 3 + 2 ] ] );

				if ( geoInfo.skeleton ) {

					buffers.vertexWeights.push( faceWeights[ 0 ] );
					buffers.vertexWeights.push( faceWeights[ 1 ] );
					buffers.vertexWeights.push( faceWeights[ 2 ] );
					buffers.vertexWeights.push( faceWeights[ 3 ] );

					buffers.vertexWeights.push( faceWeights[ ( i - 1 ) * 4 ] );
					buffers.vertexWeights.push( faceWeights[ ( i - 1 ) * 4 + 1 ] );
					buffers.vertexWeights.push( faceWeights[ ( i - 1 ) * 4 + 2 ] );
					buffers.vertexWeights.push( faceWeights[ ( i - 1 ) * 4 + 3 ] );

					buffers.vertexWeights.push( faceWeights[ i * 4 ] );
					buffers.vertexWeights.push( faceWeights[ i * 4 + 1 ] );
					buffers.vertexWeights.push( faceWeights[ i * 4 + 2 ] );
					buffers.vertexWeights.push( faceWeights[ i * 4 + 3 ] );

					buffers.weightsIndices.push( faceWeightIndices[ 0 ] );
					buffers.weightsIndices.push( faceWeightIndices[ 1 ] );
					buffers.weightsIndices.push( faceWeightIndices[ 2 ] );
					buffers.weightsIndices.push( faceWeightIndices[ 3 ] );

					buffers.weightsIndices.push( faceWeightIndices[ ( i - 1 ) * 4 ] );
					buffers.weightsIndices.push( faceWeightIndices[ ( i - 1 ) * 4 + 1 ] );
					buffers.weightsIndices.push( faceWeightIndices[ ( i - 1 ) * 4 + 2 ] );
					buffers.weightsIndices.push( faceWeightIndices[ ( i - 1 ) * 4 + 3 ] );

					buffers.weightsIndices.push( faceWeightIndices[ i * 4 ] );
					buffers.weightsIndices.push( faceWeightIndices[ i * 4 + 1 ] );
					buffers.weightsIndices.push( faceWeightIndices[ i * 4 + 2 ] );
					buffers.weightsIndices.push( faceWeightIndices[ i * 4 + 3 ] );

				}

				if ( geoInfo.color ) {

					buffers.colors.push( faceColors[ 0 ] );
					buffers.colors.push( faceColors[ 1 ] );
					buffers.colors.push( faceColors[ 2 ] );

					buffers.colors.push( faceColors[ ( i - 1 ) * 3 ] );
					buffers.colors.push( faceColors[ ( i - 1 ) * 3 + 1 ] );
					buffers.colors.push( faceColors[ ( i - 1 ) * 3 + 2 ] );

					buffers.colors.push( faceColors[ i * 3 ] );
					buffers.colors.push( faceColors[ i * 3 + 1 ] );
					buffers.colors.push( faceColors[ i * 3 + 2 ] );

				}

				if ( geoInfo.material && geoInfo.material.mappingType !== 'AllSame' ) {

					buffers.materialIndex.push( materialIndex );
					buffers.materialIndex.push( materialIndex );
					buffers.materialIndex.push( materialIndex );

				}

				if ( geoInfo.normal ) {

					buffers.normal.push( faceNormals[ 0 ] );
					buffers.normal.push( faceNormals[ 1 ] );
					buffers.normal.push( faceNormals[ 2 ] );

					buffers.normal.push( faceNormals[ ( i - 1 ) * 3 ] );
					buffers.normal.push( faceNormals[ ( i - 1 ) * 3 + 1 ] );
					buffers.normal.push( faceNormals[ ( i - 1 ) * 3 + 2 ] );

					buffers.normal.push( faceNormals[ i * 3 ] );
					buffers.normal.push( faceNormals[ i * 3 + 1 ] );
					buffers.normal.push( faceNormals[ i * 3 + 2 ] );

				}

				if ( geoInfo.uv ) {

					geoInfo.uv.forEach( function ( uv, j ) {

						if ( buffers.uvs[ j ] === undefined ) buffers.uvs[ j ] = [];

						buffers.uvs[ j ].push( faceUVs[ j ][ 0 ] );
						buffers.uvs[ j ].push( faceUVs[ j ][ 1 ] );

						buffers.uvs[ j ].push( faceUVs[ j ][ ( i - 1 ) * 2 ] );
						buffers.uvs[ j ].push( faceUVs[ j ][ ( i - 1 ) * 2 + 1 ] );

						buffers.uvs[ j ].push( faceUVs[ j ][ i * 2 ] );
						buffers.uvs[ j ].push( faceUVs[ j ][ i * 2 + 1 ] );

					} );

				}

			}

		}
246617
def create_rectangular_prism(origin, size):
    '''
    

    '''
    from lace.topology import quads_to_tris

    lower_base_plane = np.array([
        # Lower base plane
        origin,
        origin + np.array([size[0], 0, 0]),
        origin + np.array([size[0], 0, size[2]]),
        origin + np.array([0, 0, size[2]]),
    ])
    upper_base_plane = lower_base_plane + np.array([0, size[1], 0])

    vertices = np.vstack([lower_base_plane, upper_base_plane])

    faces = quads_to_tris(np.array([
        [0, 1, 2, 3],  # lower base (-y)
        [7, 6, 5, 4],  # upper base (+y)
        [4, 5, 1, 0],  # +z face
        [5, 6, 2, 1],  # +x face
        [6, 7, 3, 2],  # -z face
        [3, 7, 4, 0],  # -x face
    ]))

    return Mesh(v=vertices, f=faces)
733591
def face_index(vertices):
    """"""
    new_verts = []
    face_indices = []
    for wall in vertices:
        face_wall = []
        for vert in wall:
            if new_verts:
                if not np.isclose(vert, new_verts).all(axis=1).any():
                    new_verts.append(vert)
            else:
                    new_verts.append(vert)
            face_index = np.where(np.isclose(vert, new_verts).all(axis=1))[0][0]
            face_wall.append(face_index)
        face_indices.append(face_wall)
    return np.array(new_verts), np.array(face_indices)
248510
def generate_unit_triangles(image_width, image_height):
    """"""
    # Our triangles lie with one side parallel to the x-axis.  Let s be
    # the length of one side, and h the height of the triangle.
    #
    # The for loops (x, y) gives the coordinates of the top left-hand corner
    # of a pair of triangles:
    #
    #           (x, y) +-----+ (x + 1, y)
    #                   \   / \
    #                    \ /   \
    #    (x + 1/2, y + h) +-----+ (x + 3/2, y + h)
    #
    # where h = sin(60°) is the height of an equilateral triangle with
    # side length 1.
    #
    # On odd-numbered rows, we translate by (s/2, 0) to make the triangles
    # line up with the even-numbered rows.
    #
    # To avoid blank spaces on the edge of the canvas, the first pair of
    # triangles on each row starts at (-1, 0) -- one width before the edge
    # of the canvas.
    h = math.sin(math.pi / 3)

    for x in range(-1, image_width):
        for y in range(int(image_height / h)):

            # Add a horizontal offset on odd numbered rows
            x_ = x if (y % 2 == 0) else x + 0.5

            yield [(x_, y * h), (x_ + 1, y * h), (x_ + 0.5, (y + 1) * h)]
            yield [(x_ + 1, y * h), (x_ + 1.5, (y + 1) * h),
                   (x_ + 0.5, (y + 1) * h)]
603600
def export_wavefront(mesh,
                     include_normals=True,
                     include_texture=True):
    
    # store the multiple options for formatting
    # a vertex index for a face
    face_formats = {('v',): '{}',
                    ('v', 'vn'): '{}//{}',
                    ('v', 'vt'): '{}/{}',
                    ('v', 'vn', 'vt'): '{}/{}/{}'}
    # we are going to reference face_formats with this
    face_type = ['v']

    export = 'v '
    export += util.array_to_string(mesh.vertices,
                                   col_delim=' ',
                                   row_delim='\nv ',
                                   digits=8) + '\n'

    if include_normals and 'vertex_normals' in mesh._cache:
        # if vertex normals are stored in cache export them
        # these will have been autogenerated if they have ever been called
        face_type.append('vn')
        export += 'vn '
        export += util.array_to_string(mesh.vertex_normals,
                                       col_delim=' ',
                                       row_delim='\nvn ',
                                       digits=8) + '\n'

    if (include_texture and
        'vertex_texture' in mesh.metadata and
            len(mesh.metadata['vertex_texture']) == len(mesh.vertices)):
        # if vertex texture exists and is the right shape export here
        face_type.append('vt')
        export += 'vt '
        export += util.array_to_string(mesh.metadata['vertex_texture'],
                                       col_delim=' ',
                                       row_delim='\nvt ',
                                       digits=8) + '\n'

    # the format for a single vertex reference of a face
    face_format = face_formats[tuple(face_type)]
    faces = 'f ' + util.array_to_string(mesh.faces + 1,
                                        col_delim=' ',
                                        row_delim='\nf ',
                                        value_format=face_format)
    # add the exported faces to the export
    export += faces

    return export
388703
function Octahedron(r) {
  r = r || 0.5;

  var a = 1 / (2 * Math.sqrt(2));
  var b = 1 / 2;

  var s3 = Math.sqrt(3);
  var s6 = Math.sqrt(6);

  var vertices = [
    new Vec3(-a, 0, a), //front left
    new Vec3( a, 0, a), //front right
    new Vec3( a, 0,-a), //back right
    new Vec3(-a, 0,-a), //back left
    new Vec3( 0, b, 0), //top
    new Vec3( 0,-b, 0)  //bottom
  ];

  vertices = vertices.map(function(v) { return v.normalize().scale(r); })

  var faces = [
    [3, 0, 4],
    [2, 3, 4],
    [1, 2, 4],
    [0, 1, 4],
    [3, 2, 5],
    [0, 3, 5],
    [2, 1, 5],
    [1, 0, 5]
  ];

  var edges = [
    [0, 1],
    [1, 2],
    [2, 3],
    [3, 0],
    [0, 4],
    [1, 4],
    [2, 4],
    [3, 4],
    [0, 5],
    [1, 5],
    [2, 5],
    [3, 5]
  ];

  Geometry.call(this, { vertices: vertices, faces: faces, edges: edges });
}
289816
def _tri_from_edge(self, edge):
        
        edge = tuple(edge)
        p1 = self._edges_lookup.get(edge, None)
        p2 = self._edges_lookup.get(edge[::-1], None)
        if p1 is None:
            if p2 is None:
                raise RuntimeError("No tris connected to edge %r" % (edge,))
            return edge + (p2,)
        elif p2 is None:
            return edge + (p1,)
        else:
            raise RuntimeError("Two triangles connected to edge %r" % (edge,))
824530
function Box(sx, sy, sz) {
  sx = sx != null ? sx : 1;
  sy = sy != null ? sy : sx != null ? sx : 1;
  sz = sz != null ? sz : sx != null ? sx : 1;

  Geometry.call(this, { vertices: true, faces: true });

  var vertices = this.vertices;
  var faces = this.faces;

  var x = sx/2;
  var y = sy/2;
  var z = sz/2;

  //bottom
  vertices.push(new Vec3(-x, -y, -z));
  vertices.push(new Vec3(-x, -y,  z));
  vertices.push(new Vec3( x, -y,  z));
  vertices.push(new Vec3( x, -y, -z));

  //top
  vertices.push(new Vec3(-x,  y, -z));
  vertices.push(new Vec3(-x,  y,  z));
  vertices.push(new Vec3( x,  y,  z));
  vertices.push(new Vec3( x,  y, -z));

  //     4----7
  //    /:   /|
  //   5----6 |
  //   | 0..|.3
  //   |,   |/
  //   1----2

  faces.push([0, 3, 2, 1]); //bottom
  faces.push([4, 5, 6, 7]); //top
  faces.push([0, 1, 5, 4]); //left
  faces.push([2, 3, 7, 6]); //right
  faces.push([1, 2, 6, 5]); //front
  faces.push([3, 0, 4, 7]); //back

  this.computeNormals();
}
184707
public static Face createTriangle(Vertex v0, Vertex v1, Vertex v2, double minArea) {
        Face face = new Face();
        HalfEdge he0 = new HalfEdge(v0, face);
        HalfEdge he1 = new HalfEdge(v1, face);
        HalfEdge he2 = new HalfEdge(v2, face);

        he0.prev = he2;
        he0.next = he1;
        he1.prev = he0;
        he1.next = he2;
        he2.prev = he1;
        he2.next = he0;

        face.he0 = he0;

        // compute the normal and offset
        face.computeNormalAndCentroid(minArea);
        return face;
    }
1274767
def from_indexed_arrays(cls, name, verts, normals):
        """"""

        # Put header in string
        wavefront_str = "o {name}\n".format(name=name)


        new_verts, face_indices = face_index(verts)
        assert new_verts.shape[1] == 3, "verts should be Nx3 array"
        assert face_indices.ndim == 2

        face_indices = fan_triangulate(face_indices)

        # Write Vertex data from vert_dict
        for vert in new_verts:
            wavefront_str += "v {0} {1} {2}\n".format(*vert)

        # Write (false) UV Texture data
        wavefront_str += "vt 1.0 1.0\n"

        for norm in normals:
            wavefront_str += "vn {0} {1} {2}\n".format(*norm)

        assert len(face_indices) == len(normals) * 2
        for norm_idx, vert_idx,  in enumerate(face_indices):
            wavefront_str += "f"
            for vv in vert_idx:
                wavefront_str += " {}/{}/{}".format(vv + 1, 1, (norm_idx // 2) + 1 )
            wavefront_str += "\n"

        return cls(string=wavefront_str)
305939
def faces(self):
        

        if self._faces is None:
            if self._vertices is None:
                return None
            self.triangulate()
        return self._faces
566370
def create_triangular_prism(p1, p2, p3, height):
    '''
    

    '''
    from blmath.geometry import Plane

    base_plane = Plane.from_points(p1, p2, p3)
    lower_base_to_upper_base = height * -base_plane.normal # pylint: disable=invalid-unary-operand-type
    vertices = np.vstack(([p1, p2, p3], [p1, p2, p3] + lower_base_to_upper_base))

    faces = np.array([
        [0, 1, 2],  # base
        [0, 3, 4], [0, 4, 1],  # side 0, 3, 4, 1
        [1, 4, 5], [1, 5, 2],  # side 1, 4, 5, 2
        [2, 5, 3], [2, 3, 0],  # side 2, 5, 3, 0
        [5, 4, 3],  # base
    ])

    return Mesh(v=vertices, f=faces)
537715
def _quadPoints(size, disp1, disp2):
        """"""
        w, h = size
        x1, y1 = disp1
        x2, y2 = disp2

        return (
            x1,    -y1,
            -x1,    h + y2,
            w + x2, h - y2,
            w - x2, y1
        )
861413
def all_faces_with_verts(self, v_indices, as_boolean=False):
        '''
        
        '''
        import numpy as np
        included_vertices = np.zeros(self.v.shape[0], dtype=bool)
        included_vertices[np.array(v_indices, dtype=np.uint32)] = True
        faces_with_verts = included_vertices[self.f].all(axis=1)
        if as_boolean:
            return faces_with_verts
        return np.nonzero(faces_with_verts)[0]
2984
def concatenate(cls, *args):
        
        nargs = len(args)
        if nargs == 1:
            return args[0]

        vs = [a.v for a in args if a.v is not None]
        vcs = [a.vc for a in args if a.vc is not None]
        fs = [a.f for a in args if a.f is not None]

        if vs and len(vs) != nargs:
            raise ValueError('Expected `v` for all args or none.')
        if vcs and len(vcs) != nargs:
            raise ValueError('Expected `vc` for all args or none.')
        if fs and len(fs) != nargs:
            raise ValueError('Expected `f` for all args or none.')

        # Offset face indices by the cumulative vertex count.
        face_offsets = np.cumsum([v.shape[0] for v in vs[:-1]])
        for offset, f in zip(face_offsets, fs[1:]):  # https://bitbucket.org/logilab/pylint/issues/603/operator-generates-false-positive-unused pylint: disable=unused-variable
            f += offset

        return Mesh(
            v=np.vstack(vs) if vs else None,
            vc=np.vstack(vcs) if vcs else None,
            f=np.vstack(fs) if fs else None,
        )
710856
def isosurface_from_data(data, isolevel, origin, spacing):
    
    spacing = np.array(extent/resolution)
    if isolevel >= 0:
        triangles = marching_cubes(data, isolevel)
    else: # Wrong traingle unwinding roder -- god only knows why
        triangles = marching_cubes(-data, -isolevel)
    faces = []
    verts = []
    for i, t in enumerate(triangles):
       faces.append([i * 3, i * 3 +1, i * 3 + 2])
       verts.extend(t)
       
    faces = np.array(faces)
    verts = origin + spacing/2 + np.array(verts)*spacing
    return verts, faces
1097517
def subdivide(face, detail)
      cols = 2.0 ** detail
      a = prepare(@vertices[face.a])
      b = prepare(@vertices[face.b])
      c = prepare(@vertices[face.c])
      v = []

      # Construct all of the vertices for this subdivision.
      for i in 0..cols do
        v[i] = []

        aj = prepare(a.clone.lerp(c, i.to_f / cols.to_f))
        bj = prepare(b.clone.lerp(c, i.to_f / cols.to_f))
        rows = cols - i

        for j in 0..rows do
          v[i][j] = if j.zero? && i == cols
                      aj
                    else
                      prepare(aj.clone.lerp(bj, j.to_f / rows.to_f))
                    end
        end
      end

      # Construct all of the faces
      for i in 0...cols do
        for j in (0...(2 * (cols - i) - 1)) do
          k = j/2

          if j.even?
            make(
              v[i][k + 1],
              v[i + 1][k],
              v[i][k]
            )
          else
            make(
              v[i][k + 1],
              v[i + 1][k + 1],
              v[i + 1][k]
            )
          end
        end
      end
    end