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
00026
00027
00028
00029
00030
00031 #ifndef _ELEMENT_H
00032 #define _ELEMENT_H
00033
00034 #include <cassert>
00035 #include <stdlib.h>
00036
00037 #include "Edge.h"
00038
00039 #define MINANGLE 30.0
00040
00041 class Element {
00042 Tuple coords[3];
00043
00044
00045
00046 signed char obtuse;
00047 bool bBad;
00048 bool bDim;
00049
00050 public:
00051
00052 explicit Element(const Tuple& a, const Tuple& b, const Tuple& c)
00053 :obtuse(0), bBad(0), bDim(true)
00054 {
00055 coords[0] = a;
00056 coords[1] = b;
00057 coords[2] = c;
00058 if (b < a || c < a) {
00059 if (b < c) {
00060 coords[0] = b;
00061 coords[1] = c;
00062 coords[2] = a;
00063 } else {
00064 coords[0] = c;
00065 coords[1] = a;
00066 coords[2] = b;
00067 }
00068 }
00069
00070
00071
00072 for (int i = 0; i < 3; i++) {
00073 bool ob = false, sm = false;
00074 angleCheck(i, ob, sm, MINANGLE);
00075 if (ob) {
00076 obtuse = i + 1;
00077 } else if (sm) {
00078 bBad = true;
00079 }
00080 }
00081
00082 }
00083
00084 explicit Element(const Tuple& a, const Tuple& b)
00085 :obtuse(0), bBad(0), bDim(false)
00086 {
00087 coords[0] = a;
00088 coords[1] = b;
00089 if (b < a) {
00090 coords[0] = b;
00091 coords[1] = a;
00092 }
00093
00094 }
00095
00096
00097
00098
00099
00100 Tuple getCenter() const {
00101 if (getDim() == 2) {
00102 return (coords[0] + coords[1]) * 0.5;
00103 } else {
00104 const Tuple& a = coords[0];
00105 const Tuple& b = coords[1];
00106 const Tuple& c = coords[2];
00107 Tuple x = b - a;
00108 Tuple y = c - a;
00109 double xlen = a.distance(b);
00110 double ylen = a.distance(c);
00111 double cosine = (x * y) / (xlen * ylen);
00112 double sine_sq = 1.0 - cosine * cosine;
00113 double plen = ylen / xlen;
00114 double s = plen * cosine;
00115 double t = plen * sine_sq;
00116 double wp = (plen - cosine) / (2 * t);
00117 double wb = 0.5 - (wp * s);
00118 Tuple tmpval = a * (1 - wb - wp);
00119 tmpval = tmpval + (b * wb);
00120 return tmpval + (c * wp);
00121 }
00122 }
00123
00124 double get_radius_squared() const {
00125 return get_radius_squared(getCenter());
00126 }
00127
00128 double get_radius_squared(const Tuple& center) const {
00129 return center.distance_squared(coords[0]);
00130 }
00131
00132 bool operator<(const Element& rhs) const {
00133
00134 if (getDim() < rhs.getDim()) return false;
00135 if (getDim() > rhs.getDim()) return true;
00136 for (int i = 0; i < getDim(); i++) {
00137 if (coords[i] < rhs.coords[i]) return true;
00138 else if (coords[i] > rhs.coords[i]) return false;
00139 }
00140 return false;
00141 }
00142
00144 bool isRelated(const Element& rhs) const {
00145 int num_eq = 0;
00146 for(int i = 0; i < getDim(); ++i)
00147 for(int j = 0; j < rhs.getDim(); ++j)
00148 if (coords[i] == rhs.coords[j])
00149 ++num_eq;
00150 return num_eq == 2;
00151 }
00152
00153 bool inCircle(Tuple p) const {
00154 Tuple center = getCenter();
00155 double ds = center.distance_squared(p);
00156 return ds <= get_radius_squared(center);
00157 }
00158
00159 void angleCheck(int i, bool& ob, bool& sm, double M) const {
00160 int j = (i + 1) % getDim();
00161 int k = (i + 2) % getDim();
00162 Tuple::angleCheck(coords[j], coords[i], coords[k], ob, sm, M);
00163 }
00164
00165
00166
00167 Edge getEdge(int i) const {
00168 if (!bDim) {
00169 if (i == 0)
00170 return Edge(coords[0], coords[1]);
00171 else if (i == 1)
00172 return Edge(coords[1], coords[0]);
00173 } else {
00174 if (i == 0)
00175 return Edge(coords[0], coords[1]);
00176 else if (i == 1)
00177 return Edge(coords[1], coords[2]);
00178 else if (i == 2)
00179 return Edge(coords[2], coords[0]);
00180 }
00181 assert(0 && "unknown edge");
00182 abort();
00183 }
00184
00185 const Tuple& getPoint(int i) const {
00186 return coords[i];
00187 }
00188
00189 const Tuple& getObtuse() const {
00190 return coords[obtuse-1];
00191 }
00192
00193 Edge getOppositeObtuse() const {
00194
00195
00196 switch (obtuse) {
00197 case 1:
00198 return getEdge(1);
00199 case 2:
00200 return getEdge(2);
00201 case 3:
00202 return getEdge(0);
00203 }
00204 assert(0 && "no obtuse edge");
00205 abort();
00206 }
00207
00208
00209 bool isBad() const {
00210 return bBad;
00211 }
00212
00213 int getDim() const {
00214 return bDim ? 3 : 2;
00215 }
00216
00217 int numEdges() const {
00218 return getDim() + getDim() - 3;
00219 }
00220
00221 bool isObtuse() const {
00222 return obtuse != 0;
00223 }
00224
00229 Edge getRelatedEdge(const Element& e) const {
00230 int at = 0;
00231 Tuple d[2];
00232 for(int i = 0; i < getDim(); ++i)
00233 for(int j = 0; j < e.getDim(); ++j)
00234 if (coords[i] == e.coords[j])
00235 d[at++] = coords[i];
00236 assert(at == 2);
00237 return Edge(d[0], d[1]);
00238 }
00239
00240 std::ostream& print(std::ostream& s) const {
00241 s << '[';
00242 for (int i = 0; i < getDim(); ++i)
00243 s << coords[i] << (i < (getDim() - 1) ? ", " : "");
00244 s << ']';
00245 return s;
00246 }
00247
00248 };
00249
00250 static std::ostream& operator<<(std::ostream& s, const Element& E) {
00251 return E.print(s);
00252 }
00253
00254 #endif