Given a list of coords for 3 points,
    Compute the area of this triangle.

    Args:
        pts: [a, b, c] three points
977840
def get_tri_area(pts):
    
    a, b, c = pts[0], pts[1], pts[2]
    v1 = np.array(b) - np.array(a)
    v2 = np.array(c) - np.array(a)
    area_tri = abs(sp.linalg.norm(sp.cross(v1, v2)) / 2)
    return area_tri
147181
def signed_cell_areas(self):
        
        # http://mathworld.wolfram.com/TriangleArea.html
        assert (
            self.node_coords.shape[1] == 2
        ), "Signed areas only make sense for triangles in 2D."

        if self._signed_cell_areas is None:
            # One could make p contiguous by adding a copy(), but that's not
            # really worth it here.
            p = self.node_coords[self.cells["nodes"]].T
            # <https://stackoverflow.com/q/50411583/353337>
            self._signed_cell_areas = (
                +p[0][2] * (p[1][0] - p[1][1])
                + p[0][0] * (p[1][1] - p[1][2])
                + p[0][1] * (p[1][2] - p[1][0])
            ) / 2
        return self._signed_cell_areas
795996
function ( geometry, n ) {

		var face, i,
			faces = geometry.faces,
			vertices = geometry.vertices,
			il = faces.length,
			totalArea = 0,
			cumulativeAreas = [],
			vA, vB, vC, vD;

		// precompute face areas

		for ( i = 0; i < il; i ++ ) {

			face = faces[ i ];

			if ( face instanceof THREE.Face3 ) {

				vA = vertices[ face.a ];
				vB = vertices[ face.b ];
				vC = vertices[ face.c ];

				face._area = THREE.GeometryUtils.triangleArea( vA, vB, vC );

			} else if ( face instanceof THREE.Face4 ) {

				vA = vertices[ face.a ];
				vB = vertices[ face.b ];
				vC = vertices[ face.c ];
				vD = vertices[ face.d ];

				face._area1 = THREE.GeometryUtils.triangleArea( vA, vB, vD );
				face._area2 = THREE.GeometryUtils.triangleArea( vB, vC, vD );

				face._area = face._area1 + face._area2;

			}

			totalArea += face._area;

			cumulativeAreas[ i ] = totalArea;

		}

		// binary search cumulative areas array

		function binarySearchIndices( value ) {

			function binarySearch( start, end ) {

				// return closest larger index
				// if exact number is not found

				if ( end < start )
					return start;

				var mid = start + Math.floor( ( end - start ) / 2 );

				if ( cumulativeAreas[ mid ] > value ) {

					return binarySearch( start, mid - 1 );

				} else if ( cumulativeAreas[ mid ] < value ) {

					return binarySearch( mid + 1, end );

				} else {

					return mid;

				}

			}

			var result = binarySearch( 0, cumulativeAreas.length - 1 )
			return result;

		}

		// pick random face weighted by face area

		var r, index,
			result = [];

		var stats = {};

		for ( i = 0; i < n; i ++ ) {

			r = THREE.GeometryUtils.random() * totalArea;

			index = binarySearchIndices( r );

			result[ i ] = THREE.GeometryUtils.randomPointInFace( faces[ index ], geometry, true );

			if ( ! stats[ index ] ) {

				stats[ index ] = 1;

			} else {

				stats[ index ] += 1;

			}

		}

		return result;

	}
963660
def area_faces(self):
        
        area_faces = triangles.area(crosses=self.triangles_cross,
                                    sum=False)
        return area_faces
129514
def triangle_areas(p1,p2,p3):
    
    v1 = (p2 - p1).astype(np.float)
    v2 = (p3 - p1).astype(np.float)
    # Original:
    #   cross1 = v1[:,1] * v2[:,0]
    #   cross2 = v2[:,1] * v1[:,0]
    #   a = (cross1-cross2) / 2
    # Memory reduced:
    cross1 = v1[:, 1]
    cross1 *= v2[:, 0]
    cross2 = v2[:, 1]
    cross2 *= v1[:, 0]
    a = cross1
    a -= cross2
    a /= 2.0
    del v1, v2, cross1, cross2
    a = a.copy()  # a is a view on v1; shed one dimension.
    a = np.abs(a)
    #
    # Handle small round-off errors
    #
    a[a<np.finfo(np.float32).eps] = 0
    return a
