1 Star 0 Fork 0

吃瓜群众/MarchTet

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
MarchTet.h 8.11 KB
一键复制 编辑 原始数据 按行查看 历史
吃瓜群众 提交于 2024-03-11 17:29 . add test and report
#pragma once
#include <algorithm>
#include <ostream>
class TetIntersectMgr
{
private:
/* Definition of the tetrahedra */
double p[4][3]; // Vertex coordinate
double v[4]; // Vertex value
/* Description of the intersected surface */
int sp_surf; // Shape
double pnt_surf[4][3]; // Vertex coordinate
int loc_surf[4][2]; // Vertex location
/* Description of the remaining element below the intersected surface */
int sp_vol; // Shape
int idx_vol; // Cell index in the mesh
double pnt_vol[6][3]; // Vertex coordinate
int face_vol[5][4]; // Face composition of vertexes
public:
TetIntersectMgr()
{
reset();
}
double *coordinate(int idx)
{
return p[idx];
}
double value(int idx) const
{
return v[idx];
}
void reset()
{
for (int i = 0; i < 4; i++)
{
v[i] = 0.0;
for (int j = 0; j < 3; j++)
p[i][j] = 0.0;
}
sp_surf = -1;
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 2; j++)
loc_surf[i][j] = 0;
for (int j = 0; j < 3; j++)
pnt_surf[i][j] = 0.0;
}
sp_vol = -1;
for (int i = 0; i < 6; i++)
for (int j = 0; j < 3; j++)
pnt_vol[i][j] = 0.0;
}
int set_coordinate(int idx, double x_, double y_, double z_)
{
if (idx < 0 || idx >= 4)
return 1;
p[idx][0] = x_;
p[idx][1] = y_;
p[idx][2] = z_;
return 0;
}
void set_all_coordinate(const double *p0, const double *p1, const double *p2, const double *p3)
{
copy_coordinate(p0, p[0]);
copy_coordinate(p1, p[1]);
copy_coordinate(p2, p[2]);
copy_coordinate(p3, p[3]);
}
int set_value(int idx, double val_)
{
if (idx < 0 || idx > 3)
return 1;
v[idx] = val_;
return 0;
}
void set_all_value(double val0, double val1, double val2, double val3)
{
v[0] = val0;
v[1] = val1;
v[2] = val2;
v[3] = val3;
}
void set_all_value(const double *v_)
{
std::copy(v_, v_+4, v);
}
int set_coordinate_and_value(int idx, double x_, double y_, double z_, double val_)
{
if (idx < 0 || idx > 3)
return 1;
p[idx][0] = x_;
p[idx][1] = y_;
p[idx][2] = z_;
v[idx] = val_;
return 0;
}
int intersect()
{
int err = 0;
const int st = value_state();
switch (st)
{
case 0b0000: // -,-,-,- : all negative
case 0b1111: // +,+,+,+ : all positive
sp_surf = 0;
sp_vol = 0;
break;
case 0b0001: // -,-,-,+ : only one positive, triangle
case 0b1110: // +,+,+,- : only one negative, triangle
err = get_tri(3, 2, 1, 0);
break;
case 0b0010: // -,-,+,- : only one positive, triangle
case 0b1101: // +,+,-,+ : only one negative, triangle
err = get_tri(2, 1, 3, 0);
break;
case 0b0100: // -,+,-,- : only one positive, triangle
case 0b1011: // +,-,+,+ : only one negative, triangle
err = get_tri(1, 0, 3, 2);
break;
case 0b1000: // +,-,-,- : only one positive, triangle
case 0b0111: // -,+,+,+ : only one negative, triangle
err = get_tri(0, 3, 1, 2);
break;
case 0b0011: // -,-,+,+ : two positive & two negative, quadrilateral
case 0b1100: // +,+,-,- : two positive & two negative, quadrilateral
err = get_quad(2, 3, 1, 0);
break;
case 0b0101: // -,+,-,+ : two positive & two negative, quadrilateral
case 0b1010: // +,-,+,- : two positive & two negative, quadrilateral
err = get_quad(1, 3, 0, 2);
break;
case 0b0110: // -,+,+,- : two positive & two negative, quadrilateral
case 0b1001: // +,-,-,+ : two positive & two negative, quadrilateral
err = get_quad(1, 2, 3, 0);
break;
default:
sp_surf = -1;
sp_vol = -1;
err = 1;
break;
}
return err;
}
int report(std::ostream &out)
{
out << "Tetrahedra:" << std::endl;
for (int i = 0; i < 4; i++)
out << "[" << i << "]: p=(" << p[i][0] << ", " << p[i][1] << ", " << p[i][2] << "), v=" << v[i] << std::endl;
out << "Interface: ";
if (sp_surf == 3)
out << "TRI" << std::endl;
else if (sp_surf == 4)
out << "QUAD" << std::endl;
else
{
out << "ERR (" << sp_surf << ")" << std::endl;
return 1;
}
for (int i = 0; i < sp_surf; i++)
out << "[" << i << "]: (" << pnt_surf[i][0] << ", " << pnt_surf[i][1] << ", " << pnt_surf[i][2] << "), {" << loc_surf[i][0] << ", " << loc_surf[i][1] << "}" << std::endl;
out << "Remaining element: ";
if (sp_vol == 4)
out << "TET" << std::endl;
else if (sp_vol == 6)
out << "PRISM" << std::endl;
else
{
out << "ERR (" << sp_vol << ")" << std::endl;
return 2;
}
for (int i = 0; i < sp_vol; i++)
out << "N[" << i << "]: (" << pnt_vol[i][0] << ", " << pnt_vol[i][1] << ", " << pnt_vol[i][2] << ")" << std::endl;
return 0;
}
private:
static void copy_coordinate(const double *src, double *dst)
{
std::copy(src, src+3, dst);
}
int value_state() const
{
const int sign[4] = {
v[0] > 0.0 ? 1 : 0,
v[1] > 0.0 ? 1 : 0,
v[2] > 0.0 ? 1 : 0,
v[3] > 0.0 ? 1 : 0
};
const int st = (sign[0] << 3) | (sign[1] << 2) | (sign[2] << 1) | (sign[3]);
return st;
}
// Calculate the ratio that gives the linear interpolation value f between f1 and f2
static double calcInterpParam(double f, double f1, double f2)
{
return (f - f1) / (f2 - f1);
}
static void interpVec(const double *pa, const double *pb, double t, double *p)
{
p[0] = (1.0 - t) * pa[0] + t * pb[0];
p[1] = (1.0 - t) * pa[1] + t * pb[1];
p[2] = (1.0 - t) * pa[2] + t * pb[2];
}
int get_tri(int iv0, int iv1, int iv2, int iv3)
{
sp_surf = 3;
// Get the ratio for the intersected values in the edges
const double t01 = calcInterpParam(0.0, v[iv0], v[iv1]);
const double t02 = calcInterpParam(0.0, v[iv0], v[iv2]);
const double t03 = calcInterpParam(0.0, v[iv0], v[iv3]);
// Interpolate values and get the triangle vertices
interpVec(p[iv0], p[iv1], t01, pnt_surf[0]); loc_surf[0][0] = iv0; loc_surf[0][1] = iv1;
interpVec(p[iv0], p[iv2], t02, pnt_surf[1]); loc_surf[1][0] = iv0; loc_surf[1][1] = iv2;
interpVec(p[iv0], p[iv3], t03, pnt_surf[2]); loc_surf[2][0] = iv0; loc_surf[2][1] = iv3;
// Determine the shape of the remaining volume
if (v[iv0] > 0)
{
/* Prism */
sp_vol = 6;
copy_coordinate(p[iv1], pnt_vol[0]);
copy_coordinate(p[iv2], pnt_vol[1]);
copy_coordinate(p[iv3], pnt_vol[2]);
copy_coordinate(pnt_surf[0], pnt_vol[3]);
copy_coordinate(pnt_surf[1], pnt_vol[4]);
copy_coordinate(pnt_surf[2], pnt_vol[5]);
}
else
{
/* Tet */
sp_vol = 4;
copy_coordinate(p[iv0], pnt_vol[0]);
copy_coordinate(pnt_surf[0], pnt_vol[1]);
copy_coordinate(pnt_surf[1], pnt_vol[2]);
copy_coordinate(pnt_surf[2], pnt_vol[3]);
}
return 0;
}
int get_quad(int iv0, int iv1, int iv2, int iv3)
{
sp_surf = 4;
// Get the ratio for the intersected values in the edges
const double t02 = calcInterpParam(0.0, v[iv0], v[iv2]);
const double t21 = calcInterpParam(0.0, v[iv2], v[iv1]);
const double t13 = calcInterpParam(0.0, v[iv1], v[iv3]);
const double t30 = calcInterpParam(0.0, v[iv3], v[iv0]);
// Interpolate values and get the triangle vertices
interpVec(p[iv0], p[iv2], t02, pnt_surf[0]); loc_surf[0][0] = iv0; loc_surf[0][1] = iv2;
interpVec(p[iv2], p[iv1], t21, pnt_surf[1]); loc_surf[1][0] = iv2; loc_surf[1][1] = iv1;
interpVec(p[iv1], p[iv3], t13, pnt_surf[2]); loc_surf[2][0] = iv1; loc_surf[2][1] = iv3;
interpVec(p[iv3], p[iv0], t30, pnt_surf[3]); loc_surf[3][0] = iv3; loc_surf[3][1] = iv0;
// Determine the shape of the remaining volume
sp_vol = 6; /* Prism */
if (v[iv0] > 0)
{
copy_coordinate(pnt_surf[0], pnt_vol[0]);
copy_coordinate(pnt_surf[1], pnt_vol[1]);
copy_coordinate(p[iv2], pnt_vol[2]);
copy_coordinate(pnt_surf[3], pnt_vol[3]);
copy_coordinate(pnt_surf[2], pnt_vol[4]);
copy_coordinate(p[iv3], pnt_vol[5]);
}
else
{
copy_coordinate(pnt_surf[3], pnt_vol[0]);
copy_coordinate(p[iv0], pnt_vol[1]);
copy_coordinate(pnt_surf[0], pnt_vol[2]);
copy_coordinate(pnt_surf[2], pnt_vol[3]);
copy_coordinate(p[iv1], pnt_vol[5]);
copy_coordinate(pnt_surf[1], pnt_vol[4]);
}
return 0;
}
};
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/jiangyouyige/march-tet.git
git@gitee.com:jiangyouyige/march-tet.git
jiangyouyige
march-tet
MarchTet
master

搜索帮助

0d507c66 1850385 C8b1a773 1850385