1 #ifndef SimTK_SIMMATH_GEO_TRIANGLE_H_
2 #define SimTK_SIMMATH_GEO_TRIANGLE_H_
3 
4 /* -------------------------------------------------------------------------- *
5  *                        Simbody(tm): SimTKmath                              *
6  * -------------------------------------------------------------------------- *
7  * This is part of the SimTK biosimulation toolkit originating from           *
8  * Simbios, the NIH National Center for Physics-Based Simulation of           *
9  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
10  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody.  *
11  *                                                                            *
12  * Portions copyright (c) 2011-12 Stanford University and the Authors.        *
13  * Authors: Michael Sherman                                                   *
14  * Contributors:                                                              *
15  *                                                                            *
16  * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
17  * not use this file except in compliance with the License. You may obtain a  *
18  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
19  *                                                                            *
20  * Unless required by applicable law or agreed to in writing, software        *
21  * distributed under the License is distributed on an "AS IS" BASIS,          *
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
23  * See the License for the specific language governing permissions and        *
24  * limitations under the License.                                             *
25  * -------------------------------------------------------------------------- */
26 
27 /** @file
28 Defines primitive operations on triangles. **/
29 
30 #include "SimTKcommon.h"
31 #include "simmath/internal/common.h"
32 #include "simmath/internal/Geo.h"
33 #include "simmath/internal/Geo_Point.h"
34 #include "simmath/internal/Geo_LineSeg.h"
35 
36 #include <cassert>
37 #include <cmath>
38 #include <algorithm>
39 
40 namespace SimTK {
41 
42 //==============================================================================
43 //                              GEO TRIANGLE
44 //==============================================================================
45 /** A geometric primitive representing a triangle by its vertices as points
46 in some unspecified frame, and a collection of triangle-related utility
47 methods. We support a u-v barycentric parameterization for the triangle. **/
48 template <class P>
49 class Geo::Triangle_ {
50 typedef P               RealP;
51 typedef Vec<2,P>        Vec2P;
52 typedef Vec<3,P>        Vec3P;
53 typedef UnitVec<P,1>    UnitVec3P;
54 public:
55 /** Construct an uninitialized Triangle object; the vertices will
56 be garbage. **/
Triangle_()57 Triangle_() {}
58 /** Construct a triangle from its vertices. **/
Triangle_(const Vec3P & v0,const Vec3P & v1,const Vec3P & v2)59 Triangle_(const Vec3P& v0, const Vec3P& v1, const Vec3P& v2)
60 {  setVertices(v0,v1,v2); }
61 /** Construct a triangle from vertices stored in array which is presumed
62 to contain at least three points. **/
Triangle_(const Vec3P * vertices)63 explicit Triangle_(const Vec3P* vertices)
64 {   setVertices(vertices); }
65 /** Construct a triangle from an indirect list of vertices stored in array
66 which is presumed to contain at least three pointers to points. **/
Triangle_(const Vec3P ** vertexPointers)67 explicit Triangle_(const Vec3P** vertexPointers)
68 {   setVertices(*vertexPointers[0], *vertexPointers[1], *vertexPointers[2]); }
69 
70 /** Change one vertex of this triangle. **/
setVertex(int i,const Vec3P & p)71 Triangle_& setVertex(int i, const Vec3P& p)
72 {   assert(0<=i && i<3); v[i] = p; return *this; }
73 /** Change the vertices of this triangle. **/
setVertices(const Vec3P & v0,const Vec3P & v1,const Vec3P & v2)74 Triangle_& setVertices(const Vec3P& v0, const Vec3P& v1, const Vec3P& v2)
75 {   v[0]=v0; v[1]=v1; v[2]=v2; return *this; }
76 /** Change the vertices of this triangle, taking the new ones from an array
77 which is presumed to contain at least three points. **/
setVertices(const Vec3P * vertices)78 Triangle_& setVertices(const Vec3P* vertices)
79 {   v[0]=vertices[0]; v[1]=vertices[1]; v[2]=vertices[2]; return *this; }
80 
81 /** Access a vertex by index.\ Order is the same as construction. You can use
82 operator[] instead for a more compact notation. **/
getVertex(int i)83 const Vec3P& getVertex(int i) const
84 {   SimTK_INDEXCHECK(i,3,"Geo::Triangle_::getVertex()");
85     return v[i]; }
86 /** Get writable access to a vertex by index.\ Order is the same as
87 construction. You can use operator[] instead for a more compact notation.**/
updVertex(int i)88 Vec3P& updVertex(int i)
89 {   SimTK_INDEXCHECK(i,3,"Geo::Triangle_::updVertex()");
90     return v[i]; }
91 
92 /** Access a vertex by indexing the triangle. **/
93 const Vec3P& operator[](int i) const {return getVertex(i);}
94 /** Get writable access to a vertex by indexing the triangle. **/
95 Vec3P& operator[](int i) {return updVertex(i);}
96 
97 /** Return a LineSeg_ containing an edge of this triangle, with edges numbered
98 in a counterclockwise direction so that edge0 is v0v1, edge1 is v1v2, and
99 edge2 is v2v0. **/
getEdge(int i)100 LineSeg_<P> getEdge(int i) const
101 {   SimTK_INDEXCHECK(i,3,"Geo::Triangle_::getEdge()");
102     return LineSeg_<P>(v[i],v[(i+1)%3]); }
103 
104 /** Return a point on the triangle's face given by its (u,v) coordinates.
105 Cost is 17 flops. **/
findPoint(const Vec2P & uv)106 Vec3P findPoint(const Vec2P& uv) const
107 {   return uv[0]*v[0] + uv[1]*v[1] + (1-uv[0]-uv[1])*v[2]; }
108 
109 /** Return the centroid point on the triangle's face; this is the same as
110 findPoint(1/3,1/3) but faster. Cost is 9 flops. **/
findCentroid()111 Vec3P findCentroid() const
112 {   return (v[0]+v[1]+v[2]) / RealP(3); }
113 
114 /** Calculate the unit normal to the triangle face taking the vertices in
115 counterclockwise order. Cost is about 50 flops. **/
calcUnitNormal()116 UnitVec3P calcUnitNormal() const
117 {   return UnitVec3P((v[1]-v[0]) % (v[2]-v[0])); }
118 
119 /** Calculate the smallest bounding sphere enclosing the three vertices of
120 this triangle. We guarantee that no vertex is outside the sphere, but for
121 numerical reasons it is possible for the sphere to be a little too big. **/
calcBoundingSphere()122 Sphere_<P> calcBoundingSphere() const
123 {   return Geo::Point_<P>::calcBoundingSphere(v[0],v[1],v[2]); }
124 
125 /** Return the area of this triangle. Cost is about 40 flops. **/
calcArea()126 RealP calcArea() const
127 {   return ((v[1]-v[0]) % (v[2]-v[0])).norm() / 2; }
128 
129 /** Return the square of the area of this triangle. Cost is 23 flops. **/
calcAreaSqr()130 RealP calcAreaSqr() const
131 {   return ((v[1]-v[0]) % (v[2]-v[0])).normSqr() / 4; }
132 
133 /** Given a location in space, find the point of this triangular face that
134 is closest to that location. If the answer is not unique then one of the
135 equidistant points is returned. **/
findNearestPoint(const Vec3P & position,Vec2P & uv)136 Vec3P findNearestPoint(const Vec3P& position, Vec2P& uv) const
137 {SimTK_ASSERT_ALWAYS(!"implemented",
138 "Geo::Triangle_::findNearestPoint(): Not implemented yet.");
139 return Vec3P();}
140 
141 /** Determine whether a given ray intersects this triangle. TODO: is a
142 perfect hit on the boundary an intersection? **/
intersectsRay(const Vec3P & origin,const UnitVec3P & direction,RealP & distance,Vec2P & uv)143 bool intersectsRay(const Vec3P& origin, const UnitVec3P& direction,
144                    RealP& distance, Vec2P& uv) const
145 {SimTK_ASSERT_ALWAYS(!"implemented",
146 "Geo::Triangle_::intersectsRay(): Not implemented yet."); return false;}
147 
148 /** Determine yes/no whether this triangle overlaps another one. Note that
149 exactly touching is not overlapping. **/
150 SimTK_SIMMATH_EXPORT bool overlapsTriangle(const Triangle_<P>& other) const;
151 /** Determine whether this triangle intersects another one, and if so then
152 if they are not coplanar return the line segment representing their
153 intersection. If the triangles are coplanar and intersect we'll return true
154 and set \a isCoplanar true, but not return a line segment. Note that the
155 triangles may meet at a point so the line segment may be degenerate in any
156 case. **/
157 SimTK_SIMMATH_EXPORT bool intersectsTriangle(const Triangle_<P>& other, LineSeg_<P>& seg,
158                         bool& isCoplanar) const;
159 
160 /**@name                 Triangle-related utilities
161 These static methods work with triangles or collections of triangles. **/
162 /**@{**/
163 
164 /**@}**/
165 
166 private:
167 // Vertices in the order they were supplied in the constructor.
168 Vec3P   v[3];
169 };
170 
171 } // namespace SimTK
172 
173 #endif // SimTK_SIMMATH_GEO_TRIANGLE_H_
174