1334114
def triangulate(self):
        
        npts = self._vertices.shape[0]
        if np.any(self._vertices[0] != self._vertices[1]):
            # start != end, so edges must wrap around to beginning.
            edges = np.empty((npts, 2), dtype=np.uint32)
            edges[:, 0] = np.arange(npts)
            edges[:, 1] = edges[:, 0] + 1
            edges[-1, 1] = 0
        else:
            # start == end; no wrapping required.
            edges = np.empty((npts-1, 2), dtype=np.uint32)
            edges[:, 0] = np.arange(npts)
            edges[:, 1] = edges[:, 0] + 1

        tri = Triangulation(self._vertices, edges)
        tri.triangulate()
        return tri.pts, tri.tris
1325093
function _noArea (triangle) {
    const [v1, v2, v3] = triangle;
    return (equalPoints(v1, v2) || equalPoints(v2, v3));
}
610024
def pts_relative(pts=[], shift=[0.0, 0.0], angle=[0.0]):
    '''
    '''
    assert isinstance(pts, list) and len(pts) > 0
    l_pt_prev = None
    for pt in pts:
        assert isinstance(pt, tuple)
        l_pt = len(pt)
        assert l_pt > 1
        for i in pt:
            assert isinstance(i, float)
        if l_pt_prev is not None:
            assert l_pt == l_pt_prev
        l_pt_prev = l_pt
    assert isinstance(shift, list)
    l_sh = len(shift)
    assert l_sh == l_pt
    for i in shift:
        assert isinstance(i, float)
    assert isinstance(angle, list)
    l_angle = len(angle)
    assert l_angle == l_pt-1
    for i in angle:
        assert isinstance(i, float)
        assert abs(i) <= 2*pi

    return [pt_relative(pt, shift, angle) for pt in pts]
116696
def surface_area(self):
        
        m = self.lattice.matrix
        return np.linalg.norm(np.cross(m[0], m[1]))
1091496
def triangular_coord(coord):
    
    unitvec = np.array([[1, 0], [0.5, math.sqrt(3) / 2]])
    result = np.dot(np.array(coord), unitvec)
    return result.transpose()
1203847
def coords_for_computations(self):
        

        # TODO: need to subtract the position offset if a Mesh (in orbit)
        if self._compute_at_vertices:
            if self.pvertices is not None:
                return self.pvertices - self._pos_center
            else:
                return self.vertices - self._pos_center
        else:
            return self.centers - self._pos_center
