00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef _GFX_TRIANGLE3_
00026 #define _GFX_TRIANGLE3_
00027
00028 #include <gfx/gfx>
00029
00030 #include <base/Transform>
00031 #include <gfx/Segment3>
00032
00033 #include <iostream>
00034
00035
00036 namespace gfx {
00037
00038
00039 class Triangle3
00040 {
00041
00042 public:
00043 Triangle3() {}
00044 Triangle3(const Triangle3& t) : _p1(t._p1), _p2(t._p2), _p3(t._p3) {}
00045 Triangle3(const Point3& p1, const Point3& p2, const Point3& p3)
00046 : _p1(p1), _p2(p2), _p3(p3) {}
00047
00048 virtual ~Triangle3() {}
00049
00050 const Point3& operator[](Int i) const throw() { return e(i); }
00051 const Point3& operator()(Int i) const throw() { return e(i-1); }
00052
00053 virtual const Point3& p1() const { return _p1; }
00054 virtual const Point3& p2() const { return _p2; }
00055 virtual const Point3& p3() const { return _p3; }
00056 virtual void setp1(const Point3& p) { _p1=p; }
00057 virtual void setp2(const Point3& p) { _p2=p; }
00058 virtual void setp3(const Point3& p) { _p3=p; }
00059
00060
00061 virtual const Point3& e(Int i) const throw()
00062 {
00063 #ifdef DEBUG
00064 if ((i < 0) || (i > 2))
00065 throw std::out_of_range("vertex index out of bounds (debug check only)");
00066 #endif
00067 return (i==0)?_p1:((i==1)?_p2:_p3);
00068 }
00069
00070 const Point3& at(Int i) const throw(std::out_of_range)
00071 {
00072 if ((i < 0) || (i > 2))
00073 throw std::out_of_range("vertex index out of bounds");
00074
00075 return e(i);
00076 }
00077
00078
00079 Triangle3& operator=(const Triangle3& src) throw()
00080 {
00081 if (&src != this) {
00082 setp1(src.p1()); setp2(src.p2()); setp3(src.p3());
00083 }
00084 return *this;
00085 }
00086
00087
00088 bool operator==(const Triangle3& t) const throw()
00089 {
00090 if (&t == this) return true;
00091
00092 return ((p1()==t.p1())&&(p2()==t.p2())&&(p3()==t.p3()));
00093 }
00094
00095 bool equals(const Triangle3& t) const throw()
00096 {
00097 if (&t == this) return true;
00098
00099 return (p1().equals(t.p1()) && p2().equals(t.p2()) && p3().equals(t.p3()));
00100 }
00101
00102
00103 Vector3 normal() const throw()
00104 {
00105 Vector3 u12 = p2()-p1();
00106 Vector3 u13 = p3()-p1();
00107 Vector3 norm = cross(u12,u13);
00108 norm.normalize();
00109 return norm;
00110 }
00111
00112 Triangle3& operator+=(const Vector3& v)
00113 { setp1(p1()+v); setp2(p2()+v); setp3(p3()+v); return *this; }
00114
00115 Triangle3& operator-=(const Vector3& v)
00116 { setp1(p1()-v); setp2(p2()-v); setp3(p3()-v); return *this; }
00117
00118 Triangle3& operator*=(Real s) { _p1*=s; _p2*=s; _p3*=s; return *this; }
00119 Triangle3& operator/=(Real s) { _p1/=s; _p2/=s; _p3/=s; return *this; }
00120
00121
00122 void transform(const base::Transform& t)
00123 {
00124 setp1(t*p1());
00125 setp2(t*p2());
00126 setp3(t*p3());
00127 }
00128
00129
00130
00131 Real distanceTo(const Point3& p) const;
00132
00133
00134 Point3 pointClosestTo(const Point3& p) const;
00135
00136 bool contains(const Point3& p) const
00137 { return Math::equals(distanceTo(p),0); }
00138
00139
00140 Segment3 shortestSegmentBetween(const Segment3& s) const
00141 { Real ds; return shortestSegmentBetween(s,ds); }
00142
00143
00144 Segment3 shortestSegmentBetween(const Triangle3& t) const;
00145
00146
00147 Real distanceTo(const Segment3& s) const
00148 { Real ds; shortestSegmentBetween(s,ds); return Math::sqrt(ds); }
00149
00150
00151 Real distanceTo(const Triangle3& t) const;
00152
00153
00154
00155 bool intersect(const Triangle3& t) const;
00156
00157 class Contact
00158 {
00159 public:
00160 enum ContactType { None, Point, Segment, Triangle, Quad };
00161
00162 ContactType type;
00163 Point3& point;
00164 Segment3& segment;
00165 Triangle3& triangle;
00166
00167 Real depth;
00168 };
00169
00170
00171
00172 bool contact(const Triangle3& t, Contact& contact) const;
00173
00174
00175 protected:
00176 Point3 _p1, _p2, _p3;
00177
00178 Segment3 shortestSegmentBetween(const Segment3& seg, Real& ds) const;
00179
00180 };
00181
00182
00183
00184
00185 inline std::ostream& operator<<(std::ostream& out, const Triangle3& t)
00186 { return out << "(" << t.p1() << "," << t.p2() << "," << t.p3() << ")"; }
00187
00188
00189 }
00190
00191 #endif