4 Star 2 Fork 3

大工格智/tetgen

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
tetgenext.cxx 46.42 KB
一键复制 编辑 原始数据 按行查看 历史
MeshSmith 提交于 2022-02-12 14:11 . dev: support "meshSizeMax"
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377
#include "tetgenext.h"
#if defined(_WIN32)
#include <Windows.h>
#endif
namespace TETGEN_EXT {
void DebugBDF(std::ostream& out, size_t nnode, size_t nelem,
std::function<bool(size_t i, int32_t &nid, double *pos)> nodeFun,
std::function<bool(size_t i, int32_t &elemId, int32_t &group, int32_t &, int32_t *nodes)> elemFun)
{
auto double2Char16 = [&](double val, char* buffer)
{
sprintf(buffer, "%16.16lf", val);
buffer[15] = '\0';
return buffer;
};
auto BdfPrintNodeLong = [&](int id, double x, double y, double z, char* strBuffer)
{
char bufx[32], bufy[32], bufz[32];
sprintf(strBuffer, "%-16s%8d%-16s%-16s%-16s%-1s\n%-8s%-16s\n", "GRID*", id, "",
double2Char16(x, bufx), double2Char16(y, bufy), "*", "*", double2Char16(z, bufz));
};
auto WriteElementBdf = [&](std::ostream& out, int id, int tp, int gp, const int* nodes0, int nid_offset)
{
out.setf(std::ios::left);
int num = tp % 100;
int nodes[20];
if (gp == 0)
gp = tp;
memcpy(nodes, nodes0, num * sizeof(int));
if (tp == 203)
{
out << "CTRIA3 " << std::setw(8) << id << std::setw(8) << gp;
}
else if (tp == 204)
{
out << "CQUAD4 " << std::setw(8) << id << std::setw(8) << gp;
}
else if (tp == 304)
{
out << "CTETRA " << std::setw(8) << id << std::setw(8) << gp;
}
else if (tp == 308)
{
out << "CHEXA " << std::setw(8) << id << std::setw(8) << gp;
}
else if (tp == 306)
{
out << "CPENTA " << std::setw(8) << id << std::setw(8) << gp;
}
else if (tp == 305)
{
//out << "CPYRA " << std::setw(8) << id << std::setw(8) << gp;
out << "CHEXA " << std::setw(8) << id << std::setw(8) << gp;
tp = 308;
nodes[7] = nodes[6] = nodes[5] = nodes[4];
num = 8;
}
else if (tp == 102)
{
if (gp == 0)
gp = 1;
// out<< "PLOTEL "<<std::setw(8)<<id;
out << "CBAR " << std::setw(8) << id << std::setw(8) << gp;
// out<< "PLOTEL "<<","<<id;
}
if (num > 0)
{
int ncount = 0;
int jfield = 0;
// first line
for (jfield = 4; jfield <= 9; jfield++)
{
ncount++;
if (ncount > num) break;
out << std::setw(8) << nodes[ncount - 1] + nid_offset;
}
out << std::endl;
// following lines
while (ncount < num)
{
out << std::setw(8) << "+";
for (jfield = 2; jfield <= 9; jfield++)
{
ncount++;
if (ncount > num) break;
out << std::setw(8) << nodes[ncount - 1] + nid_offset;
}
out << std::endl;
}
} // if (num>0)
};
auto BdfPrintNodeLong2 = [&](int id, double x, double y, double z, std::ostream& out)
{
/*out << "GRID," << id << ",,"
<< boost::str(boost::format("%1$g") % x) << ","
<< boost::str(boost::format("%1$g") % y) << ","
<< boost::str(boost::format("%1$g") % z) << std::endl;*/
char strBuffer[1024];
BdfPrintNodeLong(id, x, y, z, strBuffer);
out << strBuffer;
};
int32_t nid, elemId, group, type, nodes[20];
double pos[3];
for (size_t i = 0; i < nnode; i++) {
if (!nodeFun(i, nid, pos)) {
continue;
}
BdfPrintNodeLong2(nid, pos[0], pos[1], pos[2], out);
}
for (size_t i = 0; i < nelem; i++) {
if (!elemFun(i, elemId, group, type, nodes)) {
continue;
}
WriteElementBdf(out, elemId, type, group, nodes, 0);
}
}
void DebugBDF(const std::string & fn, size_t nnode, size_t nelem,
std::function<bool(size_t i, int32_t &, double *)> nodeFun,
std::function<bool(size_t i, int32_t &, int32_t &, int32_t &, int32_t *)> elemFun)
{
std::ofstream out(fn);
DebugBDF(out, nnode, nelem, nodeFun, elemFun);
}
void DebugBdf(const tetgenio& out, const char* fn, const std::vector<int>* flagTet, bool asGroupId = false)
{
DebugBDF(fn, out.numberofpoints, out.numberoftetrahedra + out.numberoffacets, [&out](size_t i, int32_t& nid, double* pos) {
nid = (int32_t)i + 1;
memcpy(pos, out.pointlist + i * 3, 3 * sizeof(double));
return true;
}, [&](size_t i, int32_t& elemId, int32_t& group, int32_t&type, int32_t* nodes) {
elemId = (int32_t)i + 1;
if (i < out.numberoftetrahedra)
{
type = 304;
group = type;
auto tet = out.tetrahedronlist + i * 4;
nodes[0] = tet[0] + 1;
nodes[1] = tet[1] + 1;
nodes[2] = tet[2] + 1;
nodes[3] = tet[3] + 1;
if (flagTet)
{
if (asGroupId)
{
group = flagTet->at(i);
}
else if (flagTet->at(i) < 0) {
group *= 10;
}
}
}
else
{
type = 203;
group = type;
i -= out.numberoftetrahedra;
const auto& p = out.facetlist[i].polygonlist[0];
nodes[0] = p.vertexlist[0] + 1;
nodes[1] = p.vertexlist[1] + 1;
nodes[2] = p.vertexlist[2] + 1;
}
return true;
});
}
static double GetMaxSize(Json::Value& meshCtrl)
{
if (meshCtrl.isMember("meshSizeMax")) {
double dfmax;
std::stringstream ss2;
ss2 << meshCtrl["meshSizeMax"].asString();
ss2 >> dfmax;
return dfmax;
}
return -1.0;
}
static std::string Convert2TetGenCommand(Json::Value& meshCtrl, unsigned nInputTet = 0)
{
/*
-p Tetrahedralizes a piecewise linear complex (PLC).
-Y Preserves the input surface mesh (does not modify it).
-r Reconstructs a previously generated mesh.
-q Refines mesh (to improve mesh quality).
-R Mesh coarsening (to reduce the mesh elements).
-A Assigns attributes to tetrahedra in different regions.
-a Applies a maximum tetrahedron volume constraint.
-m Applies a mesh sizing function.
-i Inserts a list of additional points.
-O Specifies the level of mesh optimization.
-S Specifies maximum number of added points.
-T Sets a tolerance for coplanar test (default 10−8).
-X Suppresses use of exact arithmetic.
-M No merge of coplanar facets or very close vertices.
-w Generates weighted Delaunay (regular) triangulation.
-c Retains the convex hull of the PLC.
-d Detects self-intersections of facets of the PLC.
-z Numbers all output items starting from zero.
-f Outputs all faces to .face file.
-e Outputs all edges to .edge file.
-n Outputs tetrahedra neighbors to .neigh file.
-v Outputs Voronoi diagram to files.
-g Outputs mesh to .mesh file for viewing by Medit.
-k Outputs mesh to .vtk file for viewing by Paraview.
-J No jettison of unused vertices from output .node file.
-B Suppresses output of boundary information.
-N Suppresses output of .node file.
-E Suppresses output of .ele file.
-F Suppresses output of .face and .edge file.
-I Suppresses mesh iteration numbers.
-C Checks the consistency of the final mesh.
-Q Quiet: No terminal output except errors.
-V Verbose: Detailed information, more terminal output.
-h Help: A brief instruction for using TetGen.
*/
std::stringstream ss;
if (meshCtrl.isMember("initialDelaunaySimple")) {
ss << "pn";
return ss.str();
}
ss << "Ypni";
//ss << "pni"; //for tetrefine.
if (meshCtrl.empty()) {
ss << "q1.2CC";
return ss.str();
}
double dfmax = GetMaxSize(meshCtrl);
if (dfmax > 1.e-10) {
dfmax *= 1.4;
double volMax = dfmax * dfmax*dfmax*0.118;
ss << "a" << volMax;
}
if (meshCtrl.isMember("convexHull")) {
ss << "c";
return ss.str();
}
else if (meshCtrl.isMember("initialDelaunay")) {
Json::Value optCtrl = meshCtrl["initialDelaunay"];
if (optCtrl.isMember("removeSteiners")) {
ss << "R";
}
else if (optCtrl.isMember("removeSteiners4BL"))
{
ss << "R";
ss << "Y///1";
}
}
else if (meshCtrl.isMember("optimize")) {
if (nInputTet > 0)
ss << "r";
Json::Value optCtrl = meshCtrl["optimize"];
if (optCtrl.isMember("operationFlag")) {
int flag = optCtrl["operationFlag"].asInt();
if (flag > 0) {
ss << "O2/" << flag;
}
}
if (optCtrl.isMember("dihedralAngle")) {
double val = optCtrl["dihedralAngle"].asDouble();
if (val > 90) {
ss << "o/" << val;
}
}
double reR = 1.414, daM = 0;
if (optCtrl.isMember("RERatio")) {
double val = optCtrl["RERatio"].asDouble();
if (val > 0) {
reR = val;
}
}
if (optCtrl.isMember("dihedralAngleMin")) {
double val = optCtrl["dihedralAngleMin"].asDouble();
if (val < 90) {
daM = val;
}
}
ss << "q" << reR << "/" << daM;
return ss.str();
}
else {
ss << "q1.2CC";
return ss.str();
}
return ss.str();
}
bool ReadBdfAndWriteJson(const std::string &fn, const std::string & fnout)
{
using namespace std;
auto getblock = [](const std::string& str, int which, int length, std::stringstream& sstr)
{//创建输入流sstr
std::string block;
block = str.substr(8 * which, 8 * length);//substr()返回本字符串的一个子串,从index开始,长num个字符。
sstr.str(block);
};
typedef struct Node_
{
size_t id;
double xyz[3];
}Node;
typedef struct Elem_
{
size_t id;
int type;
int nodes[8];
int geoId;
}Cell;
size_t Nnodes = 0, Ntris = 0, Nquads = 0, Ntets;
vector<Node> nodes_in;
vector<Cell> elems_in;
vector<double> nodes;
vector<int> tris;
vector<int> quads;
vector<int> tets;
ifstream inf(fn.c_str());
if (!inf)
{
std::cout << "input error in bdfrw" << std::endl;
return false;
}
string block;
string buf;
stringstream sstr;
std::set<int> ids;
while (inf.eof() == false)
{
sstr.str("");
sstr.clear();
getline(inf, buf);
getblock(buf, 0, 1, sstr);
block.clear();
sstr >> block;
/* cout<<block<<endl;*/
if (block == "GRID*")
{
Node newN;
sstr.str("");
sstr.clear();
getblock(buf, 1, 2, sstr);
sstr >> newN.id;
{
sstr.str("");
sstr.clear();
getblock(buf, 5, 2, sstr);
sstr >> newN.xyz[0];
if (sstr.eof() == false)
{
int a = 0;
sstr >> a;
if (a < 0)
newN.xyz[0] = std::pow(10, a)*newN.xyz[0];
}
sstr.str("");
sstr.clear();
getblock(buf, 7, 2, sstr);
sstr >> newN.xyz[1];
if (sstr.eof() == false)
{
int a = 0;
sstr >> a;
if (a < 0)
newN.xyz[1] = std::pow(10, a)*newN.xyz[1];
}
sstr.str("");
sstr.clear();
getline(inf, buf, '\n');
getblock(buf, 1, 2, sstr);
sstr >> newN.xyz[2];
if (sstr.eof() == false)
{
int a = 0;
sstr >> a;
if (a < 0)
newN.xyz[2] = std::pow(10, a)*newN.xyz[2];
}
nodes_in.push_back(newN);
Nnodes++;
}
}
if (block == "CTRIA3*")
{
Cell newC;
sstr.str("");
sstr.clear();
getblock(buf, 1, 2, sstr);
sstr >> newC.id;
sstr.str("");
sstr.clear();
getblock(buf, 3, 2, sstr);
sstr >> newC.geoId;
sstr.str("");
sstr.clear();
getblock(buf, 5, 2, sstr);
sstr >> newC.nodes[0];
sstr.str("");
sstr.clear();
getblock(buf, 7, 2, sstr);
sstr >> newC.nodes[1];
sstr.str("");
sstr.clear();
getline(inf, buf, '\n');
getblock(buf, 1, 2, sstr);
sstr >> newC.nodes[2];
newC.type = 203;
elems_in.push_back(newC);
Ntris++;
}
if (block == "CQUAD4*")
{
Cell newC;
sstr.str("");
sstr.clear();
getblock(buf, 1, 2, sstr);
sstr >> newC.id;
sstr.str("");
sstr.clear();
getblock(buf, 3, 2, sstr);
sstr >> newC.geoId;
sstr.str("");
sstr.clear();
getblock(buf, 5, 2, sstr);
sstr >> newC.nodes[0];
sstr.str("");
sstr.clear();
getblock(buf, 7, 2, sstr);
sstr >> newC.nodes[1];
sstr.str("");
sstr.clear();
getline(inf, buf, '\n');
getblock(buf, 1, 2, sstr);
sstr >> newC.nodes[2];
sstr.str("");
sstr.clear();
getblock(buf, 3, 2, sstr);
sstr >> newC.nodes[3];
newC.type = 204;
elems_in.push_back(newC);
Nquads++;
}
if (block == "CTETRA*")
{
Cell newC;
sstr.str("");
sstr.clear();
getblock(buf, 1, 2, sstr);
sstr >> newC.id;
sstr.str("");
sstr.clear();
getblock(buf, 3, 2, sstr);
sstr >> newC.geoId;
sstr.str("");
sstr.clear();
getblock(buf, 5, 2, sstr);
sstr >> newC.nodes[0];
sstr.str("");
sstr.clear();
getblock(buf, 7, 2, sstr);
sstr >> newC.nodes[1];
sstr.str("");
sstr.clear();
getline(inf, buf, '\n');
getblock(buf, 1, 2, sstr);
sstr >> newC.nodes[2];
sstr.str("");
sstr.clear();
getblock(buf, 3, 2, sstr);
sstr >> newC.nodes[3];
newC.type = 304;
elems_in.push_back(newC);
Ntets++;
}
if (block == "GRID")
{
Node newN;
sstr.str("");
sstr.clear();
getblock(buf, 1, 1, sstr);
sstr >> newN.id;
{
sstr.str("");
sstr.clear();
getblock(buf, 3, 1, sstr);
sstr >> newN.xyz[0];
if (sstr.eof() == false)
{
int a = 0;
sstr >> a;
if (a < 0)
newN.xyz[0] = std::pow(10, a)*newN.xyz[0];
}
sstr.str("");
sstr.clear();
getblock(buf, 4, 1, sstr);
sstr >> newN.xyz[1];
if (sstr.eof() == false)
{
int a = 0;
sstr >> a;
if (a < 0)
newN.xyz[1] = std::pow(10, a)*newN.xyz[1];
}
sstr.str("");
sstr.clear();
getblock(buf, 5, 1, sstr);
sstr >> newN.xyz[2];
if (sstr.eof() == false)
{
int a = 0;
sstr >> a;
if (a < 0)
newN.xyz[2] = std::pow(10, a)*newN.xyz[2];
}
nodes_in.push_back(newN);
Nnodes++;
}
}
if (block == "CTRIA3")
{
Cell newC;
sstr.str("");
sstr.clear();
getblock(buf, 1, 1, sstr);
sstr >> newC.id;
sstr.str("");
sstr.clear();
getblock(buf, 2, 1, sstr);
sstr >> newC.geoId;
sstr.str("");
sstr.clear();
getblock(buf, 3, 1, sstr);
sstr >> newC.nodes[0];
sstr.str("");
sstr.clear();
getblock(buf, 4, 1, sstr);
sstr >> newC.nodes[1];
sstr.str("");
sstr.clear();
getblock(buf, 5, 1, sstr);
sstr >> newC.nodes[2];
newC.type = 203;
elems_in.push_back(newC);
Ntris++;
}
if (block == "CQUAD4")
{
Cell newC;
sstr.str("");
sstr.clear();
getblock(buf, 1, 1, sstr);
sstr >> newC.id;
sstr.str("");
sstr.clear();
getblock(buf, 2, 1, sstr);
sstr >> newC.geoId;
sstr.str("");
sstr.clear();
getblock(buf, 3, 1, sstr);
sstr >> newC.nodes[0];
sstr.str("");
sstr.clear();
getblock(buf, 4, 1, sstr);
sstr >> newC.nodes[1];
sstr.str("");
sstr.clear();
getblock(buf, 5, 1, sstr);
sstr >> newC.nodes[2];
sstr.str("");
sstr.clear();
getblock(buf, 6, 1, sstr);
sstr >> newC.nodes[3];
newC.type = 204;
elems_in.push_back(newC);
Nquads++;
}
if (block == "CTETRA")
{
Cell newC;
sstr.str("");
sstr.clear();
getblock(buf, 1, 1, sstr);
sstr >> newC.id;
sstr.str("");
sstr.clear();
getblock(buf, 2, 1, sstr);
sstr >> newC.geoId;
sstr.str("");
sstr.clear();
getblock(buf, 3, 1, sstr);
sstr >> newC.nodes[0];
sstr.str("");
sstr.clear();
getblock(buf, 4, 1, sstr);
sstr >> newC.nodes[1];
sstr.str("");
sstr.clear();
getblock(buf, 5, 1, sstr);
sstr >> newC.nodes[2];
sstr.str("");
sstr.clear();
getblock(buf, 6, 1, sstr);
sstr >> newC.nodes[3];
newC.type = 304;
elems_in.push_back(newC);
Ntets++;
}
}
inf.close();
int maxid = 1;
for (size_t i = 0; i < nodes_in.size(); i++)
{
if (maxid < nodes_in[i].id)
{
maxid = (int)nodes_in[i].id;
}
}
vector<int> idmap(maxid + 1, -1);
int Nnode2 = 0;
for (size_t i = 0; i < nodes_in.size(); ++i) {
if (idmap[nodes_in[i].id] == -1)
{
for (int j = 0; j < 3; j++)
nodes.push_back(nodes_in[i].xyz[j]);
idmap[nodes_in[i].id] = Nnode2;
Nnode2++;
}
}
int maxcellid = 1;
for (size_t i = 0; i < elems_in.size(); i++)
{
if (maxcellid < elems_in[i].id)
{
maxcellid = elems_in[i].id;
}
}
int Nelem2 = 0;
vector<int> idcellmapMB(maxcellid + 1, -1);
for (size_t i = 0; i < elems_in.size(); i++)
{
if (idcellmapMB[elems_in[i].id] == -1)
{
int geoId = elems_in[i].geoId;
if (elems_in[i].type == 203)
{
for (int j = 0; j < 3; j++)
tris.push_back(idmap[elems_in[i].nodes[j]]);
tris.push_back(geoId);
}
else if (elems_in[i].type == 204)
{
for (int j = 0; j < 4; j++)
quads.push_back(idmap[elems_in[i].nodes[j]]);
quads.push_back(geoId);
}
else if (elems_in[i].type == 304)
{
for (int j = 0; j < 4; j++)
tets.push_back(idmap[elems_in[i].nodes[j]]);
tets.push_back(geoId);
}
idcellmapMB[elems_in[i].id] = Nelem2;
Nelem2++;
}
}
//writeJson;
if (1)
{
Json::Value jsonOut;
if (!WriteData(jsonOut, "meshInput.points", nodes))
{
return false;
}
WriteData(jsonOut, "meshInput.triangles", tris);
WriteData(jsonOut, "meshInput.quadrilaterals", quads);
WriteData(jsonOut, "meshInput.tetrahedrons", tets);
if (!SetToFile(jsonOut, fnout))
return false;
}
cout << "Input BDF file successfully!" << endl;
cout << "***************************************" << endl;
cout << "Nnodes: " << Nnode2 << endl;
cout << "Ntris: " << tris.size() / 4 << endl;
cout << "Nquads: " << quads.size() / 5 << endl;
cout << "Ntets: " << tets.size() / 5 << endl;
cout << "***************************************" << endl;
return true;
}
#define PARSE_VA_MSG0(fmtO,lenO,fmtI) {va_list argptr; va_start(argptr,fmtI); vsprintf(fmtO,fmtI,argptr);va_end(argptr);}
#define PARSE_VA_MSG( fmtO,lenO,fmtI) char fmtO[lenO+1];PARSE_VA_MSG0(fmtO,lenO,fmtI);
void DebugMessageBox(const char * mg, ...)
{
#if defined(_WIN32) && defined(_DEBUG)
if (!getenv("ENABLE_PAUSE_TETGEN"))
return;
char buffer[8192];
PARSE_VA_MSG(buf, 8192, mg);
DWORD pidwin = GetCurrentProcessId();
sprintf(buffer, "%s (pid=%d)", buf, pidwin);
MessageBoxA(GetDesktopWindow(), buffer, "Debuger", MB_OK);
#endif
}
struct RefineData
{
std::vector<float> mValue;
double sizeData[4];
int32_t mSize[3];
double mStart[3], mStep[3], mStepInv[3];
double mDfMax;
RefineData()
{
mSize[0] = mSize[1] = mSize[2] = 0.0;
}
size_t sizeYZ()const { return mSize[1] * mSize[2]; }
size_t index(size_t x, size_t y, size_t z)const { return x * sizeYZ() + y * mSize[2] + z; }
void getCellIndex(const REAL *pos, int32_t*idx) const
{
for (uint32_t i = 0; i < 3; i++) {
idx[i] = (pos[i] - mStart[i]) * mStepInv[i];
if (idx[i] >= (mSize[i] - 1))
{
idx[i] = mSize[i] - 1;
}
if (idx[i] < 0) {
idx[i] = 0;
}
}
}
float valueI(int x, int y, int z)const { return mValue[index(x, y, z)]; }
double operator()(const REAL* p)const
{
REAL t[3];
int idx[3];
for (int i = 0; i < 3; i++) {
t[i] = (p[i] - mStart[i]) / mStep[0];
if (t[i] < 2 || t[i] > (mSize[i] - 3)) {
this->getCellIndex(p, idx);
return mValue[index(idx[0], idx[1], idx[2])];
}
}
int i = (int)(t[0]), j = (int)(t[1]), k = (int)(t[2]);
double a = t[0] - i, b = t[1] - j, c = t[2] - k;
double lVal = (1 - a) * (1 - b) * (1 - c) * valueI(i, j, k) + a * (1 - b) * (1 - c) * valueI(i + 1, j, k) +
(1 - a) * (b) * (1 - c) * valueI(i, j + 1, k) + a * (b) * (1 - c) * valueI(i + 1, j + 1, k) +
(1 - a) * (1 - b) * (c)*valueI(i, j, k + 1) + a * (1 - b) * (c)*valueI(i + 1, j, k + 1) +
(1 - a) * (b) * (c)*valueI(i, j + 1, k + 1) + a * (b) * (c)*valueI(i + 1, j + 1, k + 1);
if (lVal < sizeData[2])
lVal = sizeData[2];
if (lVal > sizeData[3])
lVal = sizeData[3];
return lVal;
}
};
RefineData gRefineData;
REAL Distance3D(const REAL* a, const REAL* b)
{
REAL dx = a[0] - b[0];
REAL dy = a[1] - b[1];
REAL dz = a[2] - b[2];
return sqrt(dx * dx + dy * dy + dz * dz);
}
double LenNormal(double len, double h0, double h1)
{
assert(h0 > 0 && h1 > 0);
double diff = h0 - h1;
double sum = h0 + h1;
double det = sum * 0.5e-2;
if (fabs(diff) < det)
{
return 2 * len / sum;
}
return len * log(h0 / h1) / diff;
}
bool IsTetraNeedRefine(REAL* v1, REAL* v2, REAL* v3, REAL* v4, REAL* el, REAL area)
{
static const short TET_EDGE_VERTEX[6][2] = { {0,1},{1,2},{2,0},{0,3},{1,3},{2,3} };
const REAL* pts[] = { v1 ,v2 ,v3 ,v4 };
auto getMaxLength = [&](double& max)
{
max = 0;
int whiMax = -1;
for (int i = 0; i < 6; i++)
{
double dis = Distance3D(pts[TET_EDGE_VERTEX[i][0]], pts[TET_EDGE_VERTEX[i][1]]);
if (dis > max)
{
max = dis;
whiMax = i;
}
}
return whiMax;
};
double lMax;
int whiMax = getMaxLength(lMax);
if (gRefineData.mDfMax > 0 && lMax > gRefineData.mDfMax)
{
return true;
}
if (gRefineData.mValue.empty())
return false;
double dfs[2];
dfs[0] = gRefineData(pts[TET_EDGE_VERTEX[whiMax][0]]);
if (dfs[0] <= 0)
return false;
dfs[1] = gRefineData(pts[TET_EDGE_VERTEX[whiMax][1]]);
if (dfs[1] <= 0)
return false;
double lenMax = LenNormal(lMax, dfs[0], dfs[1]);
return lenMax > 1.5;
}
class ScopedRedirect
{
public:
ScopedRedirect(const char* fn = "logfile.log")
{
_savedStream = freopen(fn, "w", stdout);
}
~ScopedRedirect()
{
fflush(_savedStream);
_savedStream = freopen("CON", "w", stdout);
}
private:
FILE *_savedStream;
};
int MeshGen2(const std::string& finput, const std::string& fout)
{
typedef ArrayHashProxy<DInt3Array, HashInt3> Int3HArray;
double mDFMax = -1;
try
{
auto MarkTetra = [](const tetgenio& in, const tetgenio& out, DIntArray& tetFlag) {
if (out.numberoftetrahedra < 1 || !out.neighborlist)
return;
if (0) {
//DebugBdf(out, "tetgen.bdf", nullptr);
}
tetFlag.resize(out.numberoftetrahedra, 0);
std::stack<int> elemStack;
int nMarked = 0;
for (int i = 0; i < out.numberoftetrahedra; i++) {
int index = i * 4;
for (int j = 0; j < 4; j++) {
int eAdj = out.neighborlist[index + j];
//outer tets.
if (eAdj < 0) {
tetFlag[i] = 1;
++nMarked;
elemStack.push(i);
break;
}
}
}
//whether tet contains boundaryfaces.
DInt3Array boundaryFace(in.numberoffacets);
for (size_t i = 0; i < in.numberoffacets; i++) {
const auto& p = in.facetlist[i].polygonlist[0];
boundaryFace[i] = Int3(p.vertexlist[0], p.vertexlist[1], p.vertexlist[2]);
}
Int3HArray tetFacesProxy(boundaryFace);
while (nMarked < out.numberoftetrahedra) {
int nNewMarked = 0;
DIntArray elemStackNext;
while (!elemStack.empty()) {
int ei = elemStack.top();
assert(tetFlag[ei] != 0);
int index = ei * 4;
elemStack.pop();
auto tet = out.tetrahedronlist + ei * 4;
for (int i = 0; i < 4; i++) {
int eAdj = out.neighborlist[index + i];
if (eAdj < 0 || tetFlag[eAdj] != 0)
continue;
//cross boundary face. face-topo may change!
int pos = tetFacesProxy.find(Int3(tet[TET_FACE_VERTEX[i][0]], tet[TET_FACE_VERTEX[i][1]], tet[TET_FACE_VERTEX[i][2]]));
if (pos < 0) {
elemStack.push(eAdj);
tetFlag[eAdj] = tetFlag[ei];
nMarked++;
++nNewMarked;
}
else {
elemStackNext.push_back(eAdj);
tetFlag[eAdj] = -tetFlag[ei];
nMarked++;
++nNewMarked;
}
}
}
if (nNewMarked < 1)
break;
Unique(elemStackNext);
for (auto it : elemStackNext) {
elemStack.push(it);
}
}
};
std::stringstream os;
ScopedRedirect redirect;
tetgenio::gPrintFun = MyPrintFun;
tetgenio tetIn, out, addin;
Json::Value jsonObj;
tetgenbehavior b;
{
if (!SetByFile(jsonObj, finput))
return -1;
std::string meshCtrl, meshdata, addmeshdata;
if (!GetValue(jsonObj, "tetgenInputMesh", meshdata))
{
return -1;
}
if (HasKey(jsonObj, "behavior"))
{
meshCtrl = Convert2TetGenCommand(jsonObj["behavior"], tetIn.numberoftetrahedra);
}
else if (!GetValue(jsonObj, "behavior4Tetgen", meshCtrl))
{
return false;
}
b.parse_commandline((char*)(meshCtrl.c_str()));
if (!tetgeniobyfile(tetIn, meshdata))
{
if (!tetgeniobystring(tetIn, meshdata))
{
return false;
}
}
gRefineData.mDfMax = -1;
double dfmax;
if (tGetValue(jsonObj, "meshSizeMax", dfmax) && dfmax > 0.0) {
gRefineData.mDfMax= dfmax;
tetIn.tetunsuitable = IsTetraNeedRefine;
}
std::string refinementsFile;
if (GetValue(jsonObj, "refinements", refinementsFile))
{
auto lmdReadRefine = [](std::istream& mIO)
{
size_t num;
mIO.read((char*)(&num), sizeof(size_t));
gRefineData.mValue.resize(num);
mIO.read((char*)gRefineData.mValue.data(), sizeof(float)*gRefineData.mValue.size());
mIO.read((char*)gRefineData.sizeData, 4 * sizeof(double));
mIO.read((char*)gRefineData.mSize, 3 * sizeof(int32_t));
mIO.read((char*)gRefineData.mStart, 3 * sizeof(double));
mIO.read((char*)gRefineData.mStep, 3 * sizeof(double));
mIO.read((char*)gRefineData.mStepInv, 3 * sizeof(double));
};
std::ifstream mIO(refinementsFile.c_str(), std::ios_base::in | std::ios_base::binary);
if (!mIO) {
std::string strOut;
if (Base64::Decode(refinementsFile, &strOut))
{
std::stringstream mIO;
mIO.write(strOut.data(), strOut.size());
lmdReadRefine(mIO);
tetIn.tetunsuitable = IsTetraNeedRefine;
}
}
else
{
lmdReadRefine(mIO);
tetIn.tetunsuitable = IsTetraNeedRefine;
}
}
if (GetValue(jsonObj, "addInputMesh", addmeshdata))
{
tetgeniobystring(addin, addmeshdata);
}
}
tetrahedralize(&b, &tetIn, &out, &addin, nullptr);
if (out.numberofpoints < 4 || out.numberoftetrahedra < 1)
return -1;
int markTetra = 1;
tGetValue(jsonObj, "markTetra", markTetra);
std::vector<int> tetFlag;
if (markTetra > 0) {
MarkTetra(tetIn, out, tetFlag);
}
int pos = fout.find_last_of('.');
if (fout.substr(pos) == ".json") {
std::string strData;
if (!tetgenio2string(out, strData, markTetra > 0? &tetFlag:nullptr))
{
return false;
}
Json::Value result;
result["meshResult"] = strData;
std::ofstream out(fout);
Json::FastWriter wr;
out << wr.write(result);
}
else if (!tetgenio2file(out, fout, markTetra > 0? &tetFlag:nullptr))
return false;
}
catch (...) {
return -1;
}
return 0;
}
int MeshGen(const std::string& finput, const std::string& fout)
{
typedef ArrayHashProxy<DInt3Array, HashInt3> Int3HArray;
try {
Json::Value jsonObj, jsonOut;
if (!SetByFile(jsonObj, finput))
return -1;
tetgenio tetIn, out, inadd;
auto ImportMesh = [&]()
{
std::vector<double> points;
if (!GetData(jsonObj, "meshInput.points", points))
{
return false;
}
tetIn.numberofpoints = points.size() / 3;
tetIn.pointlist = new REAL[tetIn.numberofpoints * 3];
memcpy(tetIn.pointlist, points.data(), points.size() * sizeof(double));
if (GetData(jsonObj, "refinements.points", points))
{
// bgmin.numberofpoints = points.size() / 4;
// bgmin.pointlist = new REAL[bgmin.numberofpoints * 3];
// bgmin.numberofpointmtrs = 1;
// bgmin.pointmtrlist = new REAL[bgmin.numberofpoints * bgmin.numberofpointmtrs];
//
//
// for (int i = 0; i < bgmin.numberofpoints; i++)
// {
// for (int j = 0; j < 3; j++)
// {
// tetIn.pointlist[i * 3 + j] = points[i * 4 + j];
// }
// bgmin.pointmtrlist[i] = points[i * 4 + 3];
// }
}
{
std::vector<int> triangles, quad;
GetData(jsonObj, "meshInput.triangles", triangles);
GetData(jsonObj, "meshInput.quadrilaterals", quad);
tetIn.numberoffacets = triangles.size() / 4 + quad.size() / 5;
if (tetIn.numberoffacets > 0) {
tetIn.facetlist = new tetgenio::facet[tetIn.numberoffacets];
tetIn.facetmarkerlist = new int[tetIn.numberoffacets];
int fi = 0;
auto ntri = triangles.size() / 4;
for (size_t i = 0; i < ntri; i++)
{
tetgenio::facet *f = &tetIn.facetlist[fi];
tetgenio::init(f);
f->numberofholes = 0;
f->numberofpolygons = 1;
f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
tetgenio::polygon *p = &f->polygonlist[0];
tetgenio::init(p);
p->numberofvertices = 3;
p->vertexlist = new int[p->numberofvertices];
for (int j = 0; j < p->numberofvertices; j++)
{
p->vertexlist[j] = triangles[i * 4 + j];
}
tetIn.facetmarkerlist[fi] = 203;
++fi;
}
int nquad = quad.size() / 5;
for (size_t i = 0; i < nquad; i++)
{
tetgenio::facet *f = &tetIn.facetlist[fi];
tetgenio::init(f);
f->numberofholes = 0;
f->numberofpolygons = 1;
f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
tetgenio::polygon *p = &f->polygonlist[0];
tetgenio::init(p);
p->numberofvertices = 4;
p->vertexlist = new int[p->numberofvertices];
for (int j = 0; j < p->numberofvertices; j++)
{
p->vertexlist[j] = quad[i * 5 + j];
}
tetIn.facetmarkerlist[fi] = 204;
++fi;
}
}
}
{
std::vector<int> tets;
GetData(jsonObj, "meshInput.tetrahedrons", tets);
int ntet = tets.size() / 5;
tetIn.numberoftetrahedra = ntet;
if (ntet > 0) {
tetIn.tetrahedronlist = new int[tetIn.numberoftetrahedra * 4];
if (!tetIn.tetrahedronlist) {
return false;
}
int index = 0;
for (size_t i = 0; i < ntet; i++) {
for (int j = 0; j < 4; j++) {
tetIn.tetrahedronlist[index++] = tets[i * 5 + j];
}
}
}
}
return true;
};
auto MarkTetra = [](const tetgenio& in, const tetgenio& out, DIntArray& tetFlag) {
if (out.numberoftetrahedra < 1 || !out.neighborlist)
return;
if (0) {
//DebugBdf(out, "tetgen.bdf", nullptr);
}
tetFlag.resize(out.numberoftetrahedra, 0);
std::stack<int> elemStack;
int nMarked = 0;
for (int i = 0; i < out.numberoftetrahedra; i++) {
int index = i * 4;
for (int j = 0; j < 4; j++) {
int eAdj = out.neighborlist[index + j];
//outer tets.
if (eAdj < 0) {
tetFlag[i] = 1;
++nMarked;
elemStack.push(i);
break;
}
}
}
//whether tet contains boundaryfaces.
DInt3Array boundaryFace(in.numberoffacets);
for (size_t i = 0; i < in.numberoffacets; i++) {
const auto& p = in.facetlist[i].polygonlist[0];
boundaryFace[i] = Int3(p.vertexlist[0], p.vertexlist[1], p.vertexlist[2]);
}
Int3HArray tetFacesProxy(boundaryFace);
while (nMarked < out.numberoftetrahedra) {
int nNewMarked = 0;
DIntArray elemStackNext;
while (!elemStack.empty()) {
int ei = elemStack.top();
assert(tetFlag[ei] != 0);
int index = ei * 4;
elemStack.pop();
auto tet = out.tetrahedronlist + ei * 4;
for (int i = 0; i < 4; i++) {
int eAdj = out.neighborlist[index + i];
if (eAdj < 0 || tetFlag[eAdj] != 0)
continue;
//cross boundary face. face-topo may change!
int pos = tetFacesProxy.find(Int3(tet[TET_FACE_VERTEX[i][0]], tet[TET_FACE_VERTEX[i][1]], tet[TET_FACE_VERTEX[i][2]]));
if (pos < 0) {
elemStack.push(eAdj);
tetFlag[eAdj] = tetFlag[ei];
nMarked++;
++nNewMarked;
}
else {
elemStackNext.push_back(eAdj);
tetFlag[eAdj] = -tetFlag[ei];
nMarked++;
++nNewMarked;
}
}
}
if (nNewMarked < 1)
break;
Unique(elemStackNext);
for (auto it : elemStackNext) {
elemStack.push(it);
}
}
};
auto ExportMesh = [&]()
{
std::vector<int> tetFlag;
MarkTetra(tetIn, out, tetFlag);
std::vector<double> points;
points.resize(out.numberofpoints * 3);
memcpy(points.data(), out.pointlist, out.numberofpoints * 3 * sizeof(double));
if (!WriteData(jsonOut, "meshOutput.points", points))
{
return false;
}
std::vector<int> tets;
int Ntet = 0;
for (size_t i = 0; i < out.numberoftetrahedra; i++)
{
if (tetFlag[i] < 0)
continue;
auto tet = out.tetrahedronlist + i * 4;
for (int j = 0; j < 4; j++) {
tets.push_back(tet[j]);
}
tets.push_back(304);
Ntet++;
}
if (!WriteData(jsonOut, "meshOutput.tetrahedrons", tets))
{
return false;
}
return true;
};
if (!ImportMesh())
return -1;
if (0) {
DebugBdf(tetIn, "tetgenIn.bdf", nullptr);
}
auto meshCtrl = Convert2TetGenCommand(jsonObj, tetIn.numberoftetrahedra);
tetgenbehavior b;
b.parse_commandline((char*)meshCtrl.c_str());
tetrahedralize(&b, &tetIn, &out, inadd.numberofpoints > 0 ? &inadd : nullptr);
if (out.numberofpoints < 4 || out.numberoftetrahedra < 1)
return -1;
if (0) {
DebugBdf(out, "tetgenOut.bdf", nullptr);
}
// ouput
if (!ExportMesh())
return -1;
if (!SetToFile(jsonOut, fout))
return false;
}
catch (...) {
return -1;
}
return 0;
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/DLUT_MeshGene/tetgen.git
git@gitee.com:DLUT_MeshGene/tetgen.git
DLUT_MeshGene
tetgen
tetgen
master

搜索帮助