972264
void run(boolean hullonly) {
    if(points.size() < 3) {
      throw new UnsupportedOperationException("There is no delaunay triangulation for less than three objects!");
    }
    int len = points.size() - 1;
    hull = new LinkedList<>();
    tris = hullonly ? null : new ArrayList<Triangle>(len);

    // 1. Seed point x_0
    final double[] seed;
    final int seedid = 0;

    final double[] sortd = new double[len];
    final int[] sorti = new int[len];
    Arrays.fill(sorti, -42); // To cause errors
    // TODO: remove duplicates.

    // 2. sort by squared Euclidean distance
    {
      Iterator<double[]> iter = points.iterator();
      seed = iter.next();
      for(int i = 0, j = 1; iter.hasNext(); j++, i++) {
        double dist = quadraticEuclidean(seed, iter.next());
        if(dist <= 0.) { // Duplicate.
          --len; // Decrease candidate set size
          --i; // Increase j, but not i.
          continue;
        }
        sortd[i] = dist;
        sorti[i] = j;
      }
      DoubleIntegerArrayQuickSort.sort(sortd, sorti, len);
    }
    // Detect some degenerate situations:
    if(len < 2) {
      hull.add(new IntIntPair(seedid, -1));
      if(len == 1) {
        hull.add(new IntIntPair(sorti[0], -1));
      }
      return;
    }
    assert (sortd[0] > 0);
    // final double[] seed2 = points.get(sort[0].second);
    final int seed2id = sorti[0];

    // 3. Find minimal triangle for these two points:
    Triangle besttri = findSmallest(seedid, seed2id, sortd, sorti, len);
    if(besttri == null) { // Degenerate
      hull.add(new IntIntPair(seedid, -1));
      hull.add(new IntIntPair(seed2id, -1));
      return;
    }
    // Note: sortd no longer accurate, recompute below!
    int start = 2; // First two points have already been processed.

    // 5. Make right-handed:
    besttri.makeClockwise(points);
    // Seed triangulation
    if(!hullonly) {
      tris.add(besttri);
    }
    // Seed convex hull (point, triangle)
    hull.add(new IntIntPair(besttri.a, 0));
    hull.add(new IntIntPair(besttri.b, 0));
    hull.add(new IntIntPair(besttri.c, 0));

    if(LOG.isDebuggingFinest()) {
      debugHull();
    }

    // 6. Resort from triangle circumcircle center
    double[] center = besttri.m;
    for(int i = start; i < len; i++) {
      sortd[i] = quadraticEuclidean(center, points.get(sorti[i]));
    }
    DoubleIntegerArrayQuickSort.sort(sortd, sorti, start, len);

    // Grow hull and triangles
    for(int i = start; i < len; i++) {
      final int pointId = sorti[i];
      final double[] newpoint = points.get(pointId);

      LinkedList<Triangle> newtris = hullonly ? null : new LinkedList<Triangle>();
      // We identify edges by their starting point. -1 is invalid.
      int hstart = -1, hend = -1;
      // Find first and last consecutive visible edge, backwards:
      {
        Iterator<IntIntPair> iter = hull.descendingIterator();
        IntIntPair next = hull.getFirst();
        double[] nextV = points.get(next.first);
        for(int pos = hull.size() - 1; iter.hasNext(); pos--) {
          IntIntPair prev = iter.next();
          double[] prevV = points.get(prev.first);
          // Not yet visible:
          if(hend < 0) {
            if(leftOf(prevV, nextV, newpoint)) {
              hstart = hend = pos;
              if(!hullonly) {
                // Clockwise, A is new point!
                Triangle tri = new Triangle(pointId, next.first, prev.first);
                assert (tri.isClockwise(points));
                assert (prev.second >= 0);
                tri.updateCircumcircle(points);
                tri.bc = prev.second;
                newtris.addFirst(tri);
              }
            }
          }
          else {
            if(leftOf(prevV, nextV, newpoint)) {
              hstart = pos;
              // Add triad:
              if(!hullonly) {
                // Clockwise, A is new point!
                Triangle tri = new Triangle(pointId, next.first, prev.first);
                assert (tri.isClockwise(points));
                assert (prev.second >= 0);
                tri.updateCircumcircle(points);
                tri.bc = prev.second;
                newtris.addFirst(tri);
              }
            }
            else {
              break;
            }
          }
          next = prev;
          nextV = prevV;
        }
      }
      // If the last edge was visible, we also need to scan forwards:
      if(hend == hull.size() - 1) {
        Iterator<IntIntPair> iter = hull.iterator();
        IntIntPair prev = iter.next();
        double[] prevV = points.get(prev.first);
        while(iter.hasNext()) {
          IntIntPair next = iter.next();
          double[] nextV = points.get(next.first);
          if(leftOf(prevV, nextV, newpoint)) {
            hend++;
            // Add triad:
            if(!hullonly) {
              // Clockwise, A is new point!
              Triangle tri = new Triangle(pointId, next.first, prev.first);
              assert (tri.isClockwise(points));
              assert (prev.second >= 0);
              tri.updateCircumcircle(points);
              tri.bc = prev.second;
              newtris.addLast(tri);
            }
          }
          else {
            break;
          }
          prev = next;
          prevV = nextV;
        }
      }
      assert (hstart >= 0 && hend >= hstart);
      // Note that hend can be larger than hull.size() now, interpret as
      // "hend % hull.size()"
      // Update hull, remove points
      final int firsttri, lasttri;
      if(hullonly) {
        firsttri = lasttri = -1;
      }
      else {
        final int tristart = tris.size();
        firsttri = tristart;
        lasttri = tristart + newtris.size() - 1;
      }
      final int hullsize = hull.size();
      if(LOG.isDebuggingFinest()) {
        LOG.debugFinest("Size: " + hullsize + " start: " + hstart + " end: " + hend);
      }
      if(hend < hullsize) {
        ListIterator<IntIntPair> iter = hull.listIterator();
        int p = 0;
        // Skip
        for(; p <= hstart; p++) {
          iter.next();
        }
        // Remove
        for(; p <= hend; p++) {
          iter.next();
          iter.remove();
        }
        // Insert, and update edge->triangle mapping
        iter.add(new IntIntPair(pointId, lasttri));
        iter.previous();
        if(!hullonly) {
          (iter.hasPrevious() ? iter.previous() : hull.getLast()).second = firsttri;
        }
      }
      else {
        ListIterator<IntIntPair> iter = hull.listIterator();
        // Remove end
        int p = hullsize;
        for(; p <= hend; p++) {
          iter.next();
          iter.remove();
        }
        // Insert
        iter.add(new IntIntPair(pointId, lasttri));
        // Wrap around
        p -= hullsize;
        IntIntPair pre = null;
        for(; p <= hstart; p++) {
          pre = iter.next();
        }
        assert (pre != null);
        pre.second = firsttri;
        // Remove remainder
        while(iter.hasNext()) {
          iter.next();
          iter.remove();
        }
      }
      if(LOG.isDebuggingFinest()) {
        debugHull();
      }
      if(!hullonly) {
        final int tristart = tris.size();
        // Connect triads (they are ordered)
        Iterator<Triangle> iter = newtris.iterator();
        for(int o = 0; iter.hasNext(); o++) {
          // This triangle has num tristart + o.
          Triangle cur = iter.next();
          cur.ca = o > 0 ? tristart + o - 1 : -1; // previously added triangle
          cur.ab = iter.hasNext() ? tristart + o + 1 : -1; // next triangle
          // cur.bc was set upon creation
          assert (cur.bc >= 0);
          Triangle other = tris.get(cur.bc);
          Orientation orient = cur.findOrientation(other);
          assert (orient != null) : "Inconsistent triangles: " + cur + " " + other;
          switch(orient){
          case ORIENT_BC_BA:
            assert (other.ab == -1) : "Inconsistent triangles: " + cur + " " + other;
            other.ab = tristart + o;
            break;
          case ORIENT_BC_CB:
            assert (other.bc == -1) : "Inconsistent triangles: " + cur + " " + other;
            other.bc = tristart + o;
            break;
          case ORIENT_BC_AC:
            assert (other.ca == -1) : "Inconsistent triangles: " + cur + " " + other;
            other.ca = tristart + o;
            break;
          default:
            assert (cur.isClockwise(points));
            assert (other.isClockwise(points));
            throw new RuntimeException("Inconsistent triangles: " + cur + " " + other + " size:" + tris.size());
          }
          tris.add(cur);
        }
        assert (tris.size() == lasttri + 1);
      }
    }
    // Now check for triangles that need flipping.
    if(!hullonly) {
      final int size = tris.size();
      long[] flippedA = BitsUtil.zero(size), flippedB = BitsUtil.zero(size);
      // Initial flip
      if(flipTriangles(flippedA) > 0) {
        for(int iterations = 1; iterations < 1000; iterations += 2) {
          if(LOG.isDebuggingFinest()) {
            debugHull();
          }
          if(flipTriangles(flippedA, flippedB) == 0) {
            break;
          }
          if(LOG.isDebuggingFinest()) {
            debugHull();
          }
          if(flipTriangles(flippedB, flippedA) == 0) {
            break;
          }
        }
      }
    }
  }
