00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdexcept>
00019 #include "vector.h"
00020 #include "linalg.h"
00021 #include "point.h"
00022 #include "tet.h"
00023 #include "tetmesh.h"
00024 #include "fmxxtopology.h"
00025
00026 namespace mesh {
00027
00028 using namespace colarray;
00029
00030 Tet::Tet(const TetMesh& mesh, id_t id, id_t corners[4], id_t material) :
00031 Entity(id), _edge_orientation(0), _material(material)
00032 {
00033
00034 for (int i = 0; i < 4; i ++)
00035 _corners[i] = corners[i];
00036
00037
00038 double volume = get_volume();
00039
00040
00041 if (1.0 + volume == 1.0)
00042 throw std::runtime_error("Tetrahedron has zero volume.");
00043
00044
00045 if (volume < 0.0)
00046 std::swap<id_t>(_corners[0], _corners[1]);
00047 }
00048
00049 void Tet::set_face_id(int i, id_t id) {
00050 _faces[i] = id;
00051 }
00052
00053 void Tet::set_edge_id(int i, id_t id) {
00054 _edges[i] = id;
00055 }
00056
00057 void Tet::set_edge_orientation(int edge_lid, bool orientation) {
00058 if (orientation)
00059 _edge_orientation |= 1 << edge_lid;
00060 else
00061 _edge_orientation &= ~(1 << edge_lid);
00062 }
00063
00064 id_t Tet::get_material_ID() const {
00065 return _material;
00066 }
00067
00068 double Tet::get_volume() const {
00069 CoordinateMatrix X(*this);
00070 return linalg::determinant(X) / 6.0;
00071 }
00072
00074 Vector3 Tet::get_center_of_gravity() const
00075 {
00076 int i;
00077 Vector3 cog(0,0,0);
00078
00079 for(i=0;i<NCORNERTET;i++)
00080 {
00081 cog+=0.25 * this->get_corner(i)->get_coord();
00082 }
00083
00084
00085 return(cog);
00086 }
00087
00088
00091 void Tet::cartesian_to_simplex(const Vector3& cartesian, Vector4& simplex) const {
00092 CoordinateMatrix X(*this);
00093 ColumnVector<double> t(3);
00094
00095 for (int i = 0; i < 4; i ++) {
00096 RowVector<double> r(X, i);
00097 Vector<double> r1(r, 1, 4);
00098 t.inject(r1);
00099 r1(0) = cartesian.x;
00100 r1(1) = cartesian.y;
00101 r1(2) = cartesian.z;
00102 simplex[i] = linalg::determinant(X) / (6.0 * get_volume());
00103 r1.inject(t);
00104 }
00105 }
00106
00107 bool Tet::is_inside(const Vector3& point) const {
00108 Vector4 simplex_coord;
00109 cartesian_to_simplex(point, simplex_coord);
00110 for (int i = 0; i < 4; i ++)
00111 if (simplex_coord[i] < 0.0)
00112 return false;
00113 for (int i = 0; i < 4; i ++)
00114 if (simplex_coord[i] > 1.0)
00115 return false;
00116 return true;
00117 }
00118
00119 bool Tet::is_inside_gracious(const Vector3& point) const {
00120 const double grace_tolerance = 1e-14;
00121 Vector4 simplex_coord;
00122
00123 cartesian_to_simplex(point, simplex_coord);
00124 for (int i = 0; i < 4; i ++)
00125 if (simplex_coord[i] < -grace_tolerance)
00126 return false;
00127 for (int i = 0; i < 4; i ++)
00128 if (simplex_coord[i] > 1.0 + grace_tolerance)
00129 return false;
00130 return true;
00131 }
00132
00133 void Tet::get_bounding_box(Vector3& center, Vector3& extent) const {
00134 Vector3 min, max, coord;
00135
00136 min = get_corner(0)->get_coord();
00137 max = min;
00138 for (int i = 1; i < 4; i ++) {
00139 coord = get_corner(i)->get_coord();
00140 min.make_floor(coord);
00141 max.make_ceil(coord);
00142 }
00143 center = max.mid_point(min);
00144 extent = 0.5 * (max - min);
00145 }
00146
00147 Tet::CoordinateMatrix::CoordinateMatrix(const Tet& tet) : colarray::Matrix<double>(4, 4) {
00148 Vector3 coord;
00149
00150 for (int i = 0; i < 4; i ++) {
00151 this->operator()(i,0) = 1.0;
00152 coord = tet.get_mesh()->get_point(tet._corners[i])->get_coord();
00153 for (int j = 0; j < 3; j ++)
00154 this->operator()(i,j+1) = coord[j];
00155 }
00156 }
00157
00158 Tet::GradientMatrix::GradientMatrix(const CoordinateMatrix& X) : colarray::Matrix<double>(3, 4) {
00159 colarray::Matrix<double> Xinv(4, 4);
00160
00161 linalg::inverse(X, Xinv);
00162
00163 this->inject(colarray::Matrix<double>(Xinv, 1, 4, 0, 4));
00164 }
00165
00166 Tet::GradientMatrix::GradientMatrix(const Tet& tet) : colarray::Matrix<double>(3, 4) {
00167 Tet::CoordinateMatrix X(tet);
00168 colarray::Matrix<double> Xinv(4, 4);
00169
00170 linalg::inverse(X, Xinv);
00171
00172 this->inject(colarray::Matrix<double>(Xinv, 1, 4, 0, 4));
00173 }
00174
00175 Point* Tet::get_corner(int i) const {
00176 return get_mesh()->get_point(get_corner_id(i));
00177 }
00178
00179 Edge* Tet::get_edge(int i) const {
00180 return get_mesh()->get_edge(get_edge_id(i));
00181 }
00182
00183 Face* Tet::get_face(int i) const {
00184 return get_mesh()->get_face(get_face_id(i));
00185 }
00186
00187 TetMesh* Tet::get_mesh() const {
00188 return TetMesh::get_instance();
00189 }
00190
00191 }