1 /*=========================================================================
3 Program: Visualization Toolkit
4 Module: $RCSfile: vtkTriangle.h,v $
6 Date: $Date: 2003/01/06 20:36:14 $
7 Version: $Revision: 1.79 $
9 Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen
11 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
13 This software is distributed WITHOUT ANY WARRANTY; without even
14 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 PURPOSE. See the above copyright notice for more information.
17 =========================================================================*/
18 // .NAME vtkTriangle - a cell that represents a triangle
19 // .SECTION Description
20 // vtkTriangle is a concrete implementation of vtkCell to represent a triangle
21 // located in 3-space.
23 #ifndef __vtkTriangle_h
24 #define __vtkTriangle_h
28 #include "vtkMath.h" // Needed for inline methods
33 class VTK_COMMON_EXPORT vtkTriangle : public vtkCell
36 static vtkTriangle *New();
37 vtkTypeRevisionMacro(vtkTriangle,vtkCell);
40 // Create a new cell and copy this triangle's information into the
41 // cell. Returns a pointer to the new cell created.
44 // Get the edge specified by edgeId (range 0 to 2) and return that edge's
46 vtkCell *GetEdge(int edgeId);
49 // See the vtkCell API for descriptions of these methods.
50 int GetCellType() {return VTK_TRIANGLE;};
51 int GetCellDimension() {return 2;};
52 int GetNumberOfEdges() {return 3;};
53 int GetNumberOfFaces() {return 0;};
54 vtkCell *GetFace(int) {return 0;};
55 int CellBoundary(int subId, float pcoords[3], vtkIdList *pts);
56 void Contour(float value, vtkDataArray *cellScalars,
57 vtkPointLocator *locator, vtkCellArray *verts,
58 vtkCellArray *lines, vtkCellArray *polys,
59 vtkPointData *inPd, vtkPointData *outPd,
60 vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd);
61 int EvaluatePosition(float x[3], float* closestPoint,
62 int& subId, float pcoords[3],
63 float& dist2, float *weights);
64 void EvaluateLocation(int& subId, float pcoords[3], float x[3],
66 int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts);
67 void Derivatives(int subId, float pcoords[3], float *values,
68 int dim, float *derivs);
71 // Clip this triangle using scalar value provided. Like contouring, except
72 // that it cuts the triangle to produce other triangles.
73 void Clip(float value, vtkDataArray *cellScalars,
74 vtkPointLocator *locator, vtkCellArray *polys,
75 vtkPointData *inPd, vtkPointData *outPd,
76 vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd,
80 // Plane intersection plus in/out test on triangle. The in/out test is
81 // performed using tol as the tolerance.
82 int IntersectWithLine(float p1[3], float p2[3], float tol, float& t,
83 float x[3], float pcoords[3], int& subId);
86 // Return the center of the triangle in parametric coordinates.
87 int GetParametricCenter(float pcoords[3]);
90 // Compute the center of the triangle.
91 static void TriangleCenter(float p1[3], float p2[3], float p3[3],
95 // Compute the area of a triangle in 3D.
96 static float TriangleArea(float p1[3], float p2[3], float p3[3]);
99 // Compute the circumcenter (center[3]) and radius (method return value) of
100 // a triangle defined by the three points x1, x2, and x3. (Note that the
101 // coordinates are 2D. 3D points can be used but the z-component will be
103 static double Circumcircle(double p1[2], double p2[2], double p3[2],
107 // Given a 2D point x[2], determine the barycentric coordinates of the point.
108 // Barycentric coordinates are a natural coordinate system for simplices that
109 // express a position as a linear combination of the vertices. For a
110 // triangle, there are three barycentric coordinates (because there are
111 // three vertices), and the sum of the coordinates must equal 1. If a
112 // point x is inside a simplex, then all three coordinates will be strictly
113 // positive. If two coordinates are zero (so the third =1), then the
114 // point x is on a vertex. If one coordinates are zero, the point x is on an
115 // edge. In this method, you must specify the vertex coordinates x1->x3.
116 // Returns 0 if triangle is degenerate.
117 static int BarycentricCoords(double x[2], double x1[2], double x2[2],
118 double x3[2], double bcoords[3]);
122 // Project triangle defined in 3D to 2D coordinates. Returns 0 if
123 // degenerate triangle; non-zero value otherwise. Input points are x1->x3;
124 // output 2D points are v1->v3.
125 static int ProjectTo2D(double x1[3], double x2[3], double x3[3],
126 double v1[2], double v2[2], double v3[2]);
129 // Compute the triangle normal from a points list, and a list of point ids
130 // that index into the points list.
131 static void ComputeNormal(vtkPoints *p, int numPts, vtkIdType *pts,
135 // Compute the triangle normal from three points.
136 static void ComputeNormal(float v1[3], float v2[3], float v3[3], float n[3]);
139 // Compute the (unnormalized) triangle normal direction from three points.
140 static void ComputeNormalDirection(float v1[3], float v2[3], float v3[3],
144 // Compute the triangle normal from three points (double-precision version).
145 static void ComputeNormal(double v1[3], double v2[3], double v3[3],
149 // Compute the (unnormalized) triangle normal direction from three points
150 // (double precision version).
151 static void ComputeNormalDirection(double v1[3], double v2[3], double v3[3],
155 // Given a point x, determine whether it is inside (within the
156 // tolerance squared, tol2) the triangle defined by the three
157 // coordinate values p1, p2, p3. Method is via comparing dot products.
158 // (Note: in current implementation the tolerance only works in the
159 // neighborhood of the three vertices of the triangle.
160 static int PointInTriangle(float x[3], float x1[3], float x2[3], float x3[3],
164 // Calculate the error quadric for this triangle. Return the
165 // quadric as a 4x4 matrix or a vtkQuadric. (from Peter
166 // Lindstrom's Siggraph 2000 paper, "Out-of-Core Simplification of
167 // Large Polygonal Models")
168 static void ComputeQuadric(float x1[3], float x2[3], float x3[3],
169 float quadric[4][4]);
170 static void ComputeQuadric(float x1[3], float x2[3], float x3[3],
171 vtkQuadric *quadric);
181 vtkTriangle(const vtkTriangle&); // Not implemented.
182 void operator=(const vtkTriangle&); // Not implemented.
185 inline int vtkTriangle::GetParametricCenter(float pcoords[3])
187 pcoords[0] = pcoords[1] = 0.333f; pcoords[2] = 0.0;
191 inline void vtkTriangle::ComputeNormalDirection(float v1[3], float v2[3],
192 float v3[3], float n[3])
194 float ax, ay, az, bx, by, bz;
196 // order is important!!! maintain consistency with triangle vertex order
197 ax = v3[0] - v2[0]; ay = v3[1] - v2[1]; az = v3[2] - v2[2];
198 bx = v1[0] - v2[0]; by = v1[1] - v2[1]; bz = v1[2] - v2[2];
200 n[0] = (ay * bz - az * by);
201 n[1] = (az * bx - ax * bz);
202 n[2] = (ax * by - ay * bx);
205 inline void vtkTriangle::ComputeNormal(float v1[3], float v2[3],
206 float v3[3], float n[3])
210 vtkTriangle::ComputeNormalDirection(v1, v2, v3, n);
212 if ( (length = static_cast<float>(sqrt((n[0]*n[0] + n[1]*n[1] + n[2]*n[2])))) != 0.0 )
220 inline void vtkTriangle::ComputeNormalDirection(double v1[3], double v2[3],
221 double v3[3], double n[3])
223 double ax, ay, az, bx, by, bz;
225 // order is important!!! maintain consistency with triangle vertex order
226 ax = v3[0] - v2[0]; ay = v3[1] - v2[1]; az = v3[2] - v2[2];
227 bx = v1[0] - v2[0]; by = v1[1] - v2[1]; bz = v1[2] - v2[2];
229 n[0] = (ay * bz - az * by);
230 n[1] = (az * bx - ax * bz);
231 n[2] = (ax * by - ay * bx);
234 inline void vtkTriangle::ComputeNormal(double v1[3], double v2[3],
235 double v3[3], double n[3])
239 vtkTriangle::ComputeNormalDirection(v1, v2, v3, n);
241 if ( (length = sqrt((n[0]*n[0] + n[1]*n[1] + n[2]*n[2]))) != 0.0 )
249 inline void vtkTriangle::TriangleCenter(float p1[3], float p2[3], float p3[3],
252 center[0] = (p1[0]+p2[0]+p3[0]) / 3.0f;
253 center[1] = (p1[1]+p2[1]+p3[1]) / 3.0f;
254 center[2] = (p1[2]+p2[2]+p3[2]) / 3.0f;
257 inline float vtkTriangle::TriangleArea(float p1[3], float p2[3], float p3[3])
260 a = vtkMath::Distance2BetweenPoints(p1,p2);
261 b = vtkMath::Distance2BetweenPoints(p2,p3);
262 c = vtkMath::Distance2BetweenPoints(p3,p1);
263 return static_cast<float>(0.25* sqrt(fabs((double)4.0*a*c - (a-b+c)*(a-b+c))));