101390
def triangles
      tris = Array.new(tri_indices.size)
      i = 0
      tri_indices.each do |tri_index|
        tris[i] =  self.triangle(i)
        i += 1
      end
      return tris
    end
1103243
def _find_cut_triangle(self, edge):
        
        edges = []  # opposite edge for each triangle attached to edge[0]
        for tri in self.tris:
            if edge[0] in tri:
                edges.append(self._edge_opposite_point(tri, edge[0]))
                
        for oedge in edges:
            o1 = self._orientation(edge, oedge[0])
            o2 = self._orientation(edge, oedge[1]) 
            #debug(edge, oedge, o1, o2)
            #debug(self.pts[np.array(edge)])
            #debug(self.pts[np.array(oedge)])
            if o1 != o2:
                return (edge[0], oedge[0], oedge[1])
        
        return None
1148986
def triangle(self, params=None, **kwargs):
        
        if params is None:
            params = ['mass_A', 'mass_B', 'mass_C', 
                      'age', 'feh', 'distance', 'AV']

        super(TripleStarModel, self).triangle(params=params, **kwargs)
268846
public Triangle setPoints(final Point2D a, final Point2D b, final Point2D c)
    {
        return setPoint2DArray(new Point2DArray(a, b, c));
    }
738010
def triangle(self, x1, y1, x2, y2, x3, y3, color):
        
        self.context.set_source_rgb(*color)
        self.context.move_to(self.tx(x1), self.ty(y1))
        self.context.line_to(self.tx(x2), self.ty(y2))
        self.context.line_to(self.tx(x3), self.ty(y3))
        self.context.line_to(self.tx(x1), self.ty(y1))
        self.context.